summaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/SConscript3
-rw-r--r--src/gallium/targets/Makefile.dri13
-rw-r--r--src/gallium/targets/libgl-gdi/SConscript1
-rw-r--r--src/glsl/.dir-locals.el3
-rw-r--r--src/glsl/.gitignore2
-rw-r--r--src/glsl/Makefile177
-rw-r--r--src/glsl/Makefile.am75
-rw-r--r--src/glsl/README190
-rw-r--r--src/glsl/SConscript112
-rw-r--r--src/glsl/TODO50
-rw-r--r--src/glsl/ast.h664
-rw-r--r--src/glsl/ast_expr.cpp96
-rw-r--r--src/glsl/ast_function.cpp1247
-rw-r--r--src/glsl/ast_to_hir.cpp2607
-rw-r--r--src/glsl/ast_type.cpp122
-rwxr-xr-xsrc/glsl/autogen.sh12
-rw-r--r--src/glsl/builtin_function.cpp14822
-rw-r--r--src/glsl/builtin_types.h290
-rw-r--r--src/glsl/builtin_variables.h98
-rw-r--r--src/glsl/builtins/ir/abs21
-rw-r--r--src/glsl/builtins/ir/acos22
-rw-r--r--src/glsl/builtins/ir/all16
-rw-r--r--src/glsl/builtins/ir/any16
-rw-r--r--src/glsl/builtins/ir/asin97
-rw-r--r--src/glsl/builtins/ir/atan154
-rw-r--r--src/glsl/builtins/ir/ceil21
-rw-r--r--src/glsl/builtins/ir/clamp148
-rw-r--r--src/glsl/builtins/ir/cos21
-rw-r--r--src/glsl/builtins/ir/cosh30
-rw-r--r--src/glsl/builtins/ir/cross7
-rw-r--r--src/glsl/builtins/ir/dFdx21
-rw-r--r--src/glsl/builtins/ir/dFdy21
-rw-r--r--src/glsl/builtins/ir/degrees21
-rw-r--r--src/glsl/builtins/ir/distance33
-rw-r--r--src/glsl/builtins/ir/dot25
-rw-r--r--src/glsl/builtins/ir/equal91
-rw-r--r--src/glsl/builtins/ir/exp21
-rw-r--r--src/glsl/builtins/ir/exp221
-rw-r--r--src/glsl/builtins/ir/faceforward37
-rw-r--r--src/glsl/builtins/ir/floor21
-rw-r--r--src/glsl/builtins/ir/fract22
-rw-r--r--src/glsl/builtins/ir/ftransform9
-rw-r--r--src/glsl/builtins/ir/fwidth29
-rw-r--r--src/glsl/builtins/ir/greaterThan91
-rw-r--r--src/glsl/builtins/ir/greaterThanEqual91
-rw-r--r--src/glsl/builtins/ir/inversesqrt21
-rw-r--r--src/glsl/builtins/ir/length21
-rw-r--r--src/glsl/builtins/ir/lessThan91
-rw-r--r--src/glsl/builtins/ir/lessThanEqual91
-rw-r--r--src/glsl/builtins/ir/log21
-rw-r--r--src/glsl/builtins/ir/log221
-rw-r--r--src/glsl/builtins/ir/matrixCompMult91
-rw-r--r--src/glsl/builtins/ir/max127
-rw-r--r--src/glsl/builtins/ir/min127
-rw-r--r--src/glsl/builtins/ir/mix88
-rw-r--r--src/glsl/builtins/ir/mod43
-rw-r--r--src/glsl/builtins/ir/noise118
-rw-r--r--src/glsl/builtins/ir/noise218
-rw-r--r--src/glsl/builtins/ir/noise318
-rw-r--r--src/glsl/builtins/ir/noise418
-rw-r--r--src/glsl/builtins/ir/normalize21
-rw-r--r--src/glsl/builtins/ir/not16
-rw-r--r--src/glsl/builtins/ir/notEqual91
-rw-r--r--src/glsl/builtins/ir/outerProduct92
-rw-r--r--src/glsl/builtins/ir/pow25
-rw-r--r--src/glsl/builtins/ir/radians21
-rw-r--r--src/glsl/builtins/ir/reflect58
-rw-r--r--src/glsl/builtins/ir/refract102
-rw-r--r--src/glsl/builtins/ir/sign42
-rw-r--r--src/glsl/builtins/ir/sin21
-rw-r--r--src/glsl/builtins/ir/sinh30
-rw-r--r--src/glsl/builtins/ir/smoothstep153
-rw-r--r--src/glsl/builtins/ir/sqrt21
-rw-r--r--src/glsl/builtins/ir/step68
-rw-r--r--src/glsl/builtins/ir/tan21
-rw-r--r--src/glsl/builtins/ir/tanh42
-rw-r--r--src/glsl/builtins/ir/transpose139
-rw-r--r--src/glsl/builtins/profiles/110.frag364
-rw-r--r--src/glsl/builtins/profiles/110.vert351
-rw-r--r--src/glsl/builtins/profiles/120.frag396
-rw-r--r--src/glsl/builtins/profiles/120.vert383
-rw-r--r--src/glsl/builtins/profiles/ARB_texture_rectangle.frag7
-rw-r--r--src/glsl/builtins/profiles/ARB_texture_rectangle.vert7
-rw-r--r--src/glsl/builtins/profiles/EXT_texture_array.frag11
-rw-r--r--src/glsl/builtins/profiles/EXT_texture_array.vert11
-rw-r--r--src/glsl/builtins/tools/builtin_function.cpp39
-rwxr-xr-xsrc/glsl/builtins/tools/generate_builtins.py207
-rwxr-xr-xsrc/glsl/builtins/tools/generate_matrixCompMultGLSL.py28
-rwxr-xr-xsrc/glsl/builtins/tools/generate_outerProductGLSL.py23
-rwxr-xr-xsrc/glsl/builtins/tools/generate_transposeGLSL.py28
-rwxr-xr-xsrc/glsl/builtins/tools/texture_builtins.py349
-rw-r--r--src/glsl/configure.ac69
-rw-r--r--src/glsl/glcpp/.gitignore8
-rw-r--r--src/glsl/glcpp/Makefile.am44
-rw-r--r--src/glsl/glcpp/README30
-rw-r--r--src/glsl/glcpp/glcpp-lex.c2640
-rw-r--r--src/glsl/glcpp/glcpp-lex.l293
-rw-r--r--src/glsl/glcpp/glcpp-parse.c4055
-rw-r--r--src/glsl/glcpp/glcpp-parse.h100
-rw-r--r--src/glsl/glcpp/glcpp-parse.y1729
-rw-r--r--src/glsl/glcpp/glcpp.c85
-rw-r--r--src/glsl/glcpp/glcpp.h222
-rw-r--r--src/glsl/glcpp/pp.c166
-rw-r--r--src/glsl/glcpp/tests/000-content-with-spaces.c1
-rw-r--r--src/glsl/glcpp/tests/000-content-with-spaces.c.expected2
-rw-r--r--src/glsl/glcpp/tests/001-define.c2
-rw-r--r--src/glsl/glcpp/tests/001-define.c.expected3
-rw-r--r--src/glsl/glcpp/tests/002-define-chain.c3
-rw-r--r--src/glsl/glcpp/tests/002-define-chain.c.expected4
-rw-r--r--src/glsl/glcpp/tests/003-define-chain-reverse.c3
-rw-r--r--src/glsl/glcpp/tests/003-define-chain-reverse.c.expected4
-rw-r--r--src/glsl/glcpp/tests/004-define-recursive.c6
-rw-r--r--src/glsl/glcpp/tests/004-define-recursive.c.expected7
-rw-r--r--src/glsl/glcpp/tests/005-define-composite-chain.c3
-rw-r--r--src/glsl/glcpp/tests/005-define-composite-chain.c.expected4
-rw-r--r--src/glsl/glcpp/tests/006-define-composite-chain-reverse.c3
-rw-r--r--src/glsl/glcpp/tests/006-define-composite-chain-reverse.c.expected4
-rw-r--r--src/glsl/glcpp/tests/007-define-composite-recursive.c6
-rw-r--r--src/glsl/glcpp/tests/007-define-composite-recursive.c.expected7
-rw-r--r--src/glsl/glcpp/tests/008-define-empty.c2
-rw-r--r--src/glsl/glcpp/tests/008-define-empty.c.expected3
-rw-r--r--src/glsl/glcpp/tests/009-undef.c4
-rw-r--r--src/glsl/glcpp/tests/009-undef.c.expected5
-rw-r--r--src/glsl/glcpp/tests/010-undef-re-define.c6
-rw-r--r--src/glsl/glcpp/tests/010-undef-re-define.c.expected7
-rw-r--r--src/glsl/glcpp/tests/011-define-func-empty.c2
-rw-r--r--src/glsl/glcpp/tests/011-define-func-empty.c.expected3
-rw-r--r--src/glsl/glcpp/tests/012-define-func-no-args.c2
-rw-r--r--src/glsl/glcpp/tests/012-define-func-no-args.c.expected3
-rw-r--r--src/glsl/glcpp/tests/013-define-func-1-arg-unused.c2
-rw-r--r--src/glsl/glcpp/tests/013-define-func-1-arg-unused.c.expected3
-rw-r--r--src/glsl/glcpp/tests/014-define-func-2-arg-unused.c2
-rw-r--r--src/glsl/glcpp/tests/014-define-func-2-arg-unused.c.expected3
-rw-r--r--src/glsl/glcpp/tests/015-define-object-with-parens.c4
-rw-r--r--src/glsl/glcpp/tests/015-define-object-with-parens.c.expected5
-rw-r--r--src/glsl/glcpp/tests/016-define-func-1-arg.c2
-rw-r--r--src/glsl/glcpp/tests/016-define-func-1-arg.c.expected3
-rw-r--r--src/glsl/glcpp/tests/017-define-func-2-args.c2
-rw-r--r--src/glsl/glcpp/tests/017-define-func-2-args.c.expected3
-rw-r--r--src/glsl/glcpp/tests/018-define-func-macro-as-parameter.c3
-rw-r--r--src/glsl/glcpp/tests/018-define-func-macro-as-parameter.c.expected4
-rw-r--r--src/glsl/glcpp/tests/019-define-func-1-arg-multi.c2
-rw-r--r--src/glsl/glcpp/tests/019-define-func-1-arg-multi.c.expected3
-rw-r--r--src/glsl/glcpp/tests/020-define-func-2-arg-multi.c2
-rw-r--r--src/glsl/glcpp/tests/020-define-func-2-arg-multi.c.expected3
-rw-r--r--src/glsl/glcpp/tests/021-define-func-compose.c3
-rw-r--r--src/glsl/glcpp/tests/021-define-func-compose.c.expected4
-rw-r--r--src/glsl/glcpp/tests/022-define-func-arg-with-parens.c2
-rw-r--r--src/glsl/glcpp/tests/022-define-func-arg-with-parens.c.expected3
-rw-r--r--src/glsl/glcpp/tests/023-define-extra-whitespace.c8
-rw-r--r--src/glsl/glcpp/tests/023-define-extra-whitespace.c.expected9
-rw-r--r--src/glsl/glcpp/tests/024-define-chain-to-self-recursion.c3
-rw-r--r--src/glsl/glcpp/tests/024-define-chain-to-self-recursion.c.expected4
-rw-r--r--src/glsl/glcpp/tests/025-func-macro-as-non-macro.c2
-rw-r--r--src/glsl/glcpp/tests/025-func-macro-as-non-macro.c.expected3
-rw-r--r--src/glsl/glcpp/tests/026-define-func-extra-newlines.c6
-rw-r--r--src/glsl/glcpp/tests/026-define-func-extra-newlines.c.expected4
-rw-r--r--src/glsl/glcpp/tests/027-define-chain-obj-to-func.c3
-rw-r--r--src/glsl/glcpp/tests/027-define-chain-obj-to-func.c.expected4
-rw-r--r--src/glsl/glcpp/tests/028-define-chain-obj-to-non-func.c3
-rw-r--r--src/glsl/glcpp/tests/028-define-chain-obj-to-non-func.c.expected4
-rw-r--r--src/glsl/glcpp/tests/029-define-chain-obj-to-func-with-args.c3
-rw-r--r--src/glsl/glcpp/tests/029-define-chain-obj-to-func-with-args.c.expected4
-rw-r--r--src/glsl/glcpp/tests/030-define-chain-obj-to-func-compose.c4
-rw-r--r--src/glsl/glcpp/tests/030-define-chain-obj-to-func-compose.c.expected5
-rw-r--r--src/glsl/glcpp/tests/031-define-chain-func-to-func-compose.c4
-rw-r--r--src/glsl/glcpp/tests/031-define-chain-func-to-func-compose.c.expected5
-rw-r--r--src/glsl/glcpp/tests/032-define-func-self-recurse.c2
-rw-r--r--src/glsl/glcpp/tests/032-define-func-self-recurse.c.expected3
-rw-r--r--src/glsl/glcpp/tests/033-define-func-self-compose.c2
-rw-r--r--src/glsl/glcpp/tests/033-define-func-self-compose.c.expected3
-rw-r--r--src/glsl/glcpp/tests/034-define-func-self-compose-non-func.c2
-rw-r--r--src/glsl/glcpp/tests/034-define-func-self-compose-non-func.c.expected3
-rw-r--r--src/glsl/glcpp/tests/035-define-func-self-compose-non-func-multi-token-argument.c2
-rw-r--r--src/glsl/glcpp/tests/035-define-func-self-compose-non-func-multi-token-argument.c.expected3
-rw-r--r--src/glsl/glcpp/tests/036-define-func-non-macro-multi-token-argument.c3
-rw-r--r--src/glsl/glcpp/tests/036-define-func-non-macro-multi-token-argument.c.expected4
-rw-r--r--src/glsl/glcpp/tests/037-finalize-unexpanded-macro.c3
-rw-r--r--src/glsl/glcpp/tests/037-finalize-unexpanded-macro.c.expected4
-rw-r--r--src/glsl/glcpp/tests/038-func-arg-with-commas.c2
-rw-r--r--src/glsl/glcpp/tests/038-func-arg-with-commas.c.expected3
-rw-r--r--src/glsl/glcpp/tests/039-func-arg-obj-macro-with-comma.c3
-rw-r--r--src/glsl/glcpp/tests/039-func-arg-obj-macro-with-comma.c.expected4
-rw-r--r--src/glsl/glcpp/tests/040-token-pasting.c2
-rw-r--r--src/glsl/glcpp/tests/040-token-pasting.c.expected3
-rw-r--r--src/glsl/glcpp/tests/041-if-0.c5
-rw-r--r--src/glsl/glcpp/tests/041-if-0.c.expected6
-rw-r--r--src/glsl/glcpp/tests/042-if-1.c5
-rw-r--r--src/glsl/glcpp/tests/042-if-1.c.expected6
-rw-r--r--src/glsl/glcpp/tests/043-if-0-else.c7
-rw-r--r--src/glsl/glcpp/tests/043-if-0-else.c.expected8
-rw-r--r--src/glsl/glcpp/tests/044-if-1-else.c7
-rw-r--r--src/glsl/glcpp/tests/044-if-1-else.c.expected8
-rw-r--r--src/glsl/glcpp/tests/045-if-0-elif.c11
-rw-r--r--src/glsl/glcpp/tests/045-if-0-elif.c.expected12
-rw-r--r--src/glsl/glcpp/tests/046-if-1-elsif.c11
-rw-r--r--src/glsl/glcpp/tests/046-if-1-elsif.c.expected12
-rw-r--r--src/glsl/glcpp/tests/047-if-elif-else.c11
-rw-r--r--src/glsl/glcpp/tests/047-if-elif-else.c.expected12
-rw-r--r--src/glsl/glcpp/tests/048-if-nested.c11
-rw-r--r--src/glsl/glcpp/tests/048-if-nested.c.expected12
-rw-r--r--src/glsl/glcpp/tests/049-if-expression-precedence.c5
-rw-r--r--src/glsl/glcpp/tests/049-if-expression-precedence.c.expected6
-rw-r--r--src/glsl/glcpp/tests/050-if-defined.c17
-rw-r--r--src/glsl/glcpp/tests/050-if-defined.c.expected18
-rw-r--r--src/glsl/glcpp/tests/051-if-relational.c35
-rw-r--r--src/glsl/glcpp/tests/051-if-relational.c.expected36
-rw-r--r--src/glsl/glcpp/tests/052-if-bitwise.c20
-rw-r--r--src/glsl/glcpp/tests/052-if-bitwise.c.expected21
-rw-r--r--src/glsl/glcpp/tests/053-if-divide-and-shift.c15
-rw-r--r--src/glsl/glcpp/tests/053-if-divide-and-shift.c.expected16
-rw-r--r--src/glsl/glcpp/tests/054-if-with-macros.c34
-rw-r--r--src/glsl/glcpp/tests/054-if-with-macros.c.expected35
-rw-r--r--src/glsl/glcpp/tests/055-define-chain-obj-to-func-parens-in-text.c3
-rw-r--r--src/glsl/glcpp/tests/055-define-chain-obj-to-func-parens-in-text.c.expected4
-rw-r--r--src/glsl/glcpp/tests/056-macro-argument-with-comma.c4
-rw-r--r--src/glsl/glcpp/tests/056-macro-argument-with-comma.c.expected5
-rw-r--r--src/glsl/glcpp/tests/057-empty-arguments.c6
-rw-r--r--src/glsl/glcpp/tests/057-empty-arguments.c.expected7
-rw-r--r--src/glsl/glcpp/tests/058-token-pasting-empty-arguments.c5
-rw-r--r--src/glsl/glcpp/tests/058-token-pasting-empty-arguments.c.expected6
-rw-r--r--src/glsl/glcpp/tests/059-token-pasting-integer.c4
-rw-r--r--src/glsl/glcpp/tests/059-token-pasting-integer.c.expected5
-rw-r--r--src/glsl/glcpp/tests/060-left-paren-in-macro-right-paren-in-text.c3
-rw-r--r--src/glsl/glcpp/tests/060-left-paren-in-macro-right-paren-in-text.c.expected4
-rw-r--r--src/glsl/glcpp/tests/061-define-chain-obj-to-func-multi.c5
-rw-r--r--src/glsl/glcpp/tests/061-define-chain-obj-to-func-multi.c.expected6
-rw-r--r--src/glsl/glcpp/tests/062-if-0-skips-garbage.c5
-rw-r--r--src/glsl/glcpp/tests/062-if-0-skips-garbage.c.expected6
-rw-r--r--src/glsl/glcpp/tests/063-comments.c20
-rw-r--r--src/glsl/glcpp/tests/063-comments.c.expected14
-rw-r--r--src/glsl/glcpp/tests/064-version.c2
-rw-r--r--src/glsl/glcpp/tests/064-version.c.expected4
-rw-r--r--src/glsl/glcpp/tests/065-if-defined-parens.c17
-rw-r--r--src/glsl/glcpp/tests/065-if-defined-parens.c.expected18
-rw-r--r--src/glsl/glcpp/tests/066-if-nospace-expression.c3
-rw-r--r--src/glsl/glcpp/tests/066-if-nospace-expression.c.expected4
-rw-r--r--src/glsl/glcpp/tests/067-nested-ifdef-ifndef.c40
-rw-r--r--src/glsl/glcpp/tests/067-nested-ifdef-ifndef.c.expected41
-rw-r--r--src/glsl/glcpp/tests/068-accidental-pasting.c11
-rw-r--r--src/glsl/glcpp/tests/068-accidental-pasting.c.expected12
-rw-r--r--src/glsl/glcpp/tests/069-repeated-argument.c2
-rw-r--r--src/glsl/glcpp/tests/069-repeated-argument.c.expected3
-rw-r--r--src/glsl/glcpp/tests/070-undefined-macro-in-expression.c2
-rw-r--r--src/glsl/glcpp/tests/070-undefined-macro-in-expression.c.expected2
-rw-r--r--src/glsl/glcpp/tests/071-punctuator.c1
-rw-r--r--src/glsl/glcpp/tests/071-punctuator.c.expected2
-rw-r--r--src/glsl/glcpp/tests/072-token-pasting-same-line.c2
-rw-r--r--src/glsl/glcpp/tests/072-token-pasting-same-line.c.expected3
-rw-r--r--src/glsl/glcpp/tests/073-if-in-ifdef.c4
-rw-r--r--src/glsl/glcpp/tests/073-if-in-ifdef.c.expected5
-rw-r--r--src/glsl/glcpp/tests/074-elif-undef.c3
-rw-r--r--src/glsl/glcpp/tests/074-elif-undef.c.expected4
-rw-r--r--src/glsl/glcpp/tests/075-elif-elif-undef.c4
-rw-r--r--src/glsl/glcpp/tests/075-elif-elif-undef.c.expected5
-rw-r--r--src/glsl/glcpp/tests/076-elif-undef-nested.c5
-rw-r--r--src/glsl/glcpp/tests/076-elif-undef-nested.c.expected6
-rw-r--r--src/glsl/glcpp/tests/077-else-without-if.c1
-rw-r--r--src/glsl/glcpp/tests/077-else-without-if.c.expected4
-rw-r--r--src/glsl/glcpp/tests/078-elif-without-if.c1
-rw-r--r--src/glsl/glcpp/tests/078-elif-without-if.c.expected4
-rw-r--r--src/glsl/glcpp/tests/079-endif-without-if.c1
-rw-r--r--src/glsl/glcpp/tests/079-endif-without-if.c.expected4
-rw-r--r--src/glsl/glcpp/tests/080-if-without-expression.c4
-rw-r--r--src/glsl/glcpp/tests/080-if-without-expression.c.expected6
-rw-r--r--src/glsl/glcpp/tests/081-elif-without-expression.c3
-rw-r--r--src/glsl/glcpp/tests/081-elif-without-expression.c.expected5
-rw-r--r--src/glsl/glcpp/tests/082-invalid-paste.c2
-rw-r--r--src/glsl/glcpp/tests/082-invalid-paste.c.expected5
-rw-r--r--src/glsl/glcpp/tests/083-unterminated-if.c2
-rw-r--r--src/glsl/glcpp/tests/083-unterminated-if.c.expected5
-rw-r--r--src/glsl/glcpp/tests/084-unbalanced-parentheses.c2
-rw-r--r--src/glsl/glcpp/tests/085-incorrect-argument-count.c5
-rw-r--r--src/glsl/glcpp/tests/085-incorrect-argument-count.c.expected12
-rw-r--r--src/glsl/glcpp/tests/086-reserved-macro-names.c2
-rw-r--r--src/glsl/glcpp/tests/086-reserved-macro-names.c.expected7
-rw-r--r--src/glsl/glcpp/tests/099-c99-example.c17
-rw-r--r--src/glsl/glcpp/tests/099-c99-example.c.expected17
-rwxr-xr-xsrc/glsl/glcpp/tests/glcpp-test49
-rw-r--r--src/glsl/glsl_lexer.cpp3416
-rw-r--r--src/glsl/glsl_lexer.lpp369
-rw-r--r--src/glsl/glsl_parser.cpp5245
-rw-r--r--src/glsl/glsl_parser.h291
-rw-r--r--src/glsl/glsl_parser.ypp1508
-rw-r--r--src/glsl/glsl_parser_extras.cpp743
-rw-r--r--src/glsl/glsl_parser_extras.h214
-rw-r--r--src/glsl/glsl_symbol_table.h171
-rw-r--r--src/glsl/glsl_types.cpp550
-rw-r--r--src/glsl/glsl_types.h479
-rw-r--r--src/glsl/hir_field_selection.cpp103
-rw-r--r--src/glsl/ir.cpp1062
-rw-r--r--src/glsl/ir.h1398
-rw-r--r--src/glsl/ir_algebraic.cpp392
-rw-r--r--src/glsl/ir_basic_block.cpp149
-rw-r--r--src/glsl/ir_basic_block.h28
-rw-r--r--src/glsl/ir_clone.cpp401
-rw-r--r--src/glsl/ir_constant_expression.cpp1144
-rw-r--r--src/glsl/ir_constant_folding.cpp273
-rw-r--r--src/glsl/ir_constant_propagation.cpp435
-rw-r--r--src/glsl/ir_constant_variable.cpp198
-rw-r--r--src/glsl/ir_copy_propagation.cpp362
-rw-r--r--src/glsl/ir_dead_code.cpp135
-rw-r--r--src/glsl/ir_dead_code_local.cpp229
-rw-r--r--src/glsl/ir_dead_functions.cpp151
-rw-r--r--src/glsl/ir_div_to_mul_rcp.cpp115
-rw-r--r--src/glsl/ir_explog_to_explog2.cpp85
-rw-r--r--src/glsl/ir_expression_flattening.cpp188
-rw-r--r--src/glsl/ir_expression_flattening.h38
-rw-r--r--src/glsl/ir_function.cpp224
-rw-r--r--src/glsl/ir_function_can_inline.cpp71
-rw-r--r--src/glsl/ir_function_inlining.cpp417
-rw-r--r--src/glsl/ir_function_inlining.h30
-rw-r--r--src/glsl/ir_hierarchical_visitor.cpp295
-rw-r--r--src/glsl/ir_hierarchical_visitor.h176
-rw-r--r--src/glsl/ir_hv_accept.cpp369
-rw-r--r--src/glsl/ir_if_return.cpp246
-rw-r--r--src/glsl/ir_if_simplification.cpp84
-rw-r--r--src/glsl/ir_if_to_cond_assign.cpp168
-rw-r--r--src/glsl/ir_import_prototypes.cpp138
-rw-r--r--src/glsl/ir_mat_op_to_vec.cpp397
-rw-r--r--src/glsl/ir_mod_to_fract.cpp90
-rw-r--r--src/glsl/ir_noop_swizzle.cpp80
-rw-r--r--src/glsl/ir_optimization.h57
-rw-r--r--src/glsl/ir_print_visitor.cpp465
-rw-r--r--src/glsl/ir_print_visitor.h83
-rw-r--r--src/glsl/ir_reader.cpp1088
-rw-r--r--src/glsl/ir_reader.h34
-rw-r--r--src/glsl/ir_rvalue_visitor.cpp134
-rw-r--r--src/glsl/ir_rvalue_visitor.h47
-rw-r--r--src/glsl/ir_set_program_inouts.cpp167
-rw-r--r--src/glsl/ir_structure_splitting.cpp355
-rw-r--r--src/glsl/ir_sub_to_add_neg.cpp76
-rw-r--r--src/glsl/ir_swizzle_swizzle.cpp93
-rw-r--r--src/glsl/ir_tree_grafting.cpp361
-rw-r--r--src/glsl/ir_validate.cpp397
-rw-r--r--src/glsl/ir_variable.cpp416
-rw-r--r--src/glsl/ir_variable_refcount.cpp100
-rw-r--r--src/glsl/ir_variable_refcount.h85
-rw-r--r--src/glsl/ir_vec_index_to_cond_assign.cpp258
-rw-r--r--src/glsl/ir_vec_index_to_swizzle.cpp157
-rw-r--r--src/glsl/ir_visitor.h67
-rw-r--r--src/glsl/link_functions.cpp262
-rw-r--r--src/glsl/linker.cpp1340
-rw-r--r--src/glsl/linker.h35
-rw-r--r--src/glsl/list.h465
-rw-r--r--src/glsl/main.cpp283
-rw-r--r--src/glsl/program.h33
-rw-r--r--src/glsl/s_expression.cpp131
-rw-r--r--src/glsl/s_expression.h142
-rw-r--r--src/glsl/tests/array-01.glsl3
-rw-r--r--src/glsl/tests/array-02.glsl3
-rw-r--r--src/glsl/tests/array-03.glsl3
-rw-r--r--src/glsl/tests/array-04.glsl2
-rw-r--r--src/glsl/tests/array-05.glsl2
-rw-r--r--src/glsl/tests/array-06.glsl2
-rw-r--r--src/glsl/tests/array-07.glsl2
-rw-r--r--src/glsl/tests/array-08.glsl2
-rw-r--r--src/glsl/tests/array-09.glsl9
-rw-r--r--src/glsl/tests/array-10.glsl11
-rw-r--r--src/glsl/tests/array-11.glsl9
-rw-r--r--src/glsl/tests/array-12.glsl11
-rw-r--r--src/glsl/tests/array-13.glsl11
-rw-r--r--src/glsl/tests/attribute-01.glsl7
-rw-r--r--src/glsl/tests/attribute-02.glsl7
-rw-r--r--src/glsl/tests/attribute-03.glsl7
-rw-r--r--src/glsl/tests/attribute-04.glsl7
-rw-r--r--src/glsl/tests/attribute-05.glsl7
-rw-r--r--src/glsl/tests/attribute-06.glsl7
-rw-r--r--src/glsl/tests/attribute-07.glsl7
-rw-r--r--src/glsl/tests/attribute-08.glsl7
-rw-r--r--src/glsl/tests/attribute-09.glsl7
-rw-r--r--src/glsl/tests/attribute-10.glsl8
-rw-r--r--src/glsl/tests/attribute-11.glsl8
-rw-r--r--src/glsl/tests/condition-01.glsl8
-rw-r--r--src/glsl/tests/condition-02.glsl8
-rw-r--r--src/glsl/tests/condition-03.glsl8
-rw-r--r--src/glsl/tests/condition-04.glsl8
-rw-r--r--src/glsl/tests/condition-05.glsl13
-rw-r--r--src/glsl/tests/constructor-01.glsl6
-rw-r--r--src/glsl/tests/constructor-02.glsl7
-rw-r--r--src/glsl/tests/constructor-03.glsl12
-rw-r--r--src/glsl/tests/constructor-04.glsl14
-rw-r--r--src/glsl/tests/constructor-05.glsl13
-rw-r--r--src/glsl/tests/constructor-06.glsl13
-rw-r--r--src/glsl/tests/constructor-07.glsl13
-rw-r--r--src/glsl/tests/constructor-08.glsl13
-rw-r--r--src/glsl/tests/constructor-09.glsl26
-rw-r--r--src/glsl/tests/function-01.glsl16
-rw-r--r--src/glsl/tests/function-02.glsl16
-rw-r--r--src/glsl/tests/function-03.glsl16
-rw-r--r--src/glsl/tests/function-04.glsl15
-rw-r--r--src/glsl/tests/function-05.glsl26
-rw-r--r--src/glsl/tests/if-01.glsl11
-rw-r--r--src/glsl/tests/if-02.glsl11
-rw-r--r--src/glsl/tests/if-03.glsl11
-rw-r--r--src/glsl/tests/if-04.glsl11
-rw-r--r--src/glsl/tests/matrix-01.glsl6
-rw-r--r--src/glsl/tests/matrix-02.glsl6
-rw-r--r--src/glsl/tests/matrix-03.glsl6
-rw-r--r--src/glsl/tests/matrix-04.glsl6
-rw-r--r--src/glsl/tests/matrix-05.glsl6
-rw-r--r--src/glsl/tests/matrix-06.glsl6
-rw-r--r--src/glsl/tests/matrix-07.glsl27
-rw-r--r--src/glsl/tests/matrix-08.glsl19
-rw-r--r--src/glsl/tests/matrix-09.glsl11
-rw-r--r--src/glsl/tests/matrix-10.glsl12
-rw-r--r--src/glsl/tests/parameters-01.glsl11
-rw-r--r--src/glsl/tests/parameters-02.glsl11
-rw-r--r--src/glsl/tests/parameters-03.glsl9
-rw-r--r--src/glsl/tests/qualifier-01.glsl3
-rw-r--r--src/glsl/tests/qualifier-02.glsl2
-rw-r--r--src/glsl/tests/qualifier-03.glsl2
-rw-r--r--src/glsl/tests/qualifier-04.glsl3
-rw-r--r--src/glsl/tests/qualifier-05.glsl3
-rw-r--r--src/glsl/tests/qualifier-06.glsl7
-rw-r--r--src/glsl/tests/qualifier-07.glsl7
-rw-r--r--src/glsl/tests/swiz-01.glsl11
-rw-r--r--src/glsl/tests/swiz-02.glsl11
-rw-r--r--src/glsl/tests/void-01.glsl2
-rw-r--r--src/mesa/Makefile21
-rw-r--r--src/mesa/SConscript8
-rw-r--r--src/mesa/drivers/dri/Makefile.template4
-rw-r--r--src/mesa/drivers/dri/common/dri_util.h4
-rw-r--r--src/mesa/drivers/dri/i915/i915_context.c2
-rw-r--r--src/mesa/drivers/dri/i965/brw_program.c6
-rw-r--r--src/mesa/drivers/dri/i965/brw_vs.c8
-rw-r--r--src/mesa/drivers/dri/i965/brw_vs_emit.c25
-rw-r--r--src/mesa/drivers/dri/i965/brw_wm.c2
-rw-r--r--src/mesa/drivers/dri/i965/brw_wm.h9
-rw-r--r--src/mesa/drivers/dri/i965/brw_wm_emit.c53
-rw-r--r--src/mesa/drivers/dri/i965/brw_wm_fp.c11
-rw-r--r--src/mesa/drivers/dri/i965/brw_wm_glsl.c8
-rw-r--r--src/mesa/drivers/dri/i965/brw_wm_pass1.c6
-rw-r--r--src/mesa/drivers/dri/intel/intel_context.h1
-rw-r--r--src/mesa/drivers/dri/intel/intel_mipmap_tree.c1
-rw-r--r--src/mesa/drivers/dri/intel/intel_tex.h2
-rw-r--r--src/mesa/drivers/osmesa/Makefile3
-rw-r--r--src/mesa/main/dd.h21
-rw-r--r--src/mesa/main/imports.h28
-rw-r--r--src/mesa/main/mtypes.h24
-rw-r--r--src/mesa/main/shaderapi.c10
-rw-r--r--src/mesa/main/shaderobj.c18
-rw-r--r--src/mesa/main/shaderobj.h24
-rw-r--r--src/mesa/program/hash_table.c31
-rw-r--r--src/mesa/program/hash_table.h35
-rw-r--r--src/mesa/program/ir_to_mesa.cpp2718
-rw-r--r--src/mesa/program/ir_to_mesa.h38
-rw-r--r--src/mesa/program/prog_execute.c6
-rw-r--r--src/mesa/program/prog_instruction.h2
-rw-r--r--src/mesa/program/prog_optimize.c88
-rw-r--r--src/mesa/program/prog_parameter.c9
-rw-r--r--src/mesa/program/prog_parameter.h2
-rw-r--r--src/mesa/program/prog_print.c38
-rw-r--r--src/mesa/program/prog_print.h7
-rw-r--r--src/mesa/program/symbol_table.c59
-rw-r--r--src/mesa/program/symbol_table.h3
-rw-r--r--src/mesa/sources.mak21
-rw-r--r--src/talloc/SConscript20
-rw-r--r--src/talloc/gpl-3.0.txt674
-rw-r--r--src/talloc/lgpl-3.0.txt165
-rw-r--r--src/talloc/talloc.c2034
-rw-r--r--src/talloc/talloc.def63
-rw-r--r--src/talloc/talloc.h202
-rw-r--r--src/talloc/talloc_guide.txt757
464 files changed, 73784 insertions, 182 deletions
diff --git a/src/SConscript b/src/SConscript
index 2b46186f986..c3e34be6f76 100644
--- a/src/SConscript
+++ b/src/SConscript
@@ -5,6 +5,9 @@ if 'egl' in env['statetrackers']:
SConscript('egl/main/SConscript')
if 'mesa' in env['statetrackers']:
+ if platform == 'windows':
+ SConscript('talloc/SConscript')
+
SConscript('glsl/SConscript')
SConscript('mapi/glapi/SConscript')
SConscript('mesa/SConscript')
diff --git a/src/gallium/targets/Makefile.dri b/src/gallium/targets/Makefile.dri
index de05f96d231..59961e982aa 100644
--- a/src/gallium/targets/Makefile.dri
+++ b/src/gallium/targets/Makefile.dri
@@ -1,11 +1,12 @@
# -*-makefile-*-
+
ifeq ($(MESA_LLVM),1)
PIPE_DRIVERS += $(TOP)/src/gallium/drivers/llvmpipe/libllvmpipe.a
LDFLAGS += $(LLVM_LDFLAGS)
-LD = g++
DRIVER_EXTRAS = $(LLVM_LIBS)
-USE_CXX=1
+else
+LDFLAGS += -lstdc++
endif
MESA_MODULES = \
@@ -75,15 +76,11 @@ default: depend symlinks $(TOP)/$(LIB_DIR)/gallium $(LIBNAME) $(LIBNAME_STAGING)
$(LIBNAME): $(OBJECTS) $(MESA_MODULES) $(PIPE_DRIVERS) Makefile \
$(TOP)/src/mesa/drivers/dri/Makefile.template $(TOP)/src/mesa/drivers/dri/common/dri_test.o
- $(MKLIB) -o [email protected] -noprefix -linker '$(CC)' -ldflags '$(LDFLAGS)' \
+ $(MKLIB) -o [email protected] -noprefix -linker '$(CXX)' -ldflags '$(LDFLAGS)' \
$(OBJECTS) $(PIPE_DRIVERS) \
-Wl,--start-group $(MESA_MODULES) -Wl,--end-group \
$(DRI_LIB_DEPS) $(DRIVER_EXTRAS)
- if [ "x${USE_CXX}" == "x" ]; then \
- $(CC) $(CFLAGS) -o [email protected] $(TOP)/src/mesa/drivers/dri/common/dri_test.o [email protected] $(DRI_LIB_DEPS); \
- else \
- $(CXX) $(CFLAGS) -o [email protected] $(TOP)/src/mesa/drivers/dri/common/dri_test.o [email protected] $(DRI_LIB_DEPS); \
- fi
+ $(CXX) $(CFLAGS) -o [email protected] $(TOP)/src/mesa/drivers/dri/common/dri_test.o [email protected] $(DRI_LIB_DEPS);
diff --git a/src/gallium/targets/libgl-gdi/SConscript b/src/gallium/targets/libgl-gdi/SConscript
index 144084f74f8..12fe403f62f 100644
--- a/src/gallium/targets/libgl-gdi/SConscript
+++ b/src/gallium/targets/libgl-gdi/SConscript
@@ -17,6 +17,7 @@ if env['platform'] == 'windows':
'user32',
'kernel32',
'ws2_32',
+ talloc,
])
sources = []
diff --git a/src/glsl/.dir-locals.el b/src/glsl/.dir-locals.el
new file mode 100644
index 00000000000..be19e29a5ab
--- /dev/null
+++ b/src/glsl/.dir-locals.el
@@ -0,0 +1,3 @@
+((c-mode . ((c-basic-offset . 3)))
+ (c++-mode . ((c-basic-offset . 3)))
+)
diff --git a/src/glsl/.gitignore b/src/glsl/.gitignore
new file mode 100644
index 00000000000..4c212313e45
--- /dev/null
+++ b/src/glsl/.gitignore
@@ -0,0 +1,2 @@
+glsl_compiler
+glsl_parser.output
diff --git a/src/glsl/Makefile b/src/glsl/Makefile
index ca7f2d2ac7d..1d200b47b40 100644
--- a/src/glsl/Makefile
+++ b/src/glsl/Makefile
@@ -1,15 +1,176 @@
-# src/glsl/Makefile
+#src/glsl/pp/Makefile
TOP = ../..
include $(TOP)/configs/current
-SUBDIRS = pp cl apps
+LIBNAME = glsl
-default install clean:
- @for dir in $(SUBDIRS) ; do \
- if [ -d $$dir ] ; then \
- (cd $$dir && $(MAKE) $@) || exit 1; \
- fi \
- done
+LIBGLCPP_SOURCES = \
+ glcpp/glcpp-lex.c \
+ glcpp/glcpp-parse.c \
+ glcpp/pp.c
+GLCPP_SOURCES = \
+ $(LIBGLCPP_SOURCES) \
+ glcpp/glcpp.c
+
+C_SOURCES = \
+ $(LIBGLCPP_SOURCES)
+
+CXX_SOURCES = \
+ ast_expr.cpp \
+ ast_function.cpp \
+ ast_to_hir.cpp \
+ ast_type.cpp \
+ builtin_function.cpp \
+ glsl_lexer.cpp \
+ glsl_parser.cpp \
+ glsl_parser_extras.cpp \
+ glsl_types.cpp \
+ hir_field_selection.cpp \
+ ir_algebraic.cpp \
+ ir_basic_block.cpp \
+ ir_clone.cpp \
+ ir_constant_expression.cpp \
+ ir_constant_folding.cpp \
+ ir_constant_propagation.cpp \
+ ir_constant_variable.cpp \
+ ir_copy_propagation.cpp \
+ ir.cpp \
+ ir_dead_code.cpp \
+ ir_dead_code_local.cpp \
+ ir_dead_functions.cpp \
+ ir_div_to_mul_rcp.cpp \
+ ir_explog_to_explog2.cpp \
+ ir_expression_flattening.cpp \
+ ir_function_can_inline.cpp \
+ ir_function.cpp \
+ ir_function_inlining.cpp \
+ ir_hierarchical_visitor.cpp \
+ ir_hv_accept.cpp \
+ ir_if_return.cpp \
+ ir_if_simplification.cpp \
+ ir_if_to_cond_assign.cpp \
+ ir_import_prototypes.cpp \
+ ir_mat_op_to_vec.cpp \
+ ir_mod_to_fract.cpp \
+ ir_noop_swizzle.cpp \
+ ir_print_visitor.cpp \
+ ir_reader.cpp \
+ ir_rvalue_visitor.cpp \
+ ir_set_program_inouts.cpp \
+ ir_structure_splitting.cpp \
+ ir_sub_to_add_neg.cpp \
+ ir_swizzle_swizzle.cpp \
+ ir_tree_grafting.cpp \
+ ir_validate.cpp \
+ ir_variable.cpp \
+ ir_variable_refcount.cpp \
+ ir_vec_index_to_cond_assign.cpp \
+ ir_vec_index_to_swizzle.cpp \
+ linker.cpp \
+ link_functions.cpp \
+ s_expression.cpp
+
+LIBS = \
+ $(TOP)/src/glsl/libglsl.a \
+ $(shell pkg-config --libs talloc)
+
+APPS = glsl_compiler glcpp/glcpp
+
+GLSL2_C_SOURCES = \
+ ../mesa/program/hash_table.c \
+ ../mesa/program/symbol_table.c
+GLSL2_CXX_SOURCES = \
+ main.cpp
+
+GLSL2_OBJECTS = \
+ $(GLSL2_C_SOURCES:.c=.o) \
+ $(GLSL2_CXX_SOURCES:.cpp=.o)
+
+### Basic defines ###
+
+DEFINES += \
+ $(LIBRARY_DEFINES) \
+ $(API_DEFINES)
+
+GLCPP_OBJECTS = \
+ $(GLCPP_SOURCES:.c=.o) \
+ ../mesa/program/hash_table.o
+
+OBJECTS = \
+ $(C_SOURCES:.c=.o) \
+ $(CXX_SOURCES:.cpp=.o)
+
+INCLUDES = \
+ -I. \
+ -I../mesa \
+ -I../mapi \
+ -I../../include \
+ $(LIBRARY_INCLUDES)
+
+ALL_SOURCES = \
+ $(C_SOURCES) \
+ $(CXX_SOURCES) \
+ $(GLSL2_CXX_SOURCES) \
+ $(GLSL2_C_SOURCES)
+
+##### TARGETS #####
+
+default: depend lib$(LIBNAME).a $(APPS)
+
+lib$(LIBNAME).a: $(OBJECTS) Makefile $(TOP)/src/glsl/Makefile.template
+ $(MKLIB) -cplusplus -o $(LIBNAME) -static $(OBJECTS)
+
+depend: $(ALL_SOURCES) Makefile
+ rm -f depend
+ touch depend
+ $(MKDEP) $(MKDEP_OPTIONS) $(INCLUDES) $(ALL_SOURCES) 2> /dev/null
+
+# Remove .o and backup files
+clean:
+ rm -f $(OBJECTS) lib$(LIBNAME).a depend depend.bak
+ -rm -f $(APPS)
+
+# Dummy target
+install:
+ @echo -n ""
+
+
+##### RULES #####
+
+glsl_compiler: $(GLSL2_OBJECTS) libglsl.a
+ $(APP_CXX) $(INCLUDES) $(CFLAGS) $(LDFLAGS) $(GLSL2_OBJECTS) $(LIBS) -o $@
+
+glcpp/glcpp: $(GLCPP_OBJECTS) libglsl.a
+ $(APP_CC) $(INCLUDES) $(CFLAGS) $(LDFLAGS) $(GLCPP_OBJECTS) $(LIBS) -o $@
+
+.cpp.o:
+ $(CXX) -c $(INCLUDES) $(CXXFLAGS) $(DEFINES) $< -o $@
+
+.c.o:
+ $(CC) -c $(INCLUDES) $(CFLAGS) $(DEFINES) $< -o $@
+
+glsl_lexer.cpp: glsl_lexer.lpp
+ flex --nounistd -o$@ $<
+
+glsl_parser.cpp: glsl_parser.ypp
+ bison -v -o "$@" -p "_mesa_glsl_" --defines=glsl_parser.h $<
+
+glcpp/glcpp-lex.c: glcpp/glcpp-lex.l
+ flex --nounistd -o$@ $<
+
+glcpp/glcpp-parse.c: glcpp/glcpp-parse.y
+ bison -v -o "$@" --defines=glcpp/glcpp-parse.h $<
+
+builtins: builtin_function.cpp builtins/profiles/* builtins/ir/* builtins/tools/generate_builtins.py builtins/tools/texture_builtins.py
+ @echo Bootstrapping the compiler...
+ cp builtins/tools/builtin_function.cpp .
+ make glsl_compiler
+ @echo Regenerating builtin_function.cpp...
+ ./builtins/tools/generate_builtins.py > builtin_function.cpp
+ @echo Rebuilding the real compiler...
+ make glsl_compiler
+
+-include depend
diff --git a/src/glsl/Makefile.am b/src/glsl/Makefile.am
new file mode 100644
index 00000000000..5728a8b63da
--- /dev/null
+++ b/src/glsl/Makefile.am
@@ -0,0 +1,75 @@
+# Copyright © 2010 Intel Corporation
+# 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
+# on the rights to use, copy, modify, merge, publish, distribute, sub
+# license, 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 (including the next
+# paragraph) 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 NON-INFRINGEMENT. IN NO EVENT SHALL
+# AUTHORS, COPYRIGHT HOLDERS, AND/OR THEIR SUPPLIERS 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.
+
+AUTOMAKE_OPTIONS = foreign
+AM_CPPFLAGS = -I mesa
+
+SUBDIRS = glcpp
+
+bin_PROGRAMS = glsl
+
+glsl_LDADD = ./glcpp/libglcpp.la
+glsl_LDFLAGS = @LDFLAGS@ $(talloc_LIBS)
+glsl_SOURCES = \
+ main.cpp \
+ builtin_types.h \
+ glsl_types.cpp \
+ glsl_parser.ypp glsl_lexer.lpp glsl_parser_extras.cpp \
+ ast_expr.cpp ast_to_hir.cpp ast_function.cpp ast_type.cpp \
+ ir.cpp hir_field_selection.cpp builtin_function.cpp \
+ ir_print_visitor.cpp ir_variable.cpp ir_function.cpp \
+ ir_basic_block.cpp \
+ ir_basic_block.h \
+ ir_clone.cpp \
+ ir_constant_expression.cpp \
+ ir_constant_folding.cpp \
+ ir_constant_variable.cpp \
+ ir_copy_propagation.cpp \
+ ir_copy_propagation.h \
+ ir_dead_code.cpp \
+ ir_dead_code.h \
+ ir_dead_code_local.cpp \
+ ir_expression_flattening.cpp \
+ ir_function_can_inline.cpp \
+ ir_function_inlining.cpp \
+ ir_if_simplification.cpp \
+ ir_optimization.h \
+ ir_reader.cpp s_expression.cpp \
+ ir_hv_accept.cpp \
+ ir_hierarchical_visitor.h \
+ ir_hierarchical_visitor.cpp \
+ ir_swizzle_swizzle.cpp \
+ ir_to_mesa.cpp \
+ ir_to_mesa.h \
+ ir_validate.cpp \
+ ir_vec_index_to_swizzle.cpp \
+ linker.cpp
+
+BUILT_SOURCES = glsl_parser.h glsl_parser.cpp glsl_lexer.cpp
+CLEANFILES = $(BUILT_SOURCES)
+
+builtin_function.cpp: builtins/*/*
+ ./builtins/tools/generate_builtins.pl > builtin_function.cpp
+glsl_parser.h: glsl_parser.cpp
+
+.lpp.cpp:
+ $(LEXCOMPILE) --outfile="$@" $<
diff --git a/src/glsl/README b/src/glsl/README
new file mode 100644
index 00000000000..74520321b21
--- /dev/null
+++ b/src/glsl/README
@@ -0,0 +1,190 @@
+Welcome to Mesa's GLSL compiler. A brief overview of how things flow:
+
+1) lex and yacc-based preprocessor takes the incoming shader string
+and produces a new string containing the preprocessed shader. This
+takes care of things like #if, #ifdef, #define, and preprocessor macro
+invocations. Note that #version, #extension, and some others are
+passed straight through. See glcpp/*
+
+2) lex and yacc-based parser takes the preprocessed string and
+generates the AST (abstract syntax tree). Almost no checking is
+performed in this stage. See glsl_lexer.lpp and glsl_parser.ypp.
+
+3) The AST is converted to "HIR". This is the intermediate
+representation of the compiler. Constructors are generated, function
+calls are resolved to particular function signatures, and all the
+semantic checking is performed. See ast_*.cpp for the conversion, and
+ir.h for the IR structures.
+
+4) The driver (Mesa, or main.cpp for the standalone binary) performs
+optimizations. These include copy propagation, dead code elimination,
+constant folding, and others. Generally the driver will call
+optimizations in a loop, as each may open up opportunities for other
+optimizations to do additional work. See most files called ir_*.cpp
+
+5) linking is performed. This does checking to ensure that the
+outputs of the vertex shader match the inputs of the fragment shader,
+and assigns locations to uniforms, attributes, and varyings. See
+linker.cpp.
+
+6) The driver may perform additional optimization at this point, as
+for example dead code elimination previously couldn't remove functions
+or global variable usage when we didn't know what other code would be
+linked in.
+
+7) The driver performs code generation out of the IR, taking a linked
+shader program and producing a compiled program for each stage. See
+ir_to_mesa.cpp for Mesa IR code generation.
+
+FAQ:
+
+Q: What is HIR versus IR versus LIR?
+
+A: The idea behind the naming was that ast_to_hir would produce a
+high-level IR ("HIR"), with things like matrix operations, structure
+assignments, etc., present. A series of lowering passes would occur
+that do things like break matrix multiplication into a series of dot
+products/MADs, make structure assignment be a series of assignment of
+components, flatten if statements into conditional moves, and such,
+producing a low level IR ("LIR").
+
+However, it now appears that each driver will have different
+requirements from a LIR. A 915-generation chipset wants all functions
+inlined, all loops unrolled, all ifs flattened, no variable array
+accesses, and matrix multiplication broken down. The Mesa IR backend
+for swrast would like matrices and structure assignment broken down,
+but it can support function calls and dynamic branching. A 965 vertex
+shader IR backend could potentially even handle some matrix operations
+without breaking them down, but the 965 fragment shader IR backend
+would want to break to have (almost) all operations down channel-wise
+and perform optimization on that. As a result, there's no single
+low-level IR that will make everyone happy. So that usage has fallen
+out of favor, and each driver will perform a series of lowering passes
+to take the HIR down to whatever restrictions it wants to impose
+before doing codegen.
+
+Q: How is the IR structured?
+
+A: The best way to get started seeing it would be to run the
+standalone compiler against a shader:
+
+./glsl_compiler --dump-lir \
+ ~/src/piglit/tests/shaders/glsl-orangebook-ch06-bump.frag
+
+So for example one of the ir_instructions in main() contains:
+
+(assign (constant bool (1)) (var_ref litColor) (expression vec3 * (var_ref Surf
+aceColor) (var_ref __retval) ) )
+
+Or more visually:
+ (assign)
+ / | \
+ (var_ref) (expression *) (constant bool 1)
+ / / \
+(litColor) (var_ref) (var_ref)
+ / \
+ (SurfaceColor) (__retval)
+
+which came from:
+
+litColor = SurfaceColor * max(dot(normDelta, LightDir), 0.0);
+
+(the max call is not represented in this expression tree, as it was a
+function call that got inlined but not brought into this expression
+tree)
+
+Each of those nodes is a subclass of ir_instruction. A particular
+ir_instruction instance may only appear once in the whole IR tree with
+the exception of ir_variables, which appear once as variable
+declarations:
+
+(declare () vec3 normDelta)
+
+and multiple times as the targets of variable dereferences:
+...
+(assign (constant bool (1)) (var_ref __retval) (expression float dot
+ (var_ref normDelta) (var_ref LightDir) ) )
+...
+(assign (constant bool (1)) (var_ref __retval) (expression vec3 -
+ (var_ref LightDir) (expression vec3 * (constant float (2.000000))
+ (expression vec3 * (expression float dot (var_ref normDelta) (var_ref
+ LightDir) ) (var_ref normDelta) ) ) ) )
+...
+
+Each node has a type. Expressions may involve several different types:
+(declare (uniform ) mat4 gl_ModelViewMatrix)
+((assign (constant bool (1)) (var_ref constructor_tmp) (expression
+ vec4 * (var_ref gl_ModelViewMatrix) (var_ref gl_Vertex) ) )
+
+An expression tree can be arbitrarily deep, and the compiler tries to
+keep them structured like that so that things like algebraic
+optimizations ((color * 1.0 == color) and ((mat1 * mat2) * vec == mat1
+* (mat2 * vec))) or recognizing operation patterns for code generation
+(vec1 * vec2 + vec3 == mad(vec1, vec2, vec3)) are easier. This comes
+at the expense of additional trickery in implementing some
+optimizations like CSE where one must navigate an expression tree.
+
+Q: Why no SSA representation?
+
+A: Converting an IR tree to SSA form makes dead code elmimination,
+common subexpression elimination, and many other optimizations much
+easier. However, in our primarily vector-based language, there's some
+major questions as to how it would work. Do we do SSA on the scalar
+or vector level? If we do it at the vector level, we're going to end
+up with many different versions of the variable when encountering code
+like:
+
+(assign (constant bool (1)) (swiz x (var_ref __retval) ) (var_ref a) )
+(assign (constant bool (1)) (swiz y (var_ref __retval) ) (var_ref b) )
+(assign (constant bool (1)) (swiz z (var_ref __retval) ) (var_ref c) )
+
+If every masked update of a component relies on the previous value of
+the variable, then we're probably going to be quite limited in our
+dead code elimination wins, and recognizing common expressions may
+just not happen. On the other hand, if we operate channel-wise, then
+we'll be prone to optimizing the operation on one of the channels at
+the expense of making its instruction flow different from the other
+channels, and a vector-based GPU would end up with worse code than if
+we didn't optimize operations on that channel!
+
+Once again, it appears that our optimization requirements are driven
+significantly by the target architecture. For now, targeting the Mesa
+IR backend, SSA does not appear to be that important to producing
+excellent code, but we do expect to do some SSA-based optimizations
+for the 965 fragment shader backend when that is developed.
+
+Q: How should I expand instructions that take multiple backend instructions?
+
+Sometimes you'll have to do the expansion in your code generation --
+see, for example, ir_to_mesa.cpp's handling of ir_binop_mul for
+matrices. However, in many cases you'll want to do a pass over the IR
+to convert non-native instructions to a series of native instructions.
+For example, for the Mesa backend we have ir_div_to_mul_rcp.cpp because
+Mesa IR (and many hardware backends) only have a reciprocal
+instruction, not a divide. Implementing non-native instructions this
+way gives the chance for constant folding to occur, so (a / 2.0)
+becomes (a * 0.5) after codegen instead of (a * (1.0 / 2.0))
+
+Q: How shoud I handle my special hardware instructions with respect to IR?
+
+Our current theory is that if multiple targets have an instruction for
+some operation, then we should probably be able to represent that in
+the IR. Generally this is in the form of an ir_{bin,un}op expression
+type. For example, we initially implemented fract() using (a -
+floor(a)), but both 945 and 965 have instructions to give that result,
+and it would also simplify the implementation of mod(), so
+ir_unop_fract was added. The following areas need updating to add a
+new expression type:
+
+ir.h (new enum)
+ir.cpp:get_num_operands() (used for ir_reader)
+ir.cpp:operator_strs (used for ir_reader)
+ir_constant_expression.cpp (you probably want to be able to constant fold)
+
+You may also need to update the backends if they will see the new expr type:
+
+../mesa/shaders/ir_to_mesa.cpp
+
+You can then use the new expression from builtins (if all backends
+would rather see it), or scan the IR and convert to use your new
+expression type (see ir_mod_to_fract, for example).
diff --git a/src/glsl/SConscript b/src/glsl/SConscript
index 8e18626c404..90759275ca7 100644
--- a/src/glsl/SConscript
+++ b/src/glsl/SConscript
@@ -4,23 +4,69 @@ Import('*')
env = env.Clone()
+env.Prepend(CPPPATH = [
+ '#src/mapi',
+ '#src/mesa',
+])
+
+if env['platform'] == 'windows':
+ env.Prepend(CPPPATH = ['#src/talloc'])
+
sources = [
- 'pp/sl_pp_context.c',
- 'pp/sl_pp_define.c',
- 'pp/sl_pp_dict.c',
- 'pp/sl_pp_error.c',
- 'pp/sl_pp_expression.c',
- 'pp/sl_pp_extension.c',
- 'pp/sl_pp_if.c',
- 'pp/sl_pp_line.c',
- 'pp/sl_pp_macro.c',
- 'pp/sl_pp_pragma.c',
- 'pp/sl_pp_process.c',
- 'pp/sl_pp_purify.c',
- 'pp/sl_pp_token.c',
- 'pp/sl_pp_token_util.c',
- 'pp/sl_pp_version.c',
- 'cl/sl_cl_parse.c',
+ 'glcpp/glcpp-lex.c',
+ 'glcpp/glcpp-parse.c',
+ 'glcpp/pp.c',
+ 'ast_expr.cpp',
+ 'ast_function.cpp',
+ 'ast_to_hir.cpp',
+ 'ast_type.cpp',
+ 'builtin_function.cpp',
+ 'glsl_lexer.cpp',
+ 'glsl_parser.cpp',
+ 'glsl_parser_extras.cpp',
+ 'glsl_types.cpp',
+ 'hir_field_selection.cpp',
+ 'ir_algebraic.cpp',
+ 'ir_basic_block.cpp',
+ 'ir_clone.cpp',
+ 'ir_constant_expression.cpp',
+ 'ir_constant_folding.cpp',
+ 'ir_constant_propagation.cpp',
+ 'ir_constant_variable.cpp',
+ 'ir_copy_propagation.cpp',
+ 'ir.cpp',
+ 'ir_dead_code.cpp',
+ 'ir_dead_code_local.cpp',
+ 'ir_dead_functions.cpp',
+ 'ir_div_to_mul_rcp.cpp',
+ 'ir_explog_to_explog2.cpp',
+ 'ir_expression_flattening.cpp',
+ 'ir_function_can_inline.cpp',
+ 'ir_function.cpp',
+ 'ir_function_inlining.cpp',
+ 'ir_hierarchical_visitor.cpp',
+ 'ir_hv_accept.cpp',
+ 'ir_if_return.cpp',
+ 'ir_if_simplification.cpp',
+ 'ir_if_to_cond_assign.cpp',
+ 'ir_import_prototypes.cpp',
+ 'ir_mat_op_to_vec.cpp',
+ 'ir_mod_to_fract.cpp',
+ 'ir_print_visitor.cpp',
+ 'ir_reader.cpp',
+ 'ir_set_program_inouts.cpp',
+ 'ir_structure_splitting.cpp',
+ 'ir_sub_to_add_neg.cpp',
+ 'ir_swizzle_swizzle.cpp',
+ 'ir_tree_grafting.cpp',
+ 'ir_validate.cpp',
+ 'ir_variable.cpp',
+ 'ir_variable_refcount.cpp',
+ 'ir_vec_index_to_cond_assign.cpp',
+ 'ir_vec_index_to_swizzle.cpp',
+ 'linker.cpp',
+ 'link_functions.cpp',
+ 's_expression.cpp',
]
glsl = env.ConvenienceLibrary(
@@ -30,6 +76,9 @@ glsl = env.ConvenienceLibrary(
Export('glsl')
+# FIXME: We can't build the programs because there's a cyclic dependency between tis directory and src/mesa
+Return()
+
env = env.Clone()
if env['platform'] == 'windows':
@@ -37,33 +86,16 @@ if env['platform'] == 'windows':
'user32',
])
-env.Prepend(LIBS = [glsl])
-
-env.Program(
- target = 'purify',
- source = ['apps/purify.c'],
-)
+env.Prepend(LIBS = [glsl, talloc])
env.Program(
- target = 'tokenise',
- source = ['apps/tokenise.c'],
+ target = 'glsl2',
+ source = [
+ 'main.cpp',
+ ]
)
env.Program(
- target = 'version',
- source = ['apps/version.c'],
+ target = 'glcpp',
+ source = ['glcpp/glcpp.c'],
)
-
-env.Program(
- target = 'process',
- source = ['apps/process.c'],
-)
-
-glsl_compile = env.Program(
- target = 'compile',
- source = ['apps/compile.c'],
-)
-
-if env['platform'] == common.default_platform:
- # Only export the GLSL compiler when building for the host platform
- Export('glsl_compile')
diff --git a/src/glsl/TODO b/src/glsl/TODO
new file mode 100644
index 00000000000..07ac5f5c6e8
--- /dev/null
+++ b/src/glsl/TODO
@@ -0,0 +1,50 @@
+- Handle constant expressions of (struct == struct)
+
+- Handle constant expressions of (struct != struct)
+
+- Treat built-in functions with constant parameters as constant expressions.
+ - Rewrite all built-in functions return a single expression.
+ - Modify the HIR generator for functions to automatically inline built-in
+ functions durning translation.
+ - Care must be taken to handle both the 1.10 rules and the 1.20+ rules. In
+ 1.10, built-in functions cannot be constant expressions.
+
+- Detect code paths in non-void functions that don't reach a return statement
+
+- Handle over-riding built-in functions
+ - Is the overload per-compilation unit or per-linked shader?
+
+- Handle redeclaration of built-in variables
+ - Handle addition of qualifiers such as 'invariant' or 'centroid'.
+ - Handle resizing of arrays.
+ - Other? We'll have to look at the spec.
+
+- Improve handling of constants and their initializers. Constant initializers
+ should never generate any code. This is trival for scalar constants. It is
+ also trivial for arrays, matrices, and vectors that are accessed with
+ constant index values. For others it is more complicated. Perhaps these
+ cases should be silently converted to uniforms?
+
+1.30 features:
+
+- Implement AST-to-HIR conversion of bit-shift operators.
+
+- Implement AST-to-HIR conversion of bit-wise {&,|,^,!} operators.
+
+- Implement AST-to-HIR conversion of switch-statements
+ - switch
+ - case
+ - Update break to correcly handle mixed nexting of switch-statements
+ and loops.
+
+- Handle currently unsupported constant expression types
+ - ir_unop_bit_not
+ - ir_binop_mod
+ - ir_binop_lshift
+ - ir_binop_rshift
+ - ir_binop_bit_and
+ - ir_binop_bit_xor
+ - ir_binop_bit_or
+
+- Implement support for 1.30 style shadow compares which only return a float
+ instead of a vec4.
diff --git a/src/glsl/ast.h b/src/glsl/ast.h
new file mode 100644
index 00000000000..44c31b6e627
--- /dev/null
+++ b/src/glsl/ast.h
@@ -0,0 +1,664 @@
+/* -*- c++ -*- */
+/*
+ * Copyright © 2009 Intel Corporation
+ *
+ * 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 (including the next
+ * paragraph) 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
+ * THE AUTHORS OR COPYRIGHT HOLDERS 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.
+ */
+
+#pragma once
+#ifndef AST_H
+#define AST_H
+
+#include "list.h"
+#include "glsl_parser_extras.h"
+
+struct _mesa_glsl_parse_state;
+
+struct YYLTYPE;
+
+class ast_node {
+public:
+ /* Callers of this talloc-based new need not call delete. It's
+ * easier to just talloc_free 'ctx' (or any of its ancestors). */
+ static void* operator new(size_t size, void *ctx)
+ {
+ void *node;
+
+ node = talloc_zero_size(ctx, size);
+ assert(node != NULL);
+
+ return node;
+ }
+
+ /* If the user *does* call delete, that's OK, we will just
+ * talloc_free in that case. */
+ static void operator delete(void *table)
+ {
+ talloc_free(table);
+ }
+
+ virtual void print(void) const;
+ virtual ir_rvalue *hir(exec_list *instructions,
+ struct _mesa_glsl_parse_state *state);
+
+ /**
+ * Retrieve the source location of an AST node
+ *
+ * This function is primarily used to get the source position of an AST node
+ * into a form that can be passed to \c _mesa_glsl_error.
+ *
+ * \sa _mesa_glsl_error, ast_node::set_location
+ */
+ struct YYLTYPE get_location(void) const
+ {
+ struct YYLTYPE locp;
+
+ locp.source = this->location.source;
+ locp.first_line = this->location.line;
+ locp.first_column = this->location.column;
+ locp.last_line = locp.first_line;
+ locp.last_column = locp.first_column;
+
+ return locp;
+ }
+
+ /**
+ * Set the source location of an AST node from a parser location
+ *
+ * \sa ast_node::get_location
+ */
+ void set_location(const struct YYLTYPE &locp)
+ {
+ this->location.source = locp.source;
+ this->location.line = locp.first_line;
+ this->location.column = locp.first_column;
+ }
+
+ struct {
+ unsigned source;
+ unsigned line;
+ unsigned column;
+ } location;
+
+ exec_node link;
+
+protected:
+ ast_node(void);
+};
+
+
+enum ast_operators {
+ ast_assign,
+ ast_plus, /**< Unary + operator. */
+ ast_neg,
+ ast_add,
+ ast_sub,
+ ast_mul,
+ ast_div,
+ ast_mod,
+ ast_lshift,
+ ast_rshift,
+ ast_less,
+ ast_greater,
+ ast_lequal,
+ ast_gequal,
+ ast_equal,
+ ast_nequal,
+ ast_bit_and,
+ ast_bit_xor,
+ ast_bit_or,
+ ast_bit_not,
+ ast_logic_and,
+ ast_logic_xor,
+ ast_logic_or,
+ ast_logic_not,
+
+ ast_mul_assign,
+ ast_div_assign,
+ ast_mod_assign,
+ ast_add_assign,
+ ast_sub_assign,
+ ast_ls_assign,
+ ast_rs_assign,
+ ast_and_assign,
+ ast_xor_assign,
+ ast_or_assign,
+
+ ast_conditional,
+
+ ast_pre_inc,
+ ast_pre_dec,
+ ast_post_inc,
+ ast_post_dec,
+ ast_field_selection,
+ ast_array_index,
+
+ ast_function_call,
+
+ ast_identifier,
+ ast_int_constant,
+ ast_uint_constant,
+ ast_float_constant,
+ ast_bool_constant,
+
+ ast_sequence
+};
+
+class ast_expression : public ast_node {
+public:
+ ast_expression(int oper, ast_expression *,
+ ast_expression *, ast_expression *);
+
+ ast_expression(const char *identifier) :
+ oper(ast_identifier)
+ {
+ subexpressions[0] = NULL;
+ subexpressions[1] = NULL;
+ subexpressions[2] = NULL;
+ primary_expression.identifier = (char *) identifier;
+ }
+
+ static const char *operator_string(enum ast_operators op);
+
+ virtual ir_rvalue *hir(exec_list *instructions,
+ struct _mesa_glsl_parse_state *state);
+
+ virtual void print(void) const;
+
+ enum ast_operators oper;
+
+ ast_expression *subexpressions[3];
+
+ union {
+ char *identifier;
+ int int_constant;
+ float float_constant;
+ unsigned uint_constant;
+ int bool_constant;
+ } primary_expression;
+
+
+ /**
+ * List of expressions for an \c ast_sequence or parameters for an
+ * \c ast_function_call
+ */
+ exec_list expressions;
+};
+
+class ast_expression_bin : public ast_expression {
+public:
+ ast_expression_bin(int oper, ast_expression *, ast_expression *);
+
+ virtual void print(void) const;
+};
+
+/**
+ * Subclass of expressions for function calls
+ */
+class ast_function_expression : public ast_expression {
+public:
+ ast_function_expression(ast_expression *callee)
+ : ast_expression(ast_function_call, callee,
+ NULL, NULL),
+ cons(false)
+ {
+ /* empty */
+ }
+
+ ast_function_expression(class ast_type_specifier *type)
+ : ast_expression(ast_function_call, (ast_expression *) type,
+ NULL, NULL),
+ cons(true)
+ {
+ /* empty */
+ }
+
+ bool is_constructor() const
+ {
+ return cons;
+ }
+
+ virtual ir_rvalue *hir(exec_list *instructions,
+ struct _mesa_glsl_parse_state *state);
+
+private:
+ /**
+ * Is this function call actually a constructor?
+ */
+ bool cons;
+};
+
+
+/**
+ * Number of possible operators for an ast_expression
+ *
+ * This is done as a define instead of as an additional value in the enum so
+ * that the compiler won't generate spurious messages like "warning:
+ * enumeration value ‘ast_num_operators’ not handled in switch"
+ */
+#define AST_NUM_OPERATORS (ast_sequence + 1)
+
+
+class ast_compound_statement : public ast_node {
+public:
+ ast_compound_statement(int new_scope, ast_node *statements);
+ virtual void print(void) const;
+
+ virtual ir_rvalue *hir(exec_list *instructions,
+ struct _mesa_glsl_parse_state *state);
+
+ int new_scope;
+ exec_list statements;
+};
+
+class ast_declaration : public ast_node {
+public:
+ ast_declaration(char *identifier, int is_array, ast_expression *array_size,
+ ast_expression *initializer);
+ virtual void print(void) const;
+
+ char *identifier;
+
+ int is_array;
+ ast_expression *array_size;
+
+ ast_expression *initializer;
+};
+
+
+enum {
+ ast_precision_high = 0, /**< Default precision. */
+ ast_precision_medium,
+ ast_precision_low
+};
+
+struct ast_type_qualifier {
+ unsigned invariant:1;
+ unsigned constant:1;
+ unsigned attribute:1;
+ unsigned varying:1;
+ unsigned in:1;
+ unsigned out:1;
+ unsigned centroid:1;
+ unsigned uniform:1;
+ unsigned smooth:1;
+ unsigned flat:1;
+ unsigned noperspective:1;
+
+ /** \name Layout qualifiers for GL_ARB_fragment_coord_conventions */
+ /*@{*/
+ unsigned origin_upper_left:1;
+ unsigned pixel_center_integer:1;
+ /*@}*/
+};
+
+class ast_struct_specifier : public ast_node {
+public:
+ ast_struct_specifier(char *identifier, ast_node *declarator_list);
+ virtual void print(void) const;
+
+ virtual ir_rvalue *hir(exec_list *instructions,
+ struct _mesa_glsl_parse_state *state);
+
+ char *name;
+ exec_list declarations;
+};
+
+
+enum ast_types {
+ ast_void,
+ ast_float,
+ ast_int,
+ ast_uint,
+ ast_bool,
+ ast_vec2,
+ ast_vec3,
+ ast_vec4,
+ ast_bvec2,
+ ast_bvec3,
+ ast_bvec4,
+ ast_ivec2,
+ ast_ivec3,
+ ast_ivec4,
+ ast_uvec2,
+ ast_uvec3,
+ ast_uvec4,
+ ast_mat2,
+ ast_mat2x3,
+ ast_mat2x4,
+ ast_mat3x2,
+ ast_mat3,
+ ast_mat3x4,
+ ast_mat4x2,
+ ast_mat4x3,
+ ast_mat4,
+ ast_sampler1d,
+ ast_sampler2d,
+ ast_sampler2drect,
+ ast_sampler3d,
+ ast_samplercube,
+ ast_sampler1dshadow,
+ ast_sampler2dshadow,
+ ast_sampler2drectshadow,
+ ast_samplercubeshadow,
+ ast_sampler1darray,
+ ast_sampler2darray,
+ ast_sampler1darrayshadow,
+ ast_sampler2darrayshadow,
+ ast_isampler1d,
+ ast_isampler2d,
+ ast_isampler3d,
+ ast_isamplercube,
+ ast_isampler1darray,
+ ast_isampler2darray,
+ ast_usampler1d,
+ ast_usampler2d,
+ ast_usampler3d,
+ ast_usamplercube,
+ ast_usampler1darray,
+ ast_usampler2darray,
+
+ ast_struct,
+ ast_type_name
+};
+
+
+class ast_type_specifier : public ast_node {
+public:
+ ast_type_specifier(int specifier);
+
+ /** Construct a type specifier from a type name */
+ ast_type_specifier(const char *name)
+ : type_specifier(ast_type_name), type_name(name), structure(NULL),
+ is_array(false), array_size(NULL), precision(ast_precision_high)
+ {
+ /* empty */
+ }
+
+ /** Construct a type specifier from a structure definition */
+ ast_type_specifier(ast_struct_specifier *s)
+ : type_specifier(ast_struct), type_name(s->name), structure(s),
+ is_array(false), array_size(NULL), precision(ast_precision_high)
+ {
+ /* empty */
+ }
+
+ const struct glsl_type *glsl_type(const char **name,
+ struct _mesa_glsl_parse_state *state)
+ const;
+
+ virtual void print(void) const;
+
+ ir_rvalue *hir(exec_list *, struct _mesa_glsl_parse_state *);
+
+ enum ast_types type_specifier;
+
+ const char *type_name;
+ ast_struct_specifier *structure;
+
+ int is_array;
+ ast_expression *array_size;
+
+ unsigned precision:2;
+};
+
+
+class ast_fully_specified_type : public ast_node {
+public:
+ virtual void print(void) const;
+ bool has_qualifiers() const;
+
+ ast_type_qualifier qualifier;
+ ast_type_specifier *specifier;
+};
+
+
+class ast_declarator_list : public ast_node {
+public:
+ ast_declarator_list(ast_fully_specified_type *);
+ virtual void print(void) const;
+
+ virtual ir_rvalue *hir(exec_list *instructions,
+ struct _mesa_glsl_parse_state *state);
+
+ ast_fully_specified_type *type;
+ exec_list declarations;
+
+ /**
+ * Special flag for vertex shader "invariant" declarations.
+ *
+ * Vertex shaders can contain "invariant" variable redeclarations that do
+ * not include a type. For example, "invariant gl_Position;". This flag
+ * is used to note these cases when no type is specified.
+ */
+ int invariant;
+};
+
+
+class ast_parameter_declarator : public ast_node {
+public:
+ ast_parameter_declarator()
+ {
+ this->identifier = NULL;
+ this->is_array = false;
+ this->array_size = 0;
+ }
+
+ virtual void print(void) const;
+
+ virtual ir_rvalue *hir(exec_list *instructions,
+ struct _mesa_glsl_parse_state *state);
+
+ ast_fully_specified_type *type;
+ char *identifier;
+ int is_array;
+ ast_expression *array_size;
+
+ static void parameters_to_hir(exec_list *ast_parameters,
+ bool formal, exec_list *ir_parameters,
+ struct _mesa_glsl_parse_state *state);
+
+private:
+ /** Is this parameter declaration part of a formal parameter list? */
+ bool formal_parameter;
+
+ /**
+ * Is this parameter 'void' type?
+ *
+ * This field is set by \c ::hir.
+ */
+ bool is_void;
+};
+
+
+class ast_function : public ast_node {
+public:
+ ast_function(void);
+
+ virtual void print(void) const;
+
+ virtual ir_rvalue *hir(exec_list *instructions,
+ struct _mesa_glsl_parse_state *state);
+
+ ast_fully_specified_type *return_type;
+ char *identifier;
+
+ exec_list parameters;
+
+private:
+ /**
+ * Is this prototype part of the function definition?
+ *
+ * Used by ast_function_definition::hir to process the parameters, etc.
+ * of the function.
+ *
+ * \sa ::hir
+ */
+ bool is_definition;
+
+ /**
+ * Function signature corresponding to this function prototype instance
+ *
+ * Used by ast_function_definition::hir to process the parameters, etc.
+ * of the function.
+ *
+ * \sa ::hir
+ */
+ class ir_function_signature *signature;
+
+ friend class ast_function_definition;
+};
+
+
+class ast_declaration_statement : public ast_node {
+public:
+ ast_declaration_statement(void);
+
+ enum {
+ ast_function,
+ ast_declaration,
+ ast_precision
+ } mode;
+
+ union {
+ class ast_function *function;
+ ast_declarator_list *declarator;
+ ast_type_specifier *type;
+ ast_node *node;
+ } declaration;
+};
+
+
+class ast_expression_statement : public ast_node {
+public:
+ ast_expression_statement(ast_expression *);
+ virtual void print(void) const;
+
+ virtual ir_rvalue *hir(exec_list *instructions,
+ struct _mesa_glsl_parse_state *state);
+
+ ast_expression *expression;
+};
+
+
+class ast_case_label : public ast_node {
+public:
+
+ /**
+ * An expression of NULL means 'default'.
+ */
+ ast_expression *expression;
+};
+
+class ast_selection_statement : public ast_node {
+public:
+ ast_selection_statement(ast_expression *condition,
+ ast_node *then_statement,
+ ast_node *else_statement);
+ virtual void print(void) const;
+
+ virtual ir_rvalue *hir(exec_list *instructions,
+ struct _mesa_glsl_parse_state *state);
+
+ ast_expression *condition;
+ ast_node *then_statement;
+ ast_node *else_statement;
+};
+
+
+class ast_switch_statement : public ast_node {
+public:
+ ast_expression *expression;
+ exec_list statements;
+};
+
+class ast_iteration_statement : public ast_node {
+public:
+ ast_iteration_statement(int mode, ast_node *init, ast_node *condition,
+ ast_expression *rest_expression, ast_node *body);
+
+ virtual void print(void) const;
+
+ virtual ir_rvalue *hir(exec_list *, struct _mesa_glsl_parse_state *);
+
+ enum ast_iteration_modes {
+ ast_for,
+ ast_while,
+ ast_do_while
+ } mode;
+
+
+ ast_node *init_statement;
+ ast_node *condition;
+ ast_expression *rest_expression;
+
+ ast_node *body;
+
+private:
+ /**
+ * Generate IR from the condition of a loop
+ *
+ * This is factored out of ::hir because some loops have the condition
+ * test at the top (for and while), and others have it at the end (do-while).
+ */
+ void condition_to_hir(class ir_loop *, struct _mesa_glsl_parse_state *);
+};
+
+
+class ast_jump_statement : public ast_node {
+public:
+ ast_jump_statement(int mode, ast_expression *return_value);
+ virtual void print(void) const;
+
+ virtual ir_rvalue *hir(exec_list *instructions,
+ struct _mesa_glsl_parse_state *state);
+
+ enum ast_jump_modes {
+ ast_continue,
+ ast_break,
+ ast_return,
+ ast_discard
+ } mode;
+
+ ast_expression *opt_return_value;
+};
+
+
+class ast_function_definition : public ast_node {
+public:
+ virtual void print(void) const;
+
+ virtual ir_rvalue *hir(exec_list *instructions,
+ struct _mesa_glsl_parse_state *state);
+
+ ast_function *prototype;
+ ast_compound_statement *body;
+};
+
+
+extern void
+_mesa_ast_to_hir(exec_list *instructions, struct _mesa_glsl_parse_state *state);
+
+extern ir_rvalue *
+_mesa_ast_field_selection_to_hir(const ast_expression *expr,
+ exec_list *instructions,
+ struct _mesa_glsl_parse_state *state);
+
+#endif /* AST_H */
diff --git a/src/glsl/ast_expr.cpp b/src/glsl/ast_expr.cpp
new file mode 100644
index 00000000000..4e83decb924
--- /dev/null
+++ b/src/glsl/ast_expr.cpp
@@ -0,0 +1,96 @@
+/*
+ * Copyright © 2010 Intel Corporation
+ *
+ * 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 (including the next
+ * paragraph) 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
+ * THE AUTHORS OR COPYRIGHT HOLDERS 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.
+ */
+#include <cstdio>
+#include <cassert>
+#include "ast.h"
+
+const char *
+ast_expression::operator_string(enum ast_operators op)
+{
+ static const char *const operators[] = {
+ "=",
+ "+",
+ "-",
+ "+",
+ "-",
+ "*",
+ "/",
+ "%",
+ "<<",
+ ">>",
+ "<",
+ ">",
+ "<=",
+ ">=",
+ "==",
+ "!=",
+ "&",
+ "^",
+ "|",
+ "~",
+ "&&",
+ "^^",
+ "||",
+ "!",
+
+ "*=",
+ "/=",
+ "%=",
+ "+=",
+ "-=",
+ "<<=",
+ ">>=",
+ "&=",
+ "^=",
+ "|=",
+
+ "?:",
+
+ "++",
+ "--",
+ "++",
+ "--",
+ ".",
+ };
+
+ assert((unsigned int)op < sizeof(operators) / sizeof(operators[0]));
+
+ return operators[op];
+}
+
+
+ast_expression_bin::ast_expression_bin(int oper, ast_expression *ex0,
+ ast_expression *ex1) :
+ ast_expression(oper, ex0, ex1, NULL)
+{
+ assert((oper >= ast_plus) && (oper <= ast_logic_not));
+}
+
+
+void
+ast_expression_bin::print(void) const
+{
+ subexpressions[0]->print();
+ printf("%s ", operator_string(oper));
+ subexpressions[1]->print();
+}
diff --git a/src/glsl/ast_function.cpp b/src/glsl/ast_function.cpp
new file mode 100644
index 00000000000..6c36a04889e
--- /dev/null
+++ b/src/glsl/ast_function.cpp
@@ -0,0 +1,1247 @@
+/*
+ * Copyright © 2010 Intel Corporation
+ *
+ * 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 (including the next
+ * paragraph) 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
+ * THE AUTHORS OR COPYRIGHT HOLDERS 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.
+ */
+
+#include "glsl_symbol_table.h"
+#include "ast.h"
+#include "glsl_types.h"
+#include "ir.h"
+#include "main/macros.h"
+
+static ir_rvalue *
+convert_component(ir_rvalue *src, const glsl_type *desired_type);
+
+static unsigned
+process_parameters(exec_list *instructions, exec_list *actual_parameters,
+ exec_list *parameters,
+ struct _mesa_glsl_parse_state *state)
+{
+ unsigned count = 0;
+
+ foreach_list (n, parameters) {
+ ast_node *const ast = exec_node_data(ast_node, n, link);
+ ir_rvalue *result = ast->hir(instructions, state);
+
+ ir_constant *const constant = result->constant_expression_value();
+ if (constant != NULL)
+ result = constant;
+
+ actual_parameters->push_tail(result);
+ count++;
+ }
+
+ return count;
+}
+
+
+/**
+ * Generate a source prototype for a function signature
+ *
+ * \param return_type Return type of the function. May be \c NULL.
+ * \param name Name of the function.
+ * \param parameters Parameter list for the function. This may be either a
+ * formal or actual parameter list. Only the type is used.
+ *
+ * \return
+ * A talloced string representing the prototype of the function.
+ */
+char *
+prototype_string(const glsl_type *return_type, const char *name,
+ exec_list *parameters)
+{
+ char *str = NULL;
+
+ if (return_type != NULL)
+ str = talloc_asprintf(str, "%s ", return_type->name);
+
+ str = talloc_asprintf_append(str, "%s(", name);
+
+ const char *comma = "";
+ foreach_list(node, parameters) {
+ const ir_instruction *const param = (ir_instruction *) node;
+
+ str = talloc_asprintf_append(str, "%s%s", comma, param->type->name);
+ comma = ", ";
+ }
+
+ str = talloc_strdup_append(str, ")");
+ return str;
+}
+
+
+static ir_rvalue *
+process_call(exec_list *instructions, ir_function *f,
+ YYLTYPE *loc, exec_list *actual_parameters,
+ struct _mesa_glsl_parse_state *state)
+{
+ void *ctx = state;
+
+ ir_function_signature *sig = f->matching_signature(actual_parameters);
+
+ /* The instructions param will be used when the FINISHMEs below are done */
+ (void) instructions;
+
+ if (sig != NULL) {
+ /* Verify that 'out' and 'inout' actual parameters are lvalues. This
+ * isn't done in ir_function::matching_signature because that function
+ * cannot generate the necessary diagnostics.
+ */
+ exec_list_iterator actual_iter = actual_parameters->iterator();
+ exec_list_iterator formal_iter = sig->parameters.iterator();
+
+ while (actual_iter.has_next()) {
+ ir_rvalue *actual = (ir_rvalue *) actual_iter.get();
+ ir_variable *formal = (ir_variable *) formal_iter.get();
+
+ assert(actual != NULL);
+ assert(formal != NULL);
+
+ if ((formal->mode == ir_var_out)
+ || (formal->mode == ir_var_inout)) {
+ if (! actual->is_lvalue()) {
+ /* FINISHME: Log a better diagnostic here. There is no way
+ * FINISHME: to tell the user which parameter is invalid.
+ */
+ _mesa_glsl_error(loc, state, "`%s' parameter is not lvalue",
+ (formal->mode == ir_var_out) ? "out" : "inout");
+ }
+ }
+
+ if (formal->type->is_numeric() || formal->type->is_boolean()) {
+ ir_rvalue *converted = convert_component(actual, formal->type);
+ actual->replace_with(converted);
+ }
+
+ actual_iter.next();
+ formal_iter.next();
+ }
+
+ /* Always insert the call in the instruction stream, and return a deref
+ * of its return val if it returns a value, since we don't know if
+ * the rvalue is going to be assigned to anything or not.
+ */
+ ir_call *call = new(ctx) ir_call(sig, actual_parameters);
+ if (!sig->return_type->is_void()) {
+ ir_variable *var;
+ ir_dereference_variable *deref;
+
+ var = new(ctx) ir_variable(sig->return_type,
+ talloc_asprintf(ctx, "%s_retval",
+ sig->function_name()),
+ ir_var_temporary);
+ instructions->push_tail(var);
+
+ deref = new(ctx) ir_dereference_variable(var);
+ ir_assignment *assign = new(ctx) ir_assignment(deref, call, NULL);
+ instructions->push_tail(assign);
+ if (state->language_version >= 120)
+ var->constant_value = call->constant_expression_value();
+
+ deref = new(ctx) ir_dereference_variable(var);
+ return deref;
+ } else {
+ instructions->push_tail(call);
+ return NULL;
+ }
+ } else {
+ char *str = prototype_string(NULL, f->name, actual_parameters);
+
+ _mesa_glsl_error(loc, state, "no matching function for call to `%s'",
+ str);
+ talloc_free(str);
+
+ const char *prefix = "candidates are: ";
+ foreach_list (node, &f->signatures) {
+ ir_function_signature *sig = (ir_function_signature *) node;
+
+ str = prototype_string(sig->return_type, f->name, &sig->parameters);
+ _mesa_glsl_error(loc, state, "%s%s\n", prefix, str);
+ talloc_free(str);
+
+ prefix = " ";
+ }
+
+ return ir_call::get_error_instruction(ctx);
+ }
+}
+
+
+static ir_rvalue *
+match_function_by_name(exec_list *instructions, const char *name,
+ YYLTYPE *loc, exec_list *actual_parameters,
+ struct _mesa_glsl_parse_state *state)
+{
+ void *ctx = state;
+ ir_function *f = state->symbols->get_function(name);
+
+ if (f == NULL) {
+ _mesa_glsl_error(loc, state, "function `%s' undeclared", name);
+ return ir_call::get_error_instruction(ctx);
+ }
+
+ /* Once we've determined that the function being called might exist, try
+ * to find an overload of the function that matches the parameters.
+ */
+ return process_call(instructions, f, loc, actual_parameters, state);
+}
+
+
+/**
+ * Perform automatic type conversion of constructor parameters
+ *
+ * This implements the rules in the "Conversion and Scalar Constructors"
+ * section (GLSL 1.10 section 5.4.1), not the "Implicit Conversions" rules.
+ */
+static ir_rvalue *
+convert_component(ir_rvalue *src, const glsl_type *desired_type)
+{
+ void *ctx = talloc_parent(src);
+ const unsigned a = desired_type->base_type;
+ const unsigned b = src->type->base_type;
+ ir_expression *result = NULL;
+
+ if (src->type->is_error())
+ return src;
+
+ assert(a <= GLSL_TYPE_BOOL);
+ assert(b <= GLSL_TYPE_BOOL);
+
+ if ((a == b) || (src->type->is_integer() && desired_type->is_integer()))
+ return src;
+
+ switch (a) {
+ case GLSL_TYPE_UINT:
+ case GLSL_TYPE_INT:
+ if (b == GLSL_TYPE_FLOAT)
+ result = new(ctx) ir_expression(ir_unop_f2i, desired_type, src, NULL);
+ else {
+ assert(b == GLSL_TYPE_BOOL);
+ result = new(ctx) ir_expression(ir_unop_b2i, desired_type, src, NULL);
+ }
+ break;
+ case GLSL_TYPE_FLOAT:
+ switch (b) {
+ case GLSL_TYPE_UINT:
+ result = new(ctx) ir_expression(ir_unop_u2f, desired_type, src, NULL);
+ break;
+ case GLSL_TYPE_INT:
+ result = new(ctx) ir_expression(ir_unop_i2f, desired_type, src, NULL);
+ break;
+ case GLSL_TYPE_BOOL:
+ result = new(ctx) ir_expression(ir_unop_b2f, desired_type, src, NULL);
+ break;
+ }
+ break;
+ case GLSL_TYPE_BOOL:
+ switch (b) {
+ case GLSL_TYPE_UINT:
+ case GLSL_TYPE_INT:
+ result = new(ctx) ir_expression(ir_unop_i2b, desired_type, src, NULL);
+ break;
+ case GLSL_TYPE_FLOAT:
+ result = new(ctx) ir_expression(ir_unop_f2b, desired_type, src, NULL);
+ break;
+ }
+ break;
+ }
+
+ assert(result != NULL);
+
+ /* Try constant folding; it may fold in the conversion we just added. */
+ ir_constant *const constant = result->constant_expression_value();
+ return (constant != NULL) ? (ir_rvalue *) constant : (ir_rvalue *) result;
+}
+
+/**
+ * Dereference a specific component from a scalar, vector, or matrix
+ */
+static ir_rvalue *
+dereference_component(ir_rvalue *src, unsigned component)
+{
+ void *ctx = talloc_parent(src);
+ assert(component < src->type->components());
+
+ /* If the source is a constant, just create a new constant instead of a
+ * dereference of the existing constant.
+ */
+ ir_constant *constant = src->as_constant();
+ if (constant)
+ return new(ctx) ir_constant(constant, component);
+
+ if (src->type->is_scalar()) {
+ return src;
+ } else if (src->type->is_vector()) {
+ return new(ctx) ir_swizzle(src, component, 0, 0, 0, 1);
+ } else {
+ assert(src->type->is_matrix());
+
+ /* Dereference a row of the matrix, then call this function again to get
+ * a specific element from that row.
+ */
+ const int c = component / src->type->column_type()->vector_elements;
+ const int r = component % src->type->column_type()->vector_elements;
+ ir_constant *const col_index = new(ctx) ir_constant(c);
+ ir_dereference *const col = new(ctx) ir_dereference_array(src, col_index);
+
+ col->type = src->type->column_type();
+
+ return dereference_component(col, r);
+ }
+
+ assert(!"Should not get here.");
+ return NULL;
+}
+
+
+static ir_rvalue *
+process_array_constructor(exec_list *instructions,
+ const glsl_type *constructor_type,
+ YYLTYPE *loc, exec_list *parameters,
+ struct _mesa_glsl_parse_state *state)
+{
+ void *ctx = state;
+ /* Array constructors come in two forms: sized and unsized. Sized array
+ * constructors look like 'vec4[2](a, b)', where 'a' and 'b' are vec4
+ * variables. In this case the number of parameters must exactly match the
+ * specified size of the array.
+ *
+ * Unsized array constructors look like 'vec4[](a, b)', where 'a' and 'b'
+ * are vec4 variables. In this case the size of the array being constructed
+ * is determined by the number of parameters.
+ *
+ * From page 52 (page 58 of the PDF) of the GLSL 1.50 spec:
+ *
+ * "There must be exactly the same number of arguments as the size of
+ * the array being constructed. If no size is present in the
+ * constructor, then the array is explicitly sized to the number of
+ * arguments provided. The arguments are assigned in order, starting at
+ * element 0, to the elements of the constructed array. Each argument
+ * must be the same type as the element type of the array, or be a type
+ * that can be converted to the element type of the array according to
+ * Section 4.1.10 "Implicit Conversions.""
+ */
+ exec_list actual_parameters;
+ const unsigned parameter_count =
+ process_parameters(instructions, &actual_parameters, parameters, state);
+
+ if ((parameter_count == 0)
+ || ((constructor_type->length != 0)
+ && (constructor_type->length != parameter_count))) {
+ const unsigned min_param = (constructor_type->length == 0)
+ ? 1 : constructor_type->length;
+
+ _mesa_glsl_error(loc, state, "array constructor must have %s %u "
+ "parameter%s",
+ (constructor_type->length != 0) ? "at least" : "exactly",
+ min_param, (min_param <= 1) ? "" : "s");
+ return ir_call::get_error_instruction(ctx);
+ }
+
+ if (constructor_type->length == 0) {
+ constructor_type =
+ glsl_type::get_array_instance(constructor_type->element_type(),
+ parameter_count);
+ assert(constructor_type != NULL);
+ assert(constructor_type->length == parameter_count);
+ }
+
+ bool all_parameters_are_constant = true;
+
+ /* Type cast each parameter and, if possible, fold constants. */
+ foreach_list_safe(n, &actual_parameters) {
+ ir_rvalue *ir = (ir_rvalue *) n;
+ ir_rvalue *result = ir;
+
+ /* Apply implicit conversions (not the scalar constructor rules!) */
+ if (constructor_type->element_type()->is_float()) {
+ const glsl_type *desired_type =
+ glsl_type::get_instance(GLSL_TYPE_FLOAT,
+ ir->type->vector_elements,
+ ir->type->matrix_columns);
+ result = convert_component(ir, desired_type);
+ }
+
+ if (result->type != constructor_type->element_type()) {
+ _mesa_glsl_error(loc, state, "type error in array constructor: "
+ "expected: %s, found %s",
+ constructor_type->element_type()->name,
+ result->type->name);
+ }
+
+ /* Attempt to convert the parameter to a constant valued expression.
+ * After doing so, track whether or not all the parameters to the
+ * constructor are trivially constant valued expressions.
+ */
+ ir_rvalue *const constant = result->constant_expression_value();
+
+ if (constant != NULL)
+ result = constant;
+ else
+ all_parameters_are_constant = false;
+
+ ir->replace_with(result);
+ }
+
+ if (all_parameters_are_constant)
+ return new(ctx) ir_constant(constructor_type, &actual_parameters);
+
+ ir_variable *var = new(ctx) ir_variable(constructor_type, "array_ctor",
+ ir_var_temporary);
+ instructions->push_tail(var);
+
+ int i = 0;
+ foreach_list(node, &actual_parameters) {
+ ir_rvalue *rhs = (ir_rvalue *) node;
+ ir_rvalue *lhs = new(ctx) ir_dereference_array(var,
+ new(ctx) ir_constant(i));
+
+ ir_instruction *assignment = new(ctx) ir_assignment(lhs, rhs, NULL);
+ instructions->push_tail(assignment);
+
+ i++;
+ }
+
+ return new(ctx) ir_dereference_variable(var);
+}
+
+
+/**
+ * Try to convert a record constructor to a constant expression
+ */
+static ir_constant *
+constant_record_constructor(const glsl_type *constructor_type,
+ YYLTYPE *loc, exec_list *parameters,
+ struct _mesa_glsl_parse_state *state)
+{
+ void *ctx = state;
+ bool all_parameters_are_constant = true;
+
+ exec_node *node = parameters->head;
+ for (unsigned i = 0; i < constructor_type->length; i++) {
+ ir_instruction *ir = (ir_instruction *) node;
+
+ if (node->is_tail_sentinel()) {
+ _mesa_glsl_error(loc, state,
+ "insufficient parameters to constructor for `%s'",
+ constructor_type->name);
+ return NULL;
+ }
+
+ if (ir->type != constructor_type->fields.structure[i].type) {
+ _mesa_glsl_error(loc, state,
+ "parameter type mismatch in constructor for `%s' "
+ " (%s vs %s)",
+ constructor_type->name,
+ ir->type->name,
+ constructor_type->fields.structure[i].type->name);
+ return NULL;
+ }
+
+ if (ir->as_constant() == NULL)
+ all_parameters_are_constant = false;
+
+ node = node->next;
+ }
+
+ if (!all_parameters_are_constant)
+ return NULL;
+
+ return new(ctx) ir_constant(constructor_type, parameters);
+}
+
+
+/**
+ * Generate data for a constant matrix constructor w/a single scalar parameter
+ *
+ * Matrix constructors in GLSL can be passed a single scalar of the
+ * approriate type. In these cases, the resulting matrix is the identity
+ * matrix multipled by the specified scalar. This function generates data for
+ * that matrix.
+ *
+ * \param type Type of the desired matrix.
+ * \param initializer Scalar value used to initialize the matrix diagonal.
+ * \param data Location to store the resulting matrix.
+ */
+void
+generate_constructor_matrix(const glsl_type *type, ir_constant *initializer,
+ ir_constant_data *data)
+{
+ switch (type->base_type) {
+ case GLSL_TYPE_UINT:
+ case GLSL_TYPE_INT:
+ for (unsigned i = 0; i < type->components(); i++)
+ data->u[i] = 0;
+
+ for (unsigned i = 0; i < type->matrix_columns; i++) {
+ /* The array offset of the ith row and column of the matrix.
+ */
+ const unsigned idx = (i * type->vector_elements) + i;
+
+ data->u[idx] = initializer->value.u[0];
+ }
+ break;
+
+ case GLSL_TYPE_FLOAT:
+ for (unsigned i = 0; i < type->components(); i++)
+ data->f[i] = 0;
+
+ for (unsigned i = 0; i < type->matrix_columns; i++) {
+ /* The array offset of the ith row and column of the matrix.
+ */
+ const unsigned idx = (i * type->vector_elements) + i;
+
+ data->f[idx] = initializer->value.f[0];
+ }
+
+ break;
+
+ default:
+ assert(!"Should not get here.");
+ break;
+ }
+}
+
+
+/**
+ * Generate data for a constant vector constructor w/a single scalar parameter
+ *
+ * Vector constructors in GLSL can be passed a single scalar of the
+ * approriate type. In these cases, the resulting vector contains the specified
+ * value in all components. This function generates data for that vector.
+ *
+ * \param type Type of the desired vector.
+ * \param initializer Scalar value used to initialize the vector.
+ * \param data Location to store the resulting vector data.
+ */
+void
+generate_constructor_vector(const glsl_type *type, ir_constant *initializer,
+ ir_constant_data *data)
+{
+ switch (type->base_type) {
+ case GLSL_TYPE_UINT:
+ case GLSL_TYPE_INT:
+ for (unsigned i = 0; i < type->components(); i++)
+ data->u[i] = initializer->value.u[0];
+
+ break;
+
+ case GLSL_TYPE_FLOAT:
+ for (unsigned i = 0; i < type->components(); i++)
+ data->f[i] = initializer->value.f[0];
+
+ break;
+
+ case GLSL_TYPE_BOOL:
+ for (unsigned i = 0; i < type->components(); i++)
+ data->b[i] = initializer->value.b[0];
+
+ break;
+
+ default:
+ assert(!"Should not get here.");
+ break;
+ }
+}
+
+
+/**
+ * Determine if a list consists of a single scalar r-value
+ */
+bool
+single_scalar_parameter(exec_list *parameters)
+{
+ const ir_rvalue *const p = (ir_rvalue *) parameters->head;
+ assert(((ir_rvalue *)p)->as_rvalue() != NULL);
+
+ return (p->type->is_scalar() && p->next->is_tail_sentinel());
+}
+
+
+/**
+ * Generate inline code for a vector constructor
+ *
+ * The generated constructor code will consist of a temporary variable
+ * declaration of the same type as the constructor. A sequence of assignments
+ * from constructor parameters to the temporary will follow.
+ *
+ * \return
+ * An \c ir_dereference_variable of the temprorary generated in the constructor
+ * body.
+ */
+ir_rvalue *
+emit_inline_vector_constructor(const glsl_type *type,
+ exec_list *instructions,
+ exec_list *parameters,
+ void *ctx)
+{
+ assert(!parameters->is_empty());
+
+ ir_variable *var = new(ctx) ir_variable(type, "vec_ctor", ir_var_temporary);
+ instructions->push_tail(var);
+
+ /* There are two kinds of vector constructors.
+ *
+ * - Construct a vector from a single scalar by replicating that scalar to
+ * all components of the vector.
+ *
+ * - Construct a vector from an arbirary combination of vectors and
+ * scalars. The components of the constructor parameters are assigned
+ * to the vector in order until the vector is full.
+ */
+ const unsigned lhs_components = type->components();
+ if (single_scalar_parameter(parameters)) {
+ ir_rvalue *first_param = (ir_rvalue *)parameters->head;
+ ir_rvalue *rhs = new(ctx) ir_swizzle(first_param, 0, 0, 0, 0,
+ lhs_components);
+ ir_dereference_variable *lhs = new(ctx) ir_dereference_variable(var);
+ const unsigned mask = (1U << lhs_components) - 1;
+
+ assert(rhs->type == lhs->type);
+
+ ir_instruction *inst = new(ctx) ir_assignment(lhs, rhs, NULL, mask);
+ instructions->push_tail(inst);
+ } else {
+ unsigned base_component = 0;
+ foreach_list(node, parameters) {
+ ir_rvalue *param = (ir_rvalue *) node;
+ unsigned rhs_components = param->type->components();
+
+ /* Do not try to assign more components to the vector than it has!
+ */
+ if ((rhs_components + base_component) > lhs_components) {
+ rhs_components = lhs_components - base_component;
+ }
+
+ /* Generate a swizzle that puts the first element of the source at
+ * the location of the first element of the destination.
+ */
+ unsigned swiz[4] = { 0, 0, 0, 0 };
+ for (unsigned i = 0; i < rhs_components; i++)
+ swiz[i + base_component] = i;
+
+ /* Mask of fields to be written in the assignment.
+ */
+ const unsigned write_mask = ((1U << rhs_components) - 1)
+ << base_component;
+
+ ir_dereference *lhs = new(ctx) ir_dereference_variable(var);
+ ir_rvalue *rhs = new(ctx) ir_swizzle(param, swiz, lhs_components);
+
+ ir_instruction *inst =
+ new(ctx) ir_assignment(lhs, rhs, NULL, write_mask);
+ instructions->push_tail(inst);
+
+ /* Advance the component index by the number of components that were
+ * just assigned.
+ */
+ base_component += rhs_components;
+ }
+ }
+ return new(ctx) ir_dereference_variable(var);
+}
+
+
+/**
+ * Generate assignment of a portion of a vector to a portion of a matrix column
+ *
+ * \param src_base First component of the source to be used in assignment
+ * \param column Column of destination to be assiged
+ * \param row_base First component of the destination column to be assigned
+ * \param count Number of components to be assigned
+ *
+ * \note
+ * \c src_base + \c count must be less than or equal to the number of components
+ * in the source vector.
+ */
+ir_instruction *
+assign_to_matrix_column(ir_variable *var, unsigned column, unsigned row_base,
+ ir_rvalue *src, unsigned src_base, unsigned count,
+ void *mem_ctx)
+{
+ ir_constant *col_idx = new(mem_ctx) ir_constant(column);
+ ir_dereference *column_ref = new(mem_ctx) ir_dereference_array(var, col_idx);
+
+ assert(column_ref->type->components() >= (row_base + count));
+ assert(src->type->components() >= (src_base + count));
+
+ /* Generate a swizzle that puts the first element of the source at the
+ * location of the first element of the destination.
+ */
+ unsigned swiz[4] = { src_base, src_base, src_base, src_base };
+ for (unsigned i = 0; i < count; i++)
+ swiz[i + row_base] = src_base + i;
+
+ ir_rvalue *const rhs =
+ new(mem_ctx) ir_swizzle(src, swiz, column_ref->type->components());
+
+ /* Mask of fields to be written in the assignment.
+ */
+ const unsigned write_mask = ((1U << count) - 1) << row_base;
+
+ return new(mem_ctx) ir_assignment(column_ref, rhs, NULL, write_mask);
+}
+
+
+/**
+ * Generate inline code for a matrix constructor
+ *
+ * The generated constructor code will consist of a temporary variable
+ * declaration of the same type as the constructor. A sequence of assignments
+ * from constructor parameters to the temporary will follow.
+ *
+ * \return
+ * An \c ir_dereference_variable of the temprorary generated in the constructor
+ * body.
+ */
+ir_rvalue *
+emit_inline_matrix_constructor(const glsl_type *type,
+ exec_list *instructions,
+ exec_list *parameters,
+ void *ctx)
+{
+ assert(!parameters->is_empty());
+
+ ir_variable *var = new(ctx) ir_variable(type, "mat_ctor", ir_var_temporary);
+ instructions->push_tail(var);
+
+ /* There are three kinds of matrix constructors.
+ *
+ * - Construct a matrix from a single scalar by replicating that scalar to
+ * along the diagonal of the matrix and setting all other components to
+ * zero.
+ *
+ * - Construct a matrix from an arbirary combination of vectors and
+ * scalars. The components of the constructor parameters are assigned
+ * to the matrix in colum-major order until the matrix is full.
+ *
+ * - Construct a matrix from a single matrix. The source matrix is copied
+ * to the upper left portion of the constructed matrix, and the remaining
+ * elements take values from the identity matrix.
+ */
+ ir_rvalue *const first_param = (ir_rvalue *) parameters->head;
+ if (single_scalar_parameter(parameters)) {
+ /* Assign the scalar to the X component of a vec4, and fill the remaining
+ * components with zero.
+ */
+ ir_variable *rhs_var =
+ new(ctx) ir_variable(glsl_type::vec4_type, "mat_ctor_vec",
+ ir_var_temporary);
+ instructions->push_tail(rhs_var);
+
+ ir_constant_data zero;
+ zero.f[0] = 0.0;
+ zero.f[1] = 0.0;
+ zero.f[2] = 0.0;
+ zero.f[3] = 0.0;
+
+ ir_instruction *inst =
+ new(ctx) ir_assignment(new(ctx) ir_dereference_variable(rhs_var),
+ new(ctx) ir_constant(rhs_var->type, &zero),
+ NULL);
+ instructions->push_tail(inst);
+
+ ir_dereference *const rhs_ref = new(ctx) ir_dereference_variable(rhs_var);
+
+ inst = new(ctx) ir_assignment(rhs_ref, first_param, NULL, 0x01);
+ instructions->push_tail(inst);
+
+ /* Assign the temporary vector to each column of the destination matrix
+ * with a swizzle that puts the X component on the diagonal of the
+ * matrix. In some cases this may mean that the X component does not
+ * get assigned into the column at all (i.e., when the matrix has more
+ * columns than rows).
+ */
+ static const unsigned rhs_swiz[4][4] = {
+ { 0, 1, 1, 1 },
+ { 1, 0, 1, 1 },
+ { 1, 1, 0, 1 },
+ { 1, 1, 1, 0 }
+ };
+
+ const unsigned cols_to_init = MIN2(type->matrix_columns,
+ type->vector_elements);
+ for (unsigned i = 0; i < cols_to_init; i++) {
+ ir_constant *const col_idx = new(ctx) ir_constant(i);
+ ir_rvalue *const col_ref = new(ctx) ir_dereference_array(var, col_idx);
+
+ ir_rvalue *const rhs_ref = new(ctx) ir_dereference_variable(rhs_var);
+ ir_rvalue *const rhs = new(ctx) ir_swizzle(rhs_ref, rhs_swiz[i],
+ type->vector_elements);
+
+ inst = new(ctx) ir_assignment(col_ref, rhs, NULL);
+ instructions->push_tail(inst);
+ }
+
+ for (unsigned i = cols_to_init; i < type->matrix_columns; i++) {
+ ir_constant *const col_idx = new(ctx) ir_constant(i);
+ ir_rvalue *const col_ref = new(ctx) ir_dereference_array(var, col_idx);
+
+ ir_rvalue *const rhs_ref = new(ctx) ir_dereference_variable(rhs_var);
+ ir_rvalue *const rhs = new(ctx) ir_swizzle(rhs_ref, 1, 1, 1, 1,
+ type->vector_elements);
+
+ inst = new(ctx) ir_assignment(col_ref, rhs, NULL);
+ instructions->push_tail(inst);
+ }
+ } else if (first_param->type->is_matrix()) {
+ /* From page 50 (56 of the PDF) of the GLSL 1.50 spec:
+ *
+ * "If a matrix is constructed from a matrix, then each component
+ * (column i, row j) in the result that has a corresponding
+ * component (column i, row j) in the argument will be initialized
+ * from there. All other components will be initialized to the
+ * identity matrix. If a matrix argument is given to a matrix
+ * constructor, it is an error to have any other arguments."
+ */
+ assert(first_param->next->is_tail_sentinel());
+ ir_rvalue *const src_matrix = first_param;
+
+ /* If the source matrix is smaller, pre-initialize the relavent parts of
+ * the destination matrix to the identity matrix.
+ */
+ if ((src_matrix->type->matrix_columns < var->type->matrix_columns)
+ || (src_matrix->type->vector_elements < var->type->vector_elements)) {
+
+ /* If the source matrix has fewer rows, every column of the destination
+ * must be initialized. Otherwise only the columns in the destination
+ * that do not exist in the source must be initialized.
+ */
+ unsigned col =
+ (src_matrix->type->vector_elements < var->type->vector_elements)
+ ? 0 : src_matrix->type->matrix_columns;
+
+ const glsl_type *const col_type = var->type->column_type();
+ for (/* empty */; col < var->type->matrix_columns; col++) {
+ ir_constant_data ident;
+
+ ident.f[0] = 0.0;
+ ident.f[1] = 0.0;
+ ident.f[2] = 0.0;
+ ident.f[3] = 0.0;
+
+ ident.f[col] = 1.0;
+
+ ir_rvalue *const rhs = new(ctx) ir_constant(col_type, &ident);
+
+ ir_rvalue *const lhs =
+ new(ctx) ir_dereference_array(var, new(ctx) ir_constant(col));
+
+ ir_instruction *inst = new(ctx) ir_assignment(lhs, rhs, NULL);
+ instructions->push_tail(inst);
+ }
+ }
+
+ /* Assign columns from the source matrix to the destination matrix.
+ *
+ * Since the parameter will be used in the RHS of multiple assignments,
+ * generate a temporary and copy the paramter there.
+ */
+ ir_variable *const rhs_var =
+ new(ctx) ir_variable(first_param->type, "mat_ctor_mat",
+ ir_var_temporary);
+ instructions->push_tail(rhs_var);
+
+ ir_dereference *const rhs_var_ref =
+ new(ctx) ir_dereference_variable(rhs_var);
+ ir_instruction *const inst =
+ new(ctx) ir_assignment(rhs_var_ref, first_param, NULL);
+ instructions->push_tail(inst);
+
+
+ unsigned swiz[4] = { 0, 0, 0, 0 };
+ for (unsigned i = 1; i < src_matrix->type->vector_elements; i++)
+ swiz[i] = i;
+
+ const unsigned last_col = MIN2(src_matrix->type->matrix_columns,
+ var->type->matrix_columns);
+ const unsigned write_mask = (1U << var->type->vector_elements) - 1;
+
+ for (unsigned i = 0; i < last_col; i++) {
+ ir_dereference *const lhs =
+ new(ctx) ir_dereference_array(var, new(ctx) ir_constant(i));
+ ir_rvalue *const rhs_col =
+ new(ctx) ir_dereference_array(rhs_var, new(ctx) ir_constant(i));
+
+ /* If one matrix has columns that are smaller than the columns of the
+ * other matrix, wrap the column access of the larger with a swizzle
+ * so that the LHS and RHS of the assignment have the same size (and
+ * therefore have the same type).
+ *
+ * It would be perfectly valid to unconditionally generate the
+ * swizzles, this this will typically result in a more compact IR tree.
+ */
+ ir_rvalue *rhs;
+ if (lhs->type->vector_elements != rhs_col->type->vector_elements) {
+ rhs = new(ctx) ir_swizzle(rhs_col, swiz,
+ lhs->type->vector_elements);
+ } else {
+ rhs = rhs_col;
+ }
+
+ assert(lhs->type == rhs->type);
+
+ ir_instruction *inst =
+ new(ctx) ir_assignment(lhs, rhs, NULL, write_mask);
+ instructions->push_tail(inst);
+ }
+ } else {
+ const unsigned rows = type->matrix_columns;
+ const unsigned cols = type->vector_elements;
+ unsigned col_idx = 0;
+ unsigned row_idx = 0;
+
+ foreach_list (node, parameters) {
+ ir_rvalue *const rhs = (ir_rvalue *) node;
+ const unsigned components_remaining_this_column = rows - row_idx;
+ unsigned rhs_components = rhs->type->components();
+ unsigned rhs_base = 0;
+
+ /* Since the parameter might be used in the RHS of two assignments,
+ * generate a temporary and copy the paramter there.
+ */
+ ir_variable *rhs_var =
+ new(ctx) ir_variable(rhs->type, "mat_ctor_vec", ir_var_temporary);
+ instructions->push_tail(rhs_var);
+
+ ir_dereference *rhs_var_ref =
+ new(ctx) ir_dereference_variable(rhs_var);
+ ir_instruction *inst = new(ctx) ir_assignment(rhs_var_ref, rhs, NULL);
+ instructions->push_tail(inst);
+
+ /* Assign the current parameter to as many components of the matrix
+ * as it will fill.
+ *
+ * NOTE: A single vector parameter can span two matrix columns. A
+ * single vec4, for example, can completely fill a mat2.
+ */
+ if (rhs_components >= components_remaining_this_column) {
+ const unsigned count = MIN2(rhs_components,
+ components_remaining_this_column);
+
+ rhs_var_ref = new(ctx) ir_dereference_variable(rhs_var);
+
+ ir_instruction *inst = assign_to_matrix_column(var, col_idx,
+ row_idx,
+ rhs_var_ref, 0,
+ count, ctx);
+ instructions->push_tail(inst);
+
+ rhs_base = count;
+
+ col_idx++;
+ row_idx = 0;
+ }
+
+ /* If there is data left in the parameter and components left to be
+ * set in the destination, emit another assignment. It is possible
+ * that the assignment could be of a vec4 to the last element of the
+ * matrix. In this case col_idx==cols, but there is still data
+ * left in the source parameter. Obviously, don't emit an assignment
+ * to data outside the destination matrix.
+ */
+ if ((col_idx < cols) && (rhs_base < rhs_components)) {
+ const unsigned count = rhs_components - rhs_base;
+
+ rhs_var_ref = new(ctx) ir_dereference_variable(rhs_var);
+
+ ir_instruction *inst = assign_to_matrix_column(var, col_idx,
+ row_idx,
+ rhs_var_ref,
+ rhs_base,
+ count, ctx);
+ instructions->push_tail(inst);
+
+ row_idx += count;
+ }
+ }
+ }
+
+ return new(ctx) ir_dereference_variable(var);
+}
+
+
+ir_rvalue *
+ast_function_expression::hir(exec_list *instructions,
+ struct _mesa_glsl_parse_state *state)
+{
+ void *ctx = state;
+ /* There are three sorts of function calls.
+ *
+ * 1. constructors - The first subexpression is an ast_type_specifier.
+ * 2. methods - Only the .length() method of array types.
+ * 3. functions - Calls to regular old functions.
+ *
+ * Method calls are actually detected when the ast_field_selection
+ * expression is handled.
+ */
+ if (is_constructor()) {
+ const ast_type_specifier *type = (ast_type_specifier *) subexpressions[0];
+ YYLTYPE loc = type->get_location();
+ const char *name;
+
+ const glsl_type *const constructor_type = type->glsl_type(& name, state);
+
+
+ /* Constructors for samplers are illegal.
+ */
+ if (constructor_type->is_sampler()) {
+ _mesa_glsl_error(& loc, state, "cannot construct sampler type `%s'",
+ constructor_type->name);
+ return ir_call::get_error_instruction(ctx);
+ }
+
+ if (constructor_type->is_array()) {
+ if (state->language_version <= 110) {
+ _mesa_glsl_error(& loc, state,
+ "array constructors forbidden in GLSL 1.10");
+ return ir_call::get_error_instruction(ctx);
+ }
+
+ return process_array_constructor(instructions, constructor_type,
+ & loc, &this->expressions, state);
+ }
+
+ /* There are two kinds of constructor call. Constructors for built-in
+ * language types, such as mat4 and vec2, are free form. The only
+ * requirement is that the parameters must provide enough values of the
+ * correct scalar type. Constructors for arrays and structures must
+ * have the exact number of parameters with matching types in the
+ * correct order. These constructors follow essentially the same type
+ * matching rules as functions.
+ */
+ if (!constructor_type->is_numeric() && !constructor_type->is_boolean())
+ return ir_call::get_error_instruction(ctx);
+
+ /* Total number of components of the type being constructed. */
+ const unsigned type_components = constructor_type->components();
+
+ /* Number of components from parameters that have actually been
+ * consumed. This is used to perform several kinds of error checking.
+ */
+ unsigned components_used = 0;
+
+ unsigned matrix_parameters = 0;
+ unsigned nonmatrix_parameters = 0;
+ exec_list actual_parameters;
+
+ foreach_list (n, &this->expressions) {
+ ast_node *ast = exec_node_data(ast_node, n, link);
+ ir_rvalue *result = ast->hir(instructions, state)->as_rvalue();
+
+ /* From page 50 (page 56 of the PDF) of the GLSL 1.50 spec:
+ *
+ * "It is an error to provide extra arguments beyond this
+ * last used argument."
+ */
+ if (components_used >= type_components) {
+ _mesa_glsl_error(& loc, state, "too many parameters to `%s' "
+ "constructor",
+ constructor_type->name);
+ return ir_call::get_error_instruction(ctx);
+ }
+
+ if (!result->type->is_numeric() && !result->type->is_boolean()) {
+ _mesa_glsl_error(& loc, state, "cannot construct `%s' from a "
+ "non-numeric data type",
+ constructor_type->name);
+ return ir_call::get_error_instruction(ctx);
+ }
+
+ /* Count the number of matrix and nonmatrix parameters. This
+ * is used below to enforce some of the constructor rules.
+ */
+ if (result->type->is_matrix())
+ matrix_parameters++;
+ else
+ nonmatrix_parameters++;
+
+ actual_parameters.push_tail(result);
+ components_used += result->type->components();
+ }
+
+ /* From page 28 (page 34 of the PDF) of the GLSL 1.10 spec:
+ *
+ * "It is an error to construct matrices from other matrices. This
+ * is reserved for future use."
+ */
+ if ((state->language_version <= 110) && (matrix_parameters > 0)
+ && constructor_type->is_matrix()) {
+ _mesa_glsl_error(& loc, state, "cannot construct `%s' from a "
+ "matrix in GLSL 1.10",
+ constructor_type->name);
+ return ir_call::get_error_instruction(ctx);
+ }
+
+ /* From page 50 (page 56 of the PDF) of the GLSL 1.50 spec:
+ *
+ * "If a matrix argument is given to a matrix constructor, it is
+ * an error to have any other arguments."
+ */
+ if ((matrix_parameters > 0)
+ && ((matrix_parameters + nonmatrix_parameters) > 1)
+ && constructor_type->is_matrix()) {
+ _mesa_glsl_error(& loc, state, "for matrix `%s' constructor, "
+ "matrix must be only parameter",
+ constructor_type->name);
+ return ir_call::get_error_instruction(ctx);
+ }
+
+ /* From page 28 (page 34 of the PDF) of the GLSL 1.10 spec:
+ *
+ * "In these cases, there must be enough components provided in the
+ * arguments to provide an initializer for every component in the
+ * constructed value."
+ */
+ if ((components_used < type_components) && (components_used != 1)) {
+ _mesa_glsl_error(& loc, state, "too few components to construct "
+ "`%s'",
+ constructor_type->name);
+ return ir_call::get_error_instruction(ctx);
+ }
+
+ /* Later, we cast each parameter to the same base type as the
+ * constructor. Since there are no non-floating point matrices, we
+ * need to break them up into a series of column vectors.
+ */
+ if (constructor_type->base_type != GLSL_TYPE_FLOAT) {
+ foreach_list_safe(n, &actual_parameters) {
+ ir_rvalue *matrix = (ir_rvalue *) n;
+
+ if (!matrix->type->is_matrix())
+ continue;
+
+ /* Create a temporary containing the matrix. */
+ ir_variable *var = new(ctx) ir_variable(matrix->type, "matrix_tmp",
+ ir_var_temporary);
+ instructions->push_tail(var);
+ instructions->push_tail(new(ctx) ir_assignment(new(ctx)
+ ir_dereference_variable(var), matrix, NULL));
+ var->constant_value = matrix->constant_expression_value();
+
+ /* Replace the matrix with dereferences of its columns. */
+ for (int i = 0; i < matrix->type->matrix_columns; i++) {
+ matrix->insert_before(new (ctx) ir_dereference_array(var,
+ new(ctx) ir_constant(i)));
+ }
+ matrix->remove();
+ }
+ }
+
+ bool all_parameters_are_constant = true;
+
+ /* Type cast each parameter and, if possible, fold constants.*/
+ foreach_list_safe(n, &actual_parameters) {
+ ir_rvalue *ir = (ir_rvalue *) n;
+
+ const glsl_type *desired_type =
+ glsl_type::get_instance(constructor_type->base_type,
+ ir->type->vector_elements,
+ ir->type->matrix_columns);
+ ir_rvalue *result = convert_component(ir, desired_type);
+
+ /* Attempt to convert the parameter to a constant valued expression.
+ * After doing so, track whether or not all the parameters to the
+ * constructor are trivially constant valued expressions.
+ */
+ ir_rvalue *const constant = result->constant_expression_value();
+
+ if (constant != NULL)
+ result = constant;
+ else
+ all_parameters_are_constant = false;
+
+ if (result != ir) {
+ ir->replace_with(result);
+ }
+ }
+
+ /* If all of the parameters are trivially constant, create a
+ * constant representing the complete collection of parameters.
+ */
+ if (all_parameters_are_constant) {
+ if (components_used >= type_components)
+ return new(ctx) ir_constant(constructor_type,
+ & actual_parameters);
+
+ /* The above case must handle all scalar constructors.
+ */
+ assert(constructor_type->is_vector()
+ || constructor_type->is_matrix());
+
+ /* Constructors with exactly one component are special for
+ * vectors and matrices. For vectors it causes all elements of
+ * the vector to be filled with the value. For matrices it
+ * causes the matrix to be filled with 0 and the diagonal to be
+ * filled with the value.
+ */
+ ir_constant_data data;
+ ir_constant *const initializer =
+ (ir_constant *) actual_parameters.head;
+ if (constructor_type->is_matrix())
+ generate_constructor_matrix(constructor_type, initializer,
+ &data);
+ else
+ generate_constructor_vector(constructor_type, initializer,
+ &data);
+
+ return new(ctx) ir_constant(constructor_type, &data);
+ } else if (constructor_type->is_scalar()) {
+ return dereference_component((ir_rvalue *) actual_parameters.head,
+ 0);
+ } else if (constructor_type->is_vector()) {
+ return emit_inline_vector_constructor(constructor_type,
+ instructions,
+ &actual_parameters,
+ ctx);
+ } else {
+ assert(constructor_type->is_matrix());
+ return emit_inline_matrix_constructor(constructor_type,
+ instructions,
+ &actual_parameters,
+ ctx);
+ }
+ } else {
+ const ast_expression *id = subexpressions[0];
+ YYLTYPE loc = id->get_location();
+ exec_list actual_parameters;
+
+ process_parameters(instructions, &actual_parameters, &this->expressions,
+ state);
+
+ const glsl_type *const type =
+ state->symbols->get_type(id->primary_expression.identifier);
+
+ if ((type != NULL) && type->is_record()) {
+ ir_constant *constant =
+ constant_record_constructor(type, &loc, &actual_parameters, state);
+
+ if (constant != NULL)
+ return constant;
+ }
+
+ return match_function_by_name(instructions,
+ id->primary_expression.identifier, & loc,
+ &actual_parameters, state);
+ }
+
+ return ir_call::get_error_instruction(ctx);
+}
diff --git a/src/glsl/ast_to_hir.cpp b/src/glsl/ast_to_hir.cpp
new file mode 100644
index 00000000000..6e5d01ee265
--- /dev/null
+++ b/src/glsl/ast_to_hir.cpp
@@ -0,0 +1,2607 @@
+/*
+ * Copyright © 2010 Intel Corporation
+ *
+ * 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 (including the next
+ * paragraph) 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
+ * THE AUTHORS OR COPYRIGHT HOLDERS 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 ast_to_hir.c
+ * Convert abstract syntax to to high-level intermediate reprensentation (HIR).
+ *
+ * During the conversion to HIR, the majority of the symantic checking is
+ * preformed on the program. This includes:
+ *
+ * * Symbol table management
+ * * Type checking
+ * * Function binding
+ *
+ * The majority of this work could be done during parsing, and the parser could
+ * probably generate HIR directly. However, this results in frequent changes
+ * to the parser code. Since we do not assume that every system this complier
+ * is built on will have Flex and Bison installed, we have to store the code
+ * generated by these tools in our version control system. In other parts of
+ * the system we've seen problems where a parser was changed but the generated
+ * code was not committed, merge conflicts where created because two developers
+ * had slightly different versions of Bison installed, etc.
+ *
+ * I have also noticed that running Bison generated parsers in GDB is very
+ * irritating. When you get a segfault on '$$ = $1->foo', you can't very
+ * well 'print $1' in GDB.
+ *
+ * As a result, my preference is to put as little C code as possible in the
+ * parser (and lexer) sources.
+ */
+
+#include "main/imports.h"
+#include "main/extensions.h"
+#include "glsl_symbol_table.h"
+#include "glsl_parser_extras.h"
+#include "ast.h"
+#include "glsl_types.h"
+#include "ir.h"
+
+void
+_mesa_ast_to_hir(exec_list *instructions, struct _mesa_glsl_parse_state *state)
+{
+ _mesa_glsl_initialize_variables(instructions, state);
+ _mesa_glsl_initialize_functions(instructions, state);
+
+ state->current_function = NULL;
+
+ foreach_list_typed (ast_node, ast, link, & state->translation_unit)
+ ast->hir(instructions, state);
+}
+
+
+/**
+ * If a conversion is available, convert one operand to a different type
+ *
+ * The \c from \c ir_rvalue is converted "in place".
+ *
+ * \param to Type that the operand it to be converted to
+ * \param from Operand that is being converted
+ * \param state GLSL compiler state
+ *
+ * \return
+ * If a conversion is possible (or unnecessary), \c true is returned.
+ * Otherwise \c false is returned.
+ */
+static bool
+apply_implicit_conversion(const glsl_type *to, ir_rvalue * &from,
+ struct _mesa_glsl_parse_state *state)
+{
+ void *ctx = state;
+ if (to->base_type == from->type->base_type)
+ return true;
+
+ /* This conversion was added in GLSL 1.20. If the compilation mode is
+ * GLSL 1.10, the conversion is skipped.
+ */
+ if (state->language_version < 120)
+ return false;
+
+ /* From page 27 (page 33 of the PDF) of the GLSL 1.50 spec:
+ *
+ * "There are no implicit array or structure conversions. For
+ * example, an array of int cannot be implicitly converted to an
+ * array of float. There are no implicit conversions between
+ * signed and unsigned integers."
+ */
+ /* FINISHME: The above comment is partially a lie. There is int/uint
+ * FINISHME: conversion for immediate constants.
+ */
+ if (!to->is_float() || !from->type->is_numeric())
+ return false;
+
+ /* Convert to a floating point type with the same number of components
+ * as the original type - i.e. int to float, not int to vec4.
+ */
+ to = glsl_type::get_instance(GLSL_TYPE_FLOAT, from->type->vector_elements,
+ from->type->matrix_columns);
+
+ switch (from->type->base_type) {
+ case GLSL_TYPE_INT:
+ from = new(ctx) ir_expression(ir_unop_i2f, to, from, NULL);
+ break;
+ case GLSL_TYPE_UINT:
+ from = new(ctx) ir_expression(ir_unop_u2f, to, from, NULL);
+ break;
+ case GLSL_TYPE_BOOL:
+ from = new(ctx) ir_expression(ir_unop_b2f, to, from, NULL);
+ break;
+ default:
+ assert(0);
+ }
+
+ return true;
+}
+
+
+static const struct glsl_type *
+arithmetic_result_type(ir_rvalue * &value_a, ir_rvalue * &value_b,
+ bool multiply,
+ struct _mesa_glsl_parse_state *state, YYLTYPE *loc)
+{
+ const glsl_type *type_a = value_a->type;
+ const glsl_type *type_b = value_b->type;
+
+ /* From GLSL 1.50 spec, page 56:
+ *
+ * "The arithmetic binary operators add (+), subtract (-),
+ * multiply (*), and divide (/) operate on integer and
+ * floating-point scalars, vectors, and matrices."
+ */
+ if (!type_a->is_numeric() || !type_b->is_numeric()) {
+ _mesa_glsl_error(loc, state,
+ "Operands to arithmetic operators must be numeric");
+ return glsl_type::error_type;
+ }
+
+
+ /* "If one operand is floating-point based and the other is
+ * not, then the conversions from Section 4.1.10 "Implicit
+ * Conversions" are applied to the non-floating-point-based operand."
+ */
+ if (!apply_implicit_conversion(type_a, value_b, state)
+ && !apply_implicit_conversion(type_b, value_a, state)) {
+ _mesa_glsl_error(loc, state,
+ "Could not implicitly convert operands to "
+ "arithmetic operator");
+ return glsl_type::error_type;
+ }
+ type_a = value_a->type;
+ type_b = value_b->type;
+
+ /* "If the operands are integer types, they must both be signed or
+ * both be unsigned."
+ *
+ * From this rule and the preceeding conversion it can be inferred that
+ * both types must be GLSL_TYPE_FLOAT, or GLSL_TYPE_UINT, or GLSL_TYPE_INT.
+ * The is_numeric check above already filtered out the case where either
+ * type is not one of these, so now the base types need only be tested for
+ * equality.
+ */
+ if (type_a->base_type != type_b->base_type) {
+ _mesa_glsl_error(loc, state,
+ "base type mismatch for arithmetic operator");
+ return glsl_type::error_type;
+ }
+
+ /* "All arithmetic binary operators result in the same fundamental type
+ * (signed integer, unsigned integer, or floating-point) as the
+ * operands they operate on, after operand type conversion. After
+ * conversion, the following cases are valid
+ *
+ * * The two operands are scalars. In this case the operation is
+ * applied, resulting in a scalar."
+ */
+ if (type_a->is_scalar() && type_b->is_scalar())
+ return type_a;
+
+ /* "* One operand is a scalar, and the other is a vector or matrix.
+ * In this case, the scalar operation is applied independently to each
+ * component of the vector or matrix, resulting in the same size
+ * vector or matrix."
+ */
+ if (type_a->is_scalar()) {
+ if (!type_b->is_scalar())
+ return type_b;
+ } else if (type_b->is_scalar()) {
+ return type_a;
+ }
+
+ /* All of the combinations of <scalar, scalar>, <vector, scalar>,
+ * <scalar, vector>, <scalar, matrix>, and <matrix, scalar> have been
+ * handled.
+ */
+ assert(!type_a->is_scalar());
+ assert(!type_b->is_scalar());
+
+ /* "* The two operands are vectors of the same size. In this case, the
+ * operation is done component-wise resulting in the same size
+ * vector."
+ */
+ if (type_a->is_vector() && type_b->is_vector()) {
+ if (type_a == type_b) {
+ return type_a;
+ } else {
+ _mesa_glsl_error(loc, state,
+ "vector size mismatch for arithmetic operator");
+ return glsl_type::error_type;
+ }
+ }
+
+ /* All of the combinations of <scalar, scalar>, <vector, scalar>,
+ * <scalar, vector>, <scalar, matrix>, <matrix, scalar>, and
+ * <vector, vector> have been handled. At least one of the operands must
+ * be matrix. Further, since there are no integer matrix types, the base
+ * type of both operands must be float.
+ */
+ assert(type_a->is_matrix() || type_b->is_matrix());
+ assert(type_a->base_type == GLSL_TYPE_FLOAT);
+ assert(type_b->base_type == GLSL_TYPE_FLOAT);
+
+ /* "* The operator is add (+), subtract (-), or divide (/), and the
+ * operands are matrices with the same number of rows and the same
+ * number of columns. In this case, the operation is done component-
+ * wise resulting in the same size matrix."
+ * * The operator is multiply (*), where both operands are matrices or
+ * one operand is a vector and the other a matrix. A right vector
+ * operand is treated as a column vector and a left vector operand as a
+ * row vector. In all these cases, it is required that the number of
+ * columns of the left operand is equal to the number of rows of the
+ * right operand. Then, the multiply (*) operation does a linear
+ * algebraic multiply, yielding an object that has the same number of
+ * rows as the left operand and the same number of columns as the right
+ * operand. Section 5.10 "Vector and Matrix Operations" explains in
+ * more detail how vectors and matrices are operated on."
+ */
+ if (! multiply) {
+ if (type_a == type_b)
+ return type_a;
+ } else {
+ if (type_a->is_matrix() && type_b->is_matrix()) {
+ /* Matrix multiply. The columns of A must match the rows of B. Given
+ * the other previously tested constraints, this means the vector type
+ * of a row from A must be the same as the vector type of a column from
+ * B.
+ */
+ if (type_a->row_type() == type_b->column_type()) {
+ /* The resulting matrix has the number of columns of matrix B and
+ * the number of rows of matrix A. We get the row count of A by
+ * looking at the size of a vector that makes up a column. The
+ * transpose (size of a row) is done for B.
+ */
+ const glsl_type *const type =
+ glsl_type::get_instance(type_a->base_type,
+ type_a->column_type()->vector_elements,
+ type_b->row_type()->vector_elements);
+ assert(type != glsl_type::error_type);
+
+ return type;
+ }
+ } else if (type_a->is_matrix()) {
+ /* A is a matrix and B is a column vector. Columns of A must match
+ * rows of B. Given the other previously tested constraints, this
+ * means the vector type of a row from A must be the same as the
+ * vector the type of B.
+ */
+ if (type_a->row_type() == type_b) {
+ /* The resulting vector has a number of elements equal to
+ * the number of rows of matrix A. */
+ const glsl_type *const type =
+ glsl_type::get_instance(type_a->base_type,
+ type_a->column_type()->vector_elements,
+ 1);
+ assert(type != glsl_type::error_type);
+
+ return type;
+ }
+ } else {
+ assert(type_b->is_matrix());
+
+ /* A is a row vector and B is a matrix. Columns of A must match rows
+ * of B. Given the other previously tested constraints, this means
+ * the type of A must be the same as the vector type of a column from
+ * B.
+ */
+ if (type_a == type_b->column_type()) {
+ /* The resulting vector has a number of elements equal to
+ * the number of columns of matrix B. */
+ const glsl_type *const type =
+ glsl_type::get_instance(type_a->base_type,
+ type_b->row_type()->vector_elements,
+ 1);
+ assert(type != glsl_type::error_type);
+
+ return type;
+ }
+ }
+
+ _mesa_glsl_error(loc, state, "size mismatch for matrix multiplication");
+ return glsl_type::error_type;
+ }
+
+
+ /* "All other cases are illegal."
+ */
+ _mesa_glsl_error(loc, state, "type mismatch");
+ return glsl_type::error_type;
+}
+
+
+static const struct glsl_type *
+unary_arithmetic_result_type(const struct glsl_type *type,
+ struct _mesa_glsl_parse_state *state, YYLTYPE *loc)
+{
+ /* From GLSL 1.50 spec, page 57:
+ *
+ * "The arithmetic unary operators negate (-), post- and pre-increment
+ * and decrement (-- and ++) operate on integer or floating-point
+ * values (including vectors and matrices). All unary operators work
+ * component-wise on their operands. These result with the same type
+ * they operated on."
+ */
+ if (!type->is_numeric()) {
+ _mesa_glsl_error(loc, state,
+ "Operands to arithmetic operators must be numeric");
+ return glsl_type::error_type;
+ }
+
+ return type;
+}
+
+
+static const struct glsl_type *
+modulus_result_type(const struct glsl_type *type_a,
+ const struct glsl_type *type_b,
+ struct _mesa_glsl_parse_state *state, YYLTYPE *loc)
+{
+ /* From GLSL 1.50 spec, page 56:
+ * "The operator modulus (%) operates on signed or unsigned integers or
+ * integer vectors. The operand types must both be signed or both be
+ * unsigned."
+ */
+ if (!type_a->is_integer() || !type_b->is_integer()
+ || (type_a->base_type != type_b->base_type)) {
+ _mesa_glsl_error(loc, state, "type mismatch");
+ return glsl_type::error_type;
+ }
+
+ /* "The operands cannot be vectors of differing size. If one operand is
+ * a scalar and the other vector, then the scalar is applied component-
+ * wise to the vector, resulting in the same type as the vector. If both
+ * are vectors of the same size, the result is computed component-wise."
+ */
+ if (type_a->is_vector()) {
+ if (!type_b->is_vector()
+ || (type_a->vector_elements == type_b->vector_elements))
+ return type_a;
+ } else
+ return type_b;
+
+ /* "The operator modulus (%) is not defined for any other data types
+ * (non-integer types)."
+ */
+ _mesa_glsl_error(loc, state, "type mismatch");
+ return glsl_type::error_type;
+}
+
+
+static const struct glsl_type *
+relational_result_type(ir_rvalue * &value_a, ir_rvalue * &value_b,
+ struct _mesa_glsl_parse_state *state, YYLTYPE *loc)
+{
+ const glsl_type *type_a = value_a->type;
+ const glsl_type *type_b = value_b->type;
+
+ /* From GLSL 1.50 spec, page 56:
+ * "The relational operators greater than (>), less than (<), greater
+ * than or equal (>=), and less than or equal (<=) operate only on
+ * scalar integer and scalar floating-point expressions."
+ */
+ if (!type_a->is_numeric()
+ || !type_b->is_numeric()
+ || !type_a->is_scalar()
+ || !type_b->is_scalar()) {
+ _mesa_glsl_error(loc, state,
+ "Operands to relational operators must be scalar and "
+ "numeric");
+ return glsl_type::error_type;
+ }
+
+ /* "Either the operands' types must match, or the conversions from
+ * Section 4.1.10 "Implicit Conversions" will be applied to the integer
+ * operand, after which the types must match."
+ */
+ if (!apply_implicit_conversion(type_a, value_b, state)
+ && !apply_implicit_conversion(type_b, value_a, state)) {
+ _mesa_glsl_error(loc, state,
+ "Could not implicitly convert operands to "
+ "relational operator");
+ return glsl_type::error_type;
+ }
+ type_a = value_a->type;
+ type_b = value_b->type;
+
+ if (type_a->base_type != type_b->base_type) {
+ _mesa_glsl_error(loc, state, "base type mismatch");
+ return glsl_type::error_type;
+ }
+
+ /* "The result is scalar Boolean."
+ */
+ return glsl_type::bool_type;
+}
+
+
+/**
+ * Validates that a value can be assigned to a location with a specified type
+ *
+ * Validates that \c rhs can be assigned to some location. If the types are
+ * not an exact match but an automatic conversion is possible, \c rhs will be
+ * converted.
+ *
+ * \return
+ * \c NULL if \c rhs cannot be assigned to a location with type \c lhs_type.
+ * Otherwise the actual RHS to be assigned will be returned. This may be
+ * \c rhs, or it may be \c rhs after some type conversion.
+ *
+ * \note
+ * In addition to being used for assignments, this function is used to
+ * type-check return values.
+ */
+ir_rvalue *
+validate_assignment(struct _mesa_glsl_parse_state *state,
+ const glsl_type *lhs_type, ir_rvalue *rhs)
+{
+ const glsl_type *rhs_type = rhs->type;
+
+ /* If there is already some error in the RHS, just return it. Anything
+ * else will lead to an avalanche of error message back to the user.
+ */
+ if (rhs_type->is_error())
+ return rhs;
+
+ /* If the types are identical, the assignment can trivially proceed.
+ */
+ if (rhs_type == lhs_type)
+ return rhs;
+
+ /* If the array element types are the same and the size of the LHS is zero,
+ * the assignment is okay.
+ *
+ * Note: Whole-array assignments are not permitted in GLSL 1.10, but this
+ * is handled by ir_dereference::is_lvalue.
+ */
+ if (lhs_type->is_array() && rhs->type->is_array()
+ && (lhs_type->element_type() == rhs->type->element_type())
+ && (lhs_type->array_size() == 0)) {
+ return rhs;
+ }
+
+ /* Check for implicit conversion in GLSL 1.20 */
+ if (apply_implicit_conversion(lhs_type, rhs, state)) {
+ rhs_type = rhs->type;
+ if (rhs_type == lhs_type)
+ return rhs;
+ }
+
+ return NULL;
+}
+
+ir_rvalue *
+do_assignment(exec_list *instructions, struct _mesa_glsl_parse_state *state,
+ ir_rvalue *lhs, ir_rvalue *rhs,
+ YYLTYPE lhs_loc)
+{
+ void *ctx = state;
+ bool error_emitted = (lhs->type->is_error() || rhs->type->is_error());
+
+ if (!error_emitted) {
+ /* FINISHME: This does not handle 'foo.bar.a.b.c[5].d = 5' */
+ if (!lhs->is_lvalue()) {
+ _mesa_glsl_error(& lhs_loc, state, "non-lvalue in assignment");
+ error_emitted = true;
+ }
+ }
+
+ ir_rvalue *new_rhs = validate_assignment(state, lhs->type, rhs);
+ if (new_rhs == NULL) {
+ _mesa_glsl_error(& lhs_loc, state, "type mismatch");
+ } else {
+ rhs = new_rhs;
+
+ /* If the LHS array was not declared with a size, it takes it size from
+ * the RHS. If the LHS is an l-value and a whole array, it must be a
+ * dereference of a variable. Any other case would require that the LHS
+ * is either not an l-value or not a whole array.
+ */
+ if (lhs->type->array_size() == 0) {
+ ir_dereference *const d = lhs->as_dereference();
+
+ assert(d != NULL);
+
+ ir_variable *const var = d->variable_referenced();
+
+ assert(var != NULL);
+
+ if (var->max_array_access >= unsigned(rhs->type->array_size())) {
+ /* FINISHME: This should actually log the location of the RHS. */
+ _mesa_glsl_error(& lhs_loc, state, "array size must be > %u due to "
+ "previous access",
+ var->max_array_access);
+ }
+
+ var->type = glsl_type::get_array_instance(lhs->type->element_type(),
+ rhs->type->array_size());
+ d->type = var->type;
+ }
+ }
+
+ /* Most callers of do_assignment (assign, add_assign, pre_inc/dec,
+ * but not post_inc) need the converted assigned value as an rvalue
+ * to handle things like:
+ *
+ * i = j += 1;
+ *
+ * So we always just store the computed value being assigned to a
+ * temporary and return a deref of that temporary. If the rvalue
+ * ends up not being used, the temp will get copy-propagated out.
+ */
+ ir_variable *var = new(ctx) ir_variable(rhs->type, "assignment_tmp",
+ ir_var_temporary);
+ ir_dereference_variable *deref_var = new(ctx) ir_dereference_variable(var);
+ instructions->push_tail(var);
+ instructions->push_tail(new(ctx) ir_assignment(deref_var,
+ rhs,
+ NULL));
+ deref_var = new(ctx) ir_dereference_variable(var);
+
+ if (!error_emitted)
+ instructions->push_tail(new(ctx) ir_assignment(lhs, deref_var, NULL));
+
+ return new(ctx) ir_dereference_variable(var);
+}
+
+static ir_rvalue *
+get_lvalue_copy(exec_list *instructions, ir_rvalue *lvalue)
+{
+ void *ctx = talloc_parent(lvalue);
+ ir_variable *var;
+
+ /* FINISHME: Give unique names to the temporaries. */
+ var = new(ctx) ir_variable(lvalue->type, "_post_incdec_tmp",
+ ir_var_temporary);
+ instructions->push_tail(var);
+ var->mode = ir_var_auto;
+
+ instructions->push_tail(new(ctx) ir_assignment(new(ctx) ir_dereference_variable(var),
+ lvalue, NULL));
+
+ /* Once we've created this temporary, mark it read only so it's no
+ * longer considered an lvalue.
+ */
+ var->read_only = true;
+
+ return new(ctx) ir_dereference_variable(var);
+}
+
+
+ir_rvalue *
+ast_node::hir(exec_list *instructions,
+ struct _mesa_glsl_parse_state *state)
+{
+ (void) instructions;
+ (void) state;
+
+ return NULL;
+}
+
+
+ir_rvalue *
+ast_expression::hir(exec_list *instructions,
+ struct _mesa_glsl_parse_state *state)
+{
+ void *ctx = state;
+ static const int operations[AST_NUM_OPERATORS] = {
+ -1, /* ast_assign doesn't convert to ir_expression. */
+ -1, /* ast_plus doesn't convert to ir_expression. */
+ ir_unop_neg,
+ ir_binop_add,
+ ir_binop_sub,
+ ir_binop_mul,
+ ir_binop_div,
+ ir_binop_mod,
+ ir_binop_lshift,
+ ir_binop_rshift,
+ ir_binop_less,
+ ir_binop_greater,
+ ir_binop_lequal,
+ ir_binop_gequal,
+ ir_binop_equal,
+ ir_binop_nequal,
+ ir_binop_bit_and,
+ ir_binop_bit_xor,
+ ir_binop_bit_or,
+ ir_unop_bit_not,
+ ir_binop_logic_and,
+ ir_binop_logic_xor,
+ ir_binop_logic_or,
+ ir_unop_logic_not,
+
+ /* Note: The following block of expression types actually convert
+ * to multiple IR instructions.
+ */
+ ir_binop_mul, /* ast_mul_assign */
+ ir_binop_div, /* ast_div_assign */
+ ir_binop_mod, /* ast_mod_assign */
+ ir_binop_add, /* ast_add_assign */
+ ir_binop_sub, /* ast_sub_assign */
+ ir_binop_lshift, /* ast_ls_assign */
+ ir_binop_rshift, /* ast_rs_assign */
+ ir_binop_bit_and, /* ast_and_assign */
+ ir_binop_bit_xor, /* ast_xor_assign */
+ ir_binop_bit_or, /* ast_or_assign */
+
+ -1, /* ast_conditional doesn't convert to ir_expression. */
+ ir_binop_add, /* ast_pre_inc. */
+ ir_binop_sub, /* ast_pre_dec. */
+ ir_binop_add, /* ast_post_inc. */
+ ir_binop_sub, /* ast_post_dec. */
+ -1, /* ast_field_selection doesn't conv to ir_expression. */
+ -1, /* ast_array_index doesn't convert to ir_expression. */
+ -1, /* ast_function_call doesn't conv to ir_expression. */
+ -1, /* ast_identifier doesn't convert to ir_expression. */
+ -1, /* ast_int_constant doesn't convert to ir_expression. */
+ -1, /* ast_uint_constant doesn't conv to ir_expression. */
+ -1, /* ast_float_constant doesn't conv to ir_expression. */
+ -1, /* ast_bool_constant doesn't conv to ir_expression. */
+ -1, /* ast_sequence doesn't convert to ir_expression. */
+ };
+ ir_rvalue *result = NULL;
+ ir_rvalue *op[3];
+ const struct glsl_type *type = glsl_type::error_type;
+ bool error_emitted = false;
+ YYLTYPE loc;
+
+ loc = this->get_location();
+
+ switch (this->oper) {
+ case ast_assign: {
+ op[0] = this->subexpressions[0]->hir(instructions, state);
+ op[1] = this->subexpressions[1]->hir(instructions, state);
+
+ result = do_assignment(instructions, state, op[0], op[1],
+ this->subexpressions[0]->get_location());
+ error_emitted = result->type->is_error();
+ type = result->type;
+ break;
+ }
+
+ case ast_plus:
+ op[0] = this->subexpressions[0]->hir(instructions, state);
+
+ type = unary_arithmetic_result_type(op[0]->type, state, & loc);
+
+ error_emitted = type->is_error();
+
+ result = op[0];
+ break;
+
+ case ast_neg:
+ op[0] = this->subexpressions[0]->hir(instructions, state);
+
+ type = unary_arithmetic_result_type(op[0]->type, state, & loc);
+
+ error_emitted = type->is_error();
+
+ result = new(ctx) ir_expression(operations[this->oper], type,
+ op[0], NULL);
+ break;
+
+ case ast_add:
+ case ast_sub:
+ case ast_mul:
+ case ast_div:
+ op[0] = this->subexpressions[0]->hir(instructions, state);
+ op[1] = this->subexpressions[1]->hir(instructions, state);
+
+ type = arithmetic_result_type(op[0], op[1],
+ (this->oper == ast_mul),
+ state, & loc);
+ error_emitted = type->is_error();
+
+ result = new(ctx) ir_expression(operations[this->oper], type,
+ op[0], op[1]);
+ break;
+
+ case ast_mod:
+ op[0] = this->subexpressions[0]->hir(instructions, state);
+ op[1] = this->subexpressions[1]->hir(instructions, state);
+
+ type = modulus_result_type(op[0]->type, op[1]->type, state, & loc);
+
+ assert(operations[this->oper] == ir_binop_mod);
+
+ result = new(ctx) ir_expression(operations[this->oper], type,
+ op[0], op[1]);
+ error_emitted = type->is_error();
+ break;
+
+ case ast_lshift:
+ case ast_rshift:
+ _mesa_glsl_error(& loc, state, "FINISHME: implement bit-shift operators");
+ error_emitted = true;
+ break;
+
+ case ast_less:
+ case ast_greater:
+ case ast_lequal:
+ case ast_gequal:
+ op[0] = this->subexpressions[0]->hir(instructions, state);
+ op[1] = this->subexpressions[1]->hir(instructions, state);
+
+ type = relational_result_type(op[0], op[1], state, & loc);
+
+ /* The relational operators must either generate an error or result
+ * in a scalar boolean. See page 57 of the GLSL 1.50 spec.
+ */
+ assert(type->is_error()
+ || ((type->base_type == GLSL_TYPE_BOOL)
+ && type->is_scalar()));
+
+ result = new(ctx) ir_expression(operations[this->oper], type,
+ op[0], op[1]);
+ error_emitted = type->is_error();
+ break;
+
+ case ast_nequal:
+ case ast_equal:
+ op[0] = this->subexpressions[0]->hir(instructions, state);
+ op[1] = this->subexpressions[1]->hir(instructions, state);
+
+ /* From page 58 (page 64 of the PDF) of the GLSL 1.50 spec:
+ *
+ * "The equality operators equal (==), and not equal (!=)
+ * operate on all types. They result in a scalar Boolean. If
+ * the operand types do not match, then there must be a
+ * conversion from Section 4.1.10 "Implicit Conversions"
+ * applied to one operand that can make them match, in which
+ * case this conversion is done."
+ */
+ if ((!apply_implicit_conversion(op[0]->type, op[1], state)
+ && !apply_implicit_conversion(op[1]->type, op[0], state))
+ || (op[0]->type != op[1]->type)) {
+ _mesa_glsl_error(& loc, state, "operands of `%s' must have the same "
+ "type", (this->oper == ast_equal) ? "==" : "!=");
+ error_emitted = true;
+ } else if ((state->language_version <= 110)
+ && (op[0]->type->is_array() || op[1]->type->is_array())) {
+ _mesa_glsl_error(& loc, state, "array comparisons forbidden in "
+ "GLSL 1.10");
+ error_emitted = true;
+ }
+
+ result = new(ctx) ir_expression(operations[this->oper], glsl_type::bool_type,
+ op[0], op[1]);
+ type = glsl_type::bool_type;
+
+ assert(result->type == glsl_type::bool_type);
+ break;
+
+ case ast_bit_and:
+ case ast_bit_xor:
+ case ast_bit_or:
+ case ast_bit_not:
+ _mesa_glsl_error(& loc, state, "FINISHME: implement bit-wise operators");
+ error_emitted = true;
+ break;
+
+ case ast_logic_and: {
+ op[0] = this->subexpressions[0]->hir(instructions, state);
+
+ if (!op[0]->type->is_boolean() || !op[0]->type->is_scalar()) {
+ YYLTYPE loc = this->subexpressions[0]->get_location();
+
+ _mesa_glsl_error(& loc, state, "LHS of `%s' must be scalar boolean",
+ operator_string(this->oper));
+ error_emitted = true;
+ }
+
+ ir_constant *op0_const = op[0]->constant_expression_value();
+ if (op0_const) {
+ if (op0_const->value.b[0]) {
+ op[1] = this->subexpressions[1]->hir(instructions, state);
+
+ if (!op[1]->type->is_boolean() || !op[1]->type->is_scalar()) {
+ YYLTYPE loc = this->subexpressions[1]->get_location();
+
+ _mesa_glsl_error(& loc, state,
+ "RHS of `%s' must be scalar boolean",
+ operator_string(this->oper));
+ error_emitted = true;
+ }
+ result = op[1];
+ } else {
+ result = op0_const;
+ }
+ type = glsl_type::bool_type;
+ } else {
+ ir_variable *const tmp = new(ctx) ir_variable(glsl_type::bool_type,
+ "and_tmp",
+ ir_var_temporary);
+ instructions->push_tail(tmp);
+
+ ir_if *const stmt = new(ctx) ir_if(op[0]);
+ instructions->push_tail(stmt);
+
+ op[1] = this->subexpressions[1]->hir(&stmt->then_instructions, state);
+
+ if (!op[1]->type->is_boolean() || !op[1]->type->is_scalar()) {
+ YYLTYPE loc = this->subexpressions[1]->get_location();
+
+ _mesa_glsl_error(& loc, state,
+ "RHS of `%s' must be scalar boolean",
+ operator_string(this->oper));
+ error_emitted = true;
+ }
+
+ ir_dereference *const then_deref = new(ctx) ir_dereference_variable(tmp);
+ ir_assignment *const then_assign =
+ new(ctx) ir_assignment(then_deref, op[1], NULL);
+ stmt->then_instructions.push_tail(then_assign);
+
+ ir_dereference *const else_deref = new(ctx) ir_dereference_variable(tmp);
+ ir_assignment *const else_assign =
+ new(ctx) ir_assignment(else_deref, new(ctx) ir_constant(false), NULL);
+ stmt->else_instructions.push_tail(else_assign);
+
+ result = new(ctx) ir_dereference_variable(tmp);
+ type = tmp->type;
+ }
+ break;
+ }
+
+ case ast_logic_or: {
+ op[0] = this->subexpressions[0]->hir(instructions, state);
+
+ if (!op[0]->type->is_boolean() || !op[0]->type->is_scalar()) {
+ YYLTYPE loc = this->subexpressions[0]->get_location();
+
+ _mesa_glsl_error(& loc, state, "LHS of `%s' must be scalar boolean",
+ operator_string(this->oper));
+ error_emitted = true;
+ }
+
+ ir_constant *op0_const = op[0]->constant_expression_value();
+ if (op0_const) {
+ if (op0_const->value.b[0]) {
+ result = op0_const;
+ } else {
+ op[1] = this->subexpressions[1]->hir(instructions, state);
+
+ if (!op[1]->type->is_boolean() || !op[1]->type->is_scalar()) {
+ YYLTYPE loc = this->subexpressions[1]->get_location();
+
+ _mesa_glsl_error(& loc, state,
+ "RHS of `%s' must be scalar boolean",
+ operator_string(this->oper));
+ error_emitted = true;
+ }
+ result = op[1];
+ }
+ type = glsl_type::bool_type;
+ } else {
+ ir_variable *const tmp = new(ctx) ir_variable(glsl_type::bool_type,
+ "or_tmp",
+ ir_var_temporary);
+ instructions->push_tail(tmp);
+
+ ir_if *const stmt = new(ctx) ir_if(op[0]);
+ instructions->push_tail(stmt);
+
+ op[1] = this->subexpressions[1]->hir(&stmt->else_instructions, state);
+
+ if (!op[1]->type->is_boolean() || !op[1]->type->is_scalar()) {
+ YYLTYPE loc = this->subexpressions[1]->get_location();
+
+ _mesa_glsl_error(& loc, state, "RHS of `%s' must be scalar boolean",
+ operator_string(this->oper));
+ error_emitted = true;
+ }
+
+ ir_dereference *const then_deref = new(ctx) ir_dereference_variable(tmp);
+ ir_assignment *const then_assign =
+ new(ctx) ir_assignment(then_deref, new(ctx) ir_constant(true), NULL);
+ stmt->then_instructions.push_tail(then_assign);
+
+ ir_dereference *const else_deref = new(ctx) ir_dereference_variable(tmp);
+ ir_assignment *const else_assign =
+ new(ctx) ir_assignment(else_deref, op[1], NULL);
+ stmt->else_instructions.push_tail(else_assign);
+
+ result = new(ctx) ir_dereference_variable(tmp);
+ type = tmp->type;
+ }
+ break;
+ }
+
+ case ast_logic_xor:
+ op[0] = this->subexpressions[0]->hir(instructions, state);
+ op[1] = this->subexpressions[1]->hir(instructions, state);
+
+
+ result = new(ctx) ir_expression(operations[this->oper], glsl_type::bool_type,
+ op[0], op[1]);
+ type = glsl_type::bool_type;
+ break;
+
+ case ast_logic_not:
+ op[0] = this->subexpressions[0]->hir(instructions, state);
+
+ if (!op[0]->type->is_boolean() || !op[0]->type->is_scalar()) {
+ YYLTYPE loc = this->subexpressions[0]->get_location();
+
+ _mesa_glsl_error(& loc, state,
+ "operand of `!' must be scalar boolean");
+ error_emitted = true;
+ }
+
+ result = new(ctx) ir_expression(operations[this->oper], glsl_type::bool_type,
+ op[0], NULL);
+ type = glsl_type::bool_type;
+ break;
+
+ case ast_mul_assign:
+ case ast_div_assign:
+ case ast_add_assign:
+ case ast_sub_assign: {
+ op[0] = this->subexpressions[0]->hir(instructions, state);
+ op[1] = this->subexpressions[1]->hir(instructions, state);
+
+ type = arithmetic_result_type(op[0], op[1],
+ (this->oper == ast_mul_assign),
+ state, & loc);
+
+ ir_rvalue *temp_rhs = new(ctx) ir_expression(operations[this->oper], type,
+ op[0], op[1]);
+
+ result = do_assignment(instructions, state,
+ op[0]->clone(ctx, NULL), temp_rhs,
+ this->subexpressions[0]->get_location());
+ type = result->type;
+ error_emitted = (op[0]->type->is_error());
+
+ /* GLSL 1.10 does not allow array assignment. However, we don't have to
+ * explicitly test for this because none of the binary expression
+ * operators allow array operands either.
+ */
+
+ break;
+ }
+
+ case ast_mod_assign: {
+ op[0] = this->subexpressions[0]->hir(instructions, state);
+ op[1] = this->subexpressions[1]->hir(instructions, state);
+
+ type = modulus_result_type(op[0]->type, op[1]->type, state, & loc);
+
+ assert(operations[this->oper] == ir_binop_mod);
+
+ ir_rvalue *temp_rhs;
+ temp_rhs = new(ctx) ir_expression(operations[this->oper], type,
+ op[0], op[1]);
+
+ result = do_assignment(instructions, state,
+ op[0]->clone(ctx, NULL), temp_rhs,
+ this->subexpressions[0]->get_location());
+ type = result->type;
+ error_emitted = type->is_error();
+ break;
+ }
+
+ case ast_ls_assign:
+ case ast_rs_assign:
+ _mesa_glsl_error(& loc, state,
+ "FINISHME: implement bit-shift assignment operators");
+ error_emitted = true;
+ break;
+
+ case ast_and_assign:
+ case ast_xor_assign:
+ case ast_or_assign:
+ _mesa_glsl_error(& loc, state,
+ "FINISHME: implement logic assignment operators");
+ error_emitted = true;
+ break;
+
+ case ast_conditional: {
+ op[0] = this->subexpressions[0]->hir(instructions, state);
+
+ /* From page 59 (page 65 of the PDF) of the GLSL 1.50 spec:
+ *
+ * "The ternary selection operator (?:). It operates on three
+ * expressions (exp1 ? exp2 : exp3). This operator evaluates the
+ * first expression, which must result in a scalar Boolean."
+ */
+ if (!op[0]->type->is_boolean() || !op[0]->type->is_scalar()) {
+ YYLTYPE loc = this->subexpressions[0]->get_location();
+
+ _mesa_glsl_error(& loc, state, "?: condition must be scalar boolean");
+ error_emitted = true;
+ }
+
+ /* The :? operator is implemented by generating an anonymous temporary
+ * followed by an if-statement. The last instruction in each branch of
+ * the if-statement assigns a value to the anonymous temporary. This
+ * temporary is the r-value of the expression.
+ */
+ exec_list then_instructions;
+ exec_list else_instructions;
+
+ op[1] = this->subexpressions[1]->hir(&then_instructions, state);
+ op[2] = this->subexpressions[2]->hir(&else_instructions, state);
+
+ /* From page 59 (page 65 of the PDF) of the GLSL 1.50 spec:
+ *
+ * "The second and third expressions can be any type, as
+ * long their types match, or there is a conversion in
+ * Section 4.1.10 "Implicit Conversions" that can be applied
+ * to one of the expressions to make their types match. This
+ * resulting matching type is the type of the entire
+ * expression."
+ */
+ if ((!apply_implicit_conversion(op[1]->type, op[2], state)
+ && !apply_implicit_conversion(op[2]->type, op[1], state))
+ || (op[1]->type != op[2]->type)) {
+ YYLTYPE loc = this->subexpressions[1]->get_location();
+
+ _mesa_glsl_error(& loc, state, "Second and third operands of ?: "
+ "operator must have matching types.");
+ error_emitted = true;
+ type = glsl_type::error_type;
+ } else {
+ type = op[1]->type;
+ }
+
+ ir_constant *cond_val = op[0]->constant_expression_value();
+ ir_constant *then_val = op[1]->constant_expression_value();
+ ir_constant *else_val = op[2]->constant_expression_value();
+
+ if (then_instructions.is_empty()
+ && else_instructions.is_empty()
+ && (cond_val != NULL) && (then_val != NULL) && (else_val != NULL)) {
+ result = (cond_val->value.b[0]) ? then_val : else_val;
+ } else {
+ ir_variable *const tmp =
+ new(ctx) ir_variable(type, "conditional_tmp", ir_var_temporary);
+ instructions->push_tail(tmp);
+
+ ir_if *const stmt = new(ctx) ir_if(op[0]);
+ instructions->push_tail(stmt);
+
+ then_instructions.move_nodes_to(& stmt->then_instructions);
+ ir_dereference *const then_deref =
+ new(ctx) ir_dereference_variable(tmp);
+ ir_assignment *const then_assign =
+ new(ctx) ir_assignment(then_deref, op[1], NULL);
+ stmt->then_instructions.push_tail(then_assign);
+
+ else_instructions.move_nodes_to(& stmt->else_instructions);
+ ir_dereference *const else_deref =
+ new(ctx) ir_dereference_variable(tmp);
+ ir_assignment *const else_assign =
+ new(ctx) ir_assignment(else_deref, op[2], NULL);
+ stmt->else_instructions.push_tail(else_assign);
+
+ result = new(ctx) ir_dereference_variable(tmp);
+ }
+ break;
+ }
+
+ case ast_pre_inc:
+ case ast_pre_dec: {
+ op[0] = this->subexpressions[0]->hir(instructions, state);
+ if (op[0]->type->base_type == GLSL_TYPE_FLOAT)
+ op[1] = new(ctx) ir_constant(1.0f);
+ else
+ op[1] = new(ctx) ir_constant(1);
+
+ type = arithmetic_result_type(op[0], op[1], false, state, & loc);
+
+ ir_rvalue *temp_rhs;
+ temp_rhs = new(ctx) ir_expression(operations[this->oper], type,
+ op[0], op[1]);
+
+ result = do_assignment(instructions, state,
+ op[0]->clone(ctx, NULL), temp_rhs,
+ this->subexpressions[0]->get_location());
+ type = result->type;
+ error_emitted = op[0]->type->is_error();
+ break;
+ }
+
+ case ast_post_inc:
+ case ast_post_dec: {
+ op[0] = this->subexpressions[0]->hir(instructions, state);
+ if (op[0]->type->base_type == GLSL_TYPE_FLOAT)
+ op[1] = new(ctx) ir_constant(1.0f);
+ else
+ op[1] = new(ctx) ir_constant(1);
+
+ error_emitted = op[0]->type->is_error() || op[1]->type->is_error();
+
+ type = arithmetic_result_type(op[0], op[1], false, state, & loc);
+
+ ir_rvalue *temp_rhs;
+ temp_rhs = new(ctx) ir_expression(operations[this->oper], type,
+ op[0], op[1]);
+
+ /* Get a temporary of a copy of the lvalue before it's modified.
+ * This may get thrown away later.
+ */
+ result = get_lvalue_copy(instructions, op[0]->clone(ctx, NULL));
+
+ (void)do_assignment(instructions, state,
+ op[0]->clone(ctx, NULL), temp_rhs,
+ this->subexpressions[0]->get_location());
+
+ type = result->type;
+ error_emitted = op[0]->type->is_error();
+ break;
+ }
+
+ case ast_field_selection:
+ result = _mesa_ast_field_selection_to_hir(this, instructions, state);
+ type = result->type;
+ break;
+
+ case ast_array_index: {
+ YYLTYPE index_loc = subexpressions[1]->get_location();
+
+ op[0] = subexpressions[0]->hir(instructions, state);
+ op[1] = subexpressions[1]->hir(instructions, state);
+
+ error_emitted = op[0]->type->is_error() || op[1]->type->is_error();
+
+ ir_rvalue *const array = op[0];
+
+ result = new(ctx) ir_dereference_array(op[0], op[1]);
+
+ /* Do not use op[0] after this point. Use array.
+ */
+ op[0] = NULL;
+
+
+ if (error_emitted)
+ break;
+
+ if (!array->type->is_array()
+ && !array->type->is_matrix()
+ && !array->type->is_vector()) {
+ _mesa_glsl_error(& index_loc, state,
+ "cannot dereference non-array / non-matrix / "
+ "non-vector");
+ error_emitted = true;
+ }
+
+ if (!op[1]->type->is_integer()) {
+ _mesa_glsl_error(& index_loc, state,
+ "array index must be integer type");
+ error_emitted = true;
+ } else if (!op[1]->type->is_scalar()) {
+ _mesa_glsl_error(& index_loc, state,
+ "array index must be scalar");
+ error_emitted = true;
+ }
+
+ /* If the array index is a constant expression and the array has a
+ * declared size, ensure that the access is in-bounds. If the array
+ * index is not a constant expression, ensure that the array has a
+ * declared size.
+ */
+ ir_constant *const const_index = op[1]->constant_expression_value();
+ if (const_index != NULL) {
+ const int idx = const_index->value.i[0];
+ const char *type_name;
+ unsigned bound = 0;
+
+ if (array->type->is_matrix()) {
+ type_name = "matrix";
+ } else if (array->type->is_vector()) {
+ type_name = "vector";
+ } else {
+ type_name = "array";
+ }
+
+ /* From page 24 (page 30 of the PDF) of the GLSL 1.50 spec:
+ *
+ * "It is illegal to declare an array with a size, and then
+ * later (in the same shader) index the same array with an
+ * integral constant expression greater than or equal to the
+ * declared size. It is also illegal to index an array with a
+ * negative constant expression."
+ */
+ if (array->type->is_matrix()) {
+ if (array->type->row_type()->vector_elements <= idx) {
+ bound = array->type->row_type()->vector_elements;
+ }
+ } else if (array->type->is_vector()) {
+ if (array->type->vector_elements <= idx) {
+ bound = array->type->vector_elements;
+ }
+ } else {
+ if ((array->type->array_size() > 0)
+ && (array->type->array_size() <= idx)) {
+ bound = array->type->array_size();
+ }
+ }
+
+ if (bound > 0) {
+ _mesa_glsl_error(& loc, state, "%s index must be < %u",
+ type_name, bound);
+ error_emitted = true;
+ } else if (idx < 0) {
+ _mesa_glsl_error(& loc, state, "%s index must be >= 0",
+ type_name);
+ error_emitted = true;
+ }
+
+ if (array->type->is_array()) {
+ /* If the array is a variable dereference, it dereferences the
+ * whole array, by definition. Use this to get the variable.
+ *
+ * FINISHME: Should some methods for getting / setting / testing
+ * FINISHME: array access limits be added to ir_dereference?
+ */
+ ir_variable *const v = array->whole_variable_referenced();
+ if ((v != NULL) && (unsigned(idx) > v->max_array_access))
+ v->max_array_access = idx;
+ }
+ } else if (array->type->array_size() == 0) {
+ _mesa_glsl_error(&loc, state, "unsized array index must be constant");
+ }
+
+ if (error_emitted)
+ result->type = glsl_type::error_type;
+
+ type = result->type;
+ break;
+ }
+
+ case ast_function_call:
+ /* Should *NEVER* get here. ast_function_call should always be handled
+ * by ast_function_expression::hir.
+ */
+ assert(0);
+ break;
+
+ case ast_identifier: {
+ /* ast_identifier can appear several places in a full abstract syntax
+ * tree. This particular use must be at location specified in the grammar
+ * as 'variable_identifier'.
+ */
+ ir_variable *var =
+ state->symbols->get_variable(this->primary_expression.identifier);
+
+ result = new(ctx) ir_dereference_variable(var);
+
+ if (var != NULL) {
+ type = result->type;
+ } else {
+ _mesa_glsl_error(& loc, state, "`%s' undeclared",
+ this->primary_expression.identifier);
+
+ error_emitted = true;
+ }
+ break;
+ }
+
+ case ast_int_constant:
+ type = glsl_type::int_type;
+ result = new(ctx) ir_constant(this->primary_expression.int_constant);
+ break;
+
+ case ast_uint_constant:
+ type = glsl_type::uint_type;
+ result = new(ctx) ir_constant(this->primary_expression.uint_constant);
+ break;
+
+ case ast_float_constant:
+ type = glsl_type::float_type;
+ result = new(ctx) ir_constant(this->primary_expression.float_constant);
+ break;
+
+ case ast_bool_constant:
+ type = glsl_type::bool_type;
+ result = new(ctx) ir_constant(bool(this->primary_expression.bool_constant));
+ break;
+
+ case ast_sequence: {
+ /* It should not be possible to generate a sequence in the AST without
+ * any expressions in it.
+ */
+ assert(!this->expressions.is_empty());
+
+ /* The r-value of a sequence is the last expression in the sequence. If
+ * the other expressions in the sequence do not have side-effects (and
+ * therefore add instructions to the instruction list), they get dropped
+ * on the floor.
+ */
+ foreach_list_typed (ast_node, ast, link, &this->expressions)
+ result = ast->hir(instructions, state);
+
+ type = result->type;
+
+ /* Any errors should have already been emitted in the loop above.
+ */
+ error_emitted = true;
+ break;
+ }
+ }
+
+ if (type->is_error() && !error_emitted)
+ _mesa_glsl_error(& loc, state, "type mismatch");
+
+ return result;
+}
+
+
+ir_rvalue *
+ast_expression_statement::hir(exec_list *instructions,
+ struct _mesa_glsl_parse_state *state)
+{
+ /* It is possible to have expression statements that don't have an
+ * expression. This is the solitary semicolon:
+ *
+ * for (i = 0; i < 5; i++)
+ * ;
+ *
+ * In this case the expression will be NULL. Test for NULL and don't do
+ * anything in that case.
+ */
+ if (expression != NULL)
+ expression->hir(instructions, state);
+
+ /* Statements do not have r-values.
+ */
+ return NULL;
+}
+
+
+ir_rvalue *
+ast_compound_statement::hir(exec_list *instructions,
+ struct _mesa_glsl_parse_state *state)
+{
+ if (new_scope)
+ state->symbols->push_scope();
+
+ foreach_list_typed (ast_node, ast, link, &this->statements)
+ ast->hir(instructions, state);
+
+ if (new_scope)
+ state->symbols->pop_scope();
+
+ /* Compound statements do not have r-values.
+ */
+ return NULL;
+}
+
+
+static const glsl_type *
+process_array_type(const glsl_type *base, ast_node *array_size,
+ struct _mesa_glsl_parse_state *state)
+{
+ unsigned length = 0;
+
+ /* FINISHME: Reject delcarations of multidimensional arrays. */
+
+ if (array_size != NULL) {
+ exec_list dummy_instructions;
+ ir_rvalue *const ir = array_size->hir(& dummy_instructions, state);
+ YYLTYPE loc = array_size->get_location();
+
+ /* FINISHME: Verify that the grammar forbids side-effects in array
+ * FINISHME: sizes. i.e., 'vec4 [x = 12] data'
+ */
+ assert(dummy_instructions.is_empty());
+
+ if (ir != NULL) {
+ if (!ir->type->is_integer()) {
+ _mesa_glsl_error(& loc, state, "array size must be integer type");
+ } else if (!ir->type->is_scalar()) {
+ _mesa_glsl_error(& loc, state, "array size must be scalar type");
+ } else {
+ ir_constant *const size = ir->constant_expression_value();
+
+ if (size == NULL) {
+ _mesa_glsl_error(& loc, state, "array size must be a "
+ "constant valued expression");
+ } else if (size->value.i[0] <= 0) {
+ _mesa_glsl_error(& loc, state, "array size must be > 0");
+ } else {
+ assert(size->type == ir->type);
+ length = size->value.u[0];
+ }
+ }
+ }
+ }
+
+ return glsl_type::get_array_instance(base, length);
+}
+
+
+const glsl_type *
+ast_type_specifier::glsl_type(const char **name,
+ struct _mesa_glsl_parse_state *state) const
+{
+ const struct glsl_type *type;
+
+ if ((this->type_specifier == ast_struct) && (this->type_name == NULL)) {
+ /* FINISHME: Handle annonymous structures. */
+ type = NULL;
+ } else {
+ type = state->symbols->get_type(this->type_name);
+ *name = this->type_name;
+
+ if (this->is_array) {
+ type = process_array_type(type, this->array_size, state);
+ }
+ }
+
+ return type;
+}
+
+
+static void
+apply_type_qualifier_to_variable(const struct ast_type_qualifier *qual,
+ ir_variable *var,
+ struct _mesa_glsl_parse_state *state,
+ YYLTYPE *loc)
+{
+ if (qual->invariant)
+ var->invariant = 1;
+
+ /* FINISHME: Mark 'in' variables at global scope as read-only. */
+ if (qual->constant || qual->attribute || qual->uniform
+ || (qual->varying && (state->target == fragment_shader)))
+ var->read_only = 1;
+
+ if (qual->centroid)
+ var->centroid = 1;
+
+ if (qual->attribute && state->target != vertex_shader) {
+ var->type = glsl_type::error_type;
+ _mesa_glsl_error(loc, state,
+ "`attribute' variables may not be declared in the "
+ "%s shader",
+ _mesa_glsl_shader_target_name(state->target));
+ }
+
+ /* From page 25 (page 31 of the PDF) of the GLSL 1.10 spec:
+ *
+ * "The varying qualifier can be used only with the data types
+ * float, vec2, vec3, vec4, mat2, mat3, and mat4, or arrays of
+ * these."
+ */
+ if (qual->varying) {
+ const glsl_type *non_array_type;
+
+ if (var->type && var->type->is_array())
+ non_array_type = var->type->fields.array;
+ else
+ non_array_type = var->type;
+
+ if (non_array_type && non_array_type->base_type != GLSL_TYPE_FLOAT) {
+ var->type = glsl_type::error_type;
+ _mesa_glsl_error(loc, state,
+ "varying variables must be of base type float");
+ }
+ }
+
+ /* If there is no qualifier that changes the mode of the variable, leave
+ * the setting alone.
+ */
+ if (qual->in && qual->out)
+ var->mode = ir_var_inout;
+ else if (qual->attribute || qual->in
+ || (qual->varying && (state->target == fragment_shader)))
+ var->mode = ir_var_in;
+ else if (qual->out || (qual->varying && (state->target == vertex_shader)))
+ var->mode = ir_var_out;
+ else if (qual->uniform)
+ var->mode = ir_var_uniform;
+
+ if (qual->flat)
+ var->interpolation = ir_var_flat;
+ else if (qual->noperspective)
+ var->interpolation = ir_var_noperspective;
+ else
+ var->interpolation = ir_var_smooth;
+
+ var->pixel_center_integer = qual->pixel_center_integer;
+ var->origin_upper_left = qual->origin_upper_left;
+ if ((qual->origin_upper_left || qual->pixel_center_integer)
+ && (strcmp(var->name, "gl_FragCoord") != 0)) {
+ const char *const qual_string = (qual->origin_upper_left)
+ ? "origin_upper_left" : "pixel_center_integer";
+
+ _mesa_glsl_error(loc, state,
+ "layout qualifier `%s' can only be applied to "
+ "fragment shader input `gl_FragCoord'",
+ qual_string);
+ }
+
+ if (var->type->is_array() && (state->language_version >= 120)) {
+ var->array_lvalue = true;
+ }
+}
+
+
+ir_rvalue *
+ast_declarator_list::hir(exec_list *instructions,
+ struct _mesa_glsl_parse_state *state)
+{
+ void *ctx = state;
+ const struct glsl_type *decl_type;
+ const char *type_name = NULL;
+ ir_rvalue *result = NULL;
+ YYLTYPE loc = this->get_location();
+
+ /* From page 46 (page 52 of the PDF) of the GLSL 1.50 spec:
+ *
+ * "To ensure that a particular output variable is invariant, it is
+ * necessary to use the invariant qualifier. It can either be used to
+ * qualify a previously declared variable as being invariant
+ *
+ * invariant gl_Position; // make existing gl_Position be invariant"
+ *
+ * In these cases the parser will set the 'invariant' flag in the declarator
+ * list, and the type will be NULL.
+ */
+ if (this->invariant) {
+ assert(this->type == NULL);
+
+ if (state->current_function != NULL) {
+ _mesa_glsl_error(& loc, state,
+ "All uses of `invariant' keyword must be at global "
+ "scope\n");
+ }
+
+ foreach_list_typed (ast_declaration, decl, link, &this->declarations) {
+ assert(!decl->is_array);
+ assert(decl->array_size == NULL);
+ assert(decl->initializer == NULL);
+
+ ir_variable *const earlier =
+ state->symbols->get_variable(decl->identifier);
+ if (earlier == NULL) {
+ _mesa_glsl_error(& loc, state,
+ "Undeclared variable `%s' cannot be marked "
+ "invariant\n", decl->identifier);
+ } else if ((state->target == vertex_shader)
+ && (earlier->mode != ir_var_out)) {
+ _mesa_glsl_error(& loc, state,
+ "`%s' cannot be marked invariant, vertex shader "
+ "outputs only\n", decl->identifier);
+ } else if ((state->target == fragment_shader)
+ && (earlier->mode != ir_var_in)) {
+ _mesa_glsl_error(& loc, state,
+ "`%s' cannot be marked invariant, fragment shader "
+ "inputs only\n", decl->identifier);
+ } else {
+ earlier->invariant = true;
+ }
+ }
+
+ /* Invariant redeclarations do not have r-values.
+ */
+ return NULL;
+ }
+
+ assert(this->type != NULL);
+ assert(!this->invariant);
+
+ /* The type specifier may contain a structure definition. Process that
+ * before any of the variable declarations.
+ */
+ (void) this->type->specifier->hir(instructions, state);
+
+ decl_type = this->type->specifier->glsl_type(& type_name, state);
+ if (this->declarations.is_empty()) {
+ /* The only valid case where the declaration list can be empty is when
+ * the declaration is setting the default precision of a built-in type
+ * (e.g., 'precision highp vec4;').
+ */
+
+ if (decl_type != NULL) {
+ } else {
+ _mesa_glsl_error(& loc, state, "incomplete declaration");
+ }
+ }
+
+ foreach_list_typed (ast_declaration, decl, link, &this->declarations) {
+ const struct glsl_type *var_type;
+ ir_variable *var;
+
+ /* FINISHME: Emit a warning if a variable declaration shadows a
+ * FINISHME: declaration at a higher scope.
+ */
+
+ if ((decl_type == NULL) || decl_type->is_void()) {
+ if (type_name != NULL) {
+ _mesa_glsl_error(& loc, state,
+ "invalid type `%s' in declaration of `%s'",
+ type_name, decl->identifier);
+ } else {
+ _mesa_glsl_error(& loc, state,
+ "invalid type in declaration of `%s'",
+ decl->identifier);
+ }
+ continue;
+ }
+
+ if (decl->is_array) {
+ var_type = process_array_type(decl_type, decl->array_size, state);
+ } else {
+ var_type = decl_type;
+ }
+
+ var = new(ctx) ir_variable(var_type, decl->identifier, ir_var_auto);
+
+ /* From page 22 (page 28 of the PDF) of the GLSL 1.10 specification;
+ *
+ * "Global variables can only use the qualifiers const,
+ * attribute, uni form, or varying. Only one may be
+ * specified.
+ *
+ * Local variables can only use the qualifier const."
+ *
+ * This is relaxed in GLSL 1.30.
+ */
+ if (state->language_version < 120) {
+ if (this->type->qualifier.out) {
+ _mesa_glsl_error(& loc, state,
+ "`out' qualifier in declaration of `%s' "
+ "only valid for function parameters in GLSL 1.10.",
+ decl->identifier);
+ }
+ if (this->type->qualifier.in) {
+ _mesa_glsl_error(& loc, state,
+ "`in' qualifier in declaration of `%s' "
+ "only valid for function parameters in GLSL 1.10.",
+ decl->identifier);
+ }
+ /* FINISHME: Test for other invalid qualifiers. */
+ }
+
+ apply_type_qualifier_to_variable(& this->type->qualifier, var, state,
+ & loc);
+
+ if (this->type->qualifier.invariant) {
+ if ((state->target == vertex_shader) && !(var->mode == ir_var_out ||
+ var->mode == ir_var_inout)) {
+ /* FINISHME: Note that this doesn't work for invariant on
+ * a function signature outval
+ */
+ _mesa_glsl_error(& loc, state,
+ "`%s' cannot be marked invariant, vertex shader "
+ "outputs only\n", var->name);
+ } else if ((state->target == fragment_shader) &&
+ !(var->mode == ir_var_in || var->mode == ir_var_inout)) {
+ /* FINISHME: Note that this doesn't work for invariant on
+ * a function signature inval
+ */
+ _mesa_glsl_error(& loc, state,
+ "`%s' cannot be marked invariant, fragment shader "
+ "inputs only\n", var->name);
+ }
+ }
+
+ if (state->current_function != NULL) {
+ const char *mode = NULL;
+ const char *extra = "";
+
+ /* There is no need to check for 'inout' here because the parser will
+ * only allow that in function parameter lists.
+ */
+ if (this->type->qualifier.attribute) {
+ mode = "attribute";
+ } else if (this->type->qualifier.uniform) {
+ mode = "uniform";
+ } else if (this->type->qualifier.varying) {
+ mode = "varying";
+ } else if (this->type->qualifier.in) {
+ mode = "in";
+ extra = " or in function parameter list";
+ } else if (this->type->qualifier.out) {
+ mode = "out";
+ extra = " or in function parameter list";
+ }
+
+ if (mode) {
+ _mesa_glsl_error(& loc, state,
+ "%s variable `%s' must be declared at "
+ "global scope%s",
+ mode, var->name, extra);
+ }
+ } else if (var->mode == ir_var_in) {
+ if (state->target == vertex_shader) {
+ bool error_emitted = false;
+
+ /* From page 31 (page 37 of the PDF) of the GLSL 1.50 spec:
+ *
+ * "Vertex shader inputs can only be float, floating-point
+ * vectors, matrices, signed and unsigned integers and integer
+ * vectors. Vertex shader inputs can also form arrays of these
+ * types, but not structures."
+ *
+ * From page 31 (page 27 of the PDF) of the GLSL 1.30 spec:
+ *
+ * "Vertex shader inputs can only be float, floating-point
+ * vectors, matrices, signed and unsigned integers and integer
+ * vectors. They cannot be arrays or structures."
+ *
+ * From page 23 (page 29 of the PDF) of the GLSL 1.20 spec:
+ *
+ * "The attribute qualifier can be used only with float,
+ * floating-point vectors, and matrices. Attribute variables
+ * cannot be declared as arrays or structures."
+ */
+ const glsl_type *check_type = var->type->is_array()
+ ? var->type->fields.array : var->type;
+
+ switch (check_type->base_type) {
+ case GLSL_TYPE_FLOAT:
+ break;
+ case GLSL_TYPE_UINT:
+ case GLSL_TYPE_INT:
+ if (state->language_version > 120)
+ break;
+ /* FALLTHROUGH */
+ default:
+ _mesa_glsl_error(& loc, state,
+ "vertex shader input / attribute cannot have "
+ "type %s`%s'",
+ var->type->is_array() ? "array of " : "",
+ check_type->name);
+ error_emitted = true;
+ }
+
+ if (!error_emitted && (state->language_version <= 130)
+ && var->type->is_array()) {
+ _mesa_glsl_error(& loc, state,
+ "vertex shader input / attribute cannot have "
+ "array type");
+ error_emitted = true;
+ }
+ }
+ }
+
+ /* Process the initializer and add its instructions to a temporary
+ * list. This list will be added to the instruction stream (below) after
+ * the declaration is added. This is done because in some cases (such as
+ * redeclarations) the declaration may not actually be added to the
+ * instruction stream.
+ */
+ exec_list initializer_instructions;
+ if (decl->initializer != NULL) {
+ YYLTYPE initializer_loc = decl->initializer->get_location();
+
+ /* From page 24 (page 30 of the PDF) of the GLSL 1.10 spec:
+ *
+ * "All uniform variables are read-only and are initialized either
+ * directly by an application via API commands, or indirectly by
+ * OpenGL."
+ */
+ if ((state->language_version <= 110)
+ && (var->mode == ir_var_uniform)) {
+ _mesa_glsl_error(& initializer_loc, state,
+ "cannot initialize uniforms in GLSL 1.10");
+ }
+
+ if (var->type->is_sampler()) {
+ _mesa_glsl_error(& initializer_loc, state,
+ "cannot initialize samplers");
+ }
+
+ if ((var->mode == ir_var_in) && (state->current_function == NULL)) {
+ _mesa_glsl_error(& initializer_loc, state,
+ "cannot initialize %s shader input / %s",
+ _mesa_glsl_shader_target_name(state->target),
+ (state->target == vertex_shader)
+ ? "attribute" : "varying");
+ }
+
+ ir_dereference *const lhs = new(ctx) ir_dereference_variable(var);
+ ir_rvalue *rhs = decl->initializer->hir(&initializer_instructions,
+ state);
+
+ /* Calculate the constant value if this is a const or uniform
+ * declaration.
+ */
+ if (this->type->qualifier.constant || this->type->qualifier.uniform) {
+ ir_rvalue *new_rhs = validate_assignment(state, var->type, rhs);
+ if (new_rhs != NULL) {
+ rhs = new_rhs;
+ } else {
+ _mesa_glsl_error(&initializer_loc, state,
+ "initializer of type %s cannot be assigned to "
+ "variable of type %s",
+ rhs->type->name, var->type->name);
+ }
+
+ ir_constant *constant_value = rhs->constant_expression_value();
+ if (!constant_value) {
+ _mesa_glsl_error(& initializer_loc, state,
+ "initializer of %s variable `%s' must be a "
+ "constant expression",
+ (this->type->qualifier.constant)
+ ? "const" : "uniform",
+ decl->identifier);
+ } else {
+ rhs = constant_value;
+ var->constant_value = constant_value;
+ }
+ }
+
+ if (rhs && !rhs->type->is_error()) {
+ bool temp = var->read_only;
+ if (this->type->qualifier.constant)
+ var->read_only = false;
+
+ /* Never emit code to initialize a uniform.
+ */
+ if (!this->type->qualifier.uniform)
+ result = do_assignment(&initializer_instructions, state,
+ lhs, rhs,
+ this->get_location());
+ var->read_only = temp;
+ }
+ }
+
+ /* From page 23 (page 29 of the PDF) of the GLSL 1.10 spec:
+ *
+ * "It is an error to write to a const variable outside of
+ * its declaration, so they must be initialized when
+ * declared."
+ */
+ if (this->type->qualifier.constant && decl->initializer == NULL) {
+ _mesa_glsl_error(& loc, state,
+ "const declaration of `%s' must be initialized");
+ }
+
+ /* Attempt to add the variable to the symbol table. If this fails, it
+ * means the variable has already been declared at this scope. Arrays
+ * fudge this rule a little bit.
+ *
+ * From page 24 (page 30 of the PDF) of the GLSL 1.50 spec,
+ *
+ * "It is legal to declare an array without a size and then
+ * later re-declare the same name as an array of the same
+ * type and specify a size."
+ */
+ if (state->symbols->name_declared_this_scope(decl->identifier)) {
+ ir_variable *const earlier =
+ state->symbols->get_variable(decl->identifier);
+
+ if ((earlier != NULL)
+ && (earlier->type->array_size() == 0)
+ && var->type->is_array()
+ && (var->type->element_type() == earlier->type->element_type())) {
+ /* FINISHME: This doesn't match the qualifiers on the two
+ * FINISHME: declarations. It's not 100% clear whether this is
+ * FINISHME: required or not.
+ */
+
+ /* From page 54 (page 60 of the PDF) of the GLSL 1.20 spec:
+ *
+ * "The size [of gl_TexCoord] can be at most
+ * gl_MaxTextureCoords."
+ */
+ const unsigned size = unsigned(var->type->array_size());
+ if ((strcmp("gl_TexCoord", var->name) == 0)
+ && (size > state->Const.MaxTextureCoords)) {
+ YYLTYPE loc = this->get_location();
+
+ _mesa_glsl_error(& loc, state, "`gl_TexCoord' array size cannot "
+ "be larger than gl_MaxTextureCoords (%u)\n",
+ state->Const.MaxTextureCoords);
+ } else if ((size > 0) && (size <= earlier->max_array_access)) {
+ YYLTYPE loc = this->get_location();
+
+ _mesa_glsl_error(& loc, state, "array size must be > %u due to "
+ "previous access",
+ earlier->max_array_access);
+ }
+
+ earlier->type = var->type;
+ delete var;
+ var = NULL;
+ } else if (state->extensions->ARB_fragment_coord_conventions &&
+ (earlier != NULL) &&
+ (strcmp(var->name, "gl_FragCoord") == 0) &&
+ earlier->type == var->type &&
+ earlier->mode == var->mode) {
+ /* Allow redeclaration of gl_FragCoord for ARB_fcc layout
+ * qualifiers.
+ */
+ earlier->origin_upper_left = var->origin_upper_left;
+ earlier->pixel_center_integer = var->pixel_center_integer;
+ } else {
+ YYLTYPE loc = this->get_location();
+
+ _mesa_glsl_error(& loc, state, "`%s' redeclared",
+ decl->identifier);
+ }
+
+ continue;
+ }
+
+ /* From page 15 (page 21 of the PDF) of the GLSL 1.10 spec,
+ *
+ * "Identifiers starting with "gl_" are reserved for use by
+ * OpenGL, and may not be declared in a shader as either a
+ * variable or a function."
+ */
+ if (strncmp(decl->identifier, "gl_", 3) == 0) {
+ /* FINISHME: This should only trigger if we're not redefining
+ * FINISHME: a builtin (to add a qualifier, for example).
+ */
+ _mesa_glsl_error(& loc, state,
+ "identifier `%s' uses reserved `gl_' prefix",
+ decl->identifier);
+ }
+
+ /* Push the variable declaration to the top. It means that all
+ * the variable declarations will appear in a funny
+ * last-to-first order, but otherwise we run into trouble if a
+ * function is prototyped, a global var is decled, then the
+ * function is defined with usage of the global var. See
+ * glslparsertest's CorrectModule.frag.
+ */
+ instructions->push_head(var);
+ instructions->append_list(&initializer_instructions);
+
+ /* Add the variable to the symbol table after processing the initializer.
+ * This differs from most C-like languages, but it follows the GLSL
+ * specification. From page 28 (page 34 of the PDF) of the GLSL 1.50
+ * spec:
+ *
+ * "Within a declaration, the scope of a name starts immediately
+ * after the initializer if present or immediately after the name
+ * being declared if not."
+ */
+ const bool added_variable =
+ state->symbols->add_variable(var->name, var);
+ assert(added_variable);
+ }
+
+
+ /* Generally, variable declarations do not have r-values. However,
+ * one is used for the declaration in
+ *
+ * while (bool b = some_condition()) {
+ * ...
+ * }
+ *
+ * so we return the rvalue from the last seen declaration here.
+ */
+ return result;
+}
+
+
+ir_rvalue *
+ast_parameter_declarator::hir(exec_list *instructions,
+ struct _mesa_glsl_parse_state *state)
+{
+ void *ctx = state;
+ const struct glsl_type *type;
+ const char *name = NULL;
+ YYLTYPE loc = this->get_location();
+
+ type = this->type->specifier->glsl_type(& name, state);
+
+ if (type == NULL) {
+ if (name != NULL) {
+ _mesa_glsl_error(& loc, state,
+ "invalid type `%s' in declaration of `%s'",
+ name, this->identifier);
+ } else {
+ _mesa_glsl_error(& loc, state,
+ "invalid type in declaration of `%s'",
+ this->identifier);
+ }
+
+ type = glsl_type::error_type;
+ }
+
+ /* From page 62 (page 68 of the PDF) of the GLSL 1.50 spec:
+ *
+ * "Functions that accept no input arguments need not use void in the
+ * argument list because prototypes (or definitions) are required and
+ * therefore there is no ambiguity when an empty argument list "( )" is
+ * declared. The idiom "(void)" as a parameter list is provided for
+ * convenience."
+ *
+ * Placing this check here prevents a void parameter being set up
+ * for a function, which avoids tripping up checks for main taking
+ * parameters and lookups of an unnamed symbol.
+ */
+ if (type->is_void()) {
+ if (this->identifier != NULL)
+ _mesa_glsl_error(& loc, state,
+ "named parameter cannot have type `void'");
+
+ is_void = true;
+ return NULL;
+ }
+
+ if (formal_parameter && (this->identifier == NULL)) {
+ _mesa_glsl_error(& loc, state, "formal parameter lacks a name");
+ return NULL;
+ }
+
+ is_void = false;
+ ir_variable *var = new(ctx) ir_variable(type, this->identifier, ir_var_in);
+
+ /* FINISHME: Handle array declarations. Note that this requires
+ * FINISHME: complete handling of constant expressions.
+ */
+
+ /* Apply any specified qualifiers to the parameter declaration. Note that
+ * for function parameters the default mode is 'in'.
+ */
+ apply_type_qualifier_to_variable(& this->type->qualifier, var, state, & loc);
+
+ instructions->push_tail(var);
+
+ /* Parameter declarations do not have r-values.
+ */
+ return NULL;
+}
+
+
+void
+ast_parameter_declarator::parameters_to_hir(exec_list *ast_parameters,
+ bool formal,
+ exec_list *ir_parameters,
+ _mesa_glsl_parse_state *state)
+{
+ ast_parameter_declarator *void_param = NULL;
+ unsigned count = 0;
+
+ foreach_list_typed (ast_parameter_declarator, param, link, ast_parameters) {
+ param->formal_parameter = formal;
+ param->hir(ir_parameters, state);
+
+ if (param->is_void)
+ void_param = param;
+
+ count++;
+ }
+
+ if ((void_param != NULL) && (count > 1)) {
+ YYLTYPE loc = void_param->get_location();
+
+ _mesa_glsl_error(& loc, state,
+ "`void' parameter must be only parameter");
+ }
+}
+
+
+ir_rvalue *
+ast_function::hir(exec_list *instructions,
+ struct _mesa_glsl_parse_state *state)
+{
+ void *ctx = state;
+ ir_function *f = NULL;
+ ir_function_signature *sig = NULL;
+ exec_list hir_parameters;
+
+ const char *const name = identifier;
+
+ /* Convert the list of function parameters to HIR now so that they can be
+ * used below to compare this function's signature with previously seen
+ * signatures for functions with the same name.
+ */
+ ast_parameter_declarator::parameters_to_hir(& this->parameters,
+ is_definition,
+ & hir_parameters, state);
+
+ const char *return_type_name;
+ const glsl_type *return_type =
+ this->return_type->specifier->glsl_type(& return_type_name, state);
+
+ assert(return_type != NULL);
+
+ /* From page 56 (page 62 of the PDF) of the GLSL 1.30 spec:
+ * "No qualifier is allowed on the return type of a function."
+ */
+ if (this->return_type->has_qualifiers()) {
+ YYLTYPE loc = this->get_location();
+ _mesa_glsl_error(& loc, state,
+ "function `%s' return type has qualifiers", name);
+ }
+
+ /* Verify that this function's signature either doesn't match a previously
+ * seen signature for a function with the same name, or, if a match is found,
+ * that the previously seen signature does not have an associated definition.
+ */
+ f = state->symbols->get_function(name);
+ if (f != NULL) {
+ sig = f->exact_matching_signature(&hir_parameters);
+ if (sig != NULL) {
+ const char *badvar = sig->qualifiers_match(&hir_parameters);
+ if (badvar != NULL) {
+ YYLTYPE loc = this->get_location();
+
+ _mesa_glsl_error(&loc, state, "function `%s' parameter `%s' "
+ "qualifiers don't match prototype", name, badvar);
+ }
+
+ if (sig->return_type != return_type) {
+ YYLTYPE loc = this->get_location();
+
+ _mesa_glsl_error(&loc, state, "function `%s' return type doesn't "
+ "match prototype", name);
+ }
+
+ if (is_definition && sig->is_defined) {
+ YYLTYPE loc = this->get_location();
+
+ _mesa_glsl_error(& loc, state, "function `%s' redefined", name);
+ sig = NULL;
+ }
+ }
+ } else if (state->symbols->name_declared_this_scope(name)) {
+ /* This function name shadows a non-function use of the same name.
+ */
+ YYLTYPE loc = this->get_location();
+
+ _mesa_glsl_error(& loc, state, "function name `%s' conflicts with "
+ "non-function", name);
+ sig = NULL;
+ } else {
+ f = new(ctx) ir_function(name);
+ state->symbols->add_function(f->name, f);
+
+ /* Emit the new function header */
+ instructions->push_tail(f);
+ }
+
+ /* Verify the return type of main() */
+ if (strcmp(name, "main") == 0) {
+ if (! return_type->is_void()) {
+ YYLTYPE loc = this->get_location();
+
+ _mesa_glsl_error(& loc, state, "main() must return void");
+ }
+
+ if (!hir_parameters.is_empty()) {
+ YYLTYPE loc = this->get_location();
+
+ _mesa_glsl_error(& loc, state, "main() must not take any parameters");
+ }
+ }
+
+ /* Finish storing the information about this new function in its signature.
+ */
+ if (sig == NULL) {
+ sig = new(ctx) ir_function_signature(return_type);
+ f->add_signature(sig);
+ }
+
+ sig->replace_parameters(&hir_parameters);
+ signature = sig;
+
+ /* Function declarations (prototypes) do not have r-values.
+ */
+ return NULL;
+}
+
+
+ir_rvalue *
+ast_function_definition::hir(exec_list *instructions,
+ struct _mesa_glsl_parse_state *state)
+{
+ prototype->is_definition = true;
+ prototype->hir(instructions, state);
+
+ ir_function_signature *signature = prototype->signature;
+
+ assert(state->current_function == NULL);
+ state->current_function = signature;
+ state->found_return = false;
+
+ /* Duplicate parameters declared in the prototype as concrete variables.
+ * Add these to the symbol table.
+ */
+ state->symbols->push_scope();
+ foreach_iter(exec_list_iterator, iter, signature->parameters) {
+ ir_variable *const var = ((ir_instruction *) iter.get())->as_variable();
+
+ assert(var != NULL);
+
+ /* The only way a parameter would "exist" is if two parameters have
+ * the same name.
+ */
+ if (state->symbols->name_declared_this_scope(var->name)) {
+ YYLTYPE loc = this->get_location();
+
+ _mesa_glsl_error(& loc, state, "parameter `%s' redeclared", var->name);
+ } else {
+ state->symbols->add_variable(var->name, var);
+ }
+ }
+
+ /* Convert the body of the function to HIR. */
+ this->body->hir(&signature->body, state);
+ signature->is_defined = true;
+
+ state->symbols->pop_scope();
+
+ assert(state->current_function == signature);
+ state->current_function = NULL;
+
+ if (!signature->return_type->is_void() && !state->found_return) {
+ YYLTYPE loc = this->get_location();
+ _mesa_glsl_error(& loc, state, "function `%s' has non-void return type "
+ "%s, but no return statement",
+ signature->function_name(),
+ signature->return_type->name);
+ }
+
+ /* Function definitions do not have r-values.
+ */
+ return NULL;
+}
+
+
+ir_rvalue *
+ast_jump_statement::hir(exec_list *instructions,
+ struct _mesa_glsl_parse_state *state)
+{
+ void *ctx = state;
+
+ switch (mode) {
+ case ast_return: {
+ ir_return *inst;
+ assert(state->current_function);
+
+ if (opt_return_value) {
+ if (state->current_function->return_type->base_type ==
+ GLSL_TYPE_VOID) {
+ YYLTYPE loc = this->get_location();
+
+ _mesa_glsl_error(& loc, state,
+ "`return` with a value, in function `%s' "
+ "returning void",
+ state->current_function->function_name());
+ }
+
+ ir_expression *const ret = (ir_expression *)
+ opt_return_value->hir(instructions, state);
+ assert(ret != NULL);
+
+ /* Implicit conversions are not allowed for return values. */
+ if (state->current_function->return_type != ret->type) {
+ YYLTYPE loc = this->get_location();
+
+ _mesa_glsl_error(& loc, state,
+ "`return' with wrong type %s, in function `%s' "
+ "returning %s",
+ ret->type->name,
+ state->current_function->function_name(),
+ state->current_function->return_type->name);
+ }
+
+ inst = new(ctx) ir_return(ret);
+ } else {
+ if (state->current_function->return_type->base_type !=
+ GLSL_TYPE_VOID) {
+ YYLTYPE loc = this->get_location();
+
+ _mesa_glsl_error(& loc, state,
+ "`return' with no value, in function %s returning "
+ "non-void",
+ state->current_function->function_name());
+ }
+ inst = new(ctx) ir_return;
+ }
+
+ state->found_return = true;
+ instructions->push_tail(inst);
+ break;
+ }
+
+ case ast_discard:
+ if (state->target != fragment_shader) {
+ YYLTYPE loc = this->get_location();
+
+ _mesa_glsl_error(& loc, state,
+ "`discard' may only appear in a fragment shader");
+ }
+ instructions->push_tail(new(ctx) ir_discard);
+ break;
+
+ case ast_break:
+ case ast_continue:
+ /* FINISHME: Handle switch-statements. They cannot contain 'continue',
+ * FINISHME: and they use a different IR instruction for 'break'.
+ */
+ /* FINISHME: Correctly handle the nesting. If a switch-statement is
+ * FINISHME: inside a loop, a 'continue' is valid and will bind to the
+ * FINISHME: loop.
+ */
+ if (state->loop_or_switch_nesting == NULL) {
+ YYLTYPE loc = this->get_location();
+
+ _mesa_glsl_error(& loc, state,
+ "`%s' may only appear in a loop",
+ (mode == ast_break) ? "break" : "continue");
+ } else {
+ ir_loop *const loop = state->loop_or_switch_nesting->as_loop();
+
+ /* Inline the for loop expression again, since we don't know
+ * where near the end of the loop body the normal copy of it
+ * is going to be placed.
+ */
+ if (mode == ast_continue &&
+ state->loop_or_switch_nesting_ast->rest_expression) {
+ state->loop_or_switch_nesting_ast->rest_expression->hir(instructions,
+ state);
+ }
+
+ if (loop != NULL) {
+ ir_loop_jump *const jump =
+ new(ctx) ir_loop_jump((mode == ast_break)
+ ? ir_loop_jump::jump_break
+ : ir_loop_jump::jump_continue);
+ instructions->push_tail(jump);
+ }
+ }
+
+ break;
+ }
+
+ /* Jump instructions do not have r-values.
+ */
+ return NULL;
+}
+
+
+ir_rvalue *
+ast_selection_statement::hir(exec_list *instructions,
+ struct _mesa_glsl_parse_state *state)
+{
+ void *ctx = state;
+
+ ir_rvalue *const condition = this->condition->hir(instructions, state);
+
+ /* From page 66 (page 72 of the PDF) of the GLSL 1.50 spec:
+ *
+ * "Any expression whose type evaluates to a Boolean can be used as the
+ * conditional expression bool-expression. Vector types are not accepted
+ * as the expression to if."
+ *
+ * The checks are separated so that higher quality diagnostics can be
+ * generated for cases where both rules are violated.
+ */
+ if (!condition->type->is_boolean() || !condition->type->is_scalar()) {
+ YYLTYPE loc = this->condition->get_location();
+
+ _mesa_glsl_error(& loc, state, "if-statement condition must be scalar "
+ "boolean");
+ }
+
+ ir_if *const stmt = new(ctx) ir_if(condition);
+
+ if (then_statement != NULL)
+ then_statement->hir(& stmt->then_instructions, state);
+
+ if (else_statement != NULL)
+ else_statement->hir(& stmt->else_instructions, state);
+
+ instructions->push_tail(stmt);
+
+ /* if-statements do not have r-values.
+ */
+ return NULL;
+}
+
+
+void
+ast_iteration_statement::condition_to_hir(ir_loop *stmt,
+ struct _mesa_glsl_parse_state *state)
+{
+ void *ctx = state;
+
+ if (condition != NULL) {
+ ir_rvalue *const cond =
+ condition->hir(& stmt->body_instructions, state);
+
+ if ((cond == NULL)
+ || !cond->type->is_boolean() || !cond->type->is_scalar()) {
+ YYLTYPE loc = condition->get_location();
+
+ _mesa_glsl_error(& loc, state,
+ "loop condition must be scalar boolean");
+ } else {
+ /* As the first code in the loop body, generate a block that looks
+ * like 'if (!condition) break;' as the loop termination condition.
+ */
+ ir_rvalue *const not_cond =
+ new(ctx) ir_expression(ir_unop_logic_not, glsl_type::bool_type, cond,
+ NULL);
+
+ ir_if *const if_stmt = new(ctx) ir_if(not_cond);
+
+ ir_jump *const break_stmt =
+ new(ctx) ir_loop_jump(ir_loop_jump::jump_break);
+
+ if_stmt->then_instructions.push_tail(break_stmt);
+ stmt->body_instructions.push_tail(if_stmt);
+ }
+ }
+}
+
+
+ir_rvalue *
+ast_iteration_statement::hir(exec_list *instructions,
+ struct _mesa_glsl_parse_state *state)
+{
+ void *ctx = state;
+
+ /* For-loops and while-loops start a new scope, but do-while loops do not.
+ */
+ if (mode != ast_do_while)
+ state->symbols->push_scope();
+
+ if (init_statement != NULL)
+ init_statement->hir(instructions, state);
+
+ ir_loop *const stmt = new(ctx) ir_loop();
+ instructions->push_tail(stmt);
+
+ /* Track the current loop and / or switch-statement nesting.
+ */
+ ir_instruction *const nesting = state->loop_or_switch_nesting;
+ ast_iteration_statement *nesting_ast = state->loop_or_switch_nesting_ast;
+
+ state->loop_or_switch_nesting = stmt;
+ state->loop_or_switch_nesting_ast = this;
+
+ if (mode != ast_do_while)
+ condition_to_hir(stmt, state);
+
+ if (body != NULL)
+ body->hir(& stmt->body_instructions, state);
+
+ if (rest_expression != NULL)
+ rest_expression->hir(& stmt->body_instructions, state);
+
+ if (mode == ast_do_while)
+ condition_to_hir(stmt, state);
+
+ if (mode != ast_do_while)
+ state->symbols->pop_scope();
+
+ /* Restore previous nesting before returning.
+ */
+ state->loop_or_switch_nesting = nesting;
+ state->loop_or_switch_nesting_ast = nesting_ast;
+
+ /* Loops do not have r-values.
+ */
+ return NULL;
+}
+
+
+ir_rvalue *
+ast_type_specifier::hir(exec_list *instructions,
+ struct _mesa_glsl_parse_state *state)
+{
+ if (this->structure != NULL)
+ return this->structure->hir(instructions, state);
+
+ return NULL;
+}
+
+
+ir_rvalue *
+ast_struct_specifier::hir(exec_list *instructions,
+ struct _mesa_glsl_parse_state *state)
+{
+ unsigned decl_count = 0;
+
+ /* Make an initial pass over the list of structure fields to determine how
+ * many there are. Each element in this list is an ast_declarator_list.
+ * This means that we actually need to count the number of elements in the
+ * 'declarations' list in each of the elements.
+ */
+ foreach_list_typed (ast_declarator_list, decl_list, link,
+ &this->declarations) {
+ foreach_list_const (decl_ptr, & decl_list->declarations) {
+ decl_count++;
+ }
+ }
+
+
+ /* Allocate storage for the structure fields and process the field
+ * declarations. As the declarations are processed, try to also convert
+ * the types to HIR. This ensures that structure definitions embedded in
+ * other structure definitions are processed.
+ */
+ glsl_struct_field *const fields = talloc_array(state, glsl_struct_field,
+ decl_count);
+
+ unsigned i = 0;
+ foreach_list_typed (ast_declarator_list, decl_list, link,
+ &this->declarations) {
+ const char *type_name;
+
+ decl_list->type->specifier->hir(instructions, state);
+
+ const glsl_type *decl_type =
+ decl_list->type->specifier->glsl_type(& type_name, state);
+
+ foreach_list_typed (ast_declaration, decl, link,
+ &decl_list->declarations) {
+ const struct glsl_type *const field_type =
+ (decl->is_array)
+ ? process_array_type(decl_type, decl->array_size, state)
+ : decl_type;
+
+ fields[i].type = (field_type != NULL)
+ ? field_type : glsl_type::error_type;
+ fields[i].name = decl->identifier;
+ i++;
+ }
+ }
+
+ assert(i == decl_count);
+
+ const char *name;
+ if (this->name == NULL) {
+ static unsigned anon_count = 1;
+ char buf[32];
+
+ snprintf(buf, sizeof(buf), "#anon_struct_%04x", anon_count);
+ anon_count++;
+
+ name = strdup(buf);
+ } else {
+ name = this->name;
+ }
+
+ const glsl_type *t =
+ glsl_type::get_record_instance(fields, decl_count, name);
+
+ YYLTYPE loc = this->get_location();
+ if (!state->symbols->add_type(name, t)) {
+ _mesa_glsl_error(& loc, state, "struct `%s' previously defined", name);
+ } else {
+ /* This logic is a bit tricky. It is an error to declare a structure at
+ * global scope if there is also a function with the same name.
+ */
+ if ((state->current_function == NULL)
+ && (state->symbols->get_function(name) != NULL)) {
+ _mesa_glsl_error(& loc, state, "name `%s' previously defined", name);
+ } else {
+ t->generate_constructor(state->symbols);
+ }
+
+ const glsl_type **s = (const glsl_type **)
+ realloc(state->user_structures,
+ sizeof(state->user_structures[0]) *
+ (state->num_user_structures + 1));
+ if (s != NULL) {
+ s[state->num_user_structures] = t;
+ state->user_structures = s;
+ state->num_user_structures++;
+ }
+ }
+
+ /* Structure type definitions do not have r-values.
+ */
+ return NULL;
+}
diff --git a/src/glsl/ast_type.cpp b/src/glsl/ast_type.cpp
new file mode 100644
index 00000000000..9a957044e7a
--- /dev/null
+++ b/src/glsl/ast_type.cpp
@@ -0,0 +1,122 @@
+/*
+ * Copyright © 2010 Intel Corporation
+ *
+ * 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 (including the next
+ * paragraph) 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
+ * THE AUTHORS OR COPYRIGHT HOLDERS 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.
+ */
+
+#include <cstdio>
+#include "ast.h"
+extern "C" {
+#include "program/symbol_table.h"
+}
+
+void
+ast_type_specifier::print(void) const
+{
+ if (type_specifier == ast_struct) {
+ structure->print();
+ } else {
+ printf("%s ", type_name);
+ }
+
+ if (is_array) {
+ printf("[ ");
+
+ if (array_size) {
+ array_size->print();
+ }
+
+ printf("] ");
+ }
+}
+
+ast_type_specifier::ast_type_specifier(int specifier)
+ : type_specifier(ast_types(specifier)), type_name(NULL), structure(NULL),
+ is_array(false), array_size(NULL), precision(ast_precision_high)
+{
+ static const char *const names[] = {
+ "void",
+ "float",
+ "int",
+ "uint",
+ "bool",
+ "vec2",
+ "vec3",
+ "vec4",
+ "bvec2",
+ "bvec3",
+ "bvec4",
+ "ivec2",
+ "ivec3",
+ "ivec4",
+ "uvec2",
+ "uvec3",
+ "uvec4",
+ "mat2",
+ "mat2x3",
+ "mat2x4",
+ "mat3x2",
+ "mat3",
+ "mat3x4",
+ "mat4x2",
+ "mat4x3",
+ "mat4",
+ "sampler1D",
+ "sampler2D",
+ "sampler2DRect",
+ "sampler3D",
+ "samplerCube",
+ "sampler1DShadow",
+ "sampler2DShadow",
+ "sampler2DRectShadow",
+ "samplerCubeShadow",
+ "sampler1DArray",
+ "sampler2DArray",
+ "sampler1DArrayShadow",
+ "sampler2DArrayShadow",
+ "isampler1D",
+ "isampler2D",
+ "isampler3D",
+ "isamplerCube",
+ "isampler1DArray",
+ "isampler2DArray",
+ "usampler1D",
+ "usampler2D",
+ "usampler3D",
+ "usamplerCube",
+ "usampler1DArray",
+ "usampler2DArray",
+
+ NULL, /* ast_struct */
+ NULL /* ast_type_name */
+ };
+
+ type_name = names[specifier];
+}
+
+bool
+ast_fully_specified_type::has_qualifiers() const
+{
+ return qualifier.invariant || qualifier.constant || qualifier.attribute
+ || qualifier.varying || qualifier.in
+ || qualifier.out || qualifier.centroid
+ || qualifier.uniform || qualifier.smooth
+ || qualifier.flat || qualifier.noperspective;
+}
diff --git a/src/glsl/autogen.sh b/src/glsl/autogen.sh
new file mode 100755
index 00000000000..904cd6746c8
--- /dev/null
+++ b/src/glsl/autogen.sh
@@ -0,0 +1,12 @@
+#! /bin/sh
+
+srcdir=`dirname $0`
+test -z "$srcdir" && srcdir=.
+
+ORIGDIR=`pwd`
+cd $srcdir
+
+autoreconf -v --install || exit 1
+cd $ORIGDIR || exit $?
+
+$srcdir/configure --enable-maintainer-mode "$@"
diff --git a/src/glsl/builtin_function.cpp b/src/glsl/builtin_function.cpp
new file mode 100644
index 00000000000..f2abea961d2
--- /dev/null
+++ b/src/glsl/builtin_function.cpp
@@ -0,0 +1,14822 @@
+/* DO NOT MODIFY - automatically generated by generate_builtins.py */
+/*
+ * Copyright © 2010 Intel Corporation
+ *
+ * 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 (including the next
+ * paragraph) 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
+ * THE AUTHORS OR COPYRIGHT HOLDERS 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.
+ */
+
+#include <stdio.h>
+#include "main/compiler.h"
+#include "glsl_parser_extras.h"
+#include "ir_reader.h"
+#include "program.h"
+#include "ast.h"
+
+extern "C" struct gl_shader *
+_mesa_new_shader(GLcontext *ctx, GLuint name, GLenum type);
+
+gl_shader *
+read_builtins(GLenum target, const char *protos, const char **functions, unsigned count)
+{
+ gl_shader *sh = _mesa_new_shader(NULL, 0, target);
+ struct _mesa_glsl_parse_state *st =
+ new(sh) _mesa_glsl_parse_state(NULL, target, sh);
+
+ st->language_version = 130;
+ st->ARB_texture_rectangle_enable = true;
+ st->EXT_texture_array_enable = true;
+ _mesa_glsl_initialize_types(st);
+
+ sh->ir = new(sh) exec_list;
+ sh->symbols = st->symbols;
+
+ /* Read the IR containing the prototypes */
+ _mesa_glsl_read_ir(st, sh->ir, protos, true);
+
+ /* Read ALL the function bodies, telling the IR reader not to scan for
+ * prototypes (we've already created them). The IR reader will skip any
+ * signature that does not already exist as a prototype.
+ */
+ for (unsigned i = 0; i < count; i++) {
+ _mesa_glsl_read_ir(st, sh->ir, functions[i], false);
+
+ if (st->error) {
+ printf("error reading builtin: %.35s ...\n", functions[i]);
+ talloc_free(sh);
+ return NULL;
+ }
+ }
+
+ reparent_ir(sh->ir, sh);
+ delete st;
+
+ return sh;
+}
+
+static const char *builtin_all =
+ "((function all\n"
+ " (signature bool\n"
+ " (parameters\n"
+ " (declare (in) bvec2 arg0))\n"
+ " ((return (expression bool && (swiz x (var_ref arg0))(swiz y (var_ref arg0))))))\n"
+ "\n"
+ " (signature bool\n"
+ " (parameters\n"
+ " (declare (in) bvec3 arg0))\n"
+ " ((return (expression bool && (expression bool && (swiz x (var_ref arg0))(swiz y (var_ref arg0))) (swiz z (var_ref arg0))))))\n"
+ "\n"
+ " (signature bool\n"
+ " (parameters\n"
+ " (declare (in) bvec4 arg0))\n"
+ " ((return (expression bool && (expression bool && (expression bool && (swiz x (var_ref arg0))(swiz y (var_ref arg0))) (swiz z (var_ref arg0))) (swiz w (var_ref arg0))))))\n"
+ "))\n"
+ ""
+;
+static const char *builtin_textureProj =
+ "((function textureProj\n"
+ " (signature vec4\n"
+ " (parameters\n"
+ " (declare (in) sampler1D sampler)\n"
+ " (declare (in) vec2 P) )\n"
+ " ((return (tex (var_ref sampler) (swiz x (var_ref P)) (0 0 0) (swiz y (var_ref P)) () ))))\n"
+ "\n"
+ " (signature ivec4\n"
+ " (parameters\n"
+ " (declare (in) isampler1D sampler)\n"
+ " (declare (in) vec2 P) )\n"
+ " ((return (tex (var_ref sampler) (swiz x (var_ref P)) (0 0 0) (swiz y (var_ref P)) () ))))\n"
+ "\n"
+ " (signature uvec4\n"
+ " (parameters\n"
+ " (declare (in) usampler1D sampler)\n"
+ " (declare (in) vec2 P) )\n"
+ " ((return (tex (var_ref sampler) (swiz x (var_ref P)) (0 0 0) (swiz y (var_ref P)) () ))))\n"
+ "\n"
+ " (signature vec4\n"
+ " (parameters\n"
+ " (declare (in) sampler1D sampler)\n"
+ " (declare (in) vec4 P) )\n"
+ " ((return (tex (var_ref sampler) (swiz x (var_ref P)) (0 0 0) (swiz w (var_ref P)) () ))))\n"
+ "\n"
+ " (signature ivec4\n"
+ " (parameters\n"
+ " (declare (in) isampler1D sampler)\n"
+ " (declare (in) vec4 P) )\n"
+ " ((return (tex (var_ref sampler) (swiz x (var_ref P)) (0 0 0) (swiz w (var_ref P)) () ))))\n"
+ "\n"
+ " (signature uvec4\n"
+ " (parameters\n"
+ " (declare (in) usampler1D sampler)\n"
+ " (declare (in) vec4 P) )\n"
+ " ((return (tex (var_ref sampler) (swiz x (var_ref P)) (0 0 0) (swiz w (var_ref P)) () ))))\n"
+ "\n"
+ " (signature vec4\n"
+ " (parameters\n"
+ " (declare (in) sampler2D sampler)\n"
+ " (declare (in) vec3 P) )\n"
+ " ((return (tex (var_ref sampler) (swiz xy (var_ref P)) (0 0 0) (swiz z (var_ref P)) () ))))\n"
+ "\n"
+ " (signature ivec4\n"
+ " (parameters\n"
+ " (declare (in) isampler2D sampler)\n"
+ " (declare (in) vec3 P) )\n"
+ " ((return (tex (var_ref sampler) (swiz xy (var_ref P)) (0 0 0) (swiz z (var_ref P)) () ))))\n"
+ "\n"
+ " (signature uvec4\n"
+ " (parameters\n"
+ " (declare (in) usampler2D sampler)\n"
+ " (declare (in) vec3 P) )\n"
+ " ((return (tex (var_ref sampler) (swiz xy (var_ref P)) (0 0 0) (swiz z (var_ref P)) () ))))\n"
+ "\n"
+ " (signature vec4\n"
+ " (parameters\n"
+ " (declare (in) sampler2D sampler)\n"
+ " (declare (in) vec4 P) )\n"
+ " ((return (tex (var_ref sampler) (swiz xy (var_ref P)) (0 0 0) (swiz w (var_ref P)) () ))))\n"
+ "\n"
+ " (signature ivec4\n"
+ " (parameters\n"
+ " (declare (in) isampler2D sampler)\n"
+ " (declare (in) vec4 P) )\n"
+ " ((return (tex (var_ref sampler) (swiz xy (var_ref P)) (0 0 0) (swiz w (var_ref P)) () ))))\n"
+ "\n"
+ " (signature uvec4\n"
+ " (parameters\n"
+ " (declare (in) usampler2D sampler)\n"
+ " (declare (in) vec4 P) )\n"
+ " ((return (tex (var_ref sampler) (swiz xy (var_ref P)) (0 0 0) (swiz w (var_ref P)) () ))))\n"
+ "\n"
+ " (signature vec4\n"
+ " (parameters\n"
+ " (declare (in) sampler3D sampler)\n"
+ " (declare (in) vec4 P) )\n"
+ " ((return (tex (var_ref sampler) (swiz xyz (var_ref P)) (0 0 0) (swiz w (var_ref P)) () ))))\n"
+ "\n"
+ " (signature ivec4\n"
+ " (parameters\n"
+ " (declare (in) isampler3D sampler)\n"
+ " (declare (in) vec4 P) )\n"
+ " ((return (tex (var_ref sampler) (swiz xyz (var_ref P)) (0 0 0) (swiz w (var_ref P)) () ))))\n"
+ "\n"
+ " (signature uvec4\n"
+ " (parameters\n"
+ " (declare (in) usampler3D sampler)\n"
+ " (declare (in) vec4 P) )\n"
+ " ((return (tex (var_ref sampler) (swiz xyz (var_ref P)) (0 0 0) (swiz w (var_ref P)) () ))))\n"
+ "\n"
+ " (signature vec4\n"
+ " (parameters\n"
+ " (declare (in) sampler1D sampler)\n"
+ " (declare (in) vec2 P) \n"
+ " (declare (in) float bias) )\n"
+ " ((return (txb (var_ref sampler) (swiz x (var_ref P)) (0 0 0) (swiz y (var_ref P)) () (var_ref bias) ))))\n"
+ "\n"
+ " (signature ivec4\n"
+ " (parameters\n"
+ " (declare (in) isampler1D sampler)\n"
+ " (declare (in) vec2 P) \n"
+ " (declare (in) float bias) )\n"
+ " ((return (txb (var_ref sampler) (swiz x (var_ref P)) (0 0 0) (swiz y (var_ref P)) () (var_ref bias) ))))\n"
+ "\n"
+ " (signature uvec4\n"
+ " (parameters\n"
+ " (declare (in) usampler1D sampler)\n"
+ " (declare (in) vec2 P) \n"
+ " (declare (in) float bias) )\n"
+ " ((return (txb (var_ref sampler) (swiz x (var_ref P)) (0 0 0) (swiz y (var_ref P)) () (var_ref bias) ))))\n"
+ "\n"
+ " (signature vec4\n"
+ " (parameters\n"
+ " (declare (in) sampler1D sampler)\n"
+ " (declare (in) vec4 P) \n"
+ " (declare (in) float bias) )\n"
+ " ((return (txb (var_ref sampler) (swiz x (var_ref P)) (0 0 0) (swiz w (var_ref P)) () (var_ref bias) ))))\n"
+ "\n"
+ " (signature ivec4\n"
+ " (parameters\n"
+ " (declare (in) isampler1D sampler)\n"
+ " (declare (in) vec4 P) \n"
+ " (declare (in) float bias) )\n"
+ " ((return (txb (var_ref sampler) (swiz x (var_ref P)) (0 0 0) (swiz w (var_ref P)) () (var_ref bias) ))))\n"
+ "\n"
+ " (signature uvec4\n"
+ " (parameters\n"
+ " (declare (in) usampler1D sampler)\n"
+ " (declare (in) vec4 P) \n"
+ " (declare (in) float bias) )\n"
+ " ((return (txb (var_ref sampler) (swiz x (var_ref P)) (0 0 0) (swiz w (var_ref P)) () (var_ref bias) ))))\n"
+ "\n"
+ " (signature vec4\n"
+ " (parameters\n"
+ " (declare (in) sampler2D sampler)\n"
+ " (declare (in) vec3 P) \n"
+ " (declare (in) float bias) )\n"
+ " ((return (txb (var_ref sampler) (swiz xy (var_ref P)) (0 0 0) (swiz z (var_ref P)) () (var_ref bias) ))))\n"
+ "\n"
+ " (signature ivec4\n"
+ " (parameters\n"
+ " (declare (in) isampler2D sampler)\n"
+ " (declare (in) vec3 P) \n"
+ " (declare (in) float bias) )\n"
+ " ((return (txb (var_ref sampler) (swiz xy (var_ref P)) (0 0 0) (swiz z (var_ref P)) () (var_ref bias) ))))\n"
+ "\n"
+ " (signature uvec4\n"
+ " (parameters\n"
+ " (declare (in) usampler2D sampler)\n"
+ " (declare (in) vec3 P) \n"
+ " (declare (in) float bias) )\n"
+ " ((return (txb (var_ref sampler) (swiz xy (var_ref P)) (0 0 0) (swiz z (var_ref P)) () (var_ref bias) ))))\n"
+ "\n"
+ " (signature vec4\n"
+ " (parameters\n"
+ " (declare (in) sampler2D sampler)\n"
+ " (declare (in) vec4 P) \n"
+ " (declare (in) float bias) )\n"
+ " ((return (txb (var_ref sampler) (swiz xy (var_ref P)) (0 0 0) (swiz w (var_ref P)) () (var_ref bias) ))))\n"
+ "\n"
+ " (signature ivec4\n"
+ " (parameters\n"
+ " (declare (in) isampler2D sampler)\n"
+ " (declare (in) vec4 P) \n"
+ " (declare (in) float bias) )\n"
+ " ((return (txb (var_ref sampler) (swiz xy (var_ref P)) (0 0 0) (swiz w (var_ref P)) () (var_ref bias) ))))\n"
+ "\n"
+ " (signature uvec4\n"
+ " (parameters\n"
+ " (declare (in) usampler2D sampler)\n"
+ " (declare (in) vec4 P) \n"
+ " (declare (in) float bias) )\n"
+ " ((return (txb (var_ref sampler) (swiz xy (var_ref P)) (0 0 0) (swiz w (var_ref P)) () (var_ref bias) ))))\n"
+ "\n"
+ " (signature vec4\n"
+ " (parameters\n"
+ " (declare (in) sampler3D sampler)\n"
+ " (declare (in) vec4 P) \n"
+ " (declare (in) float bias) )\n"
+ " ((return (txb (var_ref sampler) (swiz xyz (var_ref P)) (0 0 0) (swiz w (var_ref P)) () (var_ref bias) ))))\n"
+ "\n"
+ " (signature ivec4\n"
+ " (parameters\n"
+ " (declare (in) isampler3D sampler)\n"
+ " (declare (in) vec4 P) \n"
+ " (declare (in) float bias) )\n"
+ " ((return (txb (var_ref sampler) (swiz xyz (var_ref P)) (0 0 0) (swiz w (var_ref P)) () (var_ref bias) ))))\n"
+ "\n"
+ " (signature uvec4\n"
+ " (parameters\n"
+ " (declare (in) usampler3D sampler)\n"
+ " (declare (in) vec4 P) \n"
+ " (declare (in) float bias) )\n"
+ " ((return (txb (var_ref sampler) (swiz xyz (var_ref P)) (0 0 0) (swiz w (var_ref P)) () (var_ref bias) ))))\n"
+ "\n"
+ "))\n"
+ ""
+;
+static const char *builtin_fwidth =
+ "((function fwidth\n"
+ " (signature float\n"
+ " (parameters\n"
+ " (declare (in) float p))\n"
+ " ((return (expression float +\n"
+ " (expression float abs (expression float dFdx (var_ref p)))\n"
+ " (expression float abs (expression float dFdy (var_ref p)))))))\n"
+ "\n"
+ " (signature vec2\n"
+ " (parameters\n"
+ " (declare (in) vec2 p))\n"
+ " ((return (expression vec2 +\n"
+ " (expression vec2 abs (expression vec2 dFdx (var_ref p)))\n"
+ " (expression vec2 abs (expression vec2 dFdy (var_ref p)))))))\n"
+ "\n"
+ " (signature vec3\n"
+ " (parameters\n"
+ " (declare (in) vec3 p))\n"
+ " ((return (expression vec3 +\n"
+ " (expression vec3 abs (expression vec3 dFdx (var_ref p)))\n"
+ " (expression vec3 abs (expression vec3 dFdy (var_ref p)))))))\n"
+ "\n"
+ " (signature vec4\n"
+ " (parameters\n"
+ " (declare (in) vec4 p))\n"
+ " ((return (expression vec4 +\n"
+ " (expression vec4 abs (expression vec4 dFdx (var_ref p)))\n"
+ " (expression vec4 abs (expression vec4 dFdy (var_ref p)))))))\n"
+ "))\n"
+ ""
+;
+static const char *builtin_texture2DProj =
+ "((function texture2DProj\n"
+ " (signature vec4\n"
+ " (parameters\n"
+ " (declare (in) sampler2D sampler)\n"
+ " (declare (in) vec3 P) )\n"
+ " ((return (tex (var_ref sampler) (swiz xy (var_ref P)) (0 0 0) (swiz z (var_ref P)) () ))))\n"
+ "\n"
+ " (signature vec4\n"
+ " (parameters\n"
+ " (declare (in) sampler2D sampler)\n"
+ " (declare (in) vec4 P) )\n"
+ " ((return (tex (var_ref sampler) (swiz xy (var_ref P)) (0 0 0) (swiz w (var_ref P)) () ))))\n"
+ "\n"
+ " (signature vec4\n"
+ " (parameters\n"
+ " (declare (in) sampler2D sampler)\n"
+ " (declare (in) vec3 P) \n"
+ " (declare (in) float bias) )\n"
+ " ((return (txb (var_ref sampler) (swiz xy (var_ref P)) (0 0 0) (swiz z (var_ref P)) () (var_ref bias) ))))\n"
+ "\n"
+ " (signature vec4\n"
+ " (parameters\n"
+ " (declare (in) sampler2D sampler)\n"
+ " (declare (in) vec4 P) \n"
+ " (declare (in) float bias) )\n"
+ " ((return (txb (var_ref sampler) (swiz xy (var_ref P)) (0 0 0) (swiz w (var_ref P)) () (var_ref bias) ))))\n"
+ "\n"
+ "))\n"
+ ""
+;
+static const char *builtin_shadow1DProjLod =
+ "((function shadow1DProjLod\n"
+ " (signature vec4\n"
+ " (parameters\n"
+ " (declare (in) sampler1DShadow sampler)\n"
+ " (declare (in) vec4 P) \n"
+ " (declare (in) float lod) )\n"
+ " ((return (txl (var_ref sampler) (swiz x (var_ref P)) (0 0 0) (swiz w (var_ref P)) (swiz z (var_ref P)) (var_ref lod) ))))\n"
+ "\n"
+ "))\n"
+ ""
+;
+static const char *builtin_texture3DLod =
+ "((function texture3DLod\n"
+ " (signature vec4\n"
+ " (parameters\n"
+ " (declare (in) sampler3D sampler)\n"
+ " (declare (in) vec3 P) \n"
+ " (declare (in) float lod) )\n"
+ " ((return (txl (var_ref sampler) (var_ref P) (0 0 0) 1 () (var_ref lod) ))))\n"
+ "\n"
+ "))\n"
+ ""
+;
+static const char *builtin_textureCubeLod =
+ "((function textureCubeLod\n"
+ " (signature vec4\n"
+ " (parameters\n"
+ " (declare (in) samplerCube sampler)\n"
+ " (declare (in) vec3 P) \n"
+ " (declare (in) float lod) )\n"
+ " ((return (txl (var_ref sampler) (var_ref P) (0 0 0) 1 () (var_ref lod) ))))\n"
+ "\n"
+ "))\n"
+ ""
+;
+static const char *builtin_texture =
+ "((function texture\n"
+ " (signature vec4\n"
+ " (parameters\n"
+ " (declare (in) sampler1D sampler)\n"
+ " (declare (in) float P) )\n"
+ " ((return (tex (var_ref sampler) (var_ref P) (0 0 0) 1 () ))))\n"
+ "\n"
+ " (signature ivec4\n"
+ " (parameters\n"
+ " (declare (in) isampler1D sampler)\n"
+ " (declare (in) float P) )\n"
+ " ((return (tex (var_ref sampler) (var_ref P) (0 0 0) 1 () ))))\n"
+ "\n"
+ " (signature uvec4\n"
+ " (parameters\n"
+ " (declare (in) usampler1D sampler)\n"
+ " (declare (in) float P) )\n"
+ " ((return (tex (var_ref sampler) (var_ref P) (0 0 0) 1 () ))))\n"
+ "\n"
+ " (signature vec4\n"
+ " (parameters\n"
+ " (declare (in) sampler2D sampler)\n"
+ " (declare (in) vec2 P) )\n"
+ " ((return (tex (var_ref sampler) (var_ref P) (0 0 0) 1 () ))))\n"
+ "\n"
+ " (signature ivec4\n"
+ " (parameters\n"
+ " (declare (in) isampler2D sampler)\n"
+ " (declare (in) vec2 P) )\n"
+ " ((return (tex (var_ref sampler) (var_ref P) (0 0 0) 1 () ))))\n"
+ "\n"
+ " (signature uvec4\n"
+ " (parameters\n"
+ " (declare (in) usampler2D sampler)\n"
+ " (declare (in) vec2 P) )\n"
+ " ((return (tex (var_ref sampler) (var_ref P) (0 0 0) 1 () ))))\n"
+ "\n"
+ " (signature vec4\n"
+ " (parameters\n"
+ " (declare (in) sampler3D sampler)\n"
+ " (declare (in) vec3 P) )\n"
+ " ((return (tex (var_ref sampler) (var_ref P) (0 0 0) 1 () ))))\n"
+ "\n"
+ " (signature ivec4\n"
+ " (parameters\n"
+ " (declare (in) isampler3D sampler)\n"
+ " (declare (in) vec3 P) )\n"
+ " ((return (tex (var_ref sampler) (var_ref P) (0 0 0) 1 () ))))\n"
+ "\n"
+ " (signature uvec4\n"
+ " (parameters\n"
+ " (declare (in) usampler3D sampler)\n"
+ " (declare (in) vec3 P) )\n"
+ " ((return (tex (var_ref sampler) (var_ref P) (0 0 0) 1 () ))))\n"
+ "\n"
+ " (signature vec4\n"
+ " (parameters\n"
+ " (declare (in) samplerCube sampler)\n"
+ " (declare (in) vec3 P) )\n"
+ " ((return (tex (var_ref sampler) (var_ref P) (0 0 0) 1 () ))))\n"
+ "\n"
+ " (signature ivec4\n"
+ " (parameters\n"
+ " (declare (in) isamplerCube sampler)\n"
+ " (declare (in) vec3 P) )\n"
+ " ((return (tex (var_ref sampler) (var_ref P) (0 0 0) 1 () ))))\n"
+ "\n"
+ " (signature uvec4\n"
+ " (parameters\n"
+ " (declare (in) usamplerCube sampler)\n"
+ " (declare (in) vec3 P) )\n"
+ " ((return (tex (var_ref sampler) (var_ref P) (0 0 0) 1 () ))))\n"
+ "\n"
+ " (signature vec4\n"
+ " (parameters\n"
+ " (declare (in) sampler1DArray sampler)\n"
+ " (declare (in) vec2 P) )\n"
+ " ((return (tex (var_ref sampler) (var_ref P) (0 0 0) 1 () ))))\n"
+ "\n"
+ " (signature ivec4\n"
+ " (parameters\n"
+ " (declare (in) isampler1DArray sampler)\n"
+ " (declare (in) vec2 P) )\n"
+ " ((return (tex (var_ref sampler) (var_ref P) (0 0 0) 1 () ))))\n"
+ "\n"
+ " (signature uvec4\n"
+ " (parameters\n"
+ " (declare (in) usampler1DArray sampler)\n"
+ " (declare (in) vec2 P) )\n"
+ " ((return (tex (var_ref sampler) (var_ref P) (0 0 0) 1 () ))))\n"
+ "\n"
+ " (signature vec4\n"
+ " (parameters\n"
+ " (declare (in) sampler2DArray sampler)\n"
+ " (declare (in) vec3 P) )\n"
+ " ((return (tex (var_ref sampler) (var_ref P) (0 0 0) 1 () ))))\n"
+ "\n"
+ " (signature ivec4\n"
+ " (parameters\n"
+ " (declare (in) isampler2DArray sampler)\n"
+ " (declare (in) vec3 P) )\n"
+ " ((return (tex (var_ref sampler) (var_ref P) (0 0 0) 1 () ))))\n"
+ "\n"
+ " (signature uvec4\n"
+ " (parameters\n"
+ " (declare (in) usampler2DArray sampler)\n"
+ " (declare (in) vec3 P) )\n"
+ " ((return (tex (var_ref sampler) (var_ref P) (0 0 0) 1 () ))))\n"
+ "\n"
+ " (signature vec4\n"
+ " (parameters\n"
+ " (declare (in) sampler1D sampler)\n"
+ " (declare (in) float P) \n"
+ " (declare (in) float bias) )\n"
+ " ((return (txb (var_ref sampler) (var_ref P) (0 0 0) 1 () (var_ref bias) ))))\n"
+ "\n"
+ " (signature ivec4\n"
+ " (parameters\n"
+ " (declare (in) isampler1D sampler)\n"
+ " (declare (in) float P) \n"
+ " (declare (in) float bias) )\n"
+ " ((return (txb (var_ref sampler) (var_ref P) (0 0 0) 1 () (var_ref bias) ))))\n"
+ "\n"
+ " (signature uvec4\n"
+ " (parameters\n"
+ " (declare (in) usampler1D sampler)\n"
+ " (declare (in) float P) \n"
+ " (declare (in) float bias) )\n"
+ " ((return (txb (var_ref sampler) (var_ref P) (0 0 0) 1 () (var_ref bias) ))))\n"
+ "\n"
+ " (signature vec4\n"
+ " (parameters\n"
+ " (declare (in) sampler2D sampler)\n"
+ " (declare (in) vec2 P) \n"
+ " (declare (in) float bias) )\n"
+ " ((return (txb (var_ref sampler) (var_ref P) (0 0 0) 1 () (var_ref bias) ))))\n"
+ "\n"
+ " (signature ivec4\n"
+ " (parameters\n"
+ " (declare (in) isampler2D sampler)\n"
+ " (declare (in) vec2 P) \n"
+ " (declare (in) float bias) )\n"
+ " ((return (txb (var_ref sampler) (var_ref P) (0 0 0) 1 () (var_ref bias) ))))\n"
+ "\n"
+ " (signature uvec4\n"
+ " (parameters\n"
+ " (declare (in) usampler2D sampler)\n"
+ " (declare (in) vec2 P) \n"
+ " (declare (in) float bias) )\n"
+ " ((return (txb (var_ref sampler) (var_ref P) (0 0 0) 1 () (var_ref bias) ))))\n"
+ "\n"
+ " (signature vec4\n"
+ " (parameters\n"
+ " (declare (in) sampler3D sampler)\n"
+ " (declare (in) vec3 P) \n"
+ " (declare (in) float bias) )\n"
+ " ((return (txb (var_ref sampler) (var_ref P) (0 0 0) 1 () (var_ref bias) ))))\n"
+ "\n"
+ " (signature ivec4\n"
+ " (parameters\n"
+ " (declare (in) isampler3D sampler)\n"
+ " (declare (in) vec3 P) \n"
+ " (declare (in) float bias) )\n"
+ " ((return (txb (var_ref sampler) (var_ref P) (0 0 0) 1 () (var_ref bias) ))))\n"
+ "\n"
+ " (signature uvec4\n"
+ " (parameters\n"
+ " (declare (in) usampler3D sampler)\n"
+ " (declare (in) vec3 P) \n"
+ " (declare (in) float bias) )\n"
+ " ((return (txb (var_ref sampler) (var_ref P) (0 0 0) 1 () (var_ref bias) ))))\n"
+ "\n"
+ " (signature vec4\n"
+ " (parameters\n"
+ " (declare (in) samplerCube sampler)\n"
+ " (declare (in) vec3 P) \n"
+ " (declare (in) float bias) )\n"
+ " ((return (txb (var_ref sampler) (var_ref P) (0 0 0) 1 () (var_ref bias) ))))\n"
+ "\n"
+ " (signature ivec4\n"
+ " (parameters\n"
+ " (declare (in) isamplerCube sampler)\n"
+ " (declare (in) vec3 P) \n"
+ " (declare (in) float bias) )\n"
+ " ((return (txb (var_ref sampler) (var_ref P) (0 0 0) 1 () (var_ref bias) ))))\n"
+ "\n"
+ " (signature uvec4\n"
+ " (parameters\n"
+ " (declare (in) usamplerCube sampler)\n"
+ " (declare (in) vec3 P) \n"
+ " (declare (in) float bias) )\n"
+ " ((return (txb (var_ref sampler) (var_ref P) (0 0 0) 1 () (var_ref bias) ))))\n"
+ "\n"
+ " (signature vec4\n"
+ " (parameters\n"
+ " (declare (in) sampler1DArray sampler)\n"
+ " (declare (in) vec2 P) \n"
+ " (declare (in) float bias) )\n"
+ " ((return (txb (var_ref sampler) (var_ref P) (0 0 0) 1 () (var_ref bias) ))))\n"
+ "\n"
+ " (signature ivec4\n"
+ " (parameters\n"
+ " (declare (in) isampler1DArray sampler)\n"
+ " (declare (in) vec2 P) \n"
+ " (declare (in) float bias) )\n"
+ " ((return (txb (var_ref sampler) (var_ref P) (0 0 0) 1 () (var_ref bias) ))))\n"
+ "\n"
+ " (signature uvec4\n"
+ " (parameters\n"
+ " (declare (in) usampler1DArray sampler)\n"
+ " (declare (in) vec2 P) \n"
+ " (declare (in) float bias) )\n"
+ " ((return (txb (var_ref sampler) (var_ref P) (0 0 0) 1 () (var_ref bias) ))))\n"
+ "\n"
+ " (signature vec4\n"
+ " (parameters\n"
+ " (declare (in) sampler2DArray sampler)\n"
+ " (declare (in) vec3 P) \n"
+ " (declare (in) float bias) )\n"
+ " ((return (txb (var_ref sampler) (var_ref P) (0 0 0) 1 () (var_ref bias) ))))\n"
+ "\n"
+ " (signature ivec4\n"
+ " (parameters\n"
+ " (declare (in) isampler2DArray sampler)\n"
+ " (declare (in) vec3 P) \n"
+ " (declare (in) float bias) )\n"
+ " ((return (txb (var_ref sampler) (var_ref P) (0 0 0) 1 () (var_ref bias) ))))\n"
+ "\n"
+ " (signature uvec4\n"
+ " (parameters\n"
+ " (declare (in) usampler2DArray sampler)\n"
+ " (declare (in) vec3 P) \n"
+ " (declare (in) float bias) )\n"
+ " ((return (txb (var_ref sampler) (var_ref P) (0 0 0) 1 () (var_ref bias) ))))\n"
+ "\n"
+ "))\n"
+ ""
+;
+static const char *builtin_degrees =
+ "((function degrees\n"
+ " (signature float\n"
+ " (parameters\n"
+ " (declare (in) float arg0))\n"
+ " ((return (expression float * (var_ref arg0) (constant float (57.295780))))))\n"
+ "\n"
+ " (signature vec2\n"
+ " (parameters\n"
+ " (declare (in) vec2 arg0))\n"
+ " ((return (expression vec2 * (var_ref arg0) (constant float (57.295780))))))\n"
+ "\n"
+ " (signature vec3\n"
+ " (parameters\n"
+ " (declare (in) vec3 arg0))\n"
+ " ((return (expression vec3 * (var_ref arg0) (constant float (57.295780))))))\n"
+ "\n"
+ " (signature vec4\n"
+ " (parameters\n"
+ " (declare (in) vec4 arg0))\n"
+ " ((return (expression vec4 * (var_ref arg0) (constant float (57.295780))))))\n"
+ "))\n"
+ ""
+;
+static const char *builtin_texture2DArrayLod =
+ "((function texture2DArrayLod\n"
+ " (signature vec4\n"
+ " (parameters\n"
+ " (declare (in) sampler2DArray sampler)\n"
+ " (declare (in) vec3 P) \n"
+ " (declare (in) float lod) )\n"
+ " ((return (txl (var_ref sampler) (var_ref P) (0 0 0) 1 () (var_ref lod) ))))\n"
+ "\n"
+ "))\n"
+ ""
+;
+static const char *builtin_ceil =
+ "((function ceil\n"
+ " (signature float\n"
+ " (parameters\n"
+ " (declare (in) float arg0))\n"
+ " ((return (expression float ceil (var_ref arg0)))))\n"
+ "\n"
+ " (signature vec2\n"
+ " (parameters\n"
+ " (declare (in) vec2 arg0))\n"
+ " ((return (expression vec2 ceil (var_ref arg0)))))\n"
+ "\n"
+ " (signature vec3\n"
+ " (parameters\n"
+ " (declare (in) vec3 arg0))\n"
+ " ((return (expression vec3 ceil (var_ref arg0)))))\n"
+ "\n"
+ " (signature vec4\n"
+ " (parameters\n"
+ " (declare (in) vec4 arg0))\n"
+ " ((return (expression vec4 ceil (var_ref arg0)))))\n"
+ "))\n"
+ ""
+;
+static const char *builtin_texture1D =
+ "((function texture1D\n"
+ " (signature vec4\n"
+ " (parameters\n"
+ " (declare (in) sampler1D sampler)\n"
+ " (declare (in) float P) )\n"
+ " ((return (tex (var_ref sampler) (var_ref P) (0 0 0) 1 () ))))\n"
+ "\n"
+ " (signature vec4\n"
+ " (parameters\n"
+ " (declare (in) sampler1D sampler)\n"
+ " (declare (in) float P) \n"
+ " (declare (in) float bias) )\n"
+ " ((return (txb (var_ref sampler) (var_ref P) (0 0 0) 1 () (var_ref bias) ))))\n"
+ "\n"
+ "))\n"
+ ""
+;
+static const char *builtin_not =
+ "((function not\n"
+ " (signature bvec2\n"
+ " (parameters\n"
+ " (declare (in) bvec2 arg0))\n"
+ " ((return (expression bvec2 ! (var_ref arg0)))))\n"
+ "\n"
+ " (signature bvec3\n"
+ " (parameters\n"
+ " (declare (in) bvec3 arg0))\n"
+ " ((return (expression bvec3 ! (var_ref arg0)))))\n"
+ "\n"
+ " (signature bvec4\n"
+ " (parameters\n"
+ " (declare (in) bvec4 arg0))\n"
+ " ((return (expression bvec4 ! (var_ref arg0)))))\n"
+ "))\n"
+ ""
+;
+static const char *builtin_texture2DRectProj =
+ "((function texture2DRectProj\n"
+ " (signature vec4\n"
+ " (parameters\n"
+ " (declare (in) sampler2DRect sampler)\n"
+ " (declare (in) vec3 P) )\n"
+ " ((return (tex (var_ref sampler) (swiz xy (var_ref P)) (0 0 0) (swiz z (var_ref P)) () ))))\n"
+ "\n"
+ " (signature vec4\n"
+ " (parameters\n"
+ " (declare (in) sampler2DRect sampler)\n"
+ " (declare (in) vec4 P) )\n"
+ " ((return (tex (var_ref sampler) (swiz xy (var_ref P)) (0 0 0) (swiz w (var_ref P)) () ))))\n"
+ "\n"
+ "))\n"
+ ""
+;
+static const char *builtin_mod =
+ "((function mod\n"
+ " (signature float\n"
+ " (parameters\n"
+ " (declare (in) float arg0)\n"
+ " (declare (in) float arg1))\n"
+ " ((return (expression float % (var_ref arg0) (var_ref arg1)))))\n"
+ "\n"
+ " (signature vec2\n"
+ " (parameters\n"
+ " (declare (in) vec2 arg0)\n"
+ " (declare (in) vec2 arg1))\n"
+ " ((return (expression vec2 % (var_ref arg0) (var_ref arg1)))))\n"
+ "\n"
+ " (signature vec3\n"
+ " (parameters\n"
+ " (declare (in) vec3 arg0)\n"
+ " (declare (in) vec3 arg1))\n"
+ " ((return (expression vec3 % (var_ref arg0) (var_ref arg1)))))\n"
+ "\n"
+ " (signature vec4\n"
+ " (parameters\n"
+ " (declare (in) vec4 arg0)\n"
+ " (declare (in) vec4 arg1))\n"
+ " ((return (expression vec4 % (var_ref arg0) (var_ref arg1)))))\n"
+ "\n"
+ " (signature vec2\n"
+ " (parameters\n"
+ " (declare (in) vec2 arg0)\n"
+ " (declare (in) float arg1))\n"
+ " ((return (expression vec2 % (var_ref arg0) (var_ref arg1)))))\n"
+ "\n"
+ " (signature vec3\n"
+ " (parameters\n"
+ " (declare (in) vec3 arg0)\n"
+ " (declare (in) float arg1))\n"
+ " ((return (expression vec3 % (var_ref arg0) (var_ref arg1)))))\n"
+ "\n"
+ " (signature vec4\n"
+ " (parameters\n"
+ " (declare (in) vec4 arg0)\n"
+ " (declare (in) float arg1))\n"
+ " ((return (expression vec4 % (var_ref arg0) (var_ref arg1)))))\n"
+ "))\n"
+ ""
+;
+static const char *builtin_radians =
+ "((function radians\n"
+ " (signature float\n"
+ " (parameters\n"
+ " (declare (in) float arg0))\n"
+ " ((return (expression float * (var_ref arg0) (constant float (0.017453))))))\n"
+ "\n"
+ " (signature vec2\n"
+ " (parameters\n"
+ " (declare (in) vec2 arg0))\n"
+ " ((return (expression vec2 * (var_ref arg0) (constant float (0.017453))))))\n"
+ "\n"
+ " (signature vec3\n"
+ " (parameters\n"
+ " (declare (in) vec3 arg0))\n"
+ " ((return (expression vec3 * (var_ref arg0) (constant float (0.017453))))))\n"
+ "\n"
+ " (signature vec4\n"
+ " (parameters\n"
+ " (declare (in) vec4 arg0))\n"
+ " ((return (expression vec4 * (var_ref arg0) (constant float (0.017453))))))\n"
+ "))\n"
+ ""
+;
+static const char *builtin_smoothstep =
+ "((function smoothstep\n"
+ " (signature float\n"
+ " (parameters\n"
+ " (declare (in) float edge0)\n"
+ " (declare (in) float edge1)\n"
+ " (declare (in) float x))\n"
+ " ((declare () float t)\n"
+ "\n"
+ " (assign (constant bool (1)) (var_ref t)\n"
+ " (expression float max\n"
+ " (expression float min\n"
+ " (expression float / (expression float - (var_ref x) (var_ref edge0)) (expression float - (var_ref edge1) (var_ref edge0)))\n"
+ " (constant float (1.0)))\n"
+ " (constant float (0.0))))\n"
+ " (return (expression float * (var_ref t) (expression float * (var_ref t) (expression float - (constant float (3.000000)) (expression float * (constant float (2.000000)) (var_ref t))))))))\n"
+ "\n"
+ " (signature vec2\n"
+ " (parameters\n"
+ " (declare (in) float edge0)\n"
+ " (declare (in) float edge1)\n"
+ " (declare (in) vec2 x))\n"
+ " ((declare () vec2 t)\n"
+ " (declare () vec2 retval)\n"
+ "\n"
+ " (assign (constant bool (1)) (swiz x (var_ref t))\n"
+ " (expression float max\n"
+ " (expression float min\n"
+ " (expression float / (expression float - (swiz x (var_ref x)) (var_ref edge0)) (expression float - (var_ref edge1) (var_ref edge0)))\n"
+ " (constant float (1.0)))\n"
+ " (constant float (0.0))))\n"
+ " (assign (constant bool (1)) (swiz x (var_ref retval)) (expression float * (swiz x (var_ref t)) (expression float * (swiz x (var_ref t)) (expression float - (constant float (3.000000)) (expression float * (constant float (2.000000)) (swiz x (var_ref t)))))))\n"
+ "\n"
+ " (assign (constant bool (1)) (swiz y (var_ref t))\n"
+ " (expression float max\n"
+ " (expression float min\n"
+ " (expression float / (expression float - (swiz y (var_ref x)) (var_ref edge0)) (expression float - (var_ref edge1) (var_ref edge0)))\n"
+ " (constant float (1.0)))\n"
+ " (constant float (0.0))))\n"
+ " (assign (constant bool (1)) (swiz y (var_ref retval)) (expression float * (swiz y (var_ref t)) (expression float * (swiz y (var_ref t)) (expression float - (constant float (3.000000)) (expression float * (constant float (2.000000)) (swiz y (var_ref t)))))))\n"
+ " (return (var_ref retval))\n"
+ " ))\n"
+ "\n"
+ " (signature vec3\n"
+ " (parameters\n"
+ " (declare (in) float edge0)\n"
+ " (declare (in) float edge1)\n"
+ " (declare (in) vec3 x))\n"
+ " ((declare () vec3 t)\n"
+ " (declare () vec3 retval)\n"
+ "\n"
+ " (assign (constant bool (1)) (swiz x (var_ref t))\n"
+ " (expression float max\n"
+ " (expression float min\n"
+ " (expression float / (expression float - (swiz x (var_ref x)) (var_ref edge0)) (expression float - (var_ref edge1) (var_ref edge0)))\n"
+ " (constant float (1.0)))\n"
+ " (constant float (0.0))))\n"
+ " (assign (constant bool (1)) (swiz x (var_ref retval)) (expression float * (swiz x (var_ref t)) (expression float * (swiz x (var_ref t)) (expression float - (constant float (3.000000)) (expression float * (constant float (2.000000)) (swiz x (var_ref t)))))))\n"
+ "\n"
+ " (assign (constant bool (1)) (swiz y (var_ref t))\n"
+ " (expression float max\n"
+ " (expression float min\n"
+ " (expression float / (expression float - (swiz y (var_ref x)) (var_ref edge0)) (expression float - (var_ref edge1) (var_ref edge0)))\n"
+ " (constant float (1.0)))\n"
+ " (constant float (0.0))))\n"
+ " (assign (constant bool (1)) (swiz y (var_ref retval)) (expression float * (swiz y (var_ref t)) (expression float * (swiz y (var_ref t)) (expression float - (constant float (3.000000)) (expression float * (constant float (2.000000)) (swiz y (var_ref t)))))))\n"
+ "\n"
+ " (assign (constant bool (1)) (swiz z (var_ref t))\n"
+ " (expression float max\n"
+ " (expression float min\n"
+ " (expression float / (expression float - (swiz z (var_ref x)) (var_ref edge0)) (expression float - (var_ref edge1) (var_ref edge0)))\n"
+ " (constant float (1.0)))\n"
+ " (constant float (0.0))))\n"
+ " (assign (constant bool (1)) (swiz z (var_ref retval)) (expression float * (swiz z (var_ref t)) (expression float * (swiz z (var_ref t)) (expression float - (constant float (3.000000)) (expression float * (constant float (2.000000)) (swiz z (var_ref t)))))))\n"
+ " (return (var_ref retval))\n"
+ " ))\n"
+ "\n"
+ "\n"
+ " (signature vec4\n"
+ " (parameters\n"
+ " (declare (in) float edge0)\n"
+ " (declare (in) float edge1)\n"
+ " (declare (in) vec4 x))\n"
+ " ((declare () vec4 t)\n"
+ " (declare () vec4 retval)\n"
+ "\n"
+ " (assign (constant bool (1)) (swiz x (var_ref t))\n"
+ " (expression float max\n"
+ " (expression float min\n"
+ " (expression float / (expression float - (swiz x (var_ref x)) (var_ref edge0)) (expression float - (var_ref edge1) (var_ref edge0)))\n"
+ " (constant float (1.0)))\n"
+ " (constant float (0.0))))\n"
+ " (assign (constant bool (1)) (swiz x (var_ref retval)) (expression float * (swiz x (var_ref t)) (expression float * (swiz x (var_ref t)) (expression float - (constant float (3.000000)) (expression float * (constant float (2.000000)) (swiz x (var_ref t)))))))\n"
+ "\n"
+ " (assign (constant bool (1)) (swiz y (var_ref t))\n"
+ " (expression float max\n"
+ " (expression float min\n"
+ " (expression float / (expression float - (swiz y (var_ref x)) (var_ref edge0)) (expression float - (var_ref edge1) (var_ref edge0)))\n"
+ " (constant float (1.0)))\n"
+ " (constant float (0.0))))\n"
+ " (assign (constant bool (1)) (swiz y (var_ref retval)) (expression float * (swiz y (var_ref t)) (expression float * (swiz y (var_ref t)) (expression float - (constant float (3.000000)) (expression float * (constant float (2.000000)) (swiz y (var_ref t)))))))\n"
+ "\n"
+ " (assign (constant bool (1)) (swiz z (var_ref t))\n"
+ " (expression float max\n"
+ " (expression float min\n"
+ " (expression float / (expression float - (swiz z (var_ref x)) (var_ref edge0)) (expression float - (var_ref edge1) (var_ref edge0)))\n"
+ " (constant float (1.0)))\n"
+ " (constant float (0.0))))\n"
+ " (assign (constant bool (1)) (swiz z (var_ref retval)) (expression float * (swiz z (var_ref t)) (expression float * (swiz z (var_ref t)) (expression float - (constant float (3.000000)) (expression float * (constant float (2.000000)) (swiz z (var_ref t)))))))\n"
+ "\n"
+ " (assign (constant bool (1)) (swiz w (var_ref t))\n"
+ " (expression float max\n"
+ " (expression float min\n"
+ " (expression float / (expression float - (swiz w (var_ref x)) (var_ref edge0)) (expression float - (var_ref edge1) (var_ref edge0)))\n"
+ " (constant float (1.0)))\n"
+ " (constant float (0.0))))\n"
+ " (assign (constant bool (1)) (swiz w (var_ref retval)) (expression float * (swiz w (var_ref t)) (expression float * (swiz w (var_ref t)) (expression float - (constant float (3.000000)) (expression float * (constant float (2.000000)) (swiz w (var_ref t)))))))\n"
+ " (return (var_ref retval))\n"
+ " ))\n"
+ "\n"
+ " (signature vec2\n"
+ " (parameters\n"
+ " (declare (in) vec2 edge0)\n"
+ " (declare (in) vec2 edge1)\n"
+ " (declare (in) vec2 x))\n"
+ " ((return (expression vec2 max\n"
+ " (expression vec2 min\n"
+ " (expression vec2 / (expression vec2 - (var_ref x) (var_ref edge0)) (expression vec2 - (var_ref edge1) (var_ref edge0)))\n"
+ " (constant vec2 (1.0 1.0)))\n"
+ " (constant vec2 (0.0 0.0))))))\n"
+ "\n"
+ " (signature vec3\n"
+ " (parameters\n"
+ " (declare (in) vec3 edge0)\n"
+ " (declare (in) vec3 edge1)\n"
+ " (declare (in) vec3 x))\n"
+ " ((return (expression vec3 max\n"
+ " (expression vec3 min\n"
+ " (expression vec3 / (expression vec3 - (var_ref x) (var_ref edge0)) (expression vec3 - (var_ref edge1) (var_ref edge0)))\n"
+ " (constant vec3 (1.0 1.0 1.0)))\n"
+ " (constant vec3 (0.0 0.0 0.0))))))\n"
+ "\n"
+ " (signature vec4\n"
+ " (parameters\n"
+ " (declare (in) vec4 edge0)\n"
+ " (declare (in) vec4 edge1)\n"
+ " (declare (in) vec4 x))\n"
+ " ((return (expression vec4 max\n"
+ " (expression vec4 min\n"
+ " (expression vec4 / (expression vec4 - (var_ref x) (var_ref edge0)) (expression vec4 - (var_ref edge1) (var_ref edge0)))\n"
+ " (constant vec4 (1.0 1.0 1.0 1.0)))\n"
+ " (constant vec4 (0.0 0.0 0.0 0.0))))))\n"
+ "))\n"
+ "\n"
+ ""
+;
+static const char *builtin_textureProjGrad =
+ "((function textureProjGrad\n"
+ " (signature vec4\n"
+ " (parameters\n"
+ " (declare (in) sampler1D sampler)\n"
+ " (declare (in) vec2 P) \n"
+ " (declare (in) float dPdx) \n"
+ " (declare (in) float dPdy) )\n"
+ " ((return (txd (var_ref sampler) (swiz x (var_ref P)) (0 0 0) (swiz y (var_ref P)) () ((var_ref dPdx) (var_ref dPdy)) ))))\n"
+ "\n"
+ " (signature ivec4\n"
+ " (parameters\n"
+ " (declare (in) isampler1D sampler)\n"
+ " (declare (in) vec2 P) \n"
+ " (declare (in) float dPdx) \n"
+ " (declare (in) float dPdy) )\n"
+ " ((return (txd (var_ref sampler) (swiz x (var_ref P)) (0 0 0) (swiz y (var_ref P)) () ((var_ref dPdx) (var_ref dPdy)) ))))\n"
+ "\n"
+ " (signature uvec4\n"
+ " (parameters\n"
+ " (declare (in) usampler1D sampler)\n"
+ " (declare (in) vec2 P) \n"
+ " (declare (in) float dPdx) \n"
+ " (declare (in) float dPdy) )\n"
+ " ((return (txd (var_ref sampler) (swiz x (var_ref P)) (0 0 0) (swiz y (var_ref P)) () ((var_ref dPdx) (var_ref dPdy)) ))))\n"
+ "\n"
+ " (signature vec4\n"
+ " (parameters\n"
+ " (declare (in) sampler1D sampler)\n"
+ " (declare (in) vec4 P) \n"
+ " (declare (in) float dPdx) \n"
+ " (declare (in) float dPdy) )\n"
+ " ((return (txd (var_ref sampler) (swiz x (var_ref P)) (0 0 0) (swiz w (var_ref P)) () ((var_ref dPdx) (var_ref dPdy)) ))))\n"
+ "\n"
+ " (signature ivec4\n"
+ " (parameters\n"
+ " (declare (in) isampler1D sampler)\n"
+ " (declare (in) vec4 P) \n"
+ " (declare (in) float dPdx) \n"
+ " (declare (in) float dPdy) )\n"
+ " ((return (txd (var_ref sampler) (swiz x (var_ref P)) (0 0 0) (swiz w (var_ref P)) () ((var_ref dPdx) (var_ref dPdy)) ))))\n"
+ "\n"
+ " (signature uvec4\n"
+ " (parameters\n"
+ " (declare (in) usampler1D sampler)\n"
+ " (declare (in) vec4 P) \n"
+ " (declare (in) float dPdx) \n"
+ " (declare (in) float dPdy) )\n"
+ " ((return (txd (var_ref sampler) (swiz x (var_ref P)) (0 0 0) (swiz w (var_ref P)) () ((var_ref dPdx) (var_ref dPdy)) ))))\n"
+ "\n"
+ " (signature vec4\n"
+ " (parameters\n"
+ " (declare (in) sampler2D sampler)\n"
+ " (declare (in) vec3 P) \n"
+ " (declare (in) vec2 dPdx) \n"
+ " (declare (in) vec2 dPdy) )\n"
+ " ((return (txd (var_ref sampler) (swiz xy (var_ref P)) (0 0 0) (swiz z (var_ref P)) () ((var_ref dPdx) (var_ref dPdy)) ))))\n"
+ "\n"
+ " (signature ivec4\n"
+ " (parameters\n"
+ " (declare (in) isampler2D sampler)\n"
+ " (declare (in) vec3 P) \n"
+ " (declare (in) vec2 dPdx) \n"
+ " (declare (in) vec2 dPdy) )\n"
+ " ((return (txd (var_ref sampler) (swiz xy (var_ref P)) (0 0 0) (swiz z (var_ref P)) () ((var_ref dPdx) (var_ref dPdy)) ))))\n"
+ "\n"
+ " (signature uvec4\n"
+ " (parameters\n"
+ " (declare (in) usampler2D sampler)\n"
+ " (declare (in) vec3 P) \n"
+ " (declare (in) vec2 dPdx) \n"
+ " (declare (in) vec2 dPdy) )\n"
+ " ((return (txd (var_ref sampler) (swiz xy (var_ref P)) (0 0 0) (swiz z (var_ref P)) () ((var_ref dPdx) (var_ref dPdy)) ))))\n"
+ "\n"
+ " (signature vec4\n"
+ " (parameters\n"
+ " (declare (in) sampler2D sampler)\n"
+ " (declare (in) vec4 P) \n"
+ " (declare (in) vec2 dPdx) \n"
+ " (declare (in) vec2 dPdy) )\n"
+ " ((return (txd (var_ref sampler) (swiz xy (var_ref P)) (0 0 0) (swiz w (var_ref P)) () ((var_ref dPdx) (var_ref dPdy)) ))))\n"
+ "\n"
+ " (signature ivec4\n"
+ " (parameters\n"
+ " (declare (in) isampler2D sampler)\n"
+ " (declare (in) vec4 P) \n"
+ " (declare (in) vec2 dPdx) \n"
+ " (declare (in) vec2 dPdy) )\n"
+ " ((return (txd (var_ref sampler) (swiz xy (var_ref P)) (0 0 0) (swiz w (var_ref P)) () ((var_ref dPdx) (var_ref dPdy)) ))))\n"
+ "\n"
+ " (signature uvec4\n"
+ " (parameters\n"
+ " (declare (in) usampler2D sampler)\n"
+ " (declare (in) vec4 P) \n"
+ " (declare (in) vec2 dPdx) \n"
+ " (declare (in) vec2 dPdy) )\n"
+ " ((return (txd (var_ref sampler) (swiz xy (var_ref P)) (0 0 0) (swiz w (var_ref P)) () ((var_ref dPdx) (var_ref dPdy)) ))))\n"
+ "\n"
+ " (signature vec4\n"
+ " (parameters\n"
+ " (declare (in) sampler3D sampler)\n"
+ " (declare (in) vec4 P) \n"
+ " (declare (in) vec3 dPdx) \n"
+ " (declare (in) vec3 dPdy) )\n"
+ " ((return (txd (var_ref sampler) (swiz xyz (var_ref P)) (0 0 0) (swiz w (var_ref P)) () ((var_ref dPdx) (var_ref dPdy)) ))))\n"
+ "\n"
+ " (signature ivec4\n"
+ " (parameters\n"
+ " (declare (in) isampler3D sampler)\n"
+ " (declare (in) vec4 P) \n"
+ " (declare (in) vec3 dPdx) \n"
+ " (declare (in) vec3 dPdy) )\n"
+ " ((return (txd (var_ref sampler) (swiz xyz (var_ref P)) (0 0 0) (swiz w (var_ref P)) () ((var_ref dPdx) (var_ref dPdy)) ))))\n"
+ "\n"
+ " (signature uvec4\n"
+ " (parameters\n"
+ " (declare (in) usampler3D sampler)\n"
+ " (declare (in) vec4 P) \n"
+ " (declare (in) vec3 dPdx) \n"
+ " (declare (in) vec3 dPdy) )\n"
+ " ((return (txd (var_ref sampler) (swiz xyz (var_ref P)) (0 0 0) (swiz w (var_ref P)) () ((var_ref dPdx) (var_ref dPdy)) ))))\n"
+ "\n"
+ "))\n"
+ ""
+;
+static const char *builtin_dFdx =
+ "((function dFdx\n"
+ " (signature float\n"
+ " (parameters\n"
+ " (declare (in) float p))\n"
+ " ((return (expression float dFdx (var_ref p)))))\n"
+ "\n"
+ " (signature vec2\n"
+ " (parameters\n"
+ " (declare (in) vec2 p))\n"
+ " ((return (expression vec2 dFdx (var_ref p)))))\n"
+ "\n"
+ " (signature vec3\n"
+ " (parameters\n"
+ " (declare (in) vec3 p))\n"
+ " ((return (expression vec3 dFdx (var_ref p)))))\n"
+ "\n"
+ " (signature vec4\n"
+ " (parameters\n"
+ " (declare (in) vec4 p))\n"
+ " ((return (expression vec4 dFdx (var_ref p)))))\n"
+ "))\n"
+ ""
+;
+static const char *builtin_dFdy =
+ "((function dFdy\n"
+ " (signature float\n"
+ " (parameters\n"
+ " (declare (in) float p))\n"
+ " ((return (expression float dFdy (var_ref p)))))\n"
+ "\n"
+ " (signature vec2\n"
+ " (parameters\n"
+ " (declare (in) vec2 p))\n"
+ " ((return (expression vec2 dFdy (var_ref p)))))\n"
+ "\n"
+ " (signature vec3\n"
+ " (parameters\n"
+ " (declare (in) vec3 p))\n"
+ " ((return (expression vec3 dFdy (var_ref p)))))\n"
+ "\n"
+ " (signature vec4\n"
+ " (parameters\n"
+ " (declare (in) vec4 p))\n"
+ " ((return (expression vec4 dFdy (var_ref p)))))\n"
+ "))\n"
+ ""
+;
+static const char *builtin_textureGrad =
+ "((function textureGrad\n"
+ " (signature vec4\n"
+ " (parameters\n"
+ " (declare (in) sampler1D sampler)\n"
+ " (declare (in) float P) \n"
+ " (declare (in) float dPdx) \n"
+ " (declare (in) float dPdy) )\n"
+ " ((return (txd (var_ref sampler) (var_ref P) (0 0 0) 1 () ((var_ref dPdx) (var_ref dPdy)) ))))\n"
+ "\n"
+ " (signature ivec4\n"
+ " (parameters\n"
+ " (declare (in) isampler1D sampler)\n"
+ " (declare (in) float P) \n"
+ " (declare (in) float dPdx) \n"
+ " (declare (in) float dPdy) )\n"
+ " ((return (txd (var_ref sampler) (var_ref P) (0 0 0) 1 () ((var_ref dPdx) (var_ref dPdy)) ))))\n"
+ "\n"
+ " (signature uvec4\n"
+ " (parameters\n"
+ " (declare (in) usampler1D sampler)\n"
+ " (declare (in) float P) \n"
+ " (declare (in) float dPdx) \n"
+ " (declare (in) float dPdy) )\n"
+ " ((return (txd (var_ref sampler) (var_ref P) (0 0 0) 1 () ((var_ref dPdx) (var_ref dPdy)) ))))\n"
+ "\n"
+ " (signature vec4\n"
+ " (parameters\n"
+ " (declare (in) sampler2D sampler)\n"
+ " (declare (in) vec2 P) \n"
+ " (declare (in) vec2 dPdx) \n"
+ " (declare (in) vec2 dPdy) )\n"
+ " ((return (txd (var_ref sampler) (var_ref P) (0 0 0) 1 () ((var_ref dPdx) (var_ref dPdy)) ))))\n"
+ "\n"
+ " (signature ivec4\n"
+ " (parameters\n"
+ " (declare (in) isampler2D sampler)\n"
+ " (declare (in) vec2 P) \n"
+ " (declare (in) vec2 dPdx) \n"
+ " (declare (in) vec2 dPdy) )\n"
+ " ((return (txd (var_ref sampler) (var_ref P) (0 0 0) 1 () ((var_ref dPdx) (var_ref dPdy)) ))))\n"
+ "\n"
+ " (signature uvec4\n"
+ " (parameters\n"
+ " (declare (in) usampler2D sampler)\n"
+ " (declare (in) vec2 P) \n"
+ " (declare (in) vec2 dPdx) \n"
+ " (declare (in) vec2 dPdy) )\n"
+ " ((return (txd (var_ref sampler) (var_ref P) (0 0 0) 1 () ((var_ref dPdx) (var_ref dPdy)) ))))\n"
+ "\n"
+ " (signature vec4\n"
+ " (parameters\n"
+ " (declare (in) sampler3D sampler)\n"
+ " (declare (in) vec3 P) \n"
+ " (declare (in) vec3 dPdx) \n"
+ " (declare (in) vec3 dPdy) )\n"
+ " ((return (txd (var_ref sampler) (var_ref P) (0 0 0) 1 () ((var_ref dPdx) (var_ref dPdy)) ))))\n"
+ "\n"
+ " (signature ivec4\n"
+ " (parameters\n"
+ " (declare (in) isampler3D sampler)\n"
+ " (declare (in) vec3 P) \n"
+ " (declare (in) vec3 dPdx) \n"
+ " (declare (in) vec3 dPdy) )\n"
+ " ((return (txd (var_ref sampler) (var_ref P) (0 0 0) 1 () ((var_ref dPdx) (var_ref dPdy)) ))))\n"
+ "\n"
+ " (signature uvec4\n"
+ " (parameters\n"
+ " (declare (in) usampler3D sampler)\n"
+ " (declare (in) vec3 P) \n"
+ " (declare (in) vec3 dPdx) \n"
+ " (declare (in) vec3 dPdy) )\n"
+ " ((return (txd (var_ref sampler) (var_ref P) (0 0 0) 1 () ((var_ref dPdx) (var_ref dPdy)) ))))\n"
+ "\n"
+ " (signature vec4\n"
+ " (parameters\n"
+ " (declare (in) samplerCube sampler)\n"
+ " (declare (in) vec3 P) \n"
+ " (declare (in) vec3 dPdx) \n"
+ " (declare (in) vec3 dPdy) )\n"
+ " ((return (txd (var_ref sampler) (var_ref P) (0 0 0) 1 () ((var_ref dPdx) (var_ref dPdy)) ))))\n"
+ "\n"
+ " (signature ivec4\n"
+ " (parameters\n"
+ " (declare (in) isamplerCube sampler)\n"
+ " (declare (in) vec3 P) \n"
+ " (declare (in) vec3 dPdx) \n"
+ " (declare (in) vec3 dPdy) )\n"
+ " ((return (txd (var_ref sampler) (var_ref P) (0 0 0) 1 () ((var_ref dPdx) (var_ref dPdy)) ))))\n"
+ "\n"
+ " (signature uvec4\n"
+ " (parameters\n"
+ " (declare (in) usamplerCube sampler)\n"
+ " (declare (in) vec3 P) \n"
+ " (declare (in) vec3 dPdx) \n"
+ " (declare (in) vec3 dPdy) )\n"
+ " ((return (txd (var_ref sampler) (var_ref P) (0 0 0) 1 () ((var_ref dPdx) (var_ref dPdy)) ))))\n"
+ "\n"
+ " (signature vec4\n"
+ " (parameters\n"
+ " (declare (in) sampler1DArray sampler)\n"
+ " (declare (in) vec2 P) \n"
+ " (declare (in) vec2 dPdx) \n"
+ " (declare (in) vec2 dPdy) )\n"
+ " ((return (txd (var_ref sampler) (var_ref P) (0 0 0) 1 () ((var_ref dPdx) (var_ref dPdy)) ))))\n"
+ "\n"
+ " (signature ivec4\n"
+ " (parameters\n"
+ " (declare (in) isampler1DArray sampler)\n"
+ " (declare (in) vec2 P) \n"
+ " (declare (in) vec2 dPdx) \n"
+ " (declare (in) vec2 dPdy) )\n"
+ " ((return (txd (var_ref sampler) (var_ref P) (0 0 0) 1 () ((var_ref dPdx) (var_ref dPdy)) ))))\n"
+ "\n"
+ " (signature uvec4\n"
+ " (parameters\n"
+ " (declare (in) usampler1DArray sampler)\n"
+ " (declare (in) vec2 P) \n"
+ " (declare (in) vec2 dPdx) \n"
+ " (declare (in) vec2 dPdy) )\n"
+ " ((return (txd (var_ref sampler) (var_ref P) (0 0 0) 1 () ((var_ref dPdx) (var_ref dPdy)) ))))\n"
+ "\n"
+ " (signature vec4\n"
+ " (parameters\n"
+ " (declare (in) sampler2DArray sampler)\n"
+ " (declare (in) vec3 P) \n"
+ " (declare (in) vec3 dPdx) \n"
+ " (declare (in) vec3 dPdy) )\n"
+ " ((return (txd (var_ref sampler) (var_ref P) (0 0 0) 1 () ((var_ref dPdx) (var_ref dPdy)) ))))\n"
+ "\n"
+ " (signature ivec4\n"
+ " (parameters\n"
+ " (declare (in) isampler2DArray sampler)\n"
+ " (declare (in) vec3 P) \n"
+ " (declare (in) vec3 dPdx) \n"
+ " (declare (in) vec3 dPdy) )\n"
+ " ((return (txd (var_ref sampler) (var_ref P) (0 0 0) 1 () ((var_ref dPdx) (var_ref dPdy)) ))))\n"
+ "\n"
+ " (signature uvec4\n"
+ " (parameters\n"
+ " (declare (in) usampler2DArray sampler)\n"
+ " (declare (in) vec3 P) \n"
+ " (declare (in) vec3 dPdx) \n"
+ " (declare (in) vec3 dPdy) )\n"
+ " ((return (txd (var_ref sampler) (var_ref P) (0 0 0) 1 () ((var_ref dPdx) (var_ref dPdy)) ))))\n"
+ "\n"
+ "))\n"
+ ""
+;
+static const char *builtin_clamp =
+ "((function clamp\n"
+ " (signature float\n"
+ " (parameters\n"
+ " (declare (in) float arg0)\n"
+ " (declare (in) float arg1)\n"
+ " (declare (in) float arg2))\n"
+ " ((return (expression float max (expression float min (var_ref arg0) (var_ref arg2)) (var_ref arg1)))))\n"
+ "\n"
+ " (signature vec2\n"
+ " (parameters\n"
+ " (declare (in) vec2 arg0)\n"
+ " (declare (in) vec2 arg1)\n"
+ " (declare (in) vec2 arg2))\n"
+ " ((return (expression vec2 max (expression vec2 min (var_ref arg0) (var_ref arg2)) (var_ref arg1)))))\n"
+ "\n"
+ " (signature vec3\n"
+ " (parameters\n"
+ " (declare (in) vec3 arg0)\n"
+ " (declare (in) vec3 arg1)\n"
+ " (declare (in) vec3 arg2))\n"
+ " ((return (expression vec3 max (expression vec3 min (var_ref arg0) (var_ref arg2)) (var_ref arg1)))))\n"
+ "\n"
+ " (signature vec4\n"
+ " (parameters\n"
+ " (declare (in) vec4 arg0)\n"
+ " (declare (in) vec4 arg1)\n"
+ " (declare (in) vec4 arg2))\n"
+ " ((return (expression vec4 max (expression vec4 min (var_ref arg0) (var_ref arg2)) (var_ref arg1)))))\n"
+ "\n"
+ " (signature vec2\n"
+ " (parameters\n"
+ " (declare (in) vec2 arg0)\n"
+ " (declare (in) float arg1)\n"
+ " (declare (in) float arg2))\n"
+ " ((return (expression vec2 max (expression vec2 min (var_ref arg0) (var_ref arg2)) (var_ref arg1)))))\n"
+ "\n"
+ " (signature vec3\n"
+ " (parameters\n"
+ " (declare (in) vec3 arg0)\n"
+ " (declare (in) float arg1)\n"
+ " (declare (in) float arg2))\n"
+ " ((return (expression vec3 max (expression vec3 min (var_ref arg0) (var_ref arg2)) (var_ref arg1)))))\n"
+ "\n"
+ " (signature vec4\n"
+ " (parameters\n"
+ " (declare (in) vec4 arg0)\n"
+ " (declare (in) float arg1)\n"
+ " (declare (in) float arg2))\n"
+ " ((return (expression vec4 max (expression vec4 min (var_ref arg0) (var_ref arg2)) (var_ref arg1)))))\n"
+ "\n"
+ " (signature int\n"
+ " (parameters\n"
+ " (declare (in) int arg0)\n"
+ " (declare (in) int arg1)\n"
+ " (declare (in) int arg2))\n"
+ " ((return (expression int max (expression int min (var_ref arg0) (var_ref arg2)) (var_ref arg1)))))\n"
+ "\n"
+ " (signature ivec2\n"
+ " (parameters\n"
+ " (declare (in) ivec2 arg0)\n"
+ " (declare (in) ivec2 arg1)\n"
+ " (declare (in) ivec2 arg2))\n"
+ " ((return (expression ivec2 max (expression ivec2 min (var_ref arg0) (var_ref arg2)) (var_ref arg1)))))\n"
+ "\n"
+ " (signature ivec3\n"
+ " (parameters\n"
+ " (declare (in) ivec3 arg0)\n"
+ " (declare (in) ivec3 arg1)\n"
+ " (declare (in) ivec3 arg2))\n"
+ " ((return (expression ivec3 max (expression ivec3 min (var_ref arg0) (var_ref arg2)) (var_ref arg1)))))\n"
+ "\n"
+ " (signature ivec4\n"
+ " (parameters\n"
+ " (declare (in) ivec4 arg0)\n"
+ " (declare (in) ivec4 arg1)\n"
+ " (declare (in) ivec4 arg2))\n"
+ " ((return (expression ivec4 max (expression ivec4 min (var_ref arg0) (var_ref arg2)) (var_ref arg1)))))\n"
+ "\n"
+ " (signature ivec2\n"
+ " (parameters\n"
+ " (declare (in) ivec2 arg0)\n"
+ " (declare (in) int arg1)\n"
+ " (declare (in) int arg2))\n"
+ " ((return (expression ivec2 max (expression ivec2 min (var_ref arg0) (var_ref arg2)) (var_ref arg1)))))\n"
+ "\n"
+ " (signature ivec3\n"
+ " (parameters\n"
+ " (declare (in) ivec3 arg0)\n"
+ " (declare (in) int arg1)\n"
+ " (declare (in) int arg2))\n"
+ " ((return (expression ivec3 max (expression ivec3 min (var_ref arg0) (var_ref arg2)) (var_ref arg1)))))\n"
+ "\n"
+ " (signature ivec4\n"
+ " (parameters\n"
+ " (declare (in) ivec4 arg0)\n"
+ " (declare (in) int arg1)\n"
+ " (declare (in) int arg2))\n"
+ " ((return (expression ivec4 max (expression ivec4 min (var_ref arg0) (var_ref arg2)) (var_ref arg1)))))\n"
+ "\n"
+ " (signature uint\n"
+ " (parameters\n"
+ " (declare (in) uint arg0)\n"
+ " (declare (in) uint arg1)\n"
+ " (declare (in) uint arg2))\n"
+ " ((return (expression uint max (expression uint min (var_ref arg0) (var_ref arg2)) (var_ref arg1)))))\n"
+ "\n"
+ " (signature uvec2\n"
+ " (parameters\n"
+ " (declare (in) uvec2 arg0)\n"
+ " (declare (in) uvec2 arg1)\n"
+ " (declare (in) uvec2 arg2))\n"
+ " ((return (expression uvec2 max (expression uvec2 min (var_ref arg0) (var_ref arg2)) (var_ref arg1)))))\n"
+ "\n"
+ " (signature uvec3\n"
+ " (parameters\n"
+ " (declare (in) uvec3 arg0)\n"
+ " (declare (in) uvec3 arg1)\n"
+ " (declare (in) uvec3 arg2))\n"
+ " ((return (expression uvec3 max (expression uvec3 min (var_ref arg0) (var_ref arg2)) (var_ref arg1)))))\n"
+ "\n"
+ " (signature uvec4\n"
+ " (parameters\n"
+ " (declare (in) uvec4 arg0)\n"
+ " (declare (in) uvec4 arg1)\n"
+ " (declare (in) uvec4 arg2))\n"
+ " ((return (expression uvec4 max (expression uvec4 min (var_ref arg0) (var_ref arg2)) (var_ref arg1)))))\n"
+ "\n"
+ " (signature uvec2\n"
+ " (parameters\n"
+ " (declare (in) uvec2 arg0)\n"
+ " (declare (in) uint arg1)\n"
+ " (declare (in) uint arg2))\n"
+ " ((return (expression uvec2 max (expression uvec2 min (var_ref arg0) (var_ref arg2)) (var_ref arg1)))))\n"
+ "\n"
+ " (signature uvec3\n"
+ " (parameters\n"
+ " (declare (in) uvec3 arg0)\n"
+ " (declare (in) uint arg1)\n"
+ " (declare (in) uint arg2))\n"
+ " ((return (expression uvec3 max (expression uvec3 min (var_ref arg0) (var_ref arg2)) (var_ref arg1)))))\n"
+ "\n"
+ " (signature uvec4\n"
+ " (parameters\n"
+ " (declare (in) uvec4 arg0)\n"
+ " (declare (in) uint arg1)\n"
+ " (declare (in) uint arg2))\n"
+ " ((return (expression uvec4 max (expression uvec4 min (var_ref arg0) (var_ref arg2)) (var_ref arg1)))))\n"
+ "))\n"
+ ""
+;
+static const char *builtin_texture2DRect =
+ "((function texture2DRect\n"
+ " (signature vec4\n"
+ " (parameters\n"
+ " (declare (in) sampler2DRect sampler)\n"
+ " (declare (in) vec2 P) )\n"
+ " ((return (tex (var_ref sampler) (var_ref P) (0 0 0) 1 () ))))\n"
+ "\n"
+ "))\n"
+ ""
+;
+static const char *builtin_cosh =
+ "((function cosh\n"
+ " (signature float\n"
+ " (parameters\n"
+ " (declare (in) float x))\n"
+ " ((return (expression float * (constant float (0.5))\n"
+ " (expression float +\n"
+ " (expression float exp (var_ref x))\n"
+ " (expression float exp (expression float neg (var_ref x))))))))\n"
+ " (signature vec2\n"
+ " (parameters\n"
+ " (declare (in) vec2 x))\n"
+ " ((return (expression vec2 * (constant vec2 (0.5))\n"
+ " (expression vec2 +\n"
+ " (expression vec2 exp (var_ref x))\n"
+ " (expression vec2 exp (expression vec2 neg (var_ref x))))))))\n"
+ " (signature vec3\n"
+ " (parameters\n"
+ " (declare (in) vec3 x))\n"
+ " ((return (expression vec3 * (constant vec3 (0.5))\n"
+ " (expression vec3 +\n"
+ " (expression vec3 exp (var_ref x))\n"
+ " (expression vec3 exp (expression vec3 neg (var_ref x))))))))\n"
+ " (signature vec4\n"
+ " (parameters\n"
+ " (declare (in) vec4 x))\n"
+ " ((return (expression vec4 * (constant vec4 (0.5))\n"
+ " (expression vec4 +\n"
+ " (expression vec4 exp (var_ref x))\n"
+ " (expression vec4 exp (expression vec4 neg (var_ref x))))))))\n"
+ "))\n"
+ ""
+;
+static const char *builtin_texture1DArrayLod =
+ "((function texture1DArrayLod\n"
+ " (signature vec4\n"
+ " (parameters\n"
+ " (declare (in) sampler1DArray sampler)\n"
+ " (declare (in) vec2 P) \n"
+ " (declare (in) float lod) )\n"
+ " ((return (txl (var_ref sampler) (var_ref P) (0 0 0) 1 () (var_ref lod) ))))\n"
+ "\n"
+ "))\n"
+ ""
+;
+static const char *builtin_asin =
+ "((function asin\n"
+ " (signature float\n"
+ " (parameters\n"
+ " (declare (in) float x))\n"
+ " ((return (expression float *\n"
+ " (expression float sign (var_ref x))\n"
+ " (expression float -\n"
+ " (expression float *\n"
+ " (constant float (3.1415926))\n"
+ " (constant float (0.5)))\n"
+ " (expression float *\n"
+ " (expression float sqrt\n"
+ " (expression float -\n"
+ " (constant float (1.0))\n"
+ " (expression float abs (var_ref x))))\n"
+ " (expression float +\n"
+ " (constant float (1.5707288))\n"
+ " (expression float *\n"
+ " (expression float abs (var_ref x))\n"
+ " (expression float +\n"
+ " (constant float (-0.2121144))\n"
+ " (expression float *\n"
+ " (constant float (0.0742610))\n"
+ " (expression float abs (var_ref x))))))))))))\n"
+ "\n"
+ " (signature vec2\n"
+ " (parameters\n"
+ " (declare (in) vec2 x))\n"
+ " ((return (expression vec2 *\n"
+ " (expression vec2 sign (var_ref x))\n"
+ " (expression vec2 -\n"
+ " (expression float *\n"
+ " (constant float (3.1415926))\n"
+ " (constant float (0.5)))\n"
+ " (expression vec2 *\n"
+ " (expression vec2 sqrt\n"
+ " (expression vec2 -\n"
+ " (constant float (1.0))\n"
+ " (expression vec2 abs (var_ref x))))\n"
+ " (expression vec2 +\n"
+ " (constant float (1.5707288))\n"
+ " (expression vec2 *\n"
+ " (expression vec2 abs (var_ref x))\n"
+ " (expression vec2 +\n"
+ " (constant float (-0.2121144))\n"
+ " (expression vec2 *\n"
+ " (constant float (0.0742610))\n"
+ " (expression vec2 abs (var_ref x))))))))))))\n"
+ "\n"
+ " (signature vec3\n"
+ " (parameters\n"
+ " (declare (in) vec3 x))\n"
+ " ((return (expression vec3 *\n"
+ " (expression vec3 sign (var_ref x))\n"
+ " (expression vec3 -\n"
+ " (expression float *\n"
+ " (constant float (3.1415926))\n"
+ " (constant float (0.5)))\n"
+ " (expression vec3 *\n"
+ " (expression vec3 sqrt\n"
+ " (expression vec3 -\n"
+ " (constant float (1.0))\n"
+ " (expression vec3 abs (var_ref x))))\n"
+ " (expression vec3 +\n"
+ " (constant float (1.5707288))\n"
+ " (expression vec3 *\n"
+ " (expression vec3 abs (var_ref x))\n"
+ " (expression vec3 +\n"
+ " (constant float (-0.2121144))\n"
+ " (expression vec3 *\n"
+ " (constant float (0.0742610))\n"
+ " (expression vec3 abs (var_ref x))))))))))))\n"
+ "\n"
+ " (signature vec4\n"
+ " (parameters\n"
+ " (declare (in) vec4 x))\n"
+ " ((return (expression vec4 *\n"
+ " (expression vec4 sign (var_ref x))\n"
+ " (expression vec4 -\n"
+ " (expression float *\n"
+ " (constant float (3.1415926))\n"
+ " (constant float (0.5)))\n"
+ " (expression vec4 *\n"
+ " (expression vec4 sqrt\n"
+ " (expression vec4 -\n"
+ " (constant float (1.0))\n"
+ " (expression vec4 abs (var_ref x))))\n"
+ " (expression vec4 +\n"
+ " (constant float (1.5707288))\n"
+ " (expression vec4 *\n"
+ " (expression vec4 abs (var_ref x))\n"
+ " (expression vec4 +\n"
+ " (constant float (-0.2121144))\n"
+ " (expression vec4 *\n"
+ " (constant float (0.0742610))\n"
+ " (expression vec4 abs (var_ref x))))))))))))\n"
+ "))\n"
+ ""
+;
+static const char *builtin_texture1DProj =
+ "((function texture1DProj\n"
+ " (signature vec4\n"
+ " (parameters\n"
+ " (declare (in) sampler1D sampler)\n"
+ " (declare (in) vec2 P) )\n"
+ " ((return (tex (var_ref sampler) (swiz x (var_ref P)) (0 0 0) (swiz y (var_ref P)) () ))))\n"
+ "\n"
+ " (signature vec4\n"
+ " (parameters\n"
+ " (declare (in) sampler1D sampler)\n"
+ " (declare (in) vec4 P) )\n"
+ " ((return (tex (var_ref sampler) (swiz x (var_ref P)) (0 0 0) (swiz w (var_ref P)) () ))))\n"
+ "\n"
+ " (signature vec4\n"
+ " (parameters\n"
+ " (declare (in) sampler1D sampler)\n"
+ " (declare (in) vec2 P) \n"
+ " (declare (in) float bias) )\n"
+ " ((return (txb (var_ref sampler) (swiz x (var_ref P)) (0 0 0) (swiz y (var_ref P)) () (var_ref bias) ))))\n"
+ "\n"
+ " (signature vec4\n"
+ " (parameters\n"
+ " (declare (in) sampler1D sampler)\n"
+ " (declare (in) vec4 P) \n"
+ " (declare (in) float bias) )\n"
+ " ((return (txb (var_ref sampler) (swiz x (var_ref P)) (0 0 0) (swiz w (var_ref P)) () (var_ref bias) ))))\n"
+ "\n"
+ "))\n"
+ ""
+;
+static const char *builtin_lessThan =
+ "((function lessThan\n"
+ " (signature bvec2\n"
+ " (parameters\n"
+ " (declare (in) vec2 arg0)\n"
+ " (declare (in) vec2 arg1))\n"
+ " ((declare () bvec2 temp)\n"
+ " (assign (constant bool (1)) (swiz x (var_ref temp)) (expression bool < (swiz x (var_ref arg0))(swiz x (var_ref arg1)))) \n"
+ " (assign (constant bool (1)) (swiz y (var_ref temp)) (expression bool < (swiz y (var_ref arg0))(swiz y (var_ref arg1)))) \n"
+ " (return (var_ref temp))))\n"
+ "\n"
+ " (signature bvec3\n"
+ " (parameters\n"
+ " (declare (in) vec3 arg0)\n"
+ " (declare (in) vec3 arg1))\n"
+ " ((declare () bvec3 temp)\n"
+ " (assign (constant bool (1)) (swiz x (var_ref temp)) (expression bool < (swiz x (var_ref arg0))(swiz x (var_ref arg1)))) \n"
+ " (assign (constant bool (1)) (swiz y (var_ref temp)) (expression bool < (swiz y (var_ref arg0))(swiz y (var_ref arg1)))) \n"
+ " (assign (constant bool (1)) (swiz z (var_ref temp)) (expression bool < (swiz z (var_ref arg0))(swiz z (var_ref arg1)))) \n"
+ " (return (var_ref temp))))\n"
+ "\n"
+ " (signature bvec4\n"
+ " (parameters\n"
+ " (declare (in) vec4 arg0)\n"
+ " (declare (in) vec4 arg1))\n"
+ " ((declare () bvec4 temp)\n"
+ " (assign (constant bool (1)) (swiz x (var_ref temp)) (expression bool < (swiz x (var_ref arg0))(swiz x (var_ref arg1)))) \n"
+ " (assign (constant bool (1)) (swiz y (var_ref temp)) (expression bool < (swiz y (var_ref arg0))(swiz y (var_ref arg1)))) \n"
+ " (assign (constant bool (1)) (swiz z (var_ref temp)) (expression bool < (swiz z (var_ref arg0))(swiz z (var_ref arg1)))) \n"
+ " (assign (constant bool (1)) (swiz w (var_ref temp)) (expression bool < (swiz w (var_ref arg0))(swiz w (var_ref arg1)))) \n"
+ " (return (var_ref temp))))\n"
+ "\n"
+ " (signature bvec2\n"
+ " (parameters\n"
+ " (declare (in) ivec2 arg0)\n"
+ " (declare (in) ivec2 arg1))\n"
+ " ((declare () bvec2 temp)\n"
+ " (assign (constant bool (1)) (swiz x (var_ref temp)) (expression bool < (swiz x (var_ref arg0))(swiz x (var_ref arg1)))) \n"
+ " (assign (constant bool (1)) (swiz y (var_ref temp)) (expression bool < (swiz y (var_ref arg0))(swiz y (var_ref arg1)))) \n"
+ " (return (var_ref temp))))\n"
+ "\n"
+ " (signature bvec3\n"
+ " (parameters\n"
+ " (declare (in) ivec3 arg0)\n"
+ " (declare (in) ivec3 arg1))\n"
+ " ((declare () bvec3 temp)\n"
+ " (assign (constant bool (1)) (swiz x (var_ref temp)) (expression bool < (swiz x (var_ref arg0))(swiz x (var_ref arg1)))) \n"
+ " (assign (constant bool (1)) (swiz y (var_ref temp)) (expression bool < (swiz y (var_ref arg0))(swiz y (var_ref arg1)))) \n"
+ " (assign (constant bool (1)) (swiz z (var_ref temp)) (expression bool < (swiz z (var_ref arg0))(swiz z (var_ref arg1)))) \n"
+ " (return (var_ref temp))))\n"
+ "\n"
+ " (signature bvec4\n"
+ " (parameters\n"
+ " (declare (in) ivec4 arg0)\n"
+ " (declare (in) ivec4 arg1))\n"
+ " ((declare () bvec4 temp)\n"
+ " (assign (constant bool (1)) (swiz x (var_ref temp)) (expression bool < (swiz x (var_ref arg0))(swiz x (var_ref arg1)))) \n"
+ " (assign (constant bool (1)) (swiz y (var_ref temp)) (expression bool < (swiz y (var_ref arg0))(swiz y (var_ref arg1)))) \n"
+ " (assign (constant bool (1)) (swiz z (var_ref temp)) (expression bool < (swiz z (var_ref arg0))(swiz z (var_ref arg1)))) \n"
+ " (assign (constant bool (1)) (swiz w (var_ref temp)) (expression bool < (swiz w (var_ref arg0))(swiz w (var_ref arg1)))) \n"
+ " (return (var_ref temp))))\n"
+ "\n"
+ " (signature bvec2\n"
+ " (parameters\n"
+ " (declare (in) uvec2 arg0)\n"
+ " (declare (in) uvec2 arg1))\n"
+ " ((declare () bvec2 temp)\n"
+ " (assign (constant bool (1)) (swiz x (var_ref temp)) (expression bool < (swiz x (var_ref arg0))(swiz x (var_ref arg1)))) \n"
+ " (assign (constant bool (1)) (swiz y (var_ref temp)) (expression bool < (swiz y (var_ref arg0))(swiz y (var_ref arg1)))) \n"
+ " (return (var_ref temp))))\n"
+ "\n"
+ " (signature bvec3\n"
+ " (parameters\n"
+ " (declare (in) uvec3 arg0)\n"
+ " (declare (in) uvec3 arg1))\n"
+ " ((declare () bvec3 temp)\n"
+ " (assign (constant bool (1)) (swiz x (var_ref temp)) (expression bool < (swiz x (var_ref arg0))(swiz x (var_ref arg1)))) \n"
+ " (assign (constant bool (1)) (swiz y (var_ref temp)) (expression bool < (swiz y (var_ref arg0))(swiz y (var_ref arg1)))) \n"
+ " (assign (constant bool (1)) (swiz z (var_ref temp)) (expression bool < (swiz z (var_ref arg0))(swiz z (var_ref arg1)))) \n"
+ " (return (var_ref temp))))\n"
+ "\n"
+ " (signature bvec4\n"
+ " (parameters\n"
+ " (declare (in) uvec4 arg0)\n"
+ " (declare (in) uvec4 arg1))\n"
+ " ((declare () bvec4 temp)\n"
+ " (assign (constant bool (1)) (swiz x (var_ref temp)) (expression bool < (swiz x (var_ref arg0))(swiz x (var_ref arg1)))) \n"
+ " (assign (constant bool (1)) (swiz y (var_ref temp)) (expression bool < (swiz y (var_ref arg0))(swiz y (var_ref arg1)))) \n"
+ " (assign (constant bool (1)) (swiz z (var_ref temp)) (expression bool < (swiz z (var_ref arg0))(swiz z (var_ref arg1)))) \n"
+ " (assign (constant bool (1)) (swiz w (var_ref temp)) (expression bool < (swiz w (var_ref arg0))(swiz w (var_ref arg1)))) \n"
+ " (return (var_ref temp))))\n"
+ "))\n"
+ ""
+;
+static const char *builtin_shadow2DProj =
+ "((function shadow2DProj\n"
+ " (signature vec4\n"
+ " (parameters\n"
+ " (declare (in) sampler2DShadow sampler)\n"
+ " (declare (in) vec4 P) )\n"
+ " ((return (tex (var_ref sampler) (swiz xy (var_ref P)) (0 0 0) (swiz w (var_ref P)) (swiz z (var_ref P)) ))))\n"
+ "\n"
+ " (signature vec4\n"
+ " (parameters\n"
+ " (declare (in) sampler2DShadow sampler)\n"
+ " (declare (in) vec4 P) \n"
+ " (declare (in) float bias) )\n"
+ " ((return (txb (var_ref sampler) (swiz xy (var_ref P)) (0 0 0) (swiz w (var_ref P)) (swiz z (var_ref P)) (var_ref bias) ))))\n"
+ "\n"
+ "))\n"
+ ""
+;
+static const char *builtin_textureLod =
+ "((function textureLod\n"
+ " (signature vec4\n"
+ " (parameters\n"
+ " (declare (in) sampler1D sampler)\n"
+ " (declare (in) float P) \n"
+ " (declare (in) float lod) )\n"
+ " ((return (txl (var_ref sampler) (var_ref P) (0 0 0) 1 () (var_ref lod) ))))\n"
+ "\n"
+ " (signature ivec4\n"
+ " (parameters\n"
+ " (declare (in) isampler1D sampler)\n"
+ " (declare (in) float P) \n"
+ " (declare (in) float lod) )\n"
+ " ((return (txl (var_ref sampler) (var_ref P) (0 0 0) 1 () (var_ref lod) ))))\n"
+ "\n"
+ " (signature uvec4\n"
+ " (parameters\n"
+ " (declare (in) usampler1D sampler)\n"
+ " (declare (in) float P) \n"
+ " (declare (in) float lod) )\n"
+ " ((return (txl (var_ref sampler) (var_ref P) (0 0 0) 1 () (var_ref lod) ))))\n"
+ "\n"
+ " (signature vec4\n"
+ " (parameters\n"
+ " (declare (in) sampler2D sampler)\n"
+ " (declare (in) vec2 P) \n"
+ " (declare (in) float lod) )\n"
+ " ((return (txl (var_ref sampler) (var_ref P) (0 0 0) 1 () (var_ref lod) ))))\n"
+ "\n"
+ " (signature ivec4\n"
+ " (parameters\n"
+ " (declare (in) isampler2D sampler)\n"
+ " (declare (in) vec2 P) \n"
+ " (declare (in) float lod) )\n"
+ " ((return (txl (var_ref sampler) (var_ref P) (0 0 0) 1 () (var_ref lod) ))))\n"
+ "\n"
+ " (signature uvec4\n"
+ " (parameters\n"
+ " (declare (in) usampler2D sampler)\n"
+ " (declare (in) vec2 P) \n"
+ " (declare (in) float lod) )\n"
+ " ((return (txl (var_ref sampler) (var_ref P) (0 0 0) 1 () (var_ref lod) ))))\n"
+ "\n"
+ " (signature vec4\n"
+ " (parameters\n"
+ " (declare (in) sampler3D sampler)\n"
+ " (declare (in) vec3 P) \n"
+ " (declare (in) float lod) )\n"
+ " ((return (txl (var_ref sampler) (var_ref P) (0 0 0) 1 () (var_ref lod) ))))\n"
+ "\n"
+ " (signature ivec4\n"
+ " (parameters\n"
+ " (declare (in) isampler3D sampler)\n"
+ " (declare (in) vec3 P) \n"
+ " (declare (in) float lod) )\n"
+ " ((return (txl (var_ref sampler) (var_ref P) (0 0 0) 1 () (var_ref lod) ))))\n"
+ "\n"
+ " (signature uvec4\n"
+ " (parameters\n"
+ " (declare (in) usampler3D sampler)\n"
+ " (declare (in) vec3 P) \n"
+ " (declare (in) float lod) )\n"
+ " ((return (txl (var_ref sampler) (var_ref P) (0 0 0) 1 () (var_ref lod) ))))\n"
+ "\n"
+ " (signature vec4\n"
+ " (parameters\n"
+ " (declare (in) samplerCube sampler)\n"
+ " (declare (in) vec3 P) \n"
+ " (declare (in) float lod) )\n"
+ " ((return (txl (var_ref sampler) (var_ref P) (0 0 0) 1 () (var_ref lod) ))))\n"
+ "\n"
+ " (signature ivec4\n"
+ " (parameters\n"
+ " (declare (in) isamplerCube sampler)\n"
+ " (declare (in) vec3 P) \n"
+ " (declare (in) float lod) )\n"
+ " ((return (txl (var_ref sampler) (var_ref P) (0 0 0) 1 () (var_ref lod) ))))\n"
+ "\n"
+ " (signature uvec4\n"
+ " (parameters\n"
+ " (declare (in) usamplerCube sampler)\n"
+ " (declare (in) vec3 P) \n"
+ " (declare (in) float lod) )\n"
+ " ((return (txl (var_ref sampler) (var_ref P) (0 0 0) 1 () (var_ref lod) ))))\n"
+ "\n"
+ " (signature vec4\n"
+ " (parameters\n"
+ " (declare (in) sampler1DArray sampler)\n"
+ " (declare (in) vec2 P) \n"
+ " (declare (in) float lod) )\n"
+ " ((return (txl (var_ref sampler) (var_ref P) (0 0 0) 1 () (var_ref lod) ))))\n"
+ "\n"
+ " (signature ivec4\n"
+ " (parameters\n"
+ " (declare (in) isampler1DArray sampler)\n"
+ " (declare (in) vec2 P) \n"
+ " (declare (in) float lod) )\n"
+ " ((return (txl (var_ref sampler) (var_ref P) (0 0 0) 1 () (var_ref lod) ))))\n"
+ "\n"
+ " (signature uvec4\n"
+ " (parameters\n"
+ " (declare (in) usampler1DArray sampler)\n"
+ " (declare (in) vec2 P) \n"
+ " (declare (in) float lod) )\n"
+ " ((return (txl (var_ref sampler) (var_ref P) (0 0 0) 1 () (var_ref lod) ))))\n"
+ "\n"
+ " (signature vec4\n"
+ " (parameters\n"
+ " (declare (in) sampler2DArray sampler)\n"
+ " (declare (in) vec3 P) \n"
+ " (declare (in) float lod) )\n"
+ " ((return (txl (var_ref sampler) (var_ref P) (0 0 0) 1 () (var_ref lod) ))))\n"
+ "\n"
+ " (signature ivec4\n"
+ " (parameters\n"
+ " (declare (in) isampler2DArray sampler)\n"
+ " (declare (in) vec3 P) \n"
+ " (declare (in) float lod) )\n"
+ " ((return (txl (var_ref sampler) (var_ref P) (0 0 0) 1 () (var_ref lod) ))))\n"
+ "\n"
+ " (signature uvec4\n"
+ " (parameters\n"
+ " (declare (in) usampler2DArray sampler)\n"
+ " (declare (in) vec3 P) \n"
+ " (declare (in) float lod) )\n"
+ " ((return (txl (var_ref sampler) (var_ref P) (0 0 0) 1 () (var_ref lod) ))))\n"
+ "\n"
+ "))\n"
+ ""
+;
+static const char *builtin_faceforward =
+ "((function faceforward\n"
+ " (signature float\n"
+ " (parameters\n"
+ " (declare (in) float N)\n"
+ " (declare (in) float I)\n"
+ " (declare (in) float Nref))\n"
+ " ((if (expression bool < (expression float dot (var_ref Nref) (var_ref I)) (constant float (0)))\n"
+ " ((return (var_ref N)))\n"
+ " ((return (expression float neg (var_ref N)))))))\n"
+ "\n"
+ " (signature vec2\n"
+ " (parameters\n"
+ " (declare (in) vec2 N)\n"
+ " (declare (in) vec2 I)\n"
+ " (declare (in) vec2 Nref))\n"
+ " ((if (expression bool < (expression float dot (var_ref Nref) (var_ref I)) (constant float (0)))\n"
+ " ((return (var_ref N)))\n"
+ " ((return (expression vec2 neg (var_ref N)))))))\n"
+ "\n"
+ " (signature vec3\n"
+ " (parameters\n"
+ " (declare (in) vec3 N)\n"
+ " (declare (in) vec3 I)\n"
+ " (declare (in) vec3 Nref))\n"
+ " ((if (expression bool < (expression float dot (var_ref Nref) (var_ref I)) (constant float (0)))\n"
+ " ((return (var_ref N)))\n"
+ " ((return (expression vec3 neg (var_ref N)))))))\n"
+ "\n"
+ " (signature vec4\n"
+ " (parameters\n"
+ " (declare (in) vec4 N)\n"
+ " (declare (in) vec4 I)\n"
+ " (declare (in) vec4 Nref))\n"
+ " ((if (expression bool < (expression float dot (var_ref Nref) (var_ref I)) (constant float (0)))\n"
+ " ((return (var_ref N)))\n"
+ " ((return (expression vec4 neg (var_ref N)))))))\n"
+ "))\n"
+ ""
+;
+static const char *builtin_abs =
+ "((function abs\n"
+ " (signature float\n"
+ " (parameters\n"
+ " (declare (in) float arg0))\n"
+ " ((return (expression float abs (var_ref arg0)))))\n"
+ "\n"
+ " (signature vec2\n"
+ " (parameters\n"
+ " (declare (in) vec2 arg0))\n"
+ " ((return (expression vec2 abs (var_ref arg0)))))\n"
+ "\n"
+ " (signature vec3\n"
+ " (parameters\n"
+ " (declare (in) vec3 arg0))\n"
+ " ((return (expression vec3 abs (var_ref arg0)))))\n"
+ "\n"
+ " (signature vec4\n"
+ " (parameters\n"
+ " (declare (in) vec4 arg0))\n"
+ " ((return (expression vec4 abs (var_ref arg0)))))\n"
+ "))\n"
+ ""
+;
+static const char *builtin_log2 =
+ "((function log2\n"
+ " (signature float\n"
+ " (parameters\n"
+ " (declare (in) float arg0))\n"
+ " ((return (expression float log2 (var_ref arg0)))))\n"
+ "\n"
+ " (signature vec2\n"
+ " (parameters\n"
+ " (declare (in) vec2 arg0))\n"
+ " ((return (expression vec2 log2 (var_ref arg0)))))\n"
+ "\n"
+ " (signature vec3\n"
+ " (parameters\n"
+ " (declare (in) vec3 arg0))\n"
+ " ((return (expression vec3 log2 (var_ref arg0)))))\n"
+ "\n"
+ " (signature vec4\n"
+ " (parameters\n"
+ " (declare (in) vec4 arg0))\n"
+ " ((return (expression vec4 log2 (var_ref arg0)))))\n"
+ "))\n"
+ ""
+;
+static const char *builtin_shadow2DRect =
+ "((function shadow2DRect\n"
+ " (signature vec4\n"
+ " (parameters\n"
+ " (declare (in) sampler2DRectShadow sampler)\n"
+ " (declare (in) vec3 P) )\n"
+ " ((return (tex (var_ref sampler) (swiz xy (var_ref P)) (0 0 0) 1 (swiz z (var_ref P)) ))))\n"
+ "\n"
+ "))\n"
+ ""
+;
+static const char *builtin_lessThanEqual =
+ "((function lessThanEqual\n"
+ " (signature bvec2\n"
+ " (parameters\n"
+ " (declare (in) vec2 arg0)\n"
+ " (declare (in) vec2 arg1))\n"
+ " ((declare () bvec2 temp)\n"
+ " (assign (constant bool (1)) (swiz x (var_ref temp)) (expression bool <= (swiz x (var_ref arg0))(swiz x (var_ref arg1)))) \n"
+ " (assign (constant bool (1)) (swiz y (var_ref temp)) (expression bool <= (swiz y (var_ref arg0))(swiz y (var_ref arg1)))) \n"
+ " (return (var_ref temp))))\n"
+ "\n"
+ " (signature bvec3\n"
+ " (parameters\n"
+ " (declare (in) vec3 arg0)\n"
+ " (declare (in) vec3 arg1))\n"
+ " ((declare () bvec3 temp)\n"
+ " (assign (constant bool (1)) (swiz x (var_ref temp)) (expression bool <= (swiz x (var_ref arg0))(swiz x (var_ref arg1)))) \n"
+ " (assign (constant bool (1)) (swiz y (var_ref temp)) (expression bool <= (swiz y (var_ref arg0))(swiz y (var_ref arg1)))) \n"
+ " (assign (constant bool (1)) (swiz z (var_ref temp)) (expression bool <= (swiz z (var_ref arg0))(swiz z (var_ref arg1)))) \n"
+ " (return (var_ref temp))))\n"
+ "\n"
+ " (signature bvec4\n"
+ " (parameters\n"
+ " (declare (in) vec4 arg0)\n"
+ " (declare (in) vec4 arg1))\n"
+ " ((declare () bvec4 temp)\n"
+ " (assign (constant bool (1)) (swiz x (var_ref temp)) (expression bool <= (swiz x (var_ref arg0))(swiz x (var_ref arg1)))) \n"
+ " (assign (constant bool (1)) (swiz y (var_ref temp)) (expression bool <= (swiz y (var_ref arg0))(swiz y (var_ref arg1)))) \n"
+ " (assign (constant bool (1)) (swiz z (var_ref temp)) (expression bool <= (swiz z (var_ref arg0))(swiz z (var_ref arg1)))) \n"
+ " (assign (constant bool (1)) (swiz w (var_ref temp)) (expression bool <= (swiz w (var_ref arg0))(swiz w (var_ref arg1)))) \n"
+ " (return (var_ref temp))))\n"
+ "\n"
+ " (signature bvec2\n"
+ " (parameters\n"
+ " (declare (in) ivec2 arg0)\n"
+ " (declare (in) ivec2 arg1))\n"
+ " ((declare () bvec2 temp)\n"
+ " (assign (constant bool (1)) (swiz x (var_ref temp)) (expression bool <= (swiz x (var_ref arg0))(swiz x (var_ref arg1)))) \n"
+ " (assign (constant bool (1)) (swiz y (var_ref temp)) (expression bool <= (swiz y (var_ref arg0))(swiz y (var_ref arg1)))) \n"
+ " (return (var_ref temp))))\n"
+ "\n"
+ " (signature bvec3\n"
+ " (parameters\n"
+ " (declare (in) ivec3 arg0)\n"
+ " (declare (in) ivec3 arg1))\n"
+ " ((declare () bvec3 temp)\n"
+ " (assign (constant bool (1)) (swiz x (var_ref temp)) (expression bool <= (swiz x (var_ref arg0))(swiz x (var_ref arg1)))) \n"
+ " (assign (constant bool (1)) (swiz y (var_ref temp)) (expression bool <= (swiz y (var_ref arg0))(swiz y (var_ref arg1)))) \n"
+ " (assign (constant bool (1)) (swiz z (var_ref temp)) (expression bool <= (swiz z (var_ref arg0))(swiz z (var_ref arg1)))) \n"
+ " (return (var_ref temp))))\n"
+ "\n"
+ " (signature bvec4\n"
+ " (parameters\n"
+ " (declare (in) ivec4 arg0)\n"
+ " (declare (in) ivec4 arg1))\n"
+ " ((declare () bvec4 temp)\n"
+ " (assign (constant bool (1)) (swiz x (var_ref temp)) (expression bool <= (swiz x (var_ref arg0))(swiz x (var_ref arg1)))) \n"
+ " (assign (constant bool (1)) (swiz y (var_ref temp)) (expression bool <= (swiz y (var_ref arg0))(swiz y (var_ref arg1)))) \n"
+ " (assign (constant bool (1)) (swiz z (var_ref temp)) (expression bool <= (swiz z (var_ref arg0))(swiz z (var_ref arg1)))) \n"
+ " (assign (constant bool (1)) (swiz w (var_ref temp)) (expression bool <= (swiz w (var_ref arg0))(swiz w (var_ref arg1)))) \n"
+ " (return (var_ref temp))))\n"
+ "\n"
+ " (signature bvec2\n"
+ " (parameters\n"
+ " (declare (in) uvec2 arg0)\n"
+ " (declare (in) uvec2 arg1))\n"
+ " ((declare () bvec2 temp)\n"
+ " (assign (constant bool (1)) (swiz x (var_ref temp)) (expression bool <= (swiz x (var_ref arg0))(swiz x (var_ref arg1)))) \n"
+ " (assign (constant bool (1)) (swiz y (var_ref temp)) (expression bool <= (swiz y (var_ref arg0))(swiz y (var_ref arg1)))) \n"
+ " (return (var_ref temp))))\n"
+ "\n"
+ " (signature bvec3\n"
+ " (parameters\n"
+ " (declare (in) uvec3 arg0)\n"
+ " (declare (in) uvec3 arg1))\n"
+ " ((declare () bvec3 temp)\n"
+ " (assign (constant bool (1)) (swiz x (var_ref temp)) (expression bool <= (swiz x (var_ref arg0))(swiz x (var_ref arg1)))) \n"
+ " (assign (constant bool (1)) (swiz y (var_ref temp)) (expression bool <= (swiz y (var_ref arg0))(swiz y (var_ref arg1)))) \n"
+ " (assign (constant bool (1)) (swiz z (var_ref temp)) (expression bool <= (swiz z (var_ref arg0))(swiz z (var_ref arg1)))) \n"
+ " (return (var_ref temp))))\n"
+ "\n"
+ " (signature bvec4\n"
+ " (parameters\n"
+ " (declare (in) uvec4 arg0)\n"
+ " (declare (in) uvec4 arg1))\n"
+ " ((declare () bvec4 temp)\n"
+ " (assign (constant bool (1)) (swiz x (var_ref temp)) (expression bool <= (swiz x (var_ref arg0))(swiz x (var_ref arg1)))) \n"
+ " (assign (constant bool (1)) (swiz y (var_ref temp)) (expression bool <= (swiz y (var_ref arg0))(swiz y (var_ref arg1)))) \n"
+ " (assign (constant bool (1)) (swiz z (var_ref temp)) (expression bool <= (swiz z (var_ref arg0))(swiz z (var_ref arg1)))) \n"
+ " (assign (constant bool (1)) (swiz w (var_ref temp)) (expression bool <= (swiz w (var_ref arg0))(swiz w (var_ref arg1)))) \n"
+ " (return (var_ref temp))))\n"
+ "))\n"
+ ""
+;
+static const char *builtin_transpose =
+ "((function transpose\n"
+ " (signature mat2\n"
+ " (parameters\n"
+ " (declare (in) mat2 m))\n"
+ " ((declare () mat2 t)\n"
+ " (assign (constant bool (1)) (swiz x (array_ref (var_ref t) (constant int (0)))) (swiz x (array_ref (var_ref m) (constant int (0))))) \n"
+ " (assign (constant bool (1)) (swiz x (array_ref (var_ref t) (constant int (1)))) (swiz y (array_ref (var_ref m) (constant int (0))))) \n"
+ " (assign (constant bool (1)) (swiz y (array_ref (var_ref t) (constant int (0)))) (swiz x (array_ref (var_ref m) (constant int (1))))) \n"
+ " (assign (constant bool (1)) (swiz y (array_ref (var_ref t) (constant int (1)))) (swiz y (array_ref (var_ref m) (constant int (1))))) \n"
+ "(return (var_ref t))))\n"
+ "\n"
+ " (signature mat3x2\n"
+ " (parameters\n"
+ " (declare (in) mat2x3 m))\n"
+ " ((declare () mat3x2 t)\n"
+ " (assign (constant bool (1)) (swiz x (array_ref (var_ref t) (constant int (0)))) (swiz x (array_ref (var_ref m) (constant int (0))))) \n"
+ " (assign (constant bool (1)) (swiz x (array_ref (var_ref t) (constant int (1)))) (swiz y (array_ref (var_ref m) (constant int (0))))) \n"
+ " (assign (constant bool (1)) (swiz x (array_ref (var_ref t) (constant int (2)))) (swiz z (array_ref (var_ref m) (constant int (0))))) \n"
+ " (assign (constant bool (1)) (swiz y (array_ref (var_ref t) (constant int (0)))) (swiz x (array_ref (var_ref m) (constant int (1))))) \n"
+ " (assign (constant bool (1)) (swiz y (array_ref (var_ref t) (constant int (1)))) (swiz y (array_ref (var_ref m) (constant int (1))))) \n"
+ " (assign (constant bool (1)) (swiz y (array_ref (var_ref t) (constant int (2)))) (swiz z (array_ref (var_ref m) (constant int (1))))) \n"
+ "(return (var_ref t))))\n"
+ "\n"
+ " (signature mat4x2\n"
+ " (parameters\n"
+ " (declare (in) mat2x4 m))\n"
+ " ((declare () mat4x2 t)\n"
+ " (assign (constant bool (1)) (swiz x (array_ref (var_ref t) (constant int (0)))) (swiz x (array_ref (var_ref m) (constant int (0))))) \n"
+ " (assign (constant bool (1)) (swiz x (array_ref (var_ref t) (constant int (1)))) (swiz y (array_ref (var_ref m) (constant int (0))))) \n"
+ " (assign (constant bool (1)) (swiz x (array_ref (var_ref t) (constant int (2)))) (swiz z (array_ref (var_ref m) (constant int (0))))) \n"
+ " (assign (constant bool (1)) (swiz x (array_ref (var_ref t) (constant int (3)))) (swiz w (array_ref (var_ref m) (constant int (0))))) \n"
+ " (assign (constant bool (1)) (swiz y (array_ref (var_ref t) (constant int (0)))) (swiz x (array_ref (var_ref m) (constant int (1))))) \n"
+ " (assign (constant bool (1)) (swiz y (array_ref (var_ref t) (constant int (1)))) (swiz y (array_ref (var_ref m) (constant int (1))))) \n"
+ " (assign (constant bool (1)) (swiz y (array_ref (var_ref t) (constant int (2)))) (swiz z (array_ref (var_ref m) (constant int (1))))) \n"
+ " (assign (constant bool (1)) (swiz y (array_ref (var_ref t) (constant int (3)))) (swiz w (array_ref (var_ref m) (constant int (1))))) \n"
+ "(return (var_ref t))))\n"
+ "\n"
+ " (signature mat2x3\n"
+ " (parameters\n"
+ " (declare (in) mat3x2 m))\n"
+ " ((declare () mat2x3 t)\n"
+ " (assign (constant bool (1)) (swiz x (array_ref (var_ref t) (constant int (0)))) (swiz x (array_ref (var_ref m) (constant int (0))))) \n"
+ " (assign (constant bool (1)) (swiz x (array_ref (var_ref t) (constant int (1)))) (swiz y (array_ref (var_ref m) (constant int (0))))) \n"
+ " (assign (constant bool (1)) (swiz y (array_ref (var_ref t) (constant int (0)))) (swiz x (array_ref (var_ref m) (constant int (1))))) \n"
+ " (assign (constant bool (1)) (swiz y (array_ref (var_ref t) (constant int (1)))) (swiz y (array_ref (var_ref m) (constant int (1))))) \n"
+ " (assign (constant bool (1)) (swiz z (array_ref (var_ref t) (constant int (0)))) (swiz x (array_ref (var_ref m) (constant int (2))))) \n"
+ " (assign (constant bool (1)) (swiz z (array_ref (var_ref t) (constant int (1)))) (swiz y (array_ref (var_ref m) (constant int (2))))) \n"
+ "(return (var_ref t))))\n"
+ "\n"
+ " (signature mat3\n"
+ " (parameters\n"
+ " (declare (in) mat3 m))\n"
+ " ((declare () mat3 t)\n"
+ " (assign (constant bool (1)) (swiz x (array_ref (var_ref t) (constant int (0)))) (swiz x (array_ref (var_ref m) (constant int (0))))) \n"
+ " (assign (constant bool (1)) (swiz x (array_ref (var_ref t) (constant int (1)))) (swiz y (array_ref (var_ref m) (constant int (0))))) \n"
+ " (assign (constant bool (1)) (swiz x (array_ref (var_ref t) (constant int (2)))) (swiz z (array_ref (var_ref m) (constant int (0))))) \n"
+ " (assign (constant bool (1)) (swiz y (array_ref (var_ref t) (constant int (0)))) (swiz x (array_ref (var_ref m) (constant int (1))))) \n"
+ " (assign (constant bool (1)) (swiz y (array_ref (var_ref t) (constant int (1)))) (swiz y (array_ref (var_ref m) (constant int (1))))) \n"
+ " (assign (constant bool (1)) (swiz y (array_ref (var_ref t) (constant int (2)))) (swiz z (array_ref (var_ref m) (constant int (1))))) \n"
+ " (assign (constant bool (1)) (swiz z (array_ref (var_ref t) (constant int (0)))) (swiz x (array_ref (var_ref m) (constant int (2))))) \n"
+ " (assign (constant bool (1)) (swiz z (array_ref (var_ref t) (constant int (1)))) (swiz y (array_ref (var_ref m) (constant int (2))))) \n"
+ " (assign (constant bool (1)) (swiz z (array_ref (var_ref t) (constant int (2)))) (swiz z (array_ref (var_ref m) (constant int (2))))) \n"
+ "(return (var_ref t))))\n"
+ "\n"
+ " (signature mat4x3\n"
+ " (parameters\n"
+ " (declare (in) mat3x4 m))\n"
+ " ((declare () mat4x3 t)\n"
+ " (assign (constant bool (1)) (swiz x (array_ref (var_ref t) (constant int (0)))) (swiz x (array_ref (var_ref m) (constant int (0))))) \n"
+ " (assign (constant bool (1)) (swiz x (array_ref (var_ref t) (constant int (1)))) (swiz y (array_ref (var_ref m) (constant int (0))))) \n"
+ " (assign (constant bool (1)) (swiz x (array_ref (var_ref t) (constant int (2)))) (swiz z (array_ref (var_ref m) (constant int (0))))) \n"
+ " (assign (constant bool (1)) (swiz x (array_ref (var_ref t) (constant int (3)))) (swiz w (array_ref (var_ref m) (constant int (0))))) \n"
+ " (assign (constant bool (1)) (swiz y (array_ref (var_ref t) (constant int (0)))) (swiz x (array_ref (var_ref m) (constant int (1))))) \n"
+ " (assign (constant bool (1)) (swiz y (array_ref (var_ref t) (constant int (1)))) (swiz y (array_ref (var_ref m) (constant int (1))))) \n"
+ " (assign (constant bool (1)) (swiz y (array_ref (var_ref t) (constant int (2)))) (swiz z (array_ref (var_ref m) (constant int (1))))) \n"
+ " (assign (constant bool (1)) (swiz y (array_ref (var_ref t) (constant int (3)))) (swiz w (array_ref (var_ref m) (constant int (1))))) \n"
+ " (assign (constant bool (1)) (swiz z (array_ref (var_ref t) (constant int (0)))) (swiz x (array_ref (var_ref m) (constant int (2))))) \n"
+ " (assign (constant bool (1)) (swiz z (array_ref (var_ref t) (constant int (1)))) (swiz y (array_ref (var_ref m) (constant int (2))))) \n"
+ " (assign (constant bool (1)) (swiz z (array_ref (var_ref t) (constant int (2)))) (swiz z (array_ref (var_ref m) (constant int (2))))) \n"
+ " (assign (constant bool (1)) (swiz z (array_ref (var_ref t) (constant int (3)))) (swiz w (array_ref (var_ref m) (constant int (2))))) \n"
+ "(return (var_ref t))))\n"
+ "\n"
+ " (signature mat2x4\n"
+ " (parameters\n"
+ " (declare (in) mat4x2 m))\n"
+ " ((declare () mat2x4 t)\n"
+ " (assign (constant bool (1)) (swiz x (array_ref (var_ref t) (constant int (0)))) (swiz x (array_ref (var_ref m) (constant int (0))))) \n"
+ " (assign (constant bool (1)) (swiz x (array_ref (var_ref t) (constant int (1)))) (swiz y (array_ref (var_ref m) (constant int (0))))) \n"
+ " (assign (constant bool (1)) (swiz y (array_ref (var_ref t) (constant int (0)))) (swiz x (array_ref (var_ref m) (constant int (1))))) \n"
+ " (assign (constant bool (1)) (swiz y (array_ref (var_ref t) (constant int (1)))) (swiz y (array_ref (var_ref m) (constant int (1))))) \n"
+ " (assign (constant bool (1)) (swiz z (array_ref (var_ref t) (constant int (0)))) (swiz x (array_ref (var_ref m) (constant int (2))))) \n"
+ " (assign (constant bool (1)) (swiz z (array_ref (var_ref t) (constant int (1)))) (swiz y (array_ref (var_ref m) (constant int (2))))) \n"
+ " (assign (constant bool (1)) (swiz w (array_ref (var_ref t) (constant int (0)))) (swiz x (array_ref (var_ref m) (constant int (3))))) \n"
+ " (assign (constant bool (1)) (swiz w (array_ref (var_ref t) (constant int (1)))) (swiz y (array_ref (var_ref m) (constant int (3))))) \n"
+ "(return (var_ref t))))\n"
+ "\n"
+ " (signature mat3x4\n"
+ " (parameters\n"
+ " (declare (in) mat4x3 m))\n"
+ " ((declare () mat3x4 t)\n"
+ " (assign (constant bool (1)) (swiz x (array_ref (var_ref t) (constant int (0)))) (swiz x (array_ref (var_ref m) (constant int (0))))) \n"
+ " (assign (constant bool (1)) (swiz x (array_ref (var_ref t) (constant int (1)))) (swiz y (array_ref (var_ref m) (constant int (0))))) \n"
+ " (assign (constant bool (1)) (swiz x (array_ref (var_ref t) (constant int (2)))) (swiz z (array_ref (var_ref m) (constant int (0))))) \n"
+ " (assign (constant bool (1)) (swiz y (array_ref (var_ref t) (constant int (0)))) (swiz x (array_ref (var_ref m) (constant int (1))))) \n"
+ " (assign (constant bool (1)) (swiz y (array_ref (var_ref t) (constant int (1)))) (swiz y (array_ref (var_ref m) (constant int (1))))) \n"
+ " (assign (constant bool (1)) (swiz y (array_ref (var_ref t) (constant int (2)))) (swiz z (array_ref (var_ref m) (constant int (1))))) \n"
+ " (assign (constant bool (1)) (swiz z (array_ref (var_ref t) (constant int (0)))) (swiz x (array_ref (var_ref m) (constant int (2))))) \n"
+ " (assign (constant bool (1)) (swiz z (array_ref (var_ref t) (constant int (1)))) (swiz y (array_ref (var_ref m) (constant int (2))))) \n"
+ " (assign (constant bool (1)) (swiz z (array_ref (var_ref t) (constant int (2)))) (swiz z (array_ref (var_ref m) (constant int (2))))) \n"
+ " (assign (constant bool (1)) (swiz w (array_ref (var_ref t) (constant int (0)))) (swiz x (array_ref (var_ref m) (constant int (3))))) \n"
+ " (assign (constant bool (1)) (swiz w (array_ref (var_ref t) (constant int (1)))) (swiz y (array_ref (var_ref m) (constant int (3))))) \n"
+ " (assign (constant bool (1)) (swiz w (array_ref (var_ref t) (constant int (2)))) (swiz z (array_ref (var_ref m) (constant int (3))))) \n"
+ "(return (var_ref t))))\n"
+ "\n"
+ " (signature mat4\n"
+ " (parameters\n"
+ " (declare (in) mat4 m))\n"
+ " ((declare () mat4 t)\n"
+ " (assign (constant bool (1)) (swiz x (array_ref (var_ref t) (constant int (0)))) (swiz x (array_ref (var_ref m) (constant int (0))))) \n"
+ " (assign (constant bool (1)) (swiz x (array_ref (var_ref t) (constant int (1)))) (swiz y (array_ref (var_ref m) (constant int (0))))) \n"
+ " (assign (constant bool (1)) (swiz x (array_ref (var_ref t) (constant int (2)))) (swiz z (array_ref (var_ref m) (constant int (0))))) \n"
+ " (assign (constant bool (1)) (swiz x (array_ref (var_ref t) (constant int (3)))) (swiz w (array_ref (var_ref m) (constant int (0))))) \n"
+ " (assign (constant bool (1)) (swiz y (array_ref (var_ref t) (constant int (0)))) (swiz x (array_ref (var_ref m) (constant int (1))))) \n"
+ " (assign (constant bool (1)) (swiz y (array_ref (var_ref t) (constant int (1)))) (swiz y (array_ref (var_ref m) (constant int (1))))) \n"
+ " (assign (constant bool (1)) (swiz y (array_ref (var_ref t) (constant int (2)))) (swiz z (array_ref (var_ref m) (constant int (1))))) \n"
+ " (assign (constant bool (1)) (swiz y (array_ref (var_ref t) (constant int (3)))) (swiz w (array_ref (var_ref m) (constant int (1))))) \n"
+ " (assign (constant bool (1)) (swiz z (array_ref (var_ref t) (constant int (0)))) (swiz x (array_ref (var_ref m) (constant int (2))))) \n"
+ " (assign (constant bool (1)) (swiz z (array_ref (var_ref t) (constant int (1)))) (swiz y (array_ref (var_ref m) (constant int (2))))) \n"
+ " (assign (constant bool (1)) (swiz z (array_ref (var_ref t) (constant int (2)))) (swiz z (array_ref (var_ref m) (constant int (2))))) \n"
+ " (assign (constant bool (1)) (swiz z (array_ref (var_ref t) (constant int (3)))) (swiz w (array_ref (var_ref m) (constant int (2))))) \n"
+ " (assign (constant bool (1)) (swiz w (array_ref (var_ref t) (constant int (0)))) (swiz x (array_ref (var_ref m) (constant int (3))))) \n"
+ " (assign (constant bool (1)) (swiz w (array_ref (var_ref t) (constant int (1)))) (swiz y (array_ref (var_ref m) (constant int (3))))) \n"
+ " (assign (constant bool (1)) (swiz w (array_ref (var_ref t) (constant int (2)))) (swiz z (array_ref (var_ref m) (constant int (3))))) \n"
+ " (assign (constant bool (1)) (swiz w (array_ref (var_ref t) (constant int (3)))) (swiz w (array_ref (var_ref m) (constant int (3))))) \n"
+ "(return (var_ref t))))\n"
+ ")\n"
+ "\n"
+ ")\n"
+ "\n"
+ ""
+;
+static const char *builtin_step =
+ "((function step\n"
+ " (signature float\n"
+ " (parameters\n"
+ " (declare (in) float edge)\n"
+ " (declare (in) float x))\n"
+ " ((return (expression float b2f (expression bool >= (var_ref x) (var_ref edge))))))\n"
+ "\n"
+ " (signature vec2\n"
+ " (parameters\n"
+ " (declare (in) float edge)\n"
+ " (declare (in) vec2 x))\n"
+ " ((declare () vec2 t)\n"
+ " (assign (constant bool (1)) (swiz x (var_ref t)) (expression float b2f (expression bool >= (swiz x (var_ref x))(var_ref edge))))\n"
+ " (assign (constant bool (1)) (swiz y (var_ref t)) (expression float b2f (expression bool >= (swiz y (var_ref x))(var_ref edge))))\n"
+ " (return (var_ref t))))\n"
+ "\n"
+ " (signature vec3\n"
+ " (parameters\n"
+ " (declare (in) float edge)\n"
+ " (declare (in) vec3 x))\n"
+ " ((declare () vec3 t)\n"
+ " (assign (constant bool (1)) (swiz x (var_ref t)) (expression float b2f (expression bool >= (swiz x (var_ref x))(var_ref edge))))\n"
+ " (assign (constant bool (1)) (swiz y (var_ref t)) (expression float b2f (expression bool >= (swiz y (var_ref x))(var_ref edge))))\n"
+ " (assign (constant bool (1)) (swiz z (var_ref t)) (expression float b2f (expression bool >= (swiz z (var_ref x))(var_ref edge))))\n"
+ " (return (var_ref t))))\n"
+ "\n"
+ " (signature vec4\n"
+ " (parameters\n"
+ " (declare (in) float edge)\n"
+ " (declare (in) vec4 x))\n"
+ " ((declare () vec4 t)\n"
+ " (assign (constant bool (1)) (swiz x (var_ref t)) (expression float b2f (expression bool >= (swiz x (var_ref x))(var_ref edge))))\n"
+ " (assign (constant bool (1)) (swiz y (var_ref t)) (expression float b2f (expression bool >= (swiz y (var_ref x))(var_ref edge))))\n"
+ " (assign (constant bool (1)) (swiz z (var_ref t)) (expression float b2f (expression bool >= (swiz z (var_ref x))(var_ref edge))))\n"
+ " (assign (constant bool (1)) (swiz w (var_ref t)) (expression float b2f (expression bool >= (swiz w (var_ref x))(var_ref edge))))\n"
+ " (return (var_ref t))))\n"
+ "\n"
+ " (signature vec2\n"
+ " (parameters\n"
+ " (declare (in) vec2 edge)\n"
+ " (declare (in) vec2 x))\n"
+ " ((declare () vec2 t)\n"
+ " (assign (constant bool (1)) (swiz x (var_ref t)) (expression float b2f (expression bool >= (swiz x (var_ref x))(swiz x (var_ref edge)))))\n"
+ " (assign (constant bool (1)) (swiz y (var_ref t)) (expression float b2f (expression bool >= (swiz y (var_ref x))(swiz y (var_ref edge)))))\n"
+ " (return (var_ref t))))\n"
+ "\n"
+ " (signature vec3\n"
+ " (parameters\n"
+ " (declare (in) vec3 edge)\n"
+ " (declare (in) vec3 x))\n"
+ " ((declare () vec3 t)\n"
+ " (assign (constant bool (1)) (swiz x (var_ref t)) (expression float b2f (expression bool >= (swiz x (var_ref x))(swiz x (var_ref edge)))))\n"
+ " (assign (constant bool (1)) (swiz y (var_ref t)) (expression float b2f (expression bool >= (swiz y (var_ref x))(swiz y (var_ref edge)))))\n"
+ " (assign (constant bool (1)) (swiz z (var_ref t)) (expression float b2f (expression bool >= (swiz z (var_ref x))(swiz z (var_ref edge)))))\n"
+ " (return (var_ref t))))\n"
+ "\n"
+ " (signature vec4\n"
+ " (parameters\n"
+ " (declare (in) vec4 edge)\n"
+ " (declare (in) vec4 x))\n"
+ " ((declare () vec4 t)\n"
+ " (assign (constant bool (1)) (swiz x (var_ref t)) (expression float b2f (expression bool >= (swiz x (var_ref x))(swiz x (var_ref edge)))))\n"
+ " (assign (constant bool (1)) (swiz y (var_ref t)) (expression float b2f (expression bool >= (swiz y (var_ref x))(swiz y (var_ref edge)))))\n"
+ " (assign (constant bool (1)) (swiz z (var_ref t)) (expression float b2f (expression bool >= (swiz y (var_ref x))(swiz z (var_ref edge)))))\n"
+ " (assign (constant bool (1)) (swiz w (var_ref t)) (expression float b2f (expression bool >= (swiz w (var_ref x))(swiz w (var_ref edge)))))\n"
+ " (return (var_ref t))))\n"
+ "))\n"
+ "\n"
+ ""
+;
+static const char *builtin_sinh =
+ "((function sinh\n"
+ " (signature float\n"
+ " (parameters\n"
+ " (declare (in) float x))\n"
+ " ((return (expression float * (constant float (0.5))\n"
+ " (expression float -\n"
+ " (expression float exp (var_ref x))\n"
+ " (expression float exp (expression float neg (var_ref x))))))))\n"
+ " (signature vec2\n"
+ " (parameters\n"
+ " (declare (in) vec2 x))\n"
+ " ((return (expression vec2 * (constant vec2 (0.5))\n"
+ " (expression vec2 -\n"
+ " (expression vec2 exp (var_ref x))\n"
+ " (expression vec2 exp (expression vec2 neg (var_ref x))))))))\n"
+ " (signature vec3\n"
+ " (parameters\n"
+ " (declare (in) vec3 x))\n"
+ " ((return (expression vec3 * (constant vec3 (0.5))\n"
+ " (expression vec3 -\n"
+ " (expression vec3 exp (var_ref x))\n"
+ " (expression vec3 exp (expression vec3 neg (var_ref x))))))))\n"
+ " (signature vec4\n"
+ " (parameters\n"
+ " (declare (in) vec4 x))\n"
+ " ((return (expression vec4 * (constant vec4 (0.5))\n"
+ " (expression vec4 -\n"
+ " (expression vec4 exp (var_ref x))\n"
+ " (expression vec4 exp (expression vec4 neg (var_ref x))))))))\n"
+ "))\n"
+ ""
+;
+static const char *builtin_cos =
+ "((function cos\n"
+ " (signature float\n"
+ " (parameters\n"
+ " (declare (in) float angle))\n"
+ " ((return (expression float cos (var_ref angle)))))\n"
+ "\n"
+ " (signature vec2\n"
+ " (parameters\n"
+ " (declare (in) vec2 angle))\n"
+ " ((return (expression vec2 cos (var_ref angle)))))\n"
+ "\n"
+ " (signature vec3\n"
+ " (parameters\n"
+ " (declare (in) vec3 angle))\n"
+ " ((return (expression vec3 cos (var_ref angle)))))\n"
+ "\n"
+ " (signature vec4\n"
+ " (parameters\n"
+ " (declare (in) vec4 angle))\n"
+ " ((return (expression vec4 cos (var_ref angle)))))\n"
+ "))\n"
+ ""
+;
+static const char *builtin_shadow2DProjLod =
+ "((function shadow2DProjLod\n"
+ " (signature vec4\n"
+ " (parameters\n"
+ " (declare (in) sampler2DShadow sampler)\n"
+ " (declare (in) vec4 P) \n"
+ " (declare (in) float lod) )\n"
+ " ((return (txl (var_ref sampler) (swiz xy (var_ref P)) (0 0 0) (swiz w (var_ref P)) (swiz z (var_ref P)) (var_ref lod) ))))\n"
+ "\n"
+ "))\n"
+ ""
+;
+static const char *builtin_shadow2DArray =
+ "((function shadow2DArray\n"
+ " (signature vec4\n"
+ " (parameters\n"
+ " (declare (in) sampler2DArrayShadow sampler)\n"
+ " (declare (in) vec4 P) )\n"
+ " ((return (tex (var_ref sampler) (swiz xyz (var_ref P)) (0 0 0) 1 (swiz w (var_ref P)) ))))\n"
+ "\n"
+ "))\n"
+ ""
+;
+static const char *builtin_equal =
+ "((function equal\n"
+ " (signature bvec2\n"
+ " (parameters\n"
+ " (declare (in) vec2 arg0)\n"
+ " (declare (in) vec2 arg1))\n"
+ " ((declare () bvec2 temp)\n"
+ " (assign (constant bool (1)) (swiz x (var_ref temp)) (expression bool == (swiz x (var_ref arg0))(swiz x (var_ref arg1)))) \n"
+ " (assign (constant bool (1)) (swiz y (var_ref temp)) (expression bool == (swiz y (var_ref arg0))(swiz y (var_ref arg1)))) \n"
+ " (return (var_ref temp))))\n"
+ "\n"
+ " (signature bvec3\n"
+ " (parameters\n"
+ " (declare (in) vec3 arg0)\n"
+ " (declare (in) vec3 arg1))\n"
+ " ((declare () bvec3 temp)\n"
+ " (assign (constant bool (1)) (swiz x (var_ref temp)) (expression bool == (swiz x (var_ref arg0))(swiz x (var_ref arg1)))) \n"
+ " (assign (constant bool (1)) (swiz y (var_ref temp)) (expression bool == (swiz y (var_ref arg0))(swiz y (var_ref arg1)))) \n"
+ " (assign (constant bool (1)) (swiz z (var_ref temp)) (expression bool == (swiz z (var_ref arg0))(swiz z (var_ref arg1)))) \n"
+ " (return (var_ref temp))))\n"
+ "\n"
+ " (signature bvec4\n"
+ " (parameters\n"
+ " (declare (in) vec4 arg0)\n"
+ " (declare (in) vec4 arg1))\n"
+ " ((declare () bvec4 temp)\n"
+ " (assign (constant bool (1)) (swiz x (var_ref temp)) (expression bool == (swiz x (var_ref arg0))(swiz x (var_ref arg1)))) \n"
+ " (assign (constant bool (1)) (swiz y (var_ref temp)) (expression bool == (swiz y (var_ref arg0))(swiz y (var_ref arg1)))) \n"
+ " (assign (constant bool (1)) (swiz z (var_ref temp)) (expression bool == (swiz z (var_ref arg0))(swiz z (var_ref arg1)))) \n"
+ " (assign (constant bool (1)) (swiz w (var_ref temp)) (expression bool == (swiz w (var_ref arg0))(swiz w (var_ref arg1)))) \n"
+ " (return (var_ref temp))))\n"
+ "\n"
+ " (signature bvec2\n"
+ " (parameters\n"
+ " (declare (in) ivec2 arg0)\n"
+ " (declare (in) ivec2 arg1))\n"
+ " ((declare () bvec2 temp)\n"
+ " (assign (constant bool (1)) (swiz x (var_ref temp)) (expression bool == (swiz x (var_ref arg0))(swiz x (var_ref arg1)))) \n"
+ " (assign (constant bool (1)) (swiz y (var_ref temp)) (expression bool == (swiz y (var_ref arg0))(swiz y (var_ref arg1)))) \n"
+ " (return (var_ref temp))))\n"
+ "\n"
+ " (signature bvec3\n"
+ " (parameters\n"
+ " (declare (in) ivec3 arg0)\n"
+ " (declare (in) ivec3 arg1))\n"
+ " ((declare () bvec3 temp)\n"
+ " (assign (constant bool (1)) (swiz x (var_ref temp)) (expression bool == (swiz x (var_ref arg0))(swiz x (var_ref arg1)))) \n"
+ " (assign (constant bool (1)) (swiz y (var_ref temp)) (expression bool == (swiz y (var_ref arg0))(swiz y (var_ref arg1)))) \n"
+ " (assign (constant bool (1)) (swiz z (var_ref temp)) (expression bool == (swiz z (var_ref arg0))(swiz z (var_ref arg1)))) \n"
+ " (return (var_ref temp))))\n"
+ "\n"
+ " (signature bvec4\n"
+ " (parameters\n"
+ " (declare (in) ivec4 arg0)\n"
+ " (declare (in) ivec4 arg1))\n"
+ " ((declare () bvec4 temp)\n"
+ " (assign (constant bool (1)) (swiz x (var_ref temp)) (expression bool == (swiz x (var_ref arg0))(swiz x (var_ref arg1)))) \n"
+ " (assign (constant bool (1)) (swiz y (var_ref temp)) (expression bool == (swiz y (var_ref arg0))(swiz y (var_ref arg1)))) \n"
+ " (assign (constant bool (1)) (swiz z (var_ref temp)) (expression bool == (swiz z (var_ref arg0))(swiz z (var_ref arg1)))) \n"
+ " (assign (constant bool (1)) (swiz w (var_ref temp)) (expression bool == (swiz w (var_ref arg0))(swiz w (var_ref arg1)))) \n"
+ " (return (var_ref temp))))\n"
+ "\n"
+ " (signature bvec2\n"
+ " (parameters\n"
+ " (declare (in) uvec2 arg0)\n"
+ " (declare (in) uvec2 arg1))\n"
+ " ((declare () bvec2 temp)\n"
+ " (assign (constant bool (1)) (swiz x (var_ref temp)) (expression bool == (swiz x (var_ref arg0))(swiz x (var_ref arg1)))) \n"
+ " (assign (constant bool (1)) (swiz y (var_ref temp)) (expression bool == (swiz y (var_ref arg0))(swiz y (var_ref arg1)))) \n"
+ " (return (var_ref temp))))\n"
+ "\n"
+ " (signature bvec3\n"
+ " (parameters\n"
+ " (declare (in) uvec3 arg0)\n"
+ " (declare (in) uvec3 arg1))\n"
+ " ((declare () bvec3 temp)\n"
+ " (assign (constant bool (1)) (swiz x (var_ref temp)) (expression bool == (swiz x (var_ref arg0))(swiz x (var_ref arg1)))) \n"
+ " (assign (constant bool (1)) (swiz y (var_ref temp)) (expression bool == (swiz y (var_ref arg0))(swiz y (var_ref arg1)))) \n"
+ " (assign (constant bool (1)) (swiz z (var_ref temp)) (expression bool == (swiz z (var_ref arg0))(swiz z (var_ref arg1)))) \n"
+ " (return (var_ref temp))))\n"
+ "\n"
+ " (signature bvec4\n"
+ " (parameters\n"
+ " (declare (in) uvec4 arg0)\n"
+ " (declare (in) uvec4 arg1))\n"
+ " ((declare () bvec4 temp)\n"
+ " (assign (constant bool (1)) (swiz x (var_ref temp)) (expression bool == (swiz x (var_ref arg0))(swiz x (var_ref arg1)))) \n"
+ " (assign (constant bool (1)) (swiz y (var_ref temp)) (expression bool == (swiz y (var_ref arg0))(swiz y (var_ref arg1)))) \n"
+ " (assign (constant bool (1)) (swiz z (var_ref temp)) (expression bool == (swiz z (var_ref arg0))(swiz z (var_ref arg1)))) \n"
+ " (assign (constant bool (1)) (swiz w (var_ref temp)) (expression bool == (swiz w (var_ref arg0))(swiz w (var_ref arg1)))) \n"
+ " (return (var_ref temp))))\n"
+ "))\n"
+ ""
+;
+static const char *builtin_length =
+ "((function length\n"
+ " (signature float\n"
+ " (parameters\n"
+ " (declare (in) float arg0))\n"
+ " ((return (expression float sqrt (expression float dot (var_ref arg0) (var_ref arg0))))))\n"
+ "\n"
+ " (signature float\n"
+ " (parameters\n"
+ " (declare (in) vec2 arg0))\n"
+ " ((return (expression float sqrt (expression float dot (var_ref arg0) (var_ref arg0))))))\n"
+ "\n"
+ " (signature float\n"
+ " (parameters\n"
+ " (declare (in) vec3 arg0))\n"
+ " ((return (expression float sqrt (expression float dot (var_ref arg0) (var_ref arg0))))))\n"
+ "\n"
+ " (signature float\n"
+ " (parameters\n"
+ " (declare (in) vec4 arg0))\n"
+ " ((return (expression float sqrt (expression float dot (var_ref arg0) (var_ref arg0))))))\n"
+ "))\n"
+ ""
+;
+static const char *builtin_acos =
+ "((function acos\n"
+ " (signature float\n"
+ " (parameters\n"
+ " (declare (in) float x))\n"
+ " ((return (expression float - (constant float (1.5707963))\n"
+ " (call asin ((var_ref x)))))))\n"
+ " (signature vec2\n"
+ " (parameters\n"
+ " (declare (in) vec2 x))\n"
+ " ((return (expression vec2 - (constant float (1.5707963))\n"
+ " (call asin ((var_ref x)))))))\n"
+ " (signature vec3\n"
+ " (parameters\n"
+ " (declare (in) vec3 x))\n"
+ " ((return (expression vec3 - (constant float (1.5707963))\n"
+ " (call asin ((var_ref x)))))))\n"
+ " (signature vec4\n"
+ " (parameters\n"
+ " (declare (in) vec4 x))\n"
+ " ((return (expression vec4 - (constant float (1.5707963))\n"
+ " (call asin ((var_ref x)))))))\n"
+ "))\n"
+ ""
+;
+static const char *builtin_matrixCompMult =
+ "((function matrixCompMult\n"
+ " (signature mat2\n"
+ " (parameters\n"
+ " (declare (in) mat2 x)\n"
+ " (declare (in) mat2 y))\n"
+ " ((declare () mat2 z)\n"
+ " (assign (constant bool (1)) (array_ref (var_ref z) (constant int (0))) (expression vec2 * (array_ref (var_ref x) (constant int (0))) (array_ref (var_ref y) (constant int (0))))) \n"
+ " (assign (constant bool (1)) (array_ref (var_ref z) (constant int (1))) (expression vec2 * (array_ref (var_ref x) (constant int (1))) (array_ref (var_ref y) (constant int (1))))) \n"
+ "(return (var_ref z))))\n"
+ "\n"
+ " (signature mat3\n"
+ " (parameters\n"
+ " (declare (in) mat3 x)\n"
+ " (declare (in) mat3 y))\n"
+ " ((declare () mat3 z)\n"
+ " (assign (constant bool (1)) (array_ref (var_ref z) (constant int (0))) (expression vec3 * (array_ref (var_ref x) (constant int (0))) (array_ref (var_ref y) (constant int (0))))) \n"
+ " (assign (constant bool (1)) (array_ref (var_ref z) (constant int (1))) (expression vec3 * (array_ref (var_ref x) (constant int (1))) (array_ref (var_ref y) (constant int (1))))) \n"
+ " (assign (constant bool (1)) (array_ref (var_ref z) (constant int (2))) (expression vec3 * (array_ref (var_ref x) (constant int (2))) (array_ref (var_ref y) (constant int (2))))) \n"
+ "(return (var_ref z))))\n"
+ "\n"
+ " (signature mat4\n"
+ " (parameters\n"
+ " (declare (in) mat4 x)\n"
+ " (declare (in) mat4 y))\n"
+ " ((declare () mat4 z)\n"
+ " (assign (constant bool (1)) (array_ref (var_ref z) (constant int (0))) (expression vec4 * (array_ref (var_ref x) (constant int (0))) (array_ref (var_ref y) (constant int (0))))) \n"
+ " (assign (constant bool (1)) (array_ref (var_ref z) (constant int (1))) (expression vec4 * (array_ref (var_ref x) (constant int (1))) (array_ref (var_ref y) (constant int (1))))) \n"
+ " (assign (constant bool (1)) (array_ref (var_ref z) (constant int (2))) (expression vec4 * (array_ref (var_ref x) (constant int (2))) (array_ref (var_ref y) (constant int (2))))) \n"
+ " (assign (constant bool (1)) (array_ref (var_ref z) (constant int (3))) (expression vec4 * (array_ref (var_ref x) (constant int (3))) (array_ref (var_ref y) (constant int (3))))) \n"
+ "(return (var_ref z))))\n"
+ "\n"
+ " (signature mat2x3\n"
+ " (parameters\n"
+ " (declare (in) mat2x3 x)\n"
+ " (declare (in) mat2x3 y))\n"
+ " ((declare () mat2x3 z)\n"
+ " (assign (constant bool (1)) (array_ref (var_ref z) (constant int (0))) (expression vec3 * (array_ref (var_ref x) (constant int (0))) (array_ref (var_ref y) (constant int (0))))) \n"
+ " (assign (constant bool (1)) (array_ref (var_ref z) (constant int (1))) (expression vec3 * (array_ref (var_ref x) (constant int (1))) (array_ref (var_ref y) (constant int (1))))) \n"
+ "(return (var_ref z))))\n"
+ "\n"
+ " (signature mat3x2\n"
+ " (parameters\n"
+ " (declare (in) mat3x2 x)\n"
+ " (declare (in) mat3x2 y))\n"
+ " ((declare () mat3x2 z)\n"
+ " (assign (constant bool (1)) (array_ref (var_ref z) (constant int (0))) (expression vec2 * (array_ref (var_ref x) (constant int (0))) (array_ref (var_ref y) (constant int (0))))) \n"
+ " (assign (constant bool (1)) (array_ref (var_ref z) (constant int (1))) (expression vec2 * (array_ref (var_ref x) (constant int (1))) (array_ref (var_ref y) (constant int (1))))) \n"
+ " (assign (constant bool (1)) (array_ref (var_ref z) (constant int (2))) (expression vec2 * (array_ref (var_ref x) (constant int (2))) (array_ref (var_ref y) (constant int (2))))) \n"
+ "(return (var_ref z))))\n"
+ "\n"
+ " (signature mat2x4\n"
+ " (parameters\n"
+ " (declare (in) mat2x4 x)\n"
+ " (declare (in) mat2x4 y))\n"
+ " ((declare () mat2x4 z)\n"
+ " (assign (constant bool (1)) (array_ref (var_ref z) (constant int (0))) (expression vec4 * (array_ref (var_ref x) (constant int (0))) (array_ref (var_ref y) (constant int (0))))) \n"
+ " (assign (constant bool (1)) (array_ref (var_ref z) (constant int (1))) (expression vec4 * (array_ref (var_ref x) (constant int (1))) (array_ref (var_ref y) (constant int (1))))) \n"
+ "(return (var_ref z))))\n"
+ "\n"
+ " (signature mat4x2\n"
+ " (parameters\n"
+ " (declare (in) mat4x2 x)\n"
+ " (declare (in) mat4x2 y))\n"
+ " ((declare () mat4x2 z)\n"
+ " (assign (constant bool (1)) (array_ref (var_ref z) (constant int (0))) (expression vec2 * (array_ref (var_ref x) (constant int (0))) (array_ref (var_ref y) (constant int (0))))) \n"
+ " (assign (constant bool (1)) (array_ref (var_ref z) (constant int (1))) (expression vec2 * (array_ref (var_ref x) (constant int (1))) (array_ref (var_ref y) (constant int (1))))) \n"
+ " (assign (constant bool (1)) (array_ref (var_ref z) (constant int (2))) (expression vec2 * (array_ref (var_ref x) (constant int (2))) (array_ref (var_ref y) (constant int (2))))) \n"
+ " (assign (constant bool (1)) (array_ref (var_ref z) (constant int (3))) (expression vec2 * (array_ref (var_ref x) (constant int (3))) (array_ref (var_ref y) (constant int (3))))) \n"
+ "(return (var_ref z))))\n"
+ "\n"
+ " (signature mat3x4\n"
+ " (parameters\n"
+ " (declare (in) mat3x4 x)\n"
+ " (declare (in) mat3x4 y))\n"
+ " ((declare () mat3x4 z)\n"
+ " (assign (constant bool (1)) (array_ref (var_ref z) (constant int (0))) (expression vec4 * (array_ref (var_ref x) (constant int (0))) (array_ref (var_ref y) (constant int (0))))) \n"
+ " (assign (constant bool (1)) (array_ref (var_ref z) (constant int (1))) (expression vec4 * (array_ref (var_ref x) (constant int (1))) (array_ref (var_ref y) (constant int (1))))) \n"
+ " (assign (constant bool (1)) (array_ref (var_ref z) (constant int (2))) (expression vec4 * (array_ref (var_ref x) (constant int (2))) (array_ref (var_ref y) (constant int (2))))) \n"
+ "(return (var_ref z))))\n"
+ "\n"
+ " (signature mat4x3\n"
+ " (parameters\n"
+ " (declare (in) mat4x3 x)\n"
+ " (declare (in) mat4x3 y))\n"
+ " ((declare () mat4x3 z)\n"
+ " (assign (constant bool (1)) (array_ref (var_ref z) (constant int (0))) (expression vec3 * (array_ref (var_ref x) (constant int (0))) (array_ref (var_ref y) (constant int (0))))) \n"
+ " (assign (constant bool (1)) (array_ref (var_ref z) (constant int (1))) (expression vec3 * (array_ref (var_ref x) (constant int (1))) (array_ref (var_ref y) (constant int (1))))) \n"
+ " (assign (constant bool (1)) (array_ref (var_ref z) (constant int (2))) (expression vec3 * (array_ref (var_ref x) (constant int (2))) (array_ref (var_ref y) (constant int (2))))) \n"
+ " (assign (constant bool (1)) (array_ref (var_ref z) (constant int (3))) (expression vec3 * (array_ref (var_ref x) (constant int (3))) (array_ref (var_ref y) (constant int (3))))) \n"
+ "(return (var_ref z))))\n"
+ "))\n"
+ ""
+;
+static const char *builtin_pow =
+ "((function pow\n"
+ " (signature float\n"
+ " (parameters\n"
+ " (declare (in) float arg0)\n"
+ " (declare (in) float arg1))\n"
+ " ((return (expression float pow (var_ref arg0) (var_ref arg1)))))\n"
+ "\n"
+ " (signature vec2\n"
+ " (parameters\n"
+ " (declare (in) vec2 arg0)\n"
+ " (declare (in) vec2 arg1))\n"
+ " ((return (expression vec2 pow (var_ref arg0) (var_ref arg1)))))\n"
+ "\n"
+ " (signature vec3\n"
+ " (parameters\n"
+ " (declare (in) vec3 arg0)\n"
+ " (declare (in) vec3 arg1))\n"
+ " ((return (expression vec3 pow (var_ref arg0) (var_ref arg1)))))\n"
+ "\n"
+ " (signature vec4\n"
+ " (parameters\n"
+ " (declare (in) vec4 arg0)\n"
+ " (declare (in) vec4 arg1))\n"
+ " ((return (expression vec4 pow (var_ref arg0) (var_ref arg1)))))\n"
+ "))\n"
+ ""
+;
+static const char *builtin_texture2DProjLod =
+ "((function texture2DProjLod\n"
+ " (signature vec4\n"
+ " (parameters\n"
+ " (declare (in) sampler2D sampler)\n"
+ " (declare (in) vec3 P) \n"
+ " (declare (in) float lod) )\n"
+ " ((return (txl (var_ref sampler) (swiz xy (var_ref P)) (0 0 0) (swiz z (var_ref P)) () (var_ref lod) ))))\n"
+ "\n"
+ " (signature vec4\n"
+ " (parameters\n"
+ " (declare (in) sampler2D sampler)\n"
+ " (declare (in) vec4 P) \n"
+ " (declare (in) float lod) )\n"
+ " ((return (txl (var_ref sampler) (swiz xy (var_ref P)) (0 0 0) (swiz w (var_ref P)) () (var_ref lod) ))))\n"
+ "\n"
+ "))\n"
+ ""
+;
+static const char *builtin_textureProjLod =
+ "((function textureProjLod\n"
+ " (signature vec4\n"
+ " (parameters\n"
+ " (declare (in) sampler1D sampler)\n"
+ " (declare (in) vec2 P) \n"
+ " (declare (in) float lod) )\n"
+ " ((return (txl (var_ref sampler) (swiz x (var_ref P)) (0 0 0) (swiz y (var_ref P)) () (var_ref lod) ))))\n"
+ "\n"
+ " (signature ivec4\n"
+ " (parameters\n"
+ " (declare (in) isampler1D sampler)\n"
+ " (declare (in) vec2 P) \n"
+ " (declare (in) float lod) )\n"
+ " ((return (txl (var_ref sampler) (swiz x (var_ref P)) (0 0 0) (swiz y (var_ref P)) () (var_ref lod) ))))\n"
+ "\n"
+ " (signature uvec4\n"
+ " (parameters\n"
+ " (declare (in) usampler1D sampler)\n"
+ " (declare (in) vec2 P) \n"
+ " (declare (in) float lod) )\n"
+ " ((return (txl (var_ref sampler) (swiz x (var_ref P)) (0 0 0) (swiz y (var_ref P)) () (var_ref lod) ))))\n"
+ "\n"
+ " (signature vec4\n"
+ " (parameters\n"
+ " (declare (in) sampler1D sampler)\n"
+ " (declare (in) vec4 P) \n"
+ " (declare (in) float lod) )\n"
+ " ((return (txl (var_ref sampler) (swiz x (var_ref P)) (0 0 0) (swiz w (var_ref P)) () (var_ref lod) ))))\n"
+ "\n"
+ " (signature ivec4\n"
+ " (parameters\n"
+ " (declare (in) isampler1D sampler)\n"
+ " (declare (in) vec4 P) \n"
+ " (declare (in) float lod) )\n"
+ " ((return (txl (var_ref sampler) (swiz x (var_ref P)) (0 0 0) (swiz w (var_ref P)) () (var_ref lod) ))))\n"
+ "\n"
+ " (signature uvec4\n"
+ " (parameters\n"
+ " (declare (in) usampler1D sampler)\n"
+ " (declare (in) vec4 P) \n"
+ " (declare (in) float lod) )\n"
+ " ((return (txl (var_ref sampler) (swiz x (var_ref P)) (0 0 0) (swiz w (var_ref P)) () (var_ref lod) ))))\n"
+ "\n"
+ " (signature vec4\n"
+ " (parameters\n"
+ " (declare (in) sampler2D sampler)\n"
+ " (declare (in) vec3 P) \n"
+ " (declare (in) float lod) )\n"
+ " ((return (txl (var_ref sampler) (swiz xy (var_ref P)) (0 0 0) (swiz z (var_ref P)) () (var_ref lod) ))))\n"
+ "\n"
+ " (signature ivec4\n"
+ " (parameters\n"
+ " (declare (in) isampler2D sampler)\n"
+ " (declare (in) vec3 P) \n"
+ " (declare (in) float lod) )\n"
+ " ((return (txl (var_ref sampler) (swiz xy (var_ref P)) (0 0 0) (swiz z (var_ref P)) () (var_ref lod) ))))\n"
+ "\n"
+ " (signature uvec4\n"
+ " (parameters\n"
+ " (declare (in) usampler2D sampler)\n"
+ " (declare (in) vec3 P) \n"
+ " (declare (in) float lod) )\n"
+ " ((return (txl (var_ref sampler) (swiz xy (var_ref P)) (0 0 0) (swiz z (var_ref P)) () (var_ref lod) ))))\n"
+ "\n"
+ " (signature vec4\n"
+ " (parameters\n"
+ " (declare (in) sampler2D sampler)\n"
+ " (declare (in) vec4 P) \n"
+ " (declare (in) float lod) )\n"
+ " ((return (txl (var_ref sampler) (swiz xy (var_ref P)) (0 0 0) (swiz w (var_ref P)) () (var_ref lod) ))))\n"
+ "\n"
+ " (signature ivec4\n"
+ " (parameters\n"
+ " (declare (in) isampler2D sampler)\n"
+ " (declare (in) vec4 P) \n"
+ " (declare (in) float lod) )\n"
+ " ((return (txl (var_ref sampler) (swiz xy (var_ref P)) (0 0 0) (swiz w (var_ref P)) () (var_ref lod) ))))\n"
+ "\n"
+ " (signature uvec4\n"
+ " (parameters\n"
+ " (declare (in) usampler2D sampler)\n"
+ " (declare (in) vec4 P) \n"
+ " (declare (in) float lod) )\n"
+ " ((return (txl (var_ref sampler) (swiz xy (var_ref P)) (0 0 0) (swiz w (var_ref P)) () (var_ref lod) ))))\n"
+ "\n"
+ " (signature vec4\n"
+ " (parameters\n"
+ " (declare (in) sampler3D sampler)\n"
+ " (declare (in) vec4 P) \n"
+ " (declare (in) float lod) )\n"
+ " ((return (txl (var_ref sampler) (swiz xyz (var_ref P)) (0 0 0) (swiz w (var_ref P)) () (var_ref lod) ))))\n"
+ "\n"
+ " (signature ivec4\n"
+ " (parameters\n"
+ " (declare (in) isampler3D sampler)\n"
+ " (declare (in) vec4 P) \n"
+ " (declare (in) float lod) )\n"
+ " ((return (txl (var_ref sampler) (swiz xyz (var_ref P)) (0 0 0) (swiz w (var_ref P)) () (var_ref lod) ))))\n"
+ "\n"
+ " (signature uvec4\n"
+ " (parameters\n"
+ " (declare (in) usampler3D sampler)\n"
+ " (declare (in) vec4 P) \n"
+ " (declare (in) float lod) )\n"
+ " ((return (txl (var_ref sampler) (swiz xyz (var_ref P)) (0 0 0) (swiz w (var_ref P)) () (var_ref lod) ))))\n"
+ "\n"
+ "))\n"
+ ""
+;
+static const char *builtin_log =
+ "((function log\n"
+ " (signature float\n"
+ " (parameters\n"
+ " (declare (in) float arg0))\n"
+ " ((return (expression float log (var_ref arg0)))))\n"
+ "\n"
+ " (signature vec2\n"
+ " (parameters\n"
+ " (declare (in) vec2 arg0))\n"
+ " ((return (expression vec2 log (var_ref arg0)))))\n"
+ "\n"
+ " (signature vec3\n"
+ " (parameters\n"
+ " (declare (in) vec3 arg0))\n"
+ " ((return (expression vec3 log (var_ref arg0)))))\n"
+ "\n"
+ " (signature vec4\n"
+ " (parameters\n"
+ " (declare (in) vec4 arg0))\n"
+ " ((return (expression vec4 log (var_ref arg0)))))\n"
+ "))\n"
+ ""
+;
+static const char *builtin_exp2 =
+ "((function exp2\n"
+ " (signature float\n"
+ " (parameters\n"
+ " (declare (in) float arg0))\n"
+ " ((return (expression float exp2 (var_ref arg0)))))\n"
+ "\n"
+ " (signature vec2\n"
+ " (parameters\n"
+ " (declare (in) vec2 arg0))\n"
+ " ((return (expression vec2 exp2 (var_ref arg0)))))\n"
+ "\n"
+ " (signature vec3\n"
+ " (parameters\n"
+ " (declare (in) vec3 arg0))\n"
+ " ((return (expression vec3 exp2 (var_ref arg0)))))\n"
+ "\n"
+ " (signature vec4\n"
+ " (parameters\n"
+ " (declare (in) vec4 arg0))\n"
+ " ((return (expression vec4 exp2 (var_ref arg0)))))\n"
+ "))\n"
+ ""
+;
+static const char *builtin_fract =
+ "((function fract\n"
+ " (signature float\n"
+ " (parameters\n"
+ " (declare (in) float x))\n"
+ " ((return (expression float fract (var_ref x)))))\n"
+ "\n"
+ " (signature vec2\n"
+ " (parameters\n"
+ " (declare (in) vec2 x))\n"
+ " ((return (expression vec2 fract (var_ref x)))))\n"
+ "\n"
+ " (signature vec3\n"
+ " (parameters\n"
+ " (declare (in) vec3 x))\n"
+ " ((return (expression vec3 fract (var_ref x)))))\n"
+ "\n"
+ " (signature vec4\n"
+ " (parameters\n"
+ " (declare (in) vec4 x))\n"
+ " ((return (expression vec4 fract (var_ref x)))))\n"
+ "))\n"
+ "\n"
+ ""
+;
+static const char *builtin_shadow1DLod =
+ "((function shadow1DLod\n"
+ " (signature vec4\n"
+ " (parameters\n"
+ " (declare (in) sampler1DShadow sampler)\n"
+ " (declare (in) vec3 P) \n"
+ " (declare (in) float lod) )\n"
+ " ((return (txl (var_ref sampler) (swiz x (var_ref P)) (0 0 0) 1 (swiz z (var_ref P)) (var_ref lod) ))))\n"
+ "\n"
+ "))\n"
+ ""
+;
+static const char *builtin_texture1DLod =
+ "((function texture1DLod\n"
+ " (signature vec4\n"
+ " (parameters\n"
+ " (declare (in) sampler1D sampler)\n"
+ " (declare (in) float P) \n"
+ " (declare (in) float lod) )\n"
+ " ((return (txl (var_ref sampler) (var_ref P) (0 0 0) 1 () (var_ref lod) ))))\n"
+ "\n"
+ "))\n"
+ ""
+;
+static const char *builtin_texture2DArray =
+ "((function texture2DArray\n"
+ " (signature vec4\n"
+ " (parameters\n"
+ " (declare (in) sampler2DArray sampler)\n"
+ " (declare (in) vec3 P) )\n"
+ " ((return (tex (var_ref sampler) (var_ref P) (0 0 0) 1 () ))))\n"
+ "\n"
+ " (signature vec4\n"
+ " (parameters\n"
+ " (declare (in) sampler2DArray sampler)\n"
+ " (declare (in) vec3 P) \n"
+ " (declare (in) float bias) )\n"
+ " ((return (txb (var_ref sampler) (var_ref P) (0 0 0) 1 () (var_ref bias) ))))\n"
+ "\n"
+ "))\n"
+ ""
+;
+static const char *builtin_texture3DProj =
+ "((function texture3DProj\n"
+ " (signature vec4\n"
+ " (parameters\n"
+ " (declare (in) sampler3D sampler)\n"
+ " (declare (in) vec4 P) )\n"
+ " ((return (tex (var_ref sampler) (swiz xyz (var_ref P)) (0 0 0) (swiz w (var_ref P)) () ))))\n"
+ "\n"
+ " (signature vec4\n"
+ " (parameters\n"
+ " (declare (in) sampler3D sampler)\n"
+ " (declare (in) vec4 P) \n"
+ " (declare (in) float bias) )\n"
+ " ((return (txb (var_ref sampler) (swiz xyz (var_ref P)) (0 0 0) (swiz w (var_ref P)) () (var_ref bias) ))))\n"
+ "\n"
+ "))\n"
+ ""
+;
+static const char *builtin_sign =
+ "((function sign\n"
+ " (signature float\n"
+ " (parameters\n"
+ " (declare (in) float x))\n"
+ " ((return (expression float sign (var_ref x)))))\n"
+ "\n"
+ " (signature vec2\n"
+ " (parameters\n"
+ " (declare (in) vec2 x))\n"
+ " ((return (expression vec2 sign (var_ref x)))))\n"
+ "\n"
+ " (signature vec3\n"
+ " (parameters\n"
+ " (declare (in) vec3 x))\n"
+ " ((return (expression vec3 sign (var_ref x)))))\n"
+ "\n"
+ " (signature vec4\n"
+ " (parameters\n"
+ " (declare (in) vec4 x))\n"
+ " ((return (expression vec4 sign (var_ref x)))))\n"
+ "\n"
+ " (signature int\n"
+ " (parameters\n"
+ " (declare (in) int x))\n"
+ " ((return (expression int sign (var_ref x)))))\n"
+ "\n"
+ " (signature ivec2\n"
+ " (parameters\n"
+ " (declare (in) ivec2 x))\n"
+ " ((return (expression ivec2 sign (var_ref x)))))\n"
+ "\n"
+ " (signature ivec3\n"
+ " (parameters\n"
+ " (declare (in) ivec3 x))\n"
+ " ((return (expression ivec3 sign (var_ref x)))))\n"
+ "\n"
+ " (signature ivec4\n"
+ " (parameters\n"
+ " (declare (in) ivec4 x))\n"
+ " ((return (expression ivec4 sign (var_ref x)))))\n"
+ "))\n"
+ "\n"
+ ""
+;
+static const char *builtin_inversesqrt =
+ "((function inversesqrt\n"
+ " (signature float\n"
+ " (parameters\n"
+ " (declare (in) float arg0))\n"
+ " ((return (expression float rsq (var_ref arg0)))))\n"
+ "\n"
+ " (signature vec2\n"
+ " (parameters\n"
+ " (declare (in) vec2 arg0))\n"
+ " ((return (expression vec2 rsq (var_ref arg0)))))\n"
+ "\n"
+ " (signature vec3\n"
+ " (parameters\n"
+ " (declare (in) vec3 arg0))\n"
+ " ((return (expression vec3 rsq (var_ref arg0)))))\n"
+ "\n"
+ " (signature vec4\n"
+ " (parameters\n"
+ " (declare (in) vec4 arg0))\n"
+ " ((return (expression vec4 rsq (var_ref arg0)))))\n"
+ "))\n"
+ ""
+;
+static const char *builtin_distance =
+ "((function distance\n"
+ " (signature float\n"
+ " (parameters\n"
+ " (declare (in) float p0)\n"
+ " (declare (in) float p1))\n"
+ " ((declare () float p)\n"
+ " (assign (constant bool (1)) (var_ref p) (expression float - (var_ref p0) (var_ref p1)))\n"
+ " (return (expression float sqrt (expression float dot (var_ref p) (var_ref p))))))\n"
+ "\n"
+ " (signature float\n"
+ " (parameters\n"
+ " (declare (in) vec2 p0)\n"
+ " (declare (in) vec2 p1))\n"
+ " ((declare () vec2 p)\n"
+ " (assign (constant bool (1)) (var_ref p) (expression vec2 - (var_ref p0) (var_ref p1)))\n"
+ " (return (expression float sqrt (expression float dot (var_ref p) (var_ref p))))))\n"
+ "\n"
+ " (signature float\n"
+ " (parameters\n"
+ " (declare (in) vec3 p0)\n"
+ " (declare (in) vec3 p1))\n"
+ " ((declare () vec3 p)\n"
+ " (assign (constant bool (1)) (var_ref p) (expression vec3 - (var_ref p0) (var_ref p1)))\n"
+ " (return (expression float sqrt (expression float dot (var_ref p) (var_ref p))))))\n"
+ "\n"
+ " (signature float\n"
+ " (parameters\n"
+ " (declare (in) vec4 p0)\n"
+ " (declare (in) vec4 p1))\n"
+ " ((declare () vec4 p)\n"
+ " (assign (constant bool (1)) (var_ref p) (expression vec4 - (var_ref p0) (var_ref p1)))\n"
+ " (return (expression float sqrt (expression float dot (var_ref p) (var_ref p))))))\n"
+ "))\n"
+ ""
+;
+static const char *builtin_noise2 =
+ "((function noise2\n"
+ " (signature vec2\n"
+ " (parameters\n"
+ " (declare (in) float x))\n"
+ " ((return (constant vec2 (0 0)))))\n"
+ " (signature vec2\n"
+ " (parameters\n"
+ " (declare (in) vec2 x))\n"
+ " ((return (constant vec2 (0 0)))))\n"
+ " (signature vec2\n"
+ " (parameters\n"
+ " (declare (in) vec3 x))\n"
+ " ((return (constant vec2 (0 0)))))\n"
+ " (signature vec2\n"
+ " (parameters\n"
+ " (declare (in) vec4 x))\n"
+ " ((return (constant vec2 (0 0)))))\n"
+ "))\n"
+ ""
+;
+static const char *builtin_tanh =
+ "((function tanh\n"
+ " (signature float\n"
+ " (parameters\n"
+ " (declare (in) float x))\n"
+ " ((return (expression float /\n"
+ " (expression float -\n"
+ " (expression float exp (var_ref x))\n"
+ " (expression float exp (expression float neg (var_ref x))))\n"
+ " (expression float +\n"
+ " (expression float exp (var_ref x))\n"
+ " (expression float exp (expression float neg (var_ref x))))))))\n"
+ " (signature vec2\n"
+ " (parameters\n"
+ " (declare (in) vec2 x))\n"
+ " ((return (expression vec2 /\n"
+ " (expression vec2 -\n"
+ " (expression vec2 exp (var_ref x))\n"
+ " (expression vec2 exp (expression vec2 neg (var_ref x))))\n"
+ " (expression vec2 +\n"
+ " (expression vec2 exp (var_ref x))\n"
+ " (expression vec2 exp (expression vec2 neg (var_ref x))))))))\n"
+ " (signature vec3\n"
+ " (parameters\n"
+ " (declare (in) vec3 x))\n"
+ " ((return (expression vec3 /\n"
+ " (expression vec3 -\n"
+ " (expression vec3 exp (var_ref x))\n"
+ " (expression vec3 exp (expression vec3 neg (var_ref x))))\n"
+ " (expression vec3 +\n"
+ " (expression vec3 exp (var_ref x))\n"
+ " (expression vec3 exp (expression vec3 neg (var_ref x))))))))\n"
+ " (signature vec4\n"
+ " (parameters\n"
+ " (declare (in) vec4 x))\n"
+ " ((return (expression vec4 /\n"
+ " (expression vec4 -\n"
+ " (expression vec4 exp (var_ref x))\n"
+ " (expression vec4 exp (expression vec4 neg (var_ref x))))\n"
+ " (expression vec4 +\n"
+ " (expression vec4 exp (var_ref x))\n"
+ " (expression vec4 exp (expression vec4 neg (var_ref x))))))))\n"
+ "))\n"
+ ""
+;
+static const char *builtin_texture1DProjLod =
+ "((function texture1DProjLod\n"
+ " (signature vec4\n"
+ " (parameters\n"
+ " (declare (in) sampler1D sampler)\n"
+ " (declare (in) vec2 P) \n"
+ " (declare (in) float lod) )\n"
+ " ((return (txl (var_ref sampler) (swiz x (var_ref P)) (0 0 0) (swiz y (var_ref P)) () (var_ref lod) ))))\n"
+ "\n"
+ " (signature vec4\n"
+ " (parameters\n"
+ " (declare (in) sampler1D sampler)\n"
+ " (declare (in) vec4 P) \n"
+ " (declare (in) float lod) )\n"
+ " ((return (txl (var_ref sampler) (swiz x (var_ref P)) (0 0 0) (swiz w (var_ref P)) () (var_ref lod) ))))\n"
+ "\n"
+ "))\n"
+ ""
+;
+static const char *builtin_texture1DArray =
+ "((function texture1DArray\n"
+ " (signature vec4\n"
+ " (parameters\n"
+ " (declare (in) sampler1DArray sampler)\n"
+ " (declare (in) vec2 P) )\n"
+ " ((return (tex (var_ref sampler) (var_ref P) (0 0 0) 1 () ))))\n"
+ "\n"
+ " (signature vec4\n"
+ " (parameters\n"
+ " (declare (in) sampler1DArray sampler)\n"
+ " (declare (in) vec2 P) \n"
+ " (declare (in) float bias) )\n"
+ " ((return (txb (var_ref sampler) (var_ref P) (0 0 0) 1 () (var_ref bias) ))))\n"
+ "\n"
+ "))\n"
+ ""
+;
+static const char *builtin_texture2D =
+ "((function texture2D\n"
+ " (signature vec4\n"
+ " (parameters\n"
+ " (declare (in) sampler2D sampler)\n"
+ " (declare (in) vec2 P) )\n"
+ " ((return (tex (var_ref sampler) (var_ref P) (0 0 0) 1 () ))))\n"
+ "\n"
+ " (signature vec4\n"
+ " (parameters\n"
+ " (declare (in) sampler2D sampler)\n"
+ " (declare (in) vec2 P) \n"
+ " (declare (in) float bias) )\n"
+ " ((return (txb (var_ref sampler) (var_ref P) (0 0 0) 1 () (var_ref bias) ))))\n"
+ "\n"
+ "))\n"
+ ""
+;
+static const char *builtin_greaterThanEqual =
+ "((function greaterThanEqual\n"
+ " (signature bvec2\n"
+ " (parameters\n"
+ " (declare (in) vec2 arg0)\n"
+ " (declare (in) vec2 arg1))\n"
+ " ((declare () bvec2 temp)\n"
+ " (assign (constant bool (1)) (swiz x (var_ref temp)) (expression bool >= (swiz x (var_ref arg0))(swiz x (var_ref arg1)))) \n"
+ " (assign (constant bool (1)) (swiz y (var_ref temp)) (expression bool >= (swiz y (var_ref arg0))(swiz y (var_ref arg1)))) \n"
+ " (return (var_ref temp))))\n"
+ "\n"
+ " (signature bvec3\n"
+ " (parameters\n"
+ " (declare (in) vec3 arg0)\n"
+ " (declare (in) vec3 arg1))\n"
+ " ((declare () bvec3 temp)\n"
+ " (assign (constant bool (1)) (swiz x (var_ref temp)) (expression bool >= (swiz x (var_ref arg0))(swiz x (var_ref arg1)))) \n"
+ " (assign (constant bool (1)) (swiz y (var_ref temp)) (expression bool >= (swiz y (var_ref arg0))(swiz y (var_ref arg1)))) \n"
+ " (assign (constant bool (1)) (swiz z (var_ref temp)) (expression bool >= (swiz z (var_ref arg0))(swiz z (var_ref arg1)))) \n"
+ " (return (var_ref temp))))\n"
+ "\n"
+ " (signature bvec4\n"
+ " (parameters\n"
+ " (declare (in) vec4 arg0)\n"
+ " (declare (in) vec4 arg1))\n"
+ " ((declare () bvec4 temp)\n"
+ " (assign (constant bool (1)) (swiz x (var_ref temp)) (expression bool >= (swiz x (var_ref arg0))(swiz x (var_ref arg1)))) \n"
+ " (assign (constant bool (1)) (swiz y (var_ref temp)) (expression bool >= (swiz y (var_ref arg0))(swiz y (var_ref arg1)))) \n"
+ " (assign (constant bool (1)) (swiz z (var_ref temp)) (expression bool >= (swiz z (var_ref arg0))(swiz z (var_ref arg1)))) \n"
+ " (assign (constant bool (1)) (swiz w (var_ref temp)) (expression bool >= (swiz w (var_ref arg0))(swiz w (var_ref arg1)))) \n"
+ " (return (var_ref temp))))\n"
+ "\n"
+ " (signature bvec2\n"
+ " (parameters\n"
+ " (declare (in) ivec2 arg0)\n"
+ " (declare (in) ivec2 arg1))\n"
+ " ((declare () bvec2 temp)\n"
+ " (assign (constant bool (1)) (swiz x (var_ref temp)) (expression bool >= (swiz x (var_ref arg0))(swiz x (var_ref arg1)))) \n"
+ " (assign (constant bool (1)) (swiz y (var_ref temp)) (expression bool >= (swiz y (var_ref arg0))(swiz y (var_ref arg1)))) \n"
+ " (return (var_ref temp))))\n"
+ "\n"
+ " (signature bvec3\n"
+ " (parameters\n"
+ " (declare (in) ivec3 arg0)\n"
+ " (declare (in) ivec3 arg1))\n"
+ " ((declare () bvec3 temp)\n"
+ " (assign (constant bool (1)) (swiz x (var_ref temp)) (expression bool >= (swiz x (var_ref arg0))(swiz x (var_ref arg1)))) \n"
+ " (assign (constant bool (1)) (swiz y (var_ref temp)) (expression bool >= (swiz y (var_ref arg0))(swiz y (var_ref arg1)))) \n"
+ " (assign (constant bool (1)) (swiz z (var_ref temp)) (expression bool >= (swiz z (var_ref arg0))(swiz z (var_ref arg1)))) \n"
+ " (return (var_ref temp))))\n"
+ "\n"
+ " (signature bvec4\n"
+ " (parameters\n"
+ " (declare (in) ivec4 arg0)\n"
+ " (declare (in) ivec4 arg1))\n"
+ " ((declare () bvec4 temp)\n"
+ " (assign (constant bool (1)) (swiz x (var_ref temp)) (expression bool >= (swiz x (var_ref arg0))(swiz x (var_ref arg1)))) \n"
+ " (assign (constant bool (1)) (swiz y (var_ref temp)) (expression bool >= (swiz y (var_ref arg0))(swiz y (var_ref arg1)))) \n"
+ " (assign (constant bool (1)) (swiz z (var_ref temp)) (expression bool >= (swiz z (var_ref arg0))(swiz z (var_ref arg1)))) \n"
+ " (assign (constant bool (1)) (swiz w (var_ref temp)) (expression bool >= (swiz w (var_ref arg0))(swiz w (var_ref arg1)))) \n"
+ " (return (var_ref temp))))\n"
+ "\n"
+ " (signature bvec2\n"
+ " (parameters\n"
+ " (declare (in) uvec2 arg0)\n"
+ " (declare (in) uvec2 arg1))\n"
+ " ((declare () bvec2 temp)\n"
+ " (assign (constant bool (1)) (swiz x (var_ref temp)) (expression bool >= (swiz x (var_ref arg0))(swiz x (var_ref arg1)))) \n"
+ " (assign (constant bool (1)) (swiz y (var_ref temp)) (expression bool >= (swiz y (var_ref arg0))(swiz y (var_ref arg1)))) \n"
+ " (return (var_ref temp))))\n"
+ "\n"
+ " (signature bvec3\n"
+ " (parameters\n"
+ " (declare (in) uvec3 arg0)\n"
+ " (declare (in) uvec3 arg1))\n"
+ " ((declare () bvec3 temp)\n"
+ " (assign (constant bool (1)) (swiz x (var_ref temp)) (expression bool >= (swiz x (var_ref arg0))(swiz x (var_ref arg1)))) \n"
+ " (assign (constant bool (1)) (swiz y (var_ref temp)) (expression bool >= (swiz y (var_ref arg0))(swiz y (var_ref arg1)))) \n"
+ " (assign (constant bool (1)) (swiz z (var_ref temp)) (expression bool >= (swiz z (var_ref arg0))(swiz z (var_ref arg1)))) \n"
+ " (return (var_ref temp))))\n"
+ "\n"
+ " (signature bvec4\n"
+ " (parameters\n"
+ " (declare (in) uvec4 arg0)\n"
+ " (declare (in) uvec4 arg1))\n"
+ " ((declare () bvec4 temp)\n"
+ " (assign (constant bool (1)) (swiz x (var_ref temp)) (expression bool >= (swiz x (var_ref arg0))(swiz x (var_ref arg1)))) \n"
+ " (assign (constant bool (1)) (swiz y (var_ref temp)) (expression bool >= (swiz y (var_ref arg0))(swiz y (var_ref arg1)))) \n"
+ " (assign (constant bool (1)) (swiz z (var_ref temp)) (expression bool >= (swiz z (var_ref arg0))(swiz z (var_ref arg1)))) \n"
+ " (assign (constant bool (1)) (swiz w (var_ref temp)) (expression bool >= (swiz w (var_ref arg0))(swiz w (var_ref arg1)))) \n"
+ " (return (var_ref temp))))\n"
+ "))\n"
+ ""
+;
+static const char *builtin_texture3DProjLod =
+ "((function texture3DProjLod\n"
+ " (signature vec4\n"
+ " (parameters\n"
+ " (declare (in) sampler3D sampler)\n"
+ " (declare (in) vec4 P) \n"
+ " (declare (in) float lod) )\n"
+ " ((return (txl (var_ref sampler) (swiz xyz (var_ref P)) (0 0 0) (swiz w (var_ref P)) () (var_ref lod) ))))\n"
+ "\n"
+ "))\n"
+ ""
+;
+static const char *builtin_tan =
+ "((function tan\n"
+ " (signature float\n"
+ " (parameters\n"
+ " (declare (in) float angle))\n"
+ " ((return (expression float / (expression float sin (var_ref angle)) (expression float cos (var_ref angle))))))\n"
+ "\n"
+ " (signature vec2\n"
+ " (parameters\n"
+ " (declare (in) vec2 angle))\n"
+ " ((return (expression vec2 / (expression vec2 sin (var_ref angle)) (expression vec2 cos (var_ref angle))))))\n"
+ "\n"
+ " (signature vec3\n"
+ " (parameters\n"
+ " (declare (in) vec3 angle))\n"
+ " ((return (expression vec3 / (expression vec3 sin (var_ref angle)) (expression vec3 cos (var_ref angle))))))\n"
+ "\n"
+ " (signature vec4\n"
+ " (parameters\n"
+ " (declare (in) vec4 angle))\n"
+ " ((return (expression vec4 / (expression vec4 sin (var_ref angle)) (expression vec4 cos (var_ref angle))))))\n"
+ "))\n"
+ ""
+;
+static const char *builtin_any =
+ "((function any\n"
+ " (signature bool\n"
+ " (parameters\n"
+ " (declare (in) bvec2 arg0))\n"
+ " ((return (expression bool || (swiz x (var_ref arg0))(swiz y (var_ref arg0))))))\n"
+ "\n"
+ " (signature bool\n"
+ " (parameters\n"
+ " (declare (in) bvec3 arg0))\n"
+ " ((return (expression bool || (expression bool || (swiz x (var_ref arg0))(swiz y (var_ref arg0))) (swiz z (var_ref arg0))))))\n"
+ "\n"
+ " (signature bool\n"
+ " (parameters\n"
+ " (declare (in) bvec4 arg0))\n"
+ " ((return (expression bool || (expression bool || (expression bool || (swiz x (var_ref arg0))(swiz y (var_ref arg0))) (swiz z (var_ref arg0))) (swiz w (var_ref arg0))))))\n"
+ "))\n"
+ ""
+;
+static const char *builtin_normalize =
+ "((function normalize\n"
+ " (signature float\n"
+ " (parameters\n"
+ " (declare (in) float arg0))\n"
+ " ((return (expression float * (var_ref arg0) (expression float rsq (expression float dot (var_ref arg0) (var_ref arg0)))))))\n"
+ "\n"
+ " (signature vec2\n"
+ " (parameters\n"
+ " (declare (in) vec2 arg0))\n"
+ " ((return (expression vec2 * (var_ref arg0) (expression float rsq (expression float dot (var_ref arg0) (var_ref arg0)))))))\n"
+ "\n"
+ " (signature vec3\n"
+ " (parameters\n"
+ " (declare (in) vec3 arg0))\n"
+ " ((return (expression vec3 * (var_ref arg0) (expression float rsq (expression float dot (var_ref arg0) (var_ref arg0)))))))\n"
+ "\n"
+ " (signature vec4\n"
+ " (parameters\n"
+ " (declare (in) vec4 arg0))\n"
+ " ((return (expression vec4 * (var_ref arg0) (expression float rsq (expression float dot (var_ref arg0) (var_ref arg0)))))))\n"
+ "))\n"
+ ""
+;
+static const char *builtin_shadow1DProj =
+ "((function shadow1DProj\n"
+ " (signature vec4\n"
+ " (parameters\n"
+ " (declare (in) sampler1DShadow sampler)\n"
+ " (declare (in) vec4 P) )\n"
+ " ((return (tex (var_ref sampler) (swiz x (var_ref P)) (0 0 0) (swiz w (var_ref P)) (swiz z (var_ref P)) ))))\n"
+ "\n"
+ " (signature vec4\n"
+ " (parameters\n"
+ " (declare (in) sampler1DShadow sampler)\n"
+ " (declare (in) vec4 P) \n"
+ " (declare (in) float bias) )\n"
+ " ((return (txb (var_ref sampler) (swiz x (var_ref P)) (0 0 0) (swiz w (var_ref P)) (swiz z (var_ref P)) (var_ref bias) ))))\n"
+ "\n"
+ "))\n"
+ ""
+;
+static const char *builtin_floor =
+ "((function floor\n"
+ " (signature float\n"
+ " (parameters\n"
+ " (declare (in) float arg0))\n"
+ " ((return (expression float floor (var_ref arg0)))))\n"
+ "\n"
+ " (signature vec2\n"
+ " (parameters\n"
+ " (declare (in) vec2 arg0))\n"
+ " ((return (expression vec2 floor (var_ref arg0)))))\n"
+ "\n"
+ " (signature vec3\n"
+ " (parameters\n"
+ " (declare (in) vec3 arg0))\n"
+ " ((return (expression vec3 floor (var_ref arg0)))))\n"
+ "\n"
+ " (signature vec4\n"
+ " (parameters\n"
+ " (declare (in) vec4 arg0))\n"
+ " ((return (expression vec4 floor (var_ref arg0)))))\n"
+ "))\n"
+ ""
+;
+static const char *builtin_cross =
+ "((function cross\n"
+ " (signature vec3\n"
+ " (parameters\n"
+ " (declare (in) vec3 arg0)\n"
+ " (declare (in) vec3 arg1))\n"
+ " ((return (expression vec3 cross (var_ref arg0) (var_ref arg1)))))\n"
+ "))\n"
+ ""
+;
+static const char *builtin_sqrt =
+ "((function sqrt\n"
+ " (signature float\n"
+ " (parameters\n"
+ " (declare (in) float arg0))\n"
+ " ((return (expression float sqrt (var_ref arg0)))))\n"
+ "\n"
+ " (signature vec2\n"
+ " (parameters\n"
+ " (declare (in) vec2 arg0))\n"
+ " ((return (expression vec2 sqrt (var_ref arg0)))))\n"
+ "\n"
+ " (signature vec3\n"
+ " (parameters\n"
+ " (declare (in) vec3 arg0))\n"
+ " ((return (expression vec3 sqrt (var_ref arg0)))))\n"
+ "\n"
+ " (signature vec4\n"
+ " (parameters\n"
+ " (declare (in) vec4 arg0))\n"
+ " ((return (expression vec4 sqrt (var_ref arg0)))))\n"
+ "))\n"
+ ""
+;
+static const char *builtin_mix =
+ "((function mix\n"
+ " (signature float\n"
+ " (parameters\n"
+ " (declare (in) float arg0)\n"
+ " (declare (in) float arg1)\n"
+ " (declare (in) float arg2))\n"
+ " ((return (expression float + (expression float * (var_ref arg0) (expression float - (constant float (1.000000)) (var_ref arg2))) (expression float * (var_ref arg1) (var_ref arg2))))))\n"
+ "\n"
+ " (signature vec2\n"
+ " (parameters\n"
+ " (declare (in) vec2 arg0)\n"
+ " (declare (in) vec2 arg1)\n"
+ " (declare (in) vec2 arg2))\n"
+ " ((return (expression vec2 + (expression vec2 * (var_ref arg0) (expression vec2 - (constant float (1.000000)) (var_ref arg2))) (expression vec2 * (var_ref arg1) (var_ref arg2))))))\n"
+ "\n"
+ " (signature vec3\n"
+ " (parameters\n"
+ " (declare (in) vec3 arg0)\n"
+ " (declare (in) vec3 arg1)\n"
+ " (declare (in) vec3 arg2))\n"
+ " ((return (expression vec3 + (expression vec3 * (var_ref arg0) (expression vec3 - (constant float (1.000000)) (var_ref arg2))) (expression vec3 * (var_ref arg1) (var_ref arg2))))))\n"
+ "\n"
+ " (signature vec4\n"
+ " (parameters\n"
+ " (declare (in) vec4 arg0)\n"
+ " (declare (in) vec4 arg1)\n"
+ " (declare (in) vec4 arg2))\n"
+ " ((return (expression vec4 + (expression vec4 * (var_ref arg0) (expression vec4 - (constant float (1.000000)) (var_ref arg2))) (expression vec4 * (var_ref arg1) (var_ref arg2))))))\n"
+ "\n"
+ " (signature vec2\n"
+ " (parameters\n"
+ " (declare (in) vec2 arg0)\n"
+ " (declare (in) vec2 arg1)\n"
+ " (declare (in) float arg2))\n"
+ " ((return (expression vec2 + (expression vec2 * (var_ref arg0) (expression float - (constant float (1.000000)) (var_ref arg2))) (expression vec2 * (var_ref arg1) (var_ref arg2))))))\n"
+ "\n"
+ " (signature vec3\n"
+ " (parameters\n"
+ " (declare (in) vec3 arg0)\n"
+ " (declare (in) vec3 arg1)\n"
+ " (declare (in) float arg2))\n"
+ " ((return (expression vec3 + (expression vec3 * (var_ref arg0) (expression float - (constant float (1.000000)) (var_ref arg2))) (expression vec3 * (var_ref arg1) (var_ref arg2))))))\n"
+ "\n"
+ " (signature vec4\n"
+ " (parameters\n"
+ " (declare (in) vec4 arg0)\n"
+ " (declare (in) vec4 arg1)\n"
+ " (declare (in) float arg2))\n"
+ " ((return (expression vec4 + (expression vec4 * (var_ref arg0) (expression float - (constant float (1.000000)) (var_ref arg2))) (expression vec4 * (var_ref arg1) (var_ref arg2))))))\n"
+ "\n"
+ " (signature float\n"
+ " (parameters\n"
+ " (declare (in) float v1)\n"
+ " (declare (in) float v2)\n"
+ " (declare (in) bool a))\n"
+ " ((assign (var_ref a) (var_ref v1) (var_ref v2))\n"
+ " (return (var_ref v1))))\n"
+ "\n"
+ " (signature vec2\n"
+ " (parameters\n"
+ " (declare (in) vec2 v1)\n"
+ " (declare (in) vec2 v2)\n"
+ " (declare (in) bvec2 a))\n"
+ " ((assign (swiz x (var_ref a)) (swiz x (var_ref v1)) (swiz x (var_ref v2)))\n"
+ " (assign (swiz y (var_ref a)) (swiz y (var_ref v1)) (swiz y (var_ref v2)))\n"
+ " (return (var_ref v1))))\n"
+ "\n"
+ " (signature vec3\n"
+ " (parameters\n"
+ " (declare (in) vec3 v1)\n"
+ " (declare (in) vec3 v2)\n"
+ " (declare (in) bvec3 a))\n"
+ " ((assign (swiz x (var_ref a)) (swiz x (var_ref v1)) (swiz x (var_ref v2)))\n"
+ " (assign (swiz y (var_ref a)) (swiz y (var_ref v1)) (swiz y (var_ref v2)))\n"
+ " (assign (swiz z (var_ref a)) (swiz z (var_ref v1)) (swiz z (var_ref v2)))\n"
+ " (return (var_ref v1))))\n"
+ "\n"
+ " (signature vec4\n"
+ " (parameters\n"
+ " (declare (in) vec4 v1)\n"
+ " (declare (in) vec4 v2)\n"
+ " (declare (in) bvec4 a))\n"
+ " ((assign (swiz x (var_ref a)) (swiz x (var_ref v1)) (swiz x (var_ref v2)))\n"
+ " (assign (swiz y (var_ref a)) (swiz y (var_ref v1)) (swiz y (var_ref v2)))\n"
+ " (assign (swiz z (var_ref a)) (swiz z (var_ref v1)) (swiz z (var_ref v2)))\n"
+ " (assign (swiz w (var_ref a)) (swiz w (var_ref v1)) (swiz w (var_ref v2)))\n"
+ " (return (var_ref v1))))\n"
+ "))\n"
+ ""
+;
+static const char *builtin_shadow1DArrayLod =
+ "((function shadow1DArrayLod\n"
+ " (signature vec4\n"
+ " (parameters\n"
+ " (declare (in) sampler1DArrayShadow sampler)\n"
+ " (declare (in) vec3 P) \n"
+ " (declare (in) float lod) )\n"
+ " ((return (txl (var_ref sampler) (swiz xy (var_ref P)) (0 0 0) 1 (swiz z (var_ref P)) (var_ref lod) ))))\n"
+ "\n"
+ "))\n"
+ ""
+;
+static const char *builtin_ftransform =
+ "((declare (uniform) mat4 gl_ModelViewProjectionMatrix)\n"
+ " (declare (in) vec4 gl_Vertex)\n"
+ " (function ftransform\n"
+ " (signature vec4\n"
+ " (parameters)\n"
+ " ((return (expression vec4 *\n"
+ " (var_ref gl_ModelViewProjectionMatrix)\n"
+ " (var_ref gl_Vertex)))))\n"
+ "))\n"
+ ""
+;
+static const char *builtin_sin =
+ "((function sin\n"
+ " (signature float\n"
+ " (parameters\n"
+ " (declare (in) float angle))\n"
+ " ((return (expression float sin (var_ref angle)))))\n"
+ "\n"
+ " (signature vec2\n"
+ " (parameters\n"
+ " (declare (in) vec2 angle))\n"
+ " ((return (expression vec2 sin (var_ref angle)))))\n"
+ "\n"
+ " (signature vec3\n"
+ " (parameters\n"
+ " (declare (in) vec3 angle))\n"
+ " ((return (expression vec3 sin (var_ref angle)))))\n"
+ "\n"
+ " (signature vec4\n"
+ " (parameters\n"
+ " (declare (in) vec4 angle))\n"
+ " ((return (expression vec4 sin (var_ref angle)))))\n"
+ "))\n"
+ ""
+;
+static const char *builtin_shadow2D =
+ "((function shadow2D\n"
+ " (signature vec4\n"
+ " (parameters\n"
+ " (declare (in) sampler2DShadow sampler)\n"
+ " (declare (in) vec3 P) )\n"
+ " ((return (tex (var_ref sampler) (swiz xy (var_ref P)) (0 0 0) 1 (swiz z (var_ref P)) ))))\n"
+ "\n"
+ " (signature vec4\n"
+ " (parameters\n"
+ " (declare (in) sampler2DShadow sampler)\n"
+ " (declare (in) vec3 P) \n"
+ " (declare (in) float bias) )\n"
+ " ((return (txb (var_ref sampler) (swiz xy (var_ref P)) (0 0 0) 1 (swiz z (var_ref P)) (var_ref bias) ))))\n"
+ "\n"
+ "))\n"
+ ""
+;
+static const char *builtin_shadow2DLod =
+ "((function shadow2DLod\n"
+ " (signature vec4\n"
+ " (parameters\n"
+ " (declare (in) sampler2DShadow sampler)\n"
+ " (declare (in) vec3 P) \n"
+ " (declare (in) float lod) )\n"
+ " ((return (txl (var_ref sampler) (swiz xy (var_ref P)) (0 0 0) 1 (swiz z (var_ref P)) (var_ref lod) ))))\n"
+ "\n"
+ "))\n"
+ ""
+;
+static const char *builtin_shadow2DRectProj =
+ "((function shadow2DRectProj\n"
+ " (signature vec4\n"
+ " (parameters\n"
+ " (declare (in) sampler2DRectShadow sampler)\n"
+ " (declare (in) vec4 P) )\n"
+ " ((return (tex (var_ref sampler) (swiz xy (var_ref P)) (0 0 0) (swiz w (var_ref P)) (swiz z (var_ref P)) ))))\n"
+ "\n"
+ "))\n"
+ ""
+;
+static const char *builtin_atan =
+ "((function atan\n"
+ " (signature float\n"
+ " (parameters\n"
+ " (declare (in) float x))\n"
+ " ((return (call asin ((expression float *\n"
+ " (var_ref x)\n"
+ " (expression float rsq\n"
+ " (expression float +\n"
+ " (expression float *\n"
+ " (var_ref x)\n"
+ " (var_ref x))\n"
+ " (constant float (1.0))))))))))\n"
+ "\n"
+ " (signature vec2\n"
+ " (parameters\n"
+ " (declare (in) vec2 y_over_x))\n"
+ " ((return (call asin ((expression vec2 *\n"
+ " (var_ref y_over_x)\n"
+ " (expression vec2 rsq\n"
+ " (expression vec2 +\n"
+ " (expression vec2 *\n"
+ " (var_ref y_over_x)\n"
+ " (var_ref y_over_x))\n"
+ " (constant float (1.0))))))))))\n"
+ "\n"
+ " (signature vec3\n"
+ " (parameters\n"
+ " (declare (in) vec3 y_over_x))\n"
+ " ((return (call asin ((expression vec3 *\n"
+ " (var_ref y_over_x)\n"
+ " (expression vec3 rsq\n"
+ " (expression vec3 +\n"
+ " (expression vec3 *\n"
+ " (var_ref y_over_x)\n"
+ " (var_ref y_over_x))\n"
+ " (constant float (1.0))))))))))\n"
+ "\n"
+ " (signature vec4\n"
+ " (parameters\n"
+ " (declare (in) vec4 y_over_x))\n"
+ " ((return (call asin ((expression vec4 *\n"
+ " (var_ref y_over_x)\n"
+ " (expression vec4 rsq\n"
+ " (expression vec4 +\n"
+ " (expression vec4 *\n"
+ " (var_ref y_over_x)\n"
+ " (var_ref y_over_x))\n"
+ " (constant float (1.0))))))))))\n"
+ "\n"
+ " (signature float\n"
+ " (parameters\n"
+ " (declare (in ) float y)\n"
+ " (declare (in ) float x)\n"
+ " )\n"
+ " (\n"
+ " (declare () float r)\n"
+ " (declare ( ) float abs_retval)\n"
+ " (assign (constant bool (1)) (var_ref abs_retval) (call abs ((var_ref x) ))\n"
+ ") \n"
+ " (if (expression bool > (var_ref abs_retval) (constant float (0.000100)) ) (\n"
+ " (declare ( ) float atan_retval)\n"
+ " (assign (constant bool (1)) (var_ref atan_retval) (call atan ((expression float / (var_ref y) (var_ref x) ) ))\n"
+ ") \n"
+ " (assign (constant bool (1)) (var_ref r) (var_ref atan_retval) ) \n"
+ " (if (expression bool < (var_ref x) (constant float (0.000000)) ) (\n"
+ " (if (expression bool >= (var_ref y) (constant float (0.000000)) ) (\n"
+ " (declare ( ) float assignment_tmp)\n"
+ " (assign (constant bool (1)) (var_ref assignment_tmp) (expression float + (var_ref r) (constant float (3.141593)) ) ) \n"
+ " (assign (constant bool (1)) (var_ref r) (var_ref assignment_tmp) ) \n"
+ " )\n"
+ " (\n"
+ " (declare ( ) float assignment_tmp)\n"
+ " (assign (constant bool (1)) (var_ref assignment_tmp) (expression float - (var_ref r) (constant float (3.141593)) ) ) \n"
+ " (assign (constant bool (1)) (var_ref r) (var_ref assignment_tmp) ) \n"
+ " ))\n"
+ "\n"
+ " )\n"
+ " (\n"
+ " ))\n"
+ "\n"
+ " )\n"
+ " (\n"
+ " (if (expression bool >= (var_ref y) (constant float (0.000000)) ) (\n"
+ " (assign (constant bool (1)) (var_ref r) (constant float (1.570796)) ) \n"
+ " )\n"
+ " (\n"
+ " (assign (constant bool (1)) (var_ref r) (constant float (-1.570796)) ) \n"
+ " ))\n"
+ "\n"
+ " ))\n"
+ "\n"
+ " (return (var_ref r) )\n"
+ " ))\n"
+ "\n"
+ "\n"
+ "\n"
+ " (signature vec2\n"
+ " (parameters\n"
+ " (declare (in) vec2 y)\n"
+ " (declare (in) vec2 x))\n"
+ " ((declare () vec2 r)\n"
+ " (assign (constant bool (1))\n"
+ " (swiz x (var_ref r))\n"
+ " (call atan ((swiz x (var_ref y))\n"
+ " (swiz x (var_ref x)))))\n"
+ " (assign (constant bool (1))\n"
+ " (swiz y (var_ref r))\n"
+ " (call atan ((swiz y (var_ref y))\n"
+ " (swiz y (var_ref x)))))\n"
+ " (return (var_ref r))))\n"
+ "\n"
+ " (signature vec3\n"
+ " (parameters\n"
+ " (declare (in) vec3 y)\n"
+ " (declare (in) vec3 x))\n"
+ " ((declare () vec3 r)\n"
+ " (assign (constant bool (1))\n"
+ " (swiz x (var_ref r))\n"
+ " (call atan ((swiz x (var_ref y))\n"
+ " (swiz x (var_ref x)))))\n"
+ " (assign (constant bool (1))\n"
+ " (swiz y (var_ref r))\n"
+ " (call atan ((swiz y (var_ref y))\n"
+ " (swiz y (var_ref x)))))\n"
+ " (assign (constant bool (1))\n"
+ " (swiz z (var_ref r))\n"
+ " (call atan ((swiz z (var_ref y))\n"
+ " (swiz z (var_ref x)))))\n"
+ " (return (var_ref r))))\n"
+ "\n"
+ " (signature vec4\n"
+ " (parameters\n"
+ " (declare (in) vec4 y)\n"
+ " (declare (in) vec4 x))\n"
+ " ((declare () vec4 r)\n"
+ " (assign (constant bool (1))\n"
+ " (swiz x (var_ref r))\n"
+ " (call atan ((swiz x (var_ref y))\n"
+ " (swiz x (var_ref x)))))\n"
+ " (assign (constant bool (1))\n"
+ " (swiz y (var_ref r))\n"
+ " (call atan ((swiz y (var_ref y))\n"
+ " (swiz y (var_ref x)))))\n"
+ " (assign (constant bool (1))\n"
+ " (swiz z (var_ref r))\n"
+ " (call atan ((swiz z (var_ref y))\n"
+ " (swiz z (var_ref x)))))\n"
+ " (assign (constant bool (1))\n"
+ " (swiz w (var_ref r))\n"
+ " (call atan ((swiz w (var_ref y))\n"
+ " (swiz w (var_ref x)))))\n"
+ " (return (var_ref r)))))\n"
+ "\n"
+ "))\n"
+ ""
+;
+static const char *builtin_max =
+ "((function max\n"
+ " (signature float\n"
+ " (parameters\n"
+ " (declare (in) float arg0)\n"
+ " (declare (in) float arg1))\n"
+ " ((return (expression float max (var_ref arg0) (var_ref arg1)))))\n"
+ "\n"
+ " (signature vec2\n"
+ " (parameters\n"
+ " (declare (in) vec2 arg0)\n"
+ " (declare (in) vec2 arg1))\n"
+ " ((return (expression vec2 max (var_ref arg0) (var_ref arg1)))))\n"
+ "\n"
+ " (signature vec3\n"
+ " (parameters\n"
+ " (declare (in) vec3 arg0)\n"
+ " (declare (in) vec3 arg1))\n"
+ " ((return (expression vec3 max (var_ref arg0) (var_ref arg1)))))\n"
+ "\n"
+ " (signature vec4\n"
+ " (parameters\n"
+ " (declare (in) vec4 arg0)\n"
+ " (declare (in) vec4 arg1))\n"
+ " ((return (expression vec4 max (var_ref arg0) (var_ref arg1)))))\n"
+ "\n"
+ " (signature vec2\n"
+ " (parameters\n"
+ " (declare (in) vec2 arg0)\n"
+ " (declare (in) float arg1))\n"
+ " ((return (expression vec2 max (var_ref arg0) (var_ref arg1)))))\n"
+ "\n"
+ " (signature vec3\n"
+ " (parameters\n"
+ " (declare (in) vec3 arg0)\n"
+ " (declare (in) float arg1))\n"
+ " ((return (expression vec3 max (var_ref arg0) (var_ref arg1)))))\n"
+ "\n"
+ " (signature vec4\n"
+ " (parameters\n"
+ " (declare (in) vec4 arg0)\n"
+ " (declare (in) float arg1))\n"
+ " ((return (expression vec4 max (var_ref arg0) (var_ref arg1)))))\n"
+ "\n"
+ " (signature int\n"
+ " (parameters\n"
+ " (declare (in) int arg0)\n"
+ " (declare (in) int arg1))\n"
+ " ((return (expression int max (var_ref arg0) (var_ref arg1)))))\n"
+ "\n"
+ " (signature ivec2\n"
+ " (parameters\n"
+ " (declare (in) ivec2 arg0)\n"
+ " (declare (in) ivec2 arg1))\n"
+ " ((return (expression ivec2 max (var_ref arg0) (var_ref arg1)))))\n"
+ "\n"
+ " (signature ivec3\n"
+ " (parameters\n"
+ " (declare (in) ivec3 arg0)\n"
+ " (declare (in) ivec3 arg1))\n"
+ " ((return (expression ivec3 max (var_ref arg0) (var_ref arg1)))))\n"
+ "\n"
+ " (signature ivec4\n"
+ " (parameters\n"
+ " (declare (in) ivec4 arg0)\n"
+ " (declare (in) ivec4 arg1))\n"
+ " ((return (expression ivec4 max (var_ref arg0) (var_ref arg1)))))\n"
+ "\n"
+ " (signature ivec2\n"
+ " (parameters\n"
+ " (declare (in) ivec2 arg0)\n"
+ " (declare (in) int arg1))\n"
+ " ((return (expression ivec2 max (var_ref arg0) (var_ref arg1)))))\n"
+ "\n"
+ " (signature ivec3\n"
+ " (parameters\n"
+ " (declare (in) ivec3 arg0)\n"
+ " (declare (in) int arg1))\n"
+ " ((return (expression ivec3 max (var_ref arg0) (var_ref arg1)))))\n"
+ "\n"
+ " (signature ivec4\n"
+ " (parameters\n"
+ " (declare (in) ivec4 arg0)\n"
+ " (declare (in) int arg1))\n"
+ " ((return (expression ivec4 max (var_ref arg0) (var_ref arg1)))))\n"
+ "\n"
+ " (signature uint\n"
+ " (parameters\n"
+ " (declare (in) uint arg0)\n"
+ " (declare (in) uint arg1))\n"
+ " ((return (expression uint max (var_ref arg0) (var_ref arg1)))))\n"
+ "\n"
+ " (signature uvec2\n"
+ " (parameters\n"
+ " (declare (in) uvec2 arg0)\n"
+ " (declare (in) uvec2 arg1))\n"
+ " ((return (expression uvec2 max (var_ref arg0) (var_ref arg1)))))\n"
+ "\n"
+ " (signature uvec3\n"
+ " (parameters\n"
+ " (declare (in) uvec3 arg0)\n"
+ " (declare (in) uvec3 arg1))\n"
+ " ((return (expression uvec3 max (var_ref arg0) (var_ref arg1)))))\n"
+ "\n"
+ " (signature uvec4\n"
+ " (parameters\n"
+ " (declare (in) uvec4 arg0)\n"
+ " (declare (in) uvec4 arg1))\n"
+ " ((return (expression uvec4 max (var_ref arg0) (var_ref arg1)))))\n"
+ "\n"
+ " (signature uvec2\n"
+ " (parameters\n"
+ " (declare (in) uvec2 arg0)\n"
+ " (declare (in) uint arg1))\n"
+ " ((return (expression uvec2 max (var_ref arg0) (var_ref arg1)))))\n"
+ "\n"
+ " (signature uvec3\n"
+ " (parameters\n"
+ " (declare (in) uvec3 arg0)\n"
+ " (declare (in) uint arg1))\n"
+ " ((return (expression uvec3 max (var_ref arg0) (var_ref arg1)))))\n"
+ "\n"
+ " (signature uvec4\n"
+ " (parameters\n"
+ " (declare (in) uvec4 arg0)\n"
+ " (declare (in) uint arg1))\n"
+ " ((return (expression uvec4 max (var_ref arg0) (var_ref arg1)))))\n"
+ "))\n"
+ ""
+;
+static const char *builtin_reflect =
+ "((function reflect\n"
+ " (signature float\n"
+ " (parameters\n"
+ " (declare (in) float i)\n"
+ " (declare (in) float n))\n"
+ " ((return (expression float -\n"
+ " (var_ref i)\n"
+ " (expression float *\n"
+ " (constant float (2.0))\n"
+ " (expression float *\n"
+ " (expression float dot\n"
+ " (var_ref n)\n"
+ " (var_ref i))\n"
+ " (var_ref n)))))))\n"
+ "\n"
+ " (signature vec2\n"
+ " (parameters\n"
+ " (declare (in) vec2 i)\n"
+ " (declare (in) vec2 n))\n"
+ " ((return (expression vec2 -\n"
+ " (var_ref i)\n"
+ " (expression vec2 *\n"
+ " (constant float (2.0))\n"
+ " (expression vec2 *\n"
+ " (expression float dot\n"
+ " (var_ref n)\n"
+ " (var_ref i))\n"
+ " (var_ref n)))))))\n"
+ "\n"
+ " (signature vec3\n"
+ " (parameters\n"
+ " (declare (in) vec3 i)\n"
+ " (declare (in) vec3 n))\n"
+ " ((return (expression vec3 -\n"
+ " (var_ref i)\n"
+ " (expression vec3 *\n"
+ " (constant float (2.0))\n"
+ " (expression vec3 *\n"
+ " (expression float dot\n"
+ " (var_ref n)\n"
+ " (var_ref i))\n"
+ " (var_ref n)))))))\n"
+ "\n"
+ " (signature vec4\n"
+ " (parameters\n"
+ " (declare (in) vec4 i)\n"
+ " (declare (in) vec4 n))\n"
+ " ((return (expression vec4 -\n"
+ " (var_ref i)\n"
+ " (expression vec4 *\n"
+ " (constant float (2.0))\n"
+ " (expression vec4 *\n"
+ " (expression float dot\n"
+ " (var_ref n)\n"
+ " (var_ref i))\n"
+ " (var_ref n)))))))\n"
+ "\n"
+ "))\n"
+ ""
+;
+static const char *builtin_texture3D =
+ "((function texture3D\n"
+ " (signature vec4\n"
+ " (parameters\n"
+ " (declare (in) sampler3D sampler)\n"
+ " (declare (in) vec3 P) )\n"
+ " ((return (tex (var_ref sampler) (var_ref P) (0 0 0) 1 () ))))\n"
+ "\n"
+ " (signature vec4\n"
+ " (parameters\n"
+ " (declare (in) sampler3D sampler)\n"
+ " (declare (in) vec3 P) \n"
+ " (declare (in) float bias) )\n"
+ " ((return (txb (var_ref sampler) (var_ref P) (0 0 0) 1 () (var_ref bias) ))))\n"
+ "\n"
+ "))\n"
+ ""
+;
+static const char *builtin_texelFetch =
+ "((function texelFetch\n"
+ " (signature vec4\n"
+ " (parameters\n"
+ " (declare (in) sampler1D sampler)\n"
+ " (declare (in) int P) \n"
+ " (declare (in) int lod) )\n"
+ " ((return (txf (var_ref sampler) (var_ref P) (0 0 0) (var_ref lod) ))))\n"
+ "\n"
+ " (signature ivec4\n"
+ " (parameters\n"
+ " (declare (in) isampler1D sampler)\n"
+ " (declare (in) int P) \n"
+ " (declare (in) int lod) )\n"
+ " ((return (txf (var_ref sampler) (var_ref P) (0 0 0) (var_ref lod) ))))\n"
+ "\n"
+ " (signature uvec4\n"
+ " (parameters\n"
+ " (declare (in) usampler1D sampler)\n"
+ " (declare (in) int P) \n"
+ " (declare (in) int lod) )\n"
+ " ((return (txf (var_ref sampler) (var_ref P) (0 0 0) (var_ref lod) ))))\n"
+ "\n"
+ " (signature vec4\n"
+ " (parameters\n"
+ " (declare (in) sampler2D sampler)\n"
+ " (declare (in) ivec2 P) \n"
+ " (declare (in) int lod) )\n"
+ " ((return (txf (var_ref sampler) (var_ref P) (0 0 0) (var_ref lod) ))))\n"
+ "\n"
+ " (signature ivec4\n"
+ " (parameters\n"
+ " (declare (in) isampler2D sampler)\n"
+ " (declare (in) ivec2 P) \n"
+ " (declare (in) int lod) )\n"
+ " ((return (txf (var_ref sampler) (var_ref P) (0 0 0) (var_ref lod) ))))\n"
+ "\n"
+ " (signature uvec4\n"
+ " (parameters\n"
+ " (declare (in) usampler2D sampler)\n"
+ " (declare (in) ivec2 P) \n"
+ " (declare (in) int lod) )\n"
+ " ((return (txf (var_ref sampler) (var_ref P) (0 0 0) (var_ref lod) ))))\n"
+ "\n"
+ " (signature vec4\n"
+ " (parameters\n"
+ " (declare (in) sampler3D sampler)\n"
+ " (declare (in) ivec3 P) \n"
+ " (declare (in) int lod) )\n"
+ " ((return (txf (var_ref sampler) (var_ref P) (0 0 0) (var_ref lod) ))))\n"
+ "\n"
+ " (signature ivec4\n"
+ " (parameters\n"
+ " (declare (in) isampler3D sampler)\n"
+ " (declare (in) ivec3 P) \n"
+ " (declare (in) int lod) )\n"
+ " ((return (txf (var_ref sampler) (var_ref P) (0 0 0) (var_ref lod) ))))\n"
+ "\n"
+ " (signature uvec4\n"
+ " (parameters\n"
+ " (declare (in) usampler3D sampler)\n"
+ " (declare (in) ivec3 P) \n"
+ " (declare (in) int lod) )\n"
+ " ((return (txf (var_ref sampler) (var_ref P) (0 0 0) (var_ref lod) ))))\n"
+ "\n"
+ " (signature vec4\n"
+ " (parameters\n"
+ " (declare (in) sampler1DArray sampler)\n"
+ " (declare (in) ivec2 P) \n"
+ " (declare (in) int lod) )\n"
+ " ((return (txf (var_ref sampler) (var_ref P) (0 0 0) (var_ref lod) ))))\n"
+ "\n"
+ " (signature ivec4\n"
+ " (parameters\n"
+ " (declare (in) isampler1DArray sampler)\n"
+ " (declare (in) ivec2 P) \n"
+ " (declare (in) int lod) )\n"
+ " ((return (txf (var_ref sampler) (var_ref P) (0 0 0) (var_ref lod) ))))\n"
+ "\n"
+ " (signature uvec4\n"
+ " (parameters\n"
+ " (declare (in) usampler1DArray sampler)\n"
+ " (declare (in) ivec2 P) \n"
+ " (declare (in) int lod) )\n"
+ " ((return (txf (var_ref sampler) (var_ref P) (0 0 0) (var_ref lod) ))))\n"
+ "\n"
+ " (signature vec4\n"
+ " (parameters\n"
+ " (declare (in) sampler2DArray sampler)\n"
+ " (declare (in) ivec3 P) \n"
+ " (declare (in) int lod) )\n"
+ " ((return (txf (var_ref sampler) (var_ref P) (0 0 0) (var_ref lod) ))))\n"
+ "\n"
+ " (signature ivec4\n"
+ " (parameters\n"
+ " (declare (in) isampler2DArray sampler)\n"
+ " (declare (in) ivec3 P) \n"
+ " (declare (in) int lod) )\n"
+ " ((return (txf (var_ref sampler) (var_ref P) (0 0 0) (var_ref lod) ))))\n"
+ "\n"
+ " (signature uvec4\n"
+ " (parameters\n"
+ " (declare (in) usampler2DArray sampler)\n"
+ " (declare (in) ivec3 P) \n"
+ " (declare (in) int lod) )\n"
+ " ((return (txf (var_ref sampler) (var_ref P) (0 0 0) (var_ref lod) ))))\n"
+ "\n"
+ "))\n"
+ ""
+;
+static const char *builtin_noise4 =
+ "((function noise4\n"
+ " (signature vec4\n"
+ " (parameters\n"
+ " (declare (in) float x))\n"
+ " ((return (constant vec4 (0 0 0 0)))))\n"
+ " (signature vec4\n"
+ " (parameters\n"
+ " (declare (in) vec2 x))\n"
+ " ((return (constant vec4 (0 0 0 0)))))\n"
+ " (signature vec4\n"
+ " (parameters\n"
+ " (declare (in) vec3 x))\n"
+ " ((return (constant vec4 (0 0 0 0)))))\n"
+ " (signature vec4\n"
+ " (parameters\n"
+ " (declare (in) vec4 x))\n"
+ " ((return (constant vec4 (0 0 0 0)))))\n"
+ "))\n"
+ ""
+;
+static const char *builtin_notEqual =
+ "((function notEqual\n"
+ " (signature bvec2\n"
+ " (parameters\n"
+ " (declare (in) vec2 arg0)\n"
+ " (declare (in) vec2 arg1))\n"
+ " ((declare () bvec2 temp)\n"
+ " (assign (constant bool (1)) (swiz x (var_ref temp)) (expression bool != (swiz x (var_ref arg0))(swiz x (var_ref arg1))))\n"
+ " (assign (constant bool (1)) (swiz y (var_ref temp)) (expression bool != (swiz y (var_ref arg0))(swiz y (var_ref arg1))))\n"
+ " (return (var_ref temp))))\n"
+ "\n"
+ " (signature bvec3\n"
+ " (parameters\n"
+ " (declare (in) vec3 arg0)\n"
+ " (declare (in) vec3 arg1))\n"
+ " ((declare () bvec3 temp)\n"
+ " (assign (constant bool (1)) (swiz x (var_ref temp)) (expression bool != (swiz x (var_ref arg0))(swiz x (var_ref arg1))))\n"
+ " (assign (constant bool (1)) (swiz y (var_ref temp)) (expression bool != (swiz y (var_ref arg0))(swiz y (var_ref arg1))))\n"
+ " (assign (constant bool (1)) (swiz z (var_ref temp)) (expression bool != (swiz z (var_ref arg0))(swiz z (var_ref arg1))))\n"
+ " (return (var_ref temp))))\n"
+ "\n"
+ " (signature bvec4\n"
+ " (parameters\n"
+ " (declare (in) vec4 arg0)\n"
+ " (declare (in) vec4 arg1))\n"
+ " ((declare () bvec4 temp)\n"
+ " (assign (constant bool (1)) (swiz x (var_ref temp)) (expression bool != (swiz x (var_ref arg0))(swiz x (var_ref arg1))))\n"
+ " (assign (constant bool (1)) (swiz y (var_ref temp)) (expression bool != (swiz y (var_ref arg0))(swiz y (var_ref arg1))))\n"
+ " (assign (constant bool (1)) (swiz z (var_ref temp)) (expression bool != (swiz z (var_ref arg0))(swiz z (var_ref arg1))))\n"
+ " (assign (constant bool (1)) (swiz w (var_ref temp)) (expression bool != (swiz w (var_ref arg0))(swiz w (var_ref arg1))))\n"
+ " (return (var_ref temp))))\n"
+ "\n"
+ " (signature bvec2\n"
+ " (parameters\n"
+ " (declare (in) ivec2 arg0)\n"
+ " (declare (in) ivec2 arg1))\n"
+ " ((declare () bvec2 temp)\n"
+ " (assign (constant bool (1)) (swiz x (var_ref temp)) (expression bool != (swiz x (var_ref arg0))(swiz x (var_ref arg1))))\n"
+ " (assign (constant bool (1)) (swiz y (var_ref temp)) (expression bool != (swiz y (var_ref arg0))(swiz y (var_ref arg1))))\n"
+ " (return (var_ref temp))))\n"
+ "\n"
+ " (signature bvec3\n"
+ " (parameters\n"
+ " (declare (in) ivec3 arg0)\n"
+ " (declare (in) ivec3 arg1))\n"
+ " ((declare () bvec3 temp)\n"
+ " (assign (constant bool (1)) (swiz x (var_ref temp)) (expression bool != (swiz x (var_ref arg0))(swiz x (var_ref arg1))))\n"
+ " (assign (constant bool (1)) (swiz y (var_ref temp)) (expression bool != (swiz y (var_ref arg0))(swiz y (var_ref arg1))))\n"
+ " (assign (constant bool (1)) (swiz z (var_ref temp)) (expression bool != (swiz z (var_ref arg0))(swiz z (var_ref arg1))))\n"
+ " (return (var_ref temp))))\n"
+ "\n"
+ " (signature bvec4\n"
+ " (parameters\n"
+ " (declare (in) ivec4 arg0)\n"
+ " (declare (in) ivec4 arg1))\n"
+ " ((declare () bvec4 temp)\n"
+ " (assign (constant bool (1)) (swiz x (var_ref temp)) (expression bool != (swiz x (var_ref arg0))(swiz x (var_ref arg1))))\n"
+ " (assign (constant bool (1)) (swiz y (var_ref temp)) (expression bool != (swiz y (var_ref arg0))(swiz y (var_ref arg1))))\n"
+ " (assign (constant bool (1)) (swiz z (var_ref temp)) (expression bool != (swiz z (var_ref arg0))(swiz z (var_ref arg1))))\n"
+ " (assign (constant bool (1)) (swiz w (var_ref temp)) (expression bool != (swiz w (var_ref arg0))(swiz w (var_ref arg1))))\n"
+ " (return (var_ref temp))))\n"
+ "\n"
+ " (signature bvec2\n"
+ " (parameters\n"
+ " (declare (in) uvec2 arg0)\n"
+ " (declare (in) uvec2 arg1))\n"
+ " ((declare () bvec2 temp)\n"
+ " (assign (constant bool (1)) (swiz x (var_ref temp)) (expression bool != (swiz x (var_ref arg0))(swiz x (var_ref arg1)))) \n"
+ " (assign (constant bool (1)) (swiz y (var_ref temp)) (expression bool != (swiz y (var_ref arg0))(swiz y (var_ref arg1)))) \n"
+ " (return (var_ref temp))))\n"
+ "\n"
+ " (signature bvec3\n"
+ " (parameters\n"
+ " (declare (in) uvec3 arg0)\n"
+ " (declare (in) uvec3 arg1))\n"
+ " ((declare () bvec3 temp)\n"
+ " (assign (constant bool (1)) (swiz x (var_ref temp)) (expression bool != (swiz x (var_ref arg0))(swiz x (var_ref arg1)))) \n"
+ " (assign (constant bool (1)) (swiz y (var_ref temp)) (expression bool != (swiz y (var_ref arg0))(swiz y (var_ref arg1)))) \n"
+ " (assign (constant bool (1)) (swiz z (var_ref temp)) (expression bool != (swiz z (var_ref arg0))(swiz z (var_ref arg1)))) \n"
+ " (return (var_ref temp))))\n"
+ "\n"
+ " (signature bvec4\n"
+ " (parameters\n"
+ " (declare (in) uvec4 arg0)\n"
+ " (declare (in) uvec4 arg1))\n"
+ " ((declare () bvec4 temp)\n"
+ " (assign (constant bool (1)) (swiz x (var_ref temp)) (expression bool != (swiz x (var_ref arg0))(swiz x (var_ref arg1)))) \n"
+ " (assign (constant bool (1)) (swiz y (var_ref temp)) (expression bool != (swiz y (var_ref arg0))(swiz y (var_ref arg1)))) \n"
+ " (assign (constant bool (1)) (swiz z (var_ref temp)) (expression bool != (swiz z (var_ref arg0))(swiz z (var_ref arg1)))) \n"
+ " (assign (constant bool (1)) (swiz w (var_ref temp)) (expression bool != (swiz w (var_ref arg0))(swiz w (var_ref arg1)))) \n"
+ " (return (var_ref temp))))\n"
+ "))\n"
+ ""
+;
+static const char *builtin_outerProduct =
+ "((function outerProduct\n"
+ " (signature mat2\n"
+ " (parameters\n"
+ " (declare (in) vec2 u)\n"
+ " (declare (in) vec2 v))\n"
+ " ((declare () mat2 m)\n"
+ " (assign (constant bool (1)) (array_ref (var_ref m) (constant int (0))) (expression vec2 * (var_ref u) (swiz x (var_ref v))))\n"
+ " (assign (constant bool (1)) (array_ref (var_ref m) (constant int (1))) (expression vec2 * (var_ref u) (swiz y (var_ref v))))\n"
+ " (return (var_ref m))))\n"
+ "\n"
+ " (signature mat2x3\n"
+ " (parameters\n"
+ " (declare (in) vec3 u)\n"
+ " (declare (in) vec2 v))\n"
+ " ((declare () mat2x3 m)\n"
+ " (assign (constant bool (1)) (array_ref (var_ref m) (constant int (0))) (expression vec3 * (var_ref u) (swiz x (var_ref v))))\n"
+ " (assign (constant bool (1)) (array_ref (var_ref m) (constant int (1))) (expression vec3 * (var_ref u) (swiz y (var_ref v))))\n"
+ " (return (var_ref m))))\n"
+ "\n"
+ " (signature mat2x4\n"
+ " (parameters\n"
+ " (declare (in) vec4 u)\n"
+ " (declare (in) vec2 v))\n"
+ " ((declare () mat2x4 m)\n"
+ " (assign (constant bool (1)) (array_ref (var_ref m) (constant int (0))) (expression vec4 * (var_ref u) (swiz x (var_ref v))))\n"
+ " (assign (constant bool (1)) (array_ref (var_ref m) (constant int (1))) (expression vec4 * (var_ref u) (swiz y (var_ref v))))\n"
+ " (return (var_ref m))))\n"
+ "\n"
+ " (signature mat3x2\n"
+ " (parameters\n"
+ " (declare (in) vec2 u)\n"
+ " (declare (in) vec3 v))\n"
+ " ((declare () mat3x2 m)\n"
+ " (assign (constant bool (1)) (array_ref (var_ref m) (constant int (0))) (expression vec2 * (var_ref u) (swiz x (var_ref v))))\n"
+ " (assign (constant bool (1)) (array_ref (var_ref m) (constant int (1))) (expression vec2 * (var_ref u) (swiz y (var_ref v))))\n"
+ " (assign (constant bool (1)) (array_ref (var_ref m) (constant int (2))) (expression vec2 * (var_ref u) (swiz z (var_ref v))))\n"
+ " (return (var_ref m))\n"
+ " ))\n"
+ "\n"
+ " (signature mat3\n"
+ " (parameters\n"
+ " (declare (in) vec3 u)\n"
+ " (declare (in) vec3 v))\n"
+ " ((declare () mat3 m)\n"
+ " (assign (constant bool (1)) (array_ref (var_ref m) (constant int (0))) (expression vec3 * (var_ref u) (swiz x (var_ref v))))\n"
+ " (assign (constant bool (1)) (array_ref (var_ref m) (constant int (1))) (expression vec3 * (var_ref u) (swiz y (var_ref v))))\n"
+ " (assign (constant bool (1)) (array_ref (var_ref m) (constant int (2))) (expression vec3 * (var_ref u) (swiz z (var_ref v))))\n"
+ " (return (var_ref m))))\n"
+ "\n"
+ " (signature mat3x4\n"
+ " (parameters\n"
+ " (declare (in) vec4 u)\n"
+ " (declare (in) vec3 v))\n"
+ " ((declare () mat3x4 m)\n"
+ " (assign (constant bool (1)) (array_ref (var_ref m) (constant int (0))) (expression vec4 * (var_ref u) (swiz x (var_ref v))))\n"
+ " (assign (constant bool (1)) (array_ref (var_ref m) (constant int (1))) (expression vec4 * (var_ref u) (swiz y (var_ref v))))\n"
+ " (assign (constant bool (1)) (array_ref (var_ref m) (constant int (2))) (expression vec4 * (var_ref u) (swiz z (var_ref v))))\n"
+ " (return (var_ref m))))\n"
+ "\n"
+ " (signature mat4x2\n"
+ " (parameters\n"
+ " (declare (in) vec2 u)\n"
+ " (declare (in) vec4 v))\n"
+ " ((declare () mat4x2 m)\n"
+ " (assign (constant bool (1)) (array_ref (var_ref m) (constant int (0))) (expression vec2 * (var_ref u) (swiz x (var_ref v))))\n"
+ " (assign (constant bool (1)) (array_ref (var_ref m) (constant int (1))) (expression vec2 * (var_ref u) (swiz y (var_ref v))))\n"
+ " (assign (constant bool (1)) (array_ref (var_ref m) (constant int (2))) (expression vec2 * (var_ref u) (swiz z (var_ref v))))\n"
+ " (assign (constant bool (1)) (array_ref (var_ref m) (constant int (3))) (expression vec2 * (var_ref u) (swiz w (var_ref v))))\n"
+ " (return (var_ref m))))\n"
+ "\n"
+ " (signature mat4x3\n"
+ " (parameters\n"
+ " (declare (in) vec3 u)\n"
+ " (declare (in) vec4 v))\n"
+ " ((declare () mat4x3 m)\n"
+ " (assign (constant bool (1)) (array_ref (var_ref m) (constant int (0))) (expression vec3 * (var_ref u) (swiz x (var_ref v))))\n"
+ " (assign (constant bool (1)) (array_ref (var_ref m) (constant int (1))) (expression vec3 * (var_ref u) (swiz y (var_ref v))))\n"
+ " (assign (constant bool (1)) (array_ref (var_ref m) (constant int (2))) (expression vec3 * (var_ref u) (swiz z (var_ref v))))\n"
+ " (assign (constant bool (1)) (array_ref (var_ref m) (constant int (3))) (expression vec3 * (var_ref u) (swiz w (var_ref v))))\n"
+ " (return (var_ref m))))\n"
+ "\n"
+ " (signature mat4\n"
+ " (parameters\n"
+ " (declare (in) vec4 u)\n"
+ " (declare (in) vec4 v))\n"
+ " ((declare () mat4 m)\n"
+ " (assign (constant bool (1)) (array_ref (var_ref m) (constant int (0))) (expression vec4 * (var_ref u) (swiz x (var_ref v))))\n"
+ " (assign (constant bool (1)) (array_ref (var_ref m) (constant int (1))) (expression vec4 * (var_ref u) (swiz y (var_ref v))))\n"
+ " (assign (constant bool (1)) (array_ref (var_ref m) (constant int (2))) (expression vec4 * (var_ref u) (swiz z (var_ref v))))\n"
+ " (assign (constant bool (1)) (array_ref (var_ref m) (constant int (3))) (expression vec4 * (var_ref u) (swiz w (var_ref v))))\n"
+ " (return (var_ref m))))\n"
+ "))\n"
+ ""
+;
+static const char *builtin_shadow1D =
+ "((function shadow1D\n"
+ " (signature vec4\n"
+ " (parameters\n"
+ " (declare (in) sampler1DShadow sampler)\n"
+ " (declare (in) vec3 P) )\n"
+ " ((return (tex (var_ref sampler) (swiz x (var_ref P)) (0 0 0) 1 (swiz z (var_ref P)) ))))\n"
+ "\n"
+ " (signature vec4\n"
+ " (parameters\n"
+ " (declare (in) sampler1DShadow sampler)\n"
+ " (declare (in) vec3 P) \n"
+ " (declare (in) float bias) )\n"
+ " ((return (txb (var_ref sampler) (swiz x (var_ref P)) (0 0 0) 1 (swiz z (var_ref P)) (var_ref bias) ))))\n"
+ "\n"
+ "))\n"
+ ""
+;
+static const char *builtin_noise1 =
+ "((function noise1\n"
+ " (signature float\n"
+ " (parameters\n"
+ " (declare (in) float x))\n"
+ " ((return (constant float (0)))))\n"
+ " (signature float\n"
+ " (parameters\n"
+ " (declare (in) vec2 x))\n"
+ " ((return (constant float (0)))))\n"
+ " (signature float\n"
+ " (parameters\n"
+ " (declare (in) vec3 x))\n"
+ " ((return (constant float (0)))))\n"
+ " (signature float\n"
+ " (parameters\n"
+ " (declare (in) vec4 x))\n"
+ " ((return (constant float (0)))))\n"
+ "))\n"
+ ""
+;
+static const char *builtin_refract =
+ "((function refract\n"
+ " (signature float\n"
+ " (parameters\n"
+ " (declare (in) float i)\n"
+ " (declare (in) float n)\n"
+ " (declare (in) float eta))\n"
+ " ((declare () float k)\n"
+ " (assign (constant bool (1)) (var_ref k)\n"
+ " (expression float - (constant float (1.0))\n"
+ " (expression float * (var_ref eta)\n"
+ " (expression float * (var_ref eta)\n"
+ " (expression float - (constant float (1.0))\n"
+ " (expression float * \n"
+ " (expression float dot (var_ref n) (var_ref i))\n"
+ " (expression float dot (var_ref n) (var_ref i))))))))\n"
+ " (if (expression bool < (var_ref k) (constant float (0.0)))\n"
+ " ((return (constant float (0.0))))\n"
+ " ((return (expression float -\n"
+ " (expression float * (var_ref eta) (var_ref i))\n"
+ " (expression float *\n"
+ " (expression float +\n"
+ " (expression float * (var_ref eta)\n"
+ " (expression float dot (var_ref n) (var_ref i)))\n"
+ " (expression float sqrt (var_ref k)))\n"
+ " (var_ref n))))))))\n"
+ "\n"
+ " (signature vec2\n"
+ " (parameters\n"
+ " (declare (in) vec2 i)\n"
+ " (declare (in) vec2 n)\n"
+ " (declare (in) float eta))\n"
+ " ((declare () float k)\n"
+ " (assign (constant bool (1)) (var_ref k)\n"
+ " (expression float - (constant float (1.0))\n"
+ " (expression float * (var_ref eta)\n"
+ " (expression float * (var_ref eta)\n"
+ " (expression float - (constant float (1.0))\n"
+ " (expression float * \n"
+ " (expression float dot (var_ref n) (var_ref i))\n"
+ " (expression float dot (var_ref n) (var_ref i))))))))\n"
+ " (if (expression bool < (var_ref k) (constant float (0.0)))\n"
+ " ((return (constant vec2 (0.0 0.0))))\n"
+ " ((return (expression vec2 -\n"
+ " (expression vec2 * (var_ref eta) (var_ref i))\n"
+ " (expression vec2 *\n"
+ " (expression float +\n"
+ " (expression float * (var_ref eta)\n"
+ " (expression float dot (var_ref n) (var_ref i)))\n"
+ " (expression float sqrt (var_ref k)))\n"
+ " (var_ref n))))))))\n"
+ "\n"
+ " (signature vec3\n"
+ " (parameters\n"
+ " (declare (in) vec3 i)\n"
+ " (declare (in) vec3 n)\n"
+ " (declare (in) float eta))\n"
+ " ((declare () float k)\n"
+ " (assign (constant bool (1)) (var_ref k)\n"
+ " (expression float - (constant float (1.0))\n"
+ " (expression float * (var_ref eta)\n"
+ " (expression float * (var_ref eta)\n"
+ " (expression float - (constant float (1.0))\n"
+ " (expression float * \n"
+ " (expression float dot (var_ref n) (var_ref i))\n"
+ " (expression float dot (var_ref n) (var_ref i))))))))\n"
+ " (if (expression bool < (var_ref k) (constant float (0.0)))\n"
+ " ((return (constant vec3 (0.0 0.0 0.0))))\n"
+ " ((return (expression vec3 -\n"
+ " (expression vec3 * (var_ref eta) (var_ref i))\n"
+ " (expression vec3 *\n"
+ " (expression float +\n"
+ " (expression float * (var_ref eta)\n"
+ " (expression float dot (var_ref n) (var_ref i)))\n"
+ " (expression float sqrt (var_ref k)))\n"
+ " (var_ref n))))))))\n"
+ "\n"
+ " (signature vec4\n"
+ " (parameters\n"
+ " (declare (in) vec4 i)\n"
+ " (declare (in) vec4 n)\n"
+ " (declare (in) float eta))\n"
+ " ((declare () float k)\n"
+ " (assign (constant bool (1)) (var_ref k)\n"
+ " (expression float - (constant float (1.0))\n"
+ " (expression float * (var_ref eta)\n"
+ " (expression float * (var_ref eta)\n"
+ " (expression float - (constant float (1.0))\n"
+ " (expression float * \n"
+ " (expression float dot (var_ref n) (var_ref i))\n"
+ " (expression float dot (var_ref n) (var_ref i))))))))\n"
+ " (if (expression bool < (var_ref k) (constant float (0.0)))\n"
+ " ((return (constant vec4 (0.0 0.0 0.0 0.0))))\n"
+ " ((return (expression vec4 -\n"
+ " (expression vec4 * (var_ref eta) (var_ref i))\n"
+ " (expression vec4 *\n"
+ " (expression float +\n"
+ " (expression float * (var_ref eta)\n"
+ " (expression float dot (var_ref n) (var_ref i)))\n"
+ " (expression float sqrt (var_ref k)))\n"
+ " (var_ref n))))))))\n"
+ "\n"
+ "))\n"
+ ""
+;
+static const char *builtin_noise3 =
+ "((function noise3\n"
+ " (signature vec3\n"
+ " (parameters\n"
+ " (declare (in) float x))\n"
+ " ((return (constant vec3 (0 0 0)))))\n"
+ " (signature vec3\n"
+ " (parameters\n"
+ " (declare (in) vec2 x))\n"
+ " ((return (constant vec3 (0 0 0)))))\n"
+ " (signature vec3\n"
+ " (parameters\n"
+ " (declare (in) vec3 x))\n"
+ " ((return (constant vec3 (0 0 0)))))\n"
+ " (signature vec3\n"
+ " (parameters\n"
+ " (declare (in) vec4 x))\n"
+ " ((return (constant vec3 (0 0 0)))))\n"
+ "))\n"
+ ""
+;
+static const char *builtin_min =
+ "((function min\n"
+ " (signature float\n"
+ " (parameters\n"
+ " (declare (in) float arg0)\n"
+ " (declare (in) float arg1))\n"
+ " ((return (expression float min (var_ref arg0) (var_ref arg1)))))\n"
+ "\n"
+ " (signature vec2\n"
+ " (parameters\n"
+ " (declare (in) vec2 arg0)\n"
+ " (declare (in) vec2 arg1))\n"
+ " ((return (expression vec2 min (var_ref arg0) (var_ref arg1)))))\n"
+ "\n"
+ " (signature vec3\n"
+ " (parameters\n"
+ " (declare (in) vec3 arg0)\n"
+ " (declare (in) vec3 arg1))\n"
+ " ((return (expression vec3 min (var_ref arg0) (var_ref arg1)))))\n"
+ "\n"
+ " (signature vec4\n"
+ " (parameters\n"
+ " (declare (in) vec4 arg0)\n"
+ " (declare (in) vec4 arg1))\n"
+ " ((return (expression vec4 min (var_ref arg0) (var_ref arg1)))))\n"
+ "\n"
+ " (signature vec2\n"
+ " (parameters\n"
+ " (declare (in) vec2 arg0)\n"
+ " (declare (in) float arg1))\n"
+ " ((return (expression vec2 min (var_ref arg0) (var_ref arg1)))))\n"
+ "\n"
+ " (signature vec3\n"
+ " (parameters\n"
+ " (declare (in) vec3 arg0)\n"
+ " (declare (in) float arg1))\n"
+ " ((return (expression vec3 min (var_ref arg0) (var_ref arg1)))))\n"
+ "\n"
+ " (signature vec4\n"
+ " (parameters\n"
+ " (declare (in) vec4 arg0)\n"
+ " (declare (in) float arg1))\n"
+ " ((return (expression vec4 min (var_ref arg0) (var_ref arg1)))))\n"
+ "\n"
+ " (signature int\n"
+ " (parameters\n"
+ " (declare (in) int arg0)\n"
+ " (declare (in) int arg1))\n"
+ " ((return (expression int min (var_ref arg0) (var_ref arg1)))))\n"
+ "\n"
+ " (signature ivec2\n"
+ " (parameters\n"
+ " (declare (in) ivec2 arg0)\n"
+ " (declare (in) ivec2 arg1))\n"
+ " ((return (expression ivec2 min (var_ref arg0) (var_ref arg1)))))\n"
+ "\n"
+ " (signature ivec3\n"
+ " (parameters\n"
+ " (declare (in) ivec3 arg0)\n"
+ " (declare (in) ivec3 arg1))\n"
+ " ((return (expression ivec3 min (var_ref arg0) (var_ref arg1)))))\n"
+ "\n"
+ " (signature ivec4\n"
+ " (parameters\n"
+ " (declare (in) ivec4 arg0)\n"
+ " (declare (in) ivec4 arg1))\n"
+ " ((return (expression ivec4 min (var_ref arg0) (var_ref arg1)))))\n"
+ "\n"
+ " (signature ivec2\n"
+ " (parameters\n"
+ " (declare (in) ivec2 arg0)\n"
+ " (declare (in) int arg1))\n"
+ " ((return (expression ivec2 min (var_ref arg0) (var_ref arg1)))))\n"
+ "\n"
+ " (signature ivec3\n"
+ " (parameters\n"
+ " (declare (in) ivec3 arg0)\n"
+ " (declare (in) int arg1))\n"
+ " ((return (expression ivec3 min (var_ref arg0) (var_ref arg1)))))\n"
+ "\n"
+ " (signature ivec4\n"
+ " (parameters\n"
+ " (declare (in) ivec4 arg0)\n"
+ " (declare (in) int arg1))\n"
+ " ((return (expression ivec4 min (var_ref arg0) (var_ref arg1)))))\n"
+ "\n"
+ " (signature uint\n"
+ " (parameters\n"
+ " (declare (in) uint arg0)\n"
+ " (declare (in) uint arg1))\n"
+ " ((return (expression uint min (var_ref arg0) (var_ref arg1)))))\n"
+ "\n"
+ " (signature uvec2\n"
+ " (parameters\n"
+ " (declare (in) uvec2 arg0)\n"
+ " (declare (in) uvec2 arg1))\n"
+ " ((return (expression uvec2 min (var_ref arg0) (var_ref arg1)))))\n"
+ "\n"
+ " (signature uvec3\n"
+ " (parameters\n"
+ " (declare (in) uvec3 arg0)\n"
+ " (declare (in) uvec3 arg1))\n"
+ " ((return (expression uvec3 min (var_ref arg0) (var_ref arg1)))))\n"
+ "\n"
+ " (signature uvec4\n"
+ " (parameters\n"
+ " (declare (in) uvec4 arg0)\n"
+ " (declare (in) uvec4 arg1))\n"
+ " ((return (expression uvec4 min (var_ref arg0) (var_ref arg1)))))\n"
+ "\n"
+ " (signature uvec2\n"
+ " (parameters\n"
+ " (declare (in) uvec2 arg0)\n"
+ " (declare (in) uint arg1))\n"
+ " ((return (expression uvec2 min (var_ref arg0) (var_ref arg1)))))\n"
+ "\n"
+ " (signature uvec3\n"
+ " (parameters\n"
+ " (declare (in) uvec3 arg0)\n"
+ " (declare (in) uint arg1))\n"
+ " ((return (expression uvec3 min (var_ref arg0) (var_ref arg1)))))\n"
+ "\n"
+ " (signature uvec4\n"
+ " (parameters\n"
+ " (declare (in) uvec4 arg0)\n"
+ " (declare (in) uint arg1))\n"
+ " ((return (expression uvec4 min (var_ref arg0) (var_ref arg1)))))\n"
+ "))\n"
+ ""
+;
+static const char *builtin_textureCube =
+ "((function textureCube\n"
+ " (signature vec4\n"
+ " (parameters\n"
+ " (declare (in) samplerCube sampler)\n"
+ " (declare (in) vec3 P) )\n"
+ " ((return (tex (var_ref sampler) (var_ref P) (0 0 0) 1 () ))))\n"
+ "\n"
+ " (signature vec4\n"
+ " (parameters\n"
+ " (declare (in) samplerCube sampler)\n"
+ " (declare (in) vec3 P) \n"
+ " (declare (in) float bias) )\n"
+ " ((return (txb (var_ref sampler) (var_ref P) (0 0 0) 1 () (var_ref bias) ))))\n"
+ "\n"
+ "))\n"
+ ""
+;
+static const char *builtin_shadow1DArray =
+ "((function shadow1DArray\n"
+ " (signature vec4\n"
+ " (parameters\n"
+ " (declare (in) sampler1DArrayShadow sampler)\n"
+ " (declare (in) vec3 P) )\n"
+ " ((return (tex (var_ref sampler) (swiz xy (var_ref P)) (0 0 0) 1 (swiz z (var_ref P)) ))))\n"
+ "\n"
+ " (signature vec4\n"
+ " (parameters\n"
+ " (declare (in) sampler1DArrayShadow sampler)\n"
+ " (declare (in) vec3 P) \n"
+ " (declare (in) float bias) )\n"
+ " ((return (txb (var_ref sampler) (swiz xy (var_ref P)) (0 0 0) 1 (swiz z (var_ref P)) (var_ref bias) ))))\n"
+ "\n"
+ "))\n"
+ ""
+;
+static const char *builtin_exp =
+ "((function exp\n"
+ " (signature float\n"
+ " (parameters\n"
+ " (declare (in) float arg0))\n"
+ " ((return (expression float exp (var_ref arg0)))))\n"
+ "\n"
+ " (signature vec2\n"
+ " (parameters\n"
+ " (declare (in) vec2 arg0))\n"
+ " ((return (expression vec2 exp (var_ref arg0)))))\n"
+ "\n"
+ " (signature vec3\n"
+ " (parameters\n"
+ " (declare (in) vec3 arg0))\n"
+ " ((return (expression vec3 exp (var_ref arg0)))))\n"
+ "\n"
+ " (signature vec4\n"
+ " (parameters\n"
+ " (declare (in) vec4 arg0))\n"
+ " ((return (expression vec4 exp (var_ref arg0)))))\n"
+ "))\n"
+ ""
+;
+static const char *builtin_greaterThan =
+ "((function greaterThan\n"
+ " (signature bvec2\n"
+ " (parameters\n"
+ " (declare (in) vec2 arg0)\n"
+ " (declare (in) vec2 arg1))\n"
+ " ((declare () bvec2 temp)\n"
+ " (assign (constant bool (1)) (swiz x (var_ref temp)) (expression bool > (swiz x (var_ref arg0))(swiz x (var_ref arg1)))) \n"
+ " (assign (constant bool (1)) (swiz y (var_ref temp)) (expression bool > (swiz y (var_ref arg0))(swiz y (var_ref arg1)))) \n"
+ " (return (var_ref temp))))\n"
+ "\n"
+ " (signature bvec3\n"
+ " (parameters\n"
+ " (declare (in) vec3 arg0)\n"
+ " (declare (in) vec3 arg1))\n"
+ " ((declare () bvec3 temp)\n"
+ " (assign (constant bool (1)) (swiz x (var_ref temp)) (expression bool > (swiz x (var_ref arg0))(swiz x (var_ref arg1)))) \n"
+ " (assign (constant bool (1)) (swiz y (var_ref temp)) (expression bool > (swiz y (var_ref arg0))(swiz y (var_ref arg1)))) \n"
+ " (assign (constant bool (1)) (swiz z (var_ref temp)) (expression bool > (swiz z (var_ref arg0))(swiz z (var_ref arg1)))) \n"
+ " (return (var_ref temp))))\n"
+ "\n"
+ " (signature bvec4\n"
+ " (parameters\n"
+ " (declare (in) vec4 arg0)\n"
+ " (declare (in) vec4 arg1))\n"
+ " ((declare () bvec4 temp)\n"
+ " (assign (constant bool (1)) (swiz x (var_ref temp)) (expression bool > (swiz x (var_ref arg0))(swiz x (var_ref arg1)))) \n"
+ " (assign (constant bool (1)) (swiz y (var_ref temp)) (expression bool > (swiz y (var_ref arg0))(swiz y (var_ref arg1)))) \n"
+ " (assign (constant bool (1)) (swiz z (var_ref temp)) (expression bool > (swiz z (var_ref arg0))(swiz z (var_ref arg1)))) \n"
+ " (assign (constant bool (1)) (swiz w (var_ref temp)) (expression bool > (swiz w (var_ref arg0))(swiz w (var_ref arg1)))) \n"
+ " (return (var_ref temp))))\n"
+ "\n"
+ " (signature bvec2\n"
+ " (parameters\n"
+ " (declare (in) ivec2 arg0)\n"
+ " (declare (in) ivec2 arg1))\n"
+ " ((declare () bvec2 temp)\n"
+ " (assign (constant bool (1)) (swiz x (var_ref temp)) (expression bool > (swiz x (var_ref arg0))(swiz x (var_ref arg1)))) \n"
+ " (assign (constant bool (1)) (swiz y (var_ref temp)) (expression bool > (swiz y (var_ref arg0))(swiz y (var_ref arg1)))) \n"
+ " (return (var_ref temp))))\n"
+ "\n"
+ " (signature bvec3\n"
+ " (parameters\n"
+ " (declare (in) ivec3 arg0)\n"
+ " (declare (in) ivec3 arg1))\n"
+ " ((declare () bvec3 temp)\n"
+ " (assign (constant bool (1)) (swiz x (var_ref temp)) (expression bool > (swiz x (var_ref arg0))(swiz x (var_ref arg1)))) \n"
+ " (assign (constant bool (1)) (swiz y (var_ref temp)) (expression bool > (swiz y (var_ref arg0))(swiz y (var_ref arg1)))) \n"
+ " (assign (constant bool (1)) (swiz z (var_ref temp)) (expression bool > (swiz z (var_ref arg0))(swiz z (var_ref arg1)))) \n"
+ " (return (var_ref temp))))\n"
+ "\n"
+ " (signature bvec4\n"
+ " (parameters\n"
+ " (declare (in) ivec4 arg0)\n"
+ " (declare (in) ivec4 arg1))\n"
+ " ((declare () bvec4 temp)\n"
+ " (assign (constant bool (1)) (swiz x (var_ref temp)) (expression bool > (swiz x (var_ref arg0))(swiz x (var_ref arg1)))) \n"
+ " (assign (constant bool (1)) (swiz y (var_ref temp)) (expression bool > (swiz y (var_ref arg0))(swiz y (var_ref arg1)))) \n"
+ " (assign (constant bool (1)) (swiz z (var_ref temp)) (expression bool > (swiz z (var_ref arg0))(swiz z (var_ref arg1)))) \n"
+ " (assign (constant bool (1)) (swiz w (var_ref temp)) (expression bool > (swiz w (var_ref arg0))(swiz w (var_ref arg1)))) \n"
+ " (return (var_ref temp))))\n"
+ "\n"
+ " (signature bvec2\n"
+ " (parameters\n"
+ " (declare (in) uvec2 arg0)\n"
+ " (declare (in) uvec2 arg1))\n"
+ " ((declare () bvec2 temp)\n"
+ " (assign (constant bool (1)) (swiz x (var_ref temp)) (expression bool > (swiz x (var_ref arg0))(swiz x (var_ref arg1)))) \n"
+ " (assign (constant bool (1)) (swiz y (var_ref temp)) (expression bool > (swiz y (var_ref arg0))(swiz y (var_ref arg1)))) \n"
+ " (return (var_ref temp))))\n"
+ "\n"
+ " (signature bvec3\n"
+ " (parameters\n"
+ " (declare (in) uvec3 arg0)\n"
+ " (declare (in) uvec3 arg1))\n"
+ " ((declare () bvec3 temp)\n"
+ " (assign (constant bool (1)) (swiz x (var_ref temp)) (expression bool > (swiz x (var_ref arg0))(swiz x (var_ref arg1)))) \n"
+ " (assign (constant bool (1)) (swiz y (var_ref temp)) (expression bool > (swiz y (var_ref arg0))(swiz y (var_ref arg1)))) \n"
+ " (assign (constant bool (1)) (swiz z (var_ref temp)) (expression bool > (swiz z (var_ref arg0))(swiz z (var_ref arg1)))) \n"
+ " (return (var_ref temp))))\n"
+ "\n"
+ " (signature bvec4\n"
+ " (parameters\n"
+ " (declare (in) uvec4 arg0)\n"
+ " (declare (in) uvec4 arg1))\n"
+ " ((declare () bvec4 temp)\n"
+ " (assign (constant bool (1)) (swiz x (var_ref temp)) (expression bool > (swiz x (var_ref arg0))(swiz x (var_ref arg1)))) \n"
+ " (assign (constant bool (1)) (swiz y (var_ref temp)) (expression bool > (swiz y (var_ref arg0))(swiz y (var_ref arg1)))) \n"
+ " (assign (constant bool (1)) (swiz z (var_ref temp)) (expression bool > (swiz z (var_ref arg0))(swiz z (var_ref arg1)))) \n"
+ " (assign (constant bool (1)) (swiz w (var_ref temp)) (expression bool > (swiz w (var_ref arg0))(swiz w (var_ref arg1)))) \n"
+ " (return (var_ref temp))))\n"
+ "))\n"
+ ""
+;
+static const char *builtin_texture2DLod =
+ "((function texture2DLod\n"
+ " (signature vec4\n"
+ " (parameters\n"
+ " (declare (in) sampler2D sampler)\n"
+ " (declare (in) vec2 P) \n"
+ " (declare (in) float lod) )\n"
+ " ((return (txl (var_ref sampler) (var_ref P) (0 0 0) 1 () (var_ref lod) ))))\n"
+ "\n"
+ "))\n"
+ ""
+;
+static const char *builtin_dot =
+ "((function dot\n"
+ " (signature float\n"
+ " (parameters\n"
+ " (declare (in) float arg0)\n"
+ " (declare (in) float arg1))\n"
+ " ((return (expression float dot (var_ref arg0) (var_ref arg1)))))\n"
+ "\n"
+ " (signature float\n"
+ " (parameters\n"
+ " (declare (in) vec2 arg0)\n"
+ " (declare (in) vec2 arg1))\n"
+ " ((return (expression float dot (var_ref arg0) (var_ref arg1)))))\n"
+ "\n"
+ " (signature float\n"
+ " (parameters\n"
+ " (declare (in) vec3 arg0)\n"
+ " (declare (in) vec3 arg1))\n"
+ " ((return (expression float dot (var_ref arg0) (var_ref arg1)))))\n"
+ "\n"
+ " (signature float\n"
+ " (parameters\n"
+ " (declare (in) vec4 arg0)\n"
+ " (declare (in) vec4 arg1))\n"
+ " ((return (expression float dot (var_ref arg0) (var_ref arg1)))))\n"
+ "))\n"
+ ""
+;
+static const char *prototypes_for_120_vert =
+ "(\n"
+ "(function radians\n"
+ " (signature float\n"
+ " (parameters\n"
+ " (declare (in ) float degrees@0x22143e0)\n"
+ " )\n"
+ " (\n"
+ " ))\n"
+ "\n"
+ " (signature vec2\n"
+ " (parameters\n"
+ " (declare (in ) vec2 degrees@0x22147b0)\n"
+ " )\n"
+ " (\n"
+ " ))\n"
+ "\n"
+ " (signature vec3\n"
+ " (parameters\n"
+ " (declare (in ) vec3 degrees@0x22149a0)\n"
+ " )\n"
+ " (\n"
+ " ))\n"
+ "\n"
+ " (signature vec4\n"
+ " (parameters\n"
+ " (declare (in ) vec4 degrees@0x2214b90)\n"
+ " )\n"
+ " (\n"
+ " ))\n"
+ "\n"
+ ")\n"
+ "\n"
+ "(function degrees\n"
+ " (signature float\n"
+ " (parameters\n"
+ " (declare (in ) float radians@0x2214d80)\n"
+ " )\n"
+ " (\n"
+ " ))\n"
+ "\n"
+ " (signature vec2\n"
+ " (parameters\n"
+ " (declare (in ) vec2 radians@0x2215150)\n"
+ " )\n"
+ " (\n"
+ " ))\n"
+ "\n"
+ " (signature vec3\n"
+ " (parameters\n"
+ " (declare (in ) vec3 radians@0x2215340)\n"
+ " )\n"
+ " (\n"
+ " ))\n"
+ "\n"
+ " (signature vec4\n"
+ " (parameters\n"
+ " (declare (in ) vec4 radians@0x2215530)\n"
+ " )\n"
+ " (\n"
+ " ))\n"
+ "\n"
+ ")\n"
+ "\n"
+ "(function sin\n"
+ " (signature float\n"
+ " (parameters\n"
+ " (declare (in ) float angle@0x2215720)\n"
+ " )\n"
+ " (\n"
+ " ))\n"
+ "\n"
+ " (signature vec2\n"
+ " (parameters\n"
+ " (declare (in ) vec2 angle@0x2215ad0)\n"
+ " )\n"
+ " (\n"
+ " ))\n"
+ "\n"
+ " (signature vec3\n"
+ " (parameters\n"
+ " (declare (in ) vec3 angle@0x2215cb0)\n"
+ " )\n"
+ " (\n"
+ " ))\n"
+ "\n"
+ " (signature vec4\n"
+ " (parameters\n"
+ " (declare (in ) vec4 angle@0x2215e90)\n"
+ " )\n"
+ " (\n"
+ " ))\n"
+ "\n"
+ ")\n"
+ "\n"
+ "(function cos\n"
+ " (signature float\n"
+ " (parameters\n"
+ " (declare (in ) float angle@0x2216070)\n"
+ " )\n"
+ " (\n"
+ " ))\n"
+ "\n"
+ " (signature vec2\n"
+ " (parameters\n"
+ " (declare (in ) vec2 angle@0x2216420)\n"
+ " )\n"
+ " (\n"
+ " ))\n"
+ "\n"
+ " (signature vec3\n"
+ " (parameters\n"
+ " (declare (in ) vec3 angle@0x2216600)\n"
+ " )\n"
+ " (\n"
+ " ))\n"
+ "\n"
+ " (signature vec4\n"
+ " (parameters\n"
+ " (declare (in ) vec4 angle@0x22167e0)\n"
+ " )\n"
+ " (\n"
+ " ))\n"
+ "\n"
+ ")\n"
+ "\n"
+ "(function tan\n"
+ " (signature float\n"
+ " (parameters\n"
+ " (declare (in ) float angle@0x22169c0)\n"
+ " )\n"
+ " (\n"
+ " ))\n"
+ "\n"
+ " (signature vec2\n"
+ " (parameters\n"
+ " (declare (in ) vec2 angle@0x2216d70)\n"
+ " )\n"
+ " (\n"
+ " ))\n"
+ "\n"
+ " (signature vec3\n"
+ " (parameters\n"
+ " (declare (in ) vec3 angle@0x2216f50)\n"
+ " )\n"
+ " (\n"
+ " ))\n"
+ "\n"
+ " (signature vec4\n"
+ " (parameters\n"
+ " (declare (in ) vec4 angle@0x2217130)\n"
+ " )\n"
+ " (\n"
+ " ))\n"
+ "\n"
+ ")\n"
+ "\n"
+ "(function asin\n"
+ " (signature float\n"
+ " (parameters\n"
+ " (declare (in ) float angle@0x2217310)\n"
+ " )\n"
+ " (\n"
+ " ))\n"
+ "\n"
+ " (signature vec2\n"
+ " (parameters\n"
+ " (declare (in ) vec2 angle@0x22176c0)\n"
+ " )\n"
+ " (\n"
+ " ))\n"
+ "\n"
+ " (signature vec3\n"
+ " (parameters\n"
+ " (declare (in ) vec3 angle@0x22178a0)\n"
+ " )\n"
+ " (\n"
+ " ))\n"
+ "\n"
+ " (signature vec4\n"
+ " (parameters\n"
+ " (declare (in ) vec4 angle@0x2217a80)\n"
+ " )\n"
+ " (\n"
+ " ))\n"
+ "\n"
+ ")\n"
+ "\n"
+ "(function acos\n"
+ " (signature float\n"
+ " (parameters\n"
+ " (declare (in ) float angle@0x2217c60)\n"
+ " )\n"
+ " (\n"
+ " ))\n"
+ "\n"
+ " (signature vec2\n"
+ " (parameters\n"
+ " (declare (in ) vec2 angle@0x2218010)\n"
+ " )\n"
+ " (\n"
+ " ))\n"
+ "\n"
+ " (signature vec3\n"
+ " (parameters\n"
+ " (declare (in ) vec3 angle@0x22181f0)\n"
+ " )\n"
+ " (\n"
+ " ))\n"
+ "\n"
+ " (signature vec4\n"
+ " (parameters\n"
+ " (declare (in ) vec4 angle@0x22183d0)\n"
+ " )\n"
+ " (\n"
+ " ))\n"
+ "\n"
+ ")\n"
+ "\n"
+ "(function atan\n"
+ " (signature float\n"
+ " (parameters\n"
+ " (declare (in ) float y@0x22185b0)\n"
+ " (declare (in ) float x@0x22186c0)\n"
+ " )\n"
+ " (\n"
+ " ))\n"
+ "\n"
+ " (signature vec2\n"
+ " (parameters\n"
+ " (declare (in ) vec2 y@0x2218a70)\n"
+ " (declare (in ) vec2 x@0x2218b80)\n"
+ " )\n"
+ " (\n"
+ " ))\n"
+ "\n"
+ " (signature vec3\n"
+ " (parameters\n"
+ " (declare (in ) vec3 y@0x2218d60)\n"
+ " (declare (in ) vec3 x@0x2218e70)\n"
+ " )\n"
+ " (\n"
+ " ))\n"
+ "\n"
+ " (signature vec4\n"
+ " (parameters\n"
+ " (declare (in ) vec4 y@0x2219050)\n"
+ " (declare (in ) vec4 x@0x2219160)\n"
+ " )\n"
+ " (\n"
+ " ))\n"
+ "\n"
+ " (signature float\n"
+ " (parameters\n"
+ " (declare (in ) float y_over_x@0x2219340)\n"
+ " )\n"
+ " (\n"
+ " ))\n"
+ "\n"
+ " (signature vec2\n"
+ " (parameters\n"
+ " (declare (in ) vec2 y_over_x@0x2219530)\n"
+ " )\n"
+ " (\n"
+ " ))\n"
+ "\n"
+ " (signature vec3\n"
+ " (parameters\n"
+ " (declare (in ) vec3 y_over_x@0x2219720)\n"
+ " )\n"
+ " (\n"
+ " ))\n"
+ "\n"
+ " (signature vec4\n"
+ " (parameters\n"
+ " (declare (in ) vec4 y_over_x@0x2219910)\n"
+ " )\n"
+ " (\n"
+ " ))\n"
+ "\n"
+ ")\n"
+ "\n"
+ "(function pow\n"
+ " (signature float\n"
+ " (parameters\n"
+ " (declare (in ) float x@0x2219b00)\n"
+ " (declare (in ) float y@0x2219c10)\n"
+ " )\n"
+ " (\n"
+ " ))\n"
+ "\n"
+ " (signature vec2\n"
+ " (parameters\n"
+ " (declare (in ) vec2 x@0x2219fc0)\n"
+ " (declare (in ) vec2 y@0x221a0d0)\n"
+ " )\n"
+ " (\n"
+ " ))\n"
+ "\n"
+ " (signature vec3\n"
+ " (parameters\n"
+ " (declare (in ) vec3 x@0x221a2b0)\n"
+ " (declare (in ) vec3 y@0x221a3c0)\n"
+ " )\n"
+ " (\n"
+ " ))\n"
+ "\n"
+ " (signature vec4\n"
+ " (parameters\n"
+ " (declare (in ) vec4 x@0x221a5a0)\n"
+ " (declare (in ) vec4 y@0x221a6b0)\n"
+ " )\n"
+ " (\n"
+ " ))\n"
+ "\n"
+ ")\n"
+ "\n"
+ "(function exp\n"
+ " (signature float\n"
+ " (parameters\n"
+ " (declare (in ) float x@0x221a890)\n"
+ " )\n"
+ " (\n"
+ " ))\n"
+ "\n"
+ " (signature vec2\n"
+ " (parameters\n"
+ " (declare (in ) vec2 x@0x221ac40)\n"
+ " )\n"
+ " (\n"
+ " ))\n"
+ "\n"
+ " (signature vec3\n"
+ " (parameters\n"
+ " (declare (in ) vec3 x@0x221ae20)\n"
+ " )\n"
+ " (\n"
+ " ))\n"
+ "\n"
+ " (signature vec4\n"
+ " (parameters\n"
+ " (declare (in ) vec4 x@0x221b000)\n"
+ " )\n"
+ " (\n"
+ " ))\n"
+ "\n"
+ ")\n"
+ "\n"
+ "(function log\n"
+ " (signature float\n"
+ " (parameters\n"
+ " (declare (in ) float x@0x221b1e0)\n"
+ " )\n"
+ " (\n"
+ " ))\n"
+ "\n"
+ " (signature vec2\n"
+ " (parameters\n"
+ " (declare (in ) vec2 x@0x221b590)\n"
+ " )\n"
+ " (\n"
+ " ))\n"
+ "\n"
+ " (signature vec3\n"
+ " (parameters\n"
+ " (declare (in ) vec3 x@0x221b770)\n"
+ " )\n"
+ " (\n"
+ " ))\n"
+ "\n"
+ " (signature vec4\n"
+ " (parameters\n"
+ " (declare (in ) vec4 x@0x221b950)\n"
+ " )\n"
+ " (\n"
+ " ))\n"
+ "\n"
+ ")\n"
+ "\n"
+ "(function exp2\n"
+ " (signature float\n"
+ " (parameters\n"
+ " (declare (in ) float x@0x221bb30)\n"
+ " )\n"
+ " (\n"
+ " ))\n"
+ "\n"
+ " (signature vec2\n"
+ " (parameters\n"
+ " (declare (in ) vec2 x@0x221bee0)\n"
+ " )\n"
+ " (\n"
+ " ))\n"
+ "\n"
+ " (signature vec3\n"
+ " (parameters\n"
+ " (declare (in ) vec3 x@0x221c0c0)\n"
+ " )\n"
+ " (\n"
+ " ))\n"
+ "\n"
+ " (signature vec4\n"
+ " (parameters\n"
+ " (declare (in ) vec4 x@0x221c2a0)\n"
+ " )\n"
+ " (\n"
+ " ))\n"
+ "\n"
+ ")\n"
+ "\n"
+ "(function log2\n"
+ " (signature float\n"
+ " (parameters\n"
+ " (declare (in ) float x@0x221c480)\n"
+ " )\n"
+ " (\n"
+ " ))\n"
+ "\n"
+ " (signature vec2\n"
+ " (parameters\n"
+ " (declare (in ) vec2 x@0x221c830)\n"
+ " )\n"
+ " (\n"
+ " ))\n"
+ "\n"
+ " (signature vec3\n"
+ " (parameters\n"
+ " (declare (in ) vec3 x@0x221ca10)\n"
+ " )\n"
+ " (\n"
+ " ))\n"
+ "\n"
+ " (signature vec4\n"
+ " (parameters\n"
+ " (declare (in ) vec4 x@0x221cbf0)\n"
+ " )\n"
+ " (\n"
+ " ))\n"
+ "\n"
+ ")\n"
+ "\n"
+ "(function sqrt\n"
+ " (signature float\n"
+ " (parameters\n"
+ " (declare (in ) float x@0x221cdd0)\n"
+ " )\n"
+ " (\n"
+ " ))\n"
+ "\n"
+ " (signature vec2\n"
+ " (parameters\n"
+ " (declare (in ) vec2 x@0x221d180)\n"
+ " )\n"
+ " (\n"
+ " ))\n"
+ "\n"
+ " (signature vec3\n"
+ " (parameters\n"
+ " (declare (in ) vec3 x@0x221d360)\n"
+ " )\n"
+ " (\n"
+ " ))\n"
+ "\n"
+ " (signature vec4\n"
+ " (parameters\n"
+ " (declare (in ) vec4 x@0x221d540)\n"
+ " )\n"
+ " (\n"
+ " ))\n"
+ "\n"
+ ")\n"
+ "\n"
+ "(function inversesqrt\n"
+ " (signature float\n"
+ " (parameters\n"
+ " (declare (in ) float x@0x221d720)\n"
+ " )\n"
+ " (\n"
+ " ))\n"
+ "\n"
+ " (signature vec2\n"
+ " (parameters\n"
+ " (declare (in ) vec2 x@0x221dae0)\n"
+ " )\n"
+ " (\n"
+ " ))\n"
+ "\n"
+ " (signature vec3\n"
+ " (parameters\n"
+ " (declare (in ) vec3 x@0x221dcc0)\n"
+ " )\n"
+ " (\n"
+ " ))\n"
+ "\n"
+ " (signature vec4\n"
+ " (parameters\n"
+ " (declare (in ) vec4 x@0x221dea0)\n"
+ " )\n"
+ " (\n"
+ " ))\n"
+ "\n"
+ ")\n"
+ "\n"
+ "(function abs\n"
+ " (signature float\n"
+ " (parameters\n"
+ " (declare (in ) float x@0x221e080)\n"
+ " )\n"
+ " (\n"
+ " ))\n"
+ "\n"
+ " (signature vec2\n"
+ " (parameters\n"
+ " (declare (in ) vec2 x@0x221e430)\n"
+ " )\n"
+ " (\n"
+ " ))\n"
+ "\n"
+ " (signature vec3\n"
+ " (parameters\n"
+ " (declare (in ) vec3 x@0x221e610)\n"
+ " )\n"
+ " (\n"
+ " ))\n"
+ "\n"
+ " (signature vec4\n"
+ " (parameters\n"
+ " (declare (in ) vec4 x@0x221e7f0)\n"
+ " )\n"
+ " (\n"
+ " ))\n"
+ "\n"
+ ")\n"
+ "\n"
+ "(function sign\n"
+ " (signature float\n"
+ " (parameters\n"
+ " (declare (in ) float x@0x221e9d0)\n"
+ " )\n"
+ " (\n"
+ " ))\n"
+ "\n"
+ " (signature vec2\n"
+ " (parameters\n"
+ " (declare (in ) vec2 x@0x221ed80)\n"
+ " )\n"
+ " (\n"
+ " ))\n"
+ "\n"
+ " (signature vec3\n"
+ " (parameters\n"
+ " (declare (in ) vec3 x@0x221ef60)\n"
+ " )\n"
+ " (\n"
+ " ))\n"
+ "\n"
+ " (signature vec4\n"
+ " (parameters\n"
+ " (declare (in ) vec4 x@0x221f140)\n"
+ " )\n"
+ " (\n"
+ " ))\n"
+ "\n"
+ ")\n"
+ "\n"
+ "(function floor\n"
+ " (signature float\n"
+ " (parameters\n"
+ " (declare (in ) float x@0x221f320)\n"
+ " )\n"
+ " (\n"
+ " ))\n"
+ "\n"
+ " (signature vec2\n"
+ " (parameters\n"
+ " (declare (in ) vec2 x@0x221f6d0)\n"
+ " )\n"
+ " (\n"
+ " ))\n"
+ "\n"
+ " (signature vec3\n"
+ " (parameters\n"
+ " (declare (in ) vec3 x@0x221f8b0)\n"
+ " )\n"
+ " (\n"
+ " ))\n"
+ "\n"
+ " (signature vec4\n"
+ " (parameters\n"
+ " (declare (in ) vec4 x@0x221fa90)\n"
+ " )\n"
+ " (\n"
+ " ))\n"
+ "\n"
+ ")\n"
+ "\n"
+ "(function ceil\n"
+ " (signature float\n"
+ " (parameters\n"
+ " (declare (in ) float x@0x221fc70)\n"
+ " )\n"
+ " (\n"
+ " ))\n"
+ "\n"
+ " (signature vec2\n"
+ " (parameters\n"
+ " (declare (in ) vec2 x@0x2220020)\n"
+ " )\n"
+ " (\n"
+ " ))\n"
+ "\n"
+ " (signature vec3\n"
+ " (parameters\n"
+ " (declare (in ) vec3 x@0x2220200)\n"
+ " )\n"
+ " (\n"
+ " ))\n"
+ "\n"
+ " (signature vec4\n"
+ " (parameters\n"
+ " (declare (in ) vec4 x@0x22203e0)\n"
+ " )\n"
+ " (\n"
+ " ))\n"
+ "\n"
+ ")\n"
+ "\n"
+ "(function fract\n"
+ " (signature float\n"
+ " (parameters\n"
+ " (declare (in ) float x@0x22205c0)\n"
+ " )\n"
+ " (\n"
+ " ))\n"
+ "\n"
+ " (signature vec2\n"
+ " (parameters\n"
+ " (declare (in ) vec2 x@0x2220970)\n"
+ " )\n"
+ " (\n"
+ " ))\n"
+ "\n"
+ " (signature vec3\n"
+ " (parameters\n"
+ " (declare (in ) vec3 x@0x2220b50)\n"
+ " )\n"
+ " (\n"
+ " ))\n"
+ "\n"
+ " (signature vec4\n"
+ " (parameters\n"
+ " (declare (in ) vec4 x@0x2220d30)\n"
+ " )\n"
+ " (\n"
+ " ))\n"
+ "\n"
+ ")\n"
+ "\n"
+ "(function mod\n"
+ " (signature float\n"
+ " (parameters\n"
+ " (declare (in ) float x@0x2220f10)\n"
+ " (declare (in ) float y@0x2221020)\n"
+ " )\n"
+ " (\n"
+ " ))\n"
+ "\n"
+ " (signature vec2\n"
+ " (parameters\n"
+ " (declare (in ) vec2 x@0x22213d0)\n"
+ " (declare (in ) float y@0x22214e0)\n"
+ " )\n"
+ " (\n"
+ " ))\n"
+ "\n"
+ " (signature vec3\n"
+ " (parameters\n"
+ " (declare (in ) vec3 x@0x22216c0)\n"
+ " (declare (in ) float y@0x22217d0)\n"
+ " )\n"
+ " (\n"
+ " ))\n"
+ "\n"
+ " (signature vec4\n"
+ " (parameters\n"
+ " (declare (in ) vec4 x@0x22219b0)\n"
+ " (declare (in ) float y@0x2221ac0)\n"
+ " )\n"
+ " (\n"
+ " ))\n"
+ "\n"
+ " (signature vec2\n"
+ " (parameters\n"
+ " (declare (in ) vec2 x@0x2221ca0)\n"
+ " (declare (in ) vec2 y@0x2221db0)\n"
+ " )\n"
+ " (\n"
+ " ))\n"
+ "\n"
+ " (signature vec3\n"
+ " (parameters\n"
+ " (declare (in ) vec3 x@0x2221f90)\n"
+ " (declare (in ) vec3 y@0x22220a0)\n"
+ " )\n"
+ " (\n"
+ " ))\n"
+ "\n"
+ " (signature vec4\n"
+ " (parameters\n"
+ " (declare (in ) vec4 x@0x2222280)\n"
+ " (declare (in ) vec4 y@0x2222390)\n"
+ " )\n"
+ " (\n"
+ " ))\n"
+ "\n"
+ ")\n"
+ "\n"
+ "(function min\n"
+ " (signature float\n"
+ " (parameters\n"
+ " (declare (in ) float x@0x2222570)\n"
+ " (declare (in ) float y@0x2222680)\n"
+ " )\n"
+ " (\n"
+ " ))\n"
+ "\n"
+ " (signature vec2\n"
+ " (parameters\n"
+ " (declare (in ) vec2 x@0x2222a30)\n"
+ " (declare (in ) vec2 y@0x2222b40)\n"
+ " )\n"
+ " (\n"
+ " ))\n"
+ "\n"
+ " (signature vec3\n"
+ " (parameters\n"
+ " (declare (in ) vec3 x@0x2222d20)\n"
+ " (declare (in ) vec3 y@0x2222e30)\n"
+ " )\n"
+ " (\n"
+ " ))\n"
+ "\n"
+ " (signature vec4\n"
+ " (parameters\n"
+ " (declare (in ) vec4 x@0x2223010)\n"
+ " (declare (in ) vec4 y@0x2223120)\n"
+ " )\n"
+ " (\n"
+ " ))\n"
+ "\n"
+ " (signature vec2\n"
+ " (parameters\n"
+ " (declare (in ) vec2 x@0x2223300)\n"
+ " (declare (in ) float y@0x2223410)\n"
+ " )\n"
+ " (\n"
+ " ))\n"
+ "\n"
+ " (signature vec3\n"
+ " (parameters\n"
+ " (declare (in ) vec3 x@0x22235f0)\n"
+ " (declare (in ) float y@0x2223700)\n"
+ " )\n"
+ " (\n"
+ " ))\n"
+ "\n"
+ " (signature vec4\n"
+ " (parameters\n"
+ " (declare (in ) vec4 x@0x22238e0)\n"
+ " (declare (in ) float y@0x22239f0)\n"
+ " )\n"
+ " (\n"
+ " ))\n"
+ "\n"
+ ")\n"
+ "\n"
+ "(function max\n"
+ " (signature float\n"
+ " (parameters\n"
+ " (declare (in ) float x@0x2223bd0)\n"
+ " (declare (in ) float y@0x2223ce0)\n"
+ " )\n"
+ " (\n"
+ " ))\n"
+ "\n"
+ " (signature vec2\n"
+ " (parameters\n"
+ " (declare (in ) vec2 x@0x2224090)\n"
+ " (declare (in ) vec2 y@0x22241a0)\n"
+ " )\n"
+ " (\n"
+ " ))\n"
+ "\n"
+ " (signature vec3\n"
+ " (parameters\n"
+ " (declare (in ) vec3 x@0x2224380)\n"
+ " (declare (in ) vec3 y@0x2224490)\n"
+ " )\n"
+ " (\n"
+ " ))\n"
+ "\n"
+ " (signature vec4\n"
+ " (parameters\n"
+ " (declare (in ) vec4 x@0x2224670)\n"
+ " (declare (in ) vec4 y@0x2224780)\n"
+ " )\n"
+ " (\n"
+ " ))\n"
+ "\n"
+ " (signature vec2\n"
+ " (parameters\n"
+ " (declare (in ) vec2 x@0x2224960)\n"
+ " (declare (in ) float y@0x2224a70)\n"
+ " )\n"
+ " (\n"
+ " ))\n"
+ "\n"
+ " (signature vec3\n"
+ " (parameters\n"
+ " (declare (in ) vec3 x@0x2224c50)\n"
+ " (declare (in ) float y@0x2224d60)\n"
+ " )\n"
+ " (\n"
+ " ))\n"
+ "\n"
+ " (signature vec4\n"
+ " (parameters\n"
+ " (declare (in ) vec4 x@0x2224f40)\n"
+ " (declare (in ) float y@0x2225050)\n"
+ " )\n"
+ " (\n"
+ " ))\n"
+ "\n"
+ ")\n"
+ "\n"
+ "(function clamp\n"
+ " (signature float\n"
+ " (parameters\n"
+ " (declare (in ) float x@0x2225230)\n"
+ " (declare (in ) float minVal@0x2225340)\n"
+ " (declare (in ) float maxVal@0x2225450)\n"
+ " )\n"
+ " (\n"
+ " ))\n"
+ "\n"
+ " (signature vec2\n"
+ " (parameters\n"
+ " (declare (in ) vec2 x@0x2225800)\n"
+ " (declare (in ) vec2 minVal@0x2225910)\n"
+ " (declare (in ) vec2 maxVal@0x2225a20)\n"
+ " )\n"
+ " (\n"
+ " ))\n"
+ "\n"
+ " (signature vec3\n"
+ " (parameters\n"
+ " (declare (in ) vec3 x@0x2225c00)\n"
+ " (declare (in ) vec3 minVal@0x2225d10)\n"
+ " (declare (in ) vec3 maxVal@0x2225e20)\n"
+ " )\n"
+ " (\n"
+ " ))\n"
+ "\n"
+ " (signature vec4\n"
+ " (parameters\n"
+ " (declare (in ) vec4 x@0x2226000)\n"
+ " (declare (in ) vec4 minVal@0x2226110)\n"
+ " (declare (in ) vec4 maxVal@0x2226220)\n"
+ " )\n"
+ " (\n"
+ " ))\n"
+ "\n"
+ " (signature vec2\n"
+ " (parameters\n"
+ " (declare (in ) vec2 x@0x2226400)\n"
+ " (declare (in ) float minVal@0x2226510)\n"
+ " (declare (in ) float maxVal@0x2226620)\n"
+ " )\n"
+ " (\n"
+ " ))\n"
+ "\n"
+ " (signature vec3\n"
+ " (parameters\n"
+ " (declare (in ) vec3 x@0x2226800)\n"
+ " (declare (in ) float minVal@0x2226910)\n"
+ " (declare (in ) float maxVal@0x2226a20)\n"
+ " )\n"
+ " (\n"
+ " ))\n"
+ "\n"
+ " (signature vec4\n"
+ " (parameters\n"
+ " (declare (in ) vec4 x@0x2226c00)\n"
+ " (declare (in ) float minVal@0x2226d10)\n"
+ " (declare (in ) float maxVal@0x2226e20)\n"
+ " )\n"
+ " (\n"
+ " ))\n"
+ "\n"
+ ")\n"
+ "\n"
+ "(function mix\n"
+ " (signature float\n"
+ " (parameters\n"
+ " (declare (in ) float x@0x2227000)\n"
+ " (declare (in ) float y@0x2227110)\n"
+ " (declare (in ) float a@0x2227220)\n"
+ " )\n"
+ " (\n"
+ " ))\n"
+ "\n"
+ " (signature vec2\n"
+ " (parameters\n"
+ " (declare (in ) vec2 x@0x22275d0)\n"
+ " (declare (in ) vec2 y@0x22276e0)\n"
+ " (declare (in ) vec2 a@0x22277f0)\n"
+ " )\n"
+ " (\n"
+ " ))\n"
+ "\n"
+ " (signature vec3\n"
+ " (parameters\n"
+ " (declare (in ) vec3 x@0x22279d0)\n"
+ " (declare (in ) vec3 y@0x2227ae0)\n"
+ " (declare (in ) vec3 a@0x2227bf0)\n"
+ " )\n"
+ " (\n"
+ " ))\n"
+ "\n"
+ " (signature vec4\n"
+ " (parameters\n"
+ " (declare (in ) vec4 x@0x2227dd0)\n"
+ " (declare (in ) vec4 y@0x2227ee0)\n"
+ " (declare (in ) vec4 a@0x2227ff0)\n"
+ " )\n"
+ " (\n"
+ " ))\n"
+ "\n"
+ " (signature vec2\n"
+ " (parameters\n"
+ " (declare (in ) vec2 x@0x22281d0)\n"
+ " (declare (in ) vec2 y@0x22282e0)\n"
+ " (declare (in ) float a@0x22283f0)\n"
+ " )\n"
+ " (\n"
+ " ))\n"
+ "\n"
+ " (signature vec3\n"
+ " (parameters\n"
+ " (declare (in ) vec3 x@0x22285d0)\n"
+ " (declare (in ) vec3 y@0x22286e0)\n"
+ " (declare (in ) float a@0x22287f0)\n"
+ " )\n"
+ " (\n"
+ " ))\n"
+ "\n"
+ " (signature vec4\n"
+ " (parameters\n"
+ " (declare (in ) vec4 x@0x22289d0)\n"
+ " (declare (in ) vec4 y@0x2228ae0)\n"
+ " (declare (in ) float a@0x2228bf0)\n"
+ " )\n"
+ " (\n"
+ " ))\n"
+ "\n"
+ ")\n"
+ "\n"
+ "(function step\n"
+ " (signature float\n"
+ " (parameters\n"
+ " (declare (in ) float edge@0x2228dd0)\n"
+ " (declare (in ) float x@0x2228ee0)\n"
+ " )\n"
+ " (\n"
+ " ))\n"
+ "\n"
+ " (signature vec2\n"
+ " (parameters\n"
+ " (declare (in ) vec2 edge@0x2229290)\n"
+ " (declare (in ) vec2 x@0x22293a0)\n"
+ " )\n"
+ " (\n"
+ " ))\n"
+ "\n"
+ " (signature vec3\n"
+ " (parameters\n"
+ " (declare (in ) vec3 edge@0x2229580)\n"
+ " (declare (in ) vec3 x@0x2229690)\n"
+ " )\n"
+ " (\n"
+ " ))\n"
+ "\n"
+ " (signature vec4\n"
+ " (parameters\n"
+ " (declare (in ) vec4 edge@0x2229870)\n"
+ " (declare (in ) vec4 x@0x2229980)\n"
+ " )\n"
+ " (\n"
+ " ))\n"
+ "\n"
+ " (signature vec2\n"
+ " (parameters\n"
+ " (declare (in ) float edge@0x2229b60)\n"
+ " (declare (in ) vec2 x@0x2229c70)\n"
+ " )\n"
+ " (\n"
+ " ))\n"
+ "\n"
+ " (signature vec3\n"
+ " (parameters\n"
+ " (declare (in ) float edge@0x2229e50)\n"
+ " (declare (in ) vec3 x@0x2229f60)\n"
+ " )\n"
+ " (\n"
+ " ))\n"
+ "\n"
+ " (signature vec4\n"
+ " (parameters\n"
+ " (declare (in ) float edge@0x222a140)\n"
+ " (declare (in ) vec4 x@0x222a250)\n"
+ " )\n"
+ " (\n"
+ " ))\n"
+ "\n"
+ ")\n"
+ "\n"
+ "(function smoothstep\n"
+ " (signature float\n"
+ " (parameters\n"
+ " (declare (in ) float edge0@0x222a430)\n"
+ " (declare (in ) float edge1@0x222a540)\n"
+ " (declare (in ) float x@0x222a650)\n"
+ " )\n"
+ " (\n"
+ " ))\n"
+ "\n"
+ " (signature vec2\n"
+ " (parameters\n"
+ " (declare (in ) vec2 edge0@0x222aa10)\n"
+ " (declare (in ) vec2 edge1@0x222ab20)\n"
+ " (declare (in ) vec2 x@0x222ac30)\n"
+ " )\n"
+ " (\n"
+ " ))\n"
+ "\n"
+ " (signature vec3\n"
+ " (parameters\n"
+ " (declare (in ) vec3 edge0@0x222ae10)\n"
+ " (declare (in ) vec3 edge1@0x222af20)\n"
+ " (declare (in ) vec3 x@0x222b030)\n"
+ " )\n"
+ " (\n"
+ " ))\n"
+ "\n"
+ " (signature vec4\n"
+ " (parameters\n"
+ " (declare (in ) vec4 edge0@0x222b210)\n"
+ " (declare (in ) vec4 edge1@0x222b320)\n"
+ " (declare (in ) vec4 x@0x222b430)\n"
+ " )\n"
+ " (\n"
+ " ))\n"
+ "\n"
+ " (signature vec2\n"
+ " (parameters\n"
+ " (declare (in ) float edge0@0x222b610)\n"
+ " (declare (in ) float edge1@0x222b720)\n"
+ " (declare (in ) vec2 x@0x222b830)\n"
+ " )\n"
+ " (\n"
+ " ))\n"
+ "\n"
+ " (signature vec3\n"
+ " (parameters\n"
+ " (declare (in ) float edge0@0x222ba10)\n"
+ " (declare (in ) float edge1@0x222bb20)\n"
+ " (declare (in ) vec3 x@0x222bc30)\n"
+ " )\n"
+ " (\n"
+ " ))\n"
+ "\n"
+ " (signature vec4\n"
+ " (parameters\n"
+ " (declare (in ) float edge0@0x222be10)\n"
+ " (declare (in ) float edge1@0x222bf20)\n"
+ " (declare (in ) vec4 x@0x222c030)\n"
+ " )\n"
+ " (\n"
+ " ))\n"
+ "\n"
+ ")\n"
+ "\n"
+ "(function length\n"
+ " (signature float\n"
+ " (parameters\n"
+ " (declare (in ) float x@0x222c210)\n"
+ " )\n"
+ " (\n"
+ " ))\n"
+ "\n"
+ " (signature float\n"
+ " (parameters\n"
+ " (declare (in ) vec2 x@0x222c5c0)\n"
+ " )\n"
+ " (\n"
+ " ))\n"
+ "\n"
+ " (signature float\n"
+ " (parameters\n"
+ " (declare (in ) vec3 x@0x222c7a0)\n"
+ " )\n"
+ " (\n"
+ " ))\n"
+ "\n"
+ " (signature float\n"
+ " (parameters\n"
+ " (declare (in ) vec4 x@0x222c980)\n"
+ " )\n"
+ " (\n"
+ " ))\n"
+ "\n"
+ ")\n"
+ "\n"
+ "(function distance\n"
+ " (signature float\n"
+ " (parameters\n"
+ " (declare (in ) float p0@0x222cb60)\n"
+ " (declare (in ) float p1@0x222cc70)\n"
+ " )\n"
+ " (\n"
+ " ))\n"
+ "\n"
+ " (signature float\n"
+ " (parameters\n"
+ " (declare (in ) vec2 p0@0x222d030)\n"
+ " (declare (in ) vec2 p1@0x222d140)\n"
+ " )\n"
+ " (\n"
+ " ))\n"
+ "\n"
+ " (signature float\n"
+ " (parameters\n"
+ " (declare (in ) vec3 p0@0x222d320)\n"
+ " (declare (in ) vec3 p1@0x222d430)\n"
+ " )\n"
+ " (\n"
+ " ))\n"
+ "\n"
+ " (signature float\n"
+ " (parameters\n"
+ " (declare (in ) vec4 p0@0x222d610)\n"
+ " (declare (in ) vec4 p1@0x222d720)\n"
+ " )\n"
+ " (\n"
+ " ))\n"
+ "\n"
+ ")\n"
+ "\n"
+ "(function dot\n"
+ " (signature float\n"
+ " (parameters\n"
+ " (declare (in ) float x@0x222d900)\n"
+ " (declare (in ) float y@0x222da10)\n"
+ " )\n"
+ " (\n"
+ " ))\n"
+ "\n"
+ " (signature float\n"
+ " (parameters\n"
+ " (declare (in ) vec2 x@0x222ddc0)\n"
+ " (declare (in ) vec2 y@0x222ded0)\n"
+ " )\n"
+ " (\n"
+ " ))\n"
+ "\n"
+ " (signature float\n"
+ " (parameters\n"
+ " (declare (in ) vec3 x@0x222e0b0)\n"
+ " (declare (in ) vec3 y@0x222e1c0)\n"
+ " )\n"
+ " (\n"
+ " ))\n"
+ "\n"
+ " (signature float\n"
+ " (parameters\n"
+ " (declare (in ) vec4 x@0x222e3a0)\n"
+ " (declare (in ) vec4 y@0x222e4b0)\n"
+ " )\n"
+ " (\n"
+ " ))\n"
+ "\n"
+ ")\n"
+ "\n"
+ "(function cross\n"
+ " (signature vec3\n"
+ " (parameters\n"
+ " (declare (in ) vec3 x@0x222e690)\n"
+ " (declare (in ) vec3 y@0x222e7a0)\n"
+ " )\n"
+ " (\n"
+ " ))\n"
+ "\n"
+ ")\n"
+ "\n"
+ "(function normalize\n"
+ " (signature float\n"
+ " (parameters\n"
+ " (declare (in ) float x@0x222eb50)\n"
+ " )\n"
+ " (\n"
+ " ))\n"
+ "\n"
+ " (signature vec2\n"
+ " (parameters\n"
+ " (declare (in ) vec2 x@0x222ef10)\n"
+ " )\n"
+ " (\n"
+ " ))\n"
+ "\n"
+ " (signature vec3\n"
+ " (parameters\n"
+ " (declare (in ) vec3 x@0x222f0f0)\n"
+ " )\n"
+ " (\n"
+ " ))\n"
+ "\n"
+ " (signature vec4\n"
+ " (parameters\n"
+ " (declare (in ) vec4 x@0x222f2d0)\n"
+ " )\n"
+ " (\n"
+ " ))\n"
+ "\n"
+ ")\n"
+ "\n"
+ "(function ftransform\n"
+ " (signature vec4\n"
+ " (parameters\n"
+ " )\n"
+ " (\n"
+ " ))\n"
+ "\n"
+ ")\n"
+ "\n"
+ "(function faceforward\n"
+ " (signature float\n"
+ " (parameters\n"
+ " (declare (in ) float N@0x222f760)\n"
+ " (declare (in ) float I@0x222f870)\n"
+ " (declare (in ) float Nref@0x222f980)\n"
+ " )\n"
+ " (\n"
+ " ))\n"
+ "\n"
+ " (signature vec2\n"
+ " (parameters\n"
+ " (declare (in ) vec2 N@0x222fd40)\n"
+ " (declare (in ) vec2 I@0x222fe50)\n"
+ " (declare (in ) vec2 Nref@0x222ff60)\n"
+ " )\n"
+ " (\n"
+ " ))\n"
+ "\n"
+ " (signature vec3\n"
+ " (parameters\n"
+ " (declare (in ) vec3 N@0x2230140)\n"
+ " (declare (in ) vec3 I@0x2230250)\n"
+ " (declare (in ) vec3 Nref@0x2230360)\n"
+ " )\n"
+ " (\n"
+ " ))\n"
+ "\n"
+ " (signature vec4\n"
+ " (parameters\n"
+ " (declare (in ) vec4 N@0x2230540)\n"
+ " (declare (in ) vec4 I@0x2230650)\n"
+ " (declare (in ) vec4 Nref@0x2230760)\n"
+ " )\n"
+ " (\n"
+ " ))\n"
+ "\n"
+ ")\n"
+ "\n"
+ "(function reflect\n"
+ " (signature float\n"
+ " (parameters\n"
+ " (declare (in ) float I@0x2230940)\n"
+ " (declare (in ) float N@0x2230a50)\n"
+ " )\n"
+ " (\n"
+ " ))\n"
+ "\n"
+ " (signature vec2\n"
+ " (parameters\n"
+ " (declare (in ) vec2 I@0x2230e10)\n"
+ " (declare (in ) vec2 N@0x2230f20)\n"
+ " )\n"
+ " (\n"
+ " ))\n"
+ "\n"
+ " (signature vec3\n"
+ " (parameters\n"
+ " (declare (in ) vec3 I@0x2231100)\n"
+ " (declare (in ) vec3 N@0x2231210)\n"
+ " )\n"
+ " (\n"
+ " ))\n"
+ "\n"
+ " (signature vec4\n"
+ " (parameters\n"
+ " (declare (in ) vec4 I@0x22313f0)\n"
+ " (declare (in ) vec4 N@0x2231500)\n"
+ " )\n"
+ " (\n"
+ " ))\n"
+ "\n"
+ ")\n"
+ "\n"
+ "(function refract\n"
+ " (signature float\n"
+ " (parameters\n"
+ " (declare (in ) float I@0x22316e0)\n"
+ " (declare (in ) float N@0x22317f0)\n"
+ " (declare (in ) float eta@0x2231900)\n"
+ " )\n"
+ " (\n"
+ " ))\n"
+ "\n"
+ " (signature vec2\n"
+ " (parameters\n"
+ " (declare (in ) vec2 I@0x2231cc0)\n"
+ " (declare (in ) vec2 N@0x2231dd0)\n"
+ " (declare (in ) float eta@0x2231ee0)\n"
+ " )\n"
+ " (\n"
+ " ))\n"
+ "\n"
+ " (signature vec3\n"
+ " (parameters\n"
+ " (declare (in ) vec3 I@0x22320c0)\n"
+ " (declare (in ) vec3 N@0x22321d0)\n"
+ " (declare (in ) float eta@0x22322e0)\n"
+ " )\n"
+ " (\n"
+ " ))\n"
+ "\n"
+ " (signature vec4\n"
+ " (parameters\n"
+ " (declare (in ) vec4 I@0x22324c0)\n"
+ " (declare (in ) vec4 N@0x22325d0)\n"
+ " (declare (in ) float eta@0x22326e0)\n"
+ " )\n"
+ " (\n"
+ " ))\n"
+ "\n"
+ ")\n"
+ "\n"
+ "(function matrixCompMult\n"
+ " (signature mat2\n"
+ " (parameters\n"
+ " (declare (in ) mat2 x@0x22328c0)\n"
+ " (declare (in ) mat2 y@0x22329d0)\n"
+ " )\n"
+ " (\n"
+ " ))\n"
+ "\n"
+ " (signature mat3\n"
+ " (parameters\n"
+ " (declare (in ) mat3 x@0x2232d90)\n"
+ " (declare (in ) mat3 y@0x2232ea0)\n"
+ " )\n"
+ " (\n"
+ " ))\n"
+ "\n"
+ " (signature mat4\n"
+ " (parameters\n"
+ " (declare (in ) mat4 x@0x2233080)\n"
+ " (declare (in ) mat4 y@0x2233190)\n"
+ " )\n"
+ " (\n"
+ " ))\n"
+ "\n"
+ " (signature mat2x3\n"
+ " (parameters\n"
+ " (declare (in ) mat2x3 x@0x2233370)\n"
+ " (declare (in ) mat2x3 y@0x2233480)\n"
+ " )\n"
+ " (\n"
+ " ))\n"
+ "\n"
+ " (signature mat2x4\n"
+ " (parameters\n"
+ " (declare (in ) mat2x4 x@0x2233660)\n"
+ " (declare (in ) mat2x4 y@0x2233770)\n"
+ " )\n"
+ " (\n"
+ " ))\n"
+ "\n"
+ " (signature mat3x2\n"
+ " (parameters\n"
+ " (declare (in ) mat3x2 x@0x2233950)\n"
+ " (declare (in ) mat3x2 y@0x2233a60)\n"
+ " )\n"
+ " (\n"
+ " ))\n"
+ "\n"
+ " (signature mat3x4\n"
+ " (parameters\n"
+ " (declare (in ) mat3x4 x@0x2233c40)\n"
+ " (declare (in ) mat3x4 y@0x2233d50)\n"
+ " )\n"
+ " (\n"
+ " ))\n"
+ "\n"
+ " (signature mat4x2\n"
+ " (parameters\n"
+ " (declare (in ) mat4x2 x@0x2233f30)\n"
+ " (declare (in ) mat4x2 y@0x2234040)\n"
+ " )\n"
+ " (\n"
+ " ))\n"
+ "\n"
+ " (signature mat4x3\n"
+ " (parameters\n"
+ " (declare (in ) mat4x3 x@0x2234220)\n"
+ " (declare (in ) mat4x3 y@0x2234330)\n"
+ " )\n"
+ " (\n"
+ " ))\n"
+ "\n"
+ ")\n"
+ "\n"
+ "(function outerProduct\n"
+ " (signature mat2\n"
+ " (parameters\n"
+ " (declare (in ) vec2 c@0x2234510)\n"
+ " (declare (in ) vec2 r@0x2234620)\n"
+ " )\n"
+ " (\n"
+ " ))\n"
+ "\n"
+ " (signature mat3\n"
+ " (parameters\n"
+ " (declare (in ) vec3 c@0x22349e0)\n"
+ " (declare (in ) vec3 r@0x2234af0)\n"
+ " )\n"
+ " (\n"
+ " ))\n"
+ "\n"
+ " (signature mat4\n"
+ " (parameters\n"
+ " (declare (in ) vec4 c@0x2234cd0)\n"
+ " (declare (in ) vec4 r@0x2234de0)\n"
+ " )\n"
+ " (\n"
+ " ))\n"
+ "\n"
+ " (signature mat2x3\n"
+ " (parameters\n"
+ " (declare (in ) vec3 c@0x2234fc0)\n"
+ " (declare (in ) vec2 r@0x22350d0)\n"
+ " )\n"
+ " (\n"
+ " ))\n"
+ "\n"
+ " (signature mat3x2\n"
+ " (parameters\n"
+ " (declare (in ) vec2 c@0x22352b0)\n"
+ " (declare (in ) vec3 r@0x22353c0)\n"
+ " )\n"
+ " (\n"
+ " ))\n"
+ "\n"
+ " (signature mat2x4\n"
+ " (parameters\n"
+ " (declare (in ) vec4 c@0x22355a0)\n"
+ " (declare (in ) vec2 r@0x22356b0)\n"
+ " )\n"
+ " (\n"
+ " ))\n"
+ "\n"
+ " (signature mat4x2\n"
+ " (parameters\n"
+ " (declare (in ) vec2 c@0x2235890)\n"
+ " (declare (in ) vec4 r@0x22359a0)\n"
+ " )\n"
+ " (\n"
+ " ))\n"
+ "\n"
+ " (signature mat3x4\n"
+ " (parameters\n"
+ " (declare (in ) vec4 c@0x2235b80)\n"
+ " (declare (in ) vec3 r@0x2235c90)\n"
+ " )\n"
+ " (\n"
+ " ))\n"
+ "\n"
+ " (signature mat4x3\n"
+ " (parameters\n"
+ " (declare (in ) vec3 c@0x2235e70)\n"
+ " (declare (in ) vec4 r@0x2235f80)\n"
+ " )\n"
+ " (\n"
+ " ))\n"
+ "\n"
+ ")\n"
+ "\n"
+ "(function transpose\n"
+ " (signature mat2\n"
+ " (parameters\n"
+ " (declare (in ) mat2 m@0x2236160)\n"
+ " )\n"
+ " (\n"
+ " ))\n"
+ "\n"
+ " (signature mat3\n"
+ " (parameters\n"
+ " (declare (in ) mat3 m@0x2236520)\n"
+ " )\n"
+ " (\n"
+ " ))\n"
+ "\n"
+ " (signature mat4\n"
+ " (parameters\n"
+ " (declare (in ) mat4 m@0x2236700)\n"
+ " )\n"
+ " (\n"
+ " ))\n"
+ "\n"
+ " (signature mat2x3\n"
+ " (parameters\n"
+ " (declare (in ) mat3x2 m@0x22368e0)\n"
+ " )\n"
+ " (\n"
+ " ))\n"
+ "\n"
+ " (signature mat3x2\n"
+ " (parameters\n"
+ " (declare (in ) mat2x3 m@0x2236ac0)\n"
+ " )\n"
+ " (\n"
+ " ))\n"
+ "\n"
+ " (signature mat2x4\n"
+ " (parameters\n"
+ " (declare (in ) mat4x2 m@0x2236ca0)\n"
+ " )\n"
+ " (\n"
+ " ))\n"
+ "\n"
+ " (signature mat4x2\n"
+ " (parameters\n"
+ " (declare (in ) mat2x4 m@0x2236e80)\n"
+ " )\n"
+ " (\n"
+ " ))\n"
+ "\n"
+ " (signature mat3x4\n"
+ " (parameters\n"
+ " (declare (in ) mat4x3 m@0x2237060)\n"
+ " )\n"
+ " (\n"
+ " ))\n"
+ "\n"
+ " (signature mat4x3\n"
+ " (parameters\n"
+ " (declare (in ) mat3x4 m@0x2237240)\n"
+ " )\n"
+ " (\n"
+ " ))\n"
+ "\n"
+ ")\n"
+ "\n"
+ "(function lessThan\n"
+ " (signature bvec2\n"
+ " (parameters\n"
+ " (declare (in ) vec2 x@0x2237420)\n"
+ " (declare (in ) vec2 y@0x2237530)\n"
+ " )\n"
+ " (\n"
+ " ))\n"
+ "\n"
+ " (signature bvec3\n"
+ " (parameters\n"
+ " (declare (in ) vec3 x@0x22378f0)\n"
+ " (declare (in ) vec3 y@0x2237a00)\n"
+ " )\n"
+ " (\n"
+ " ))\n"
+ "\n"
+ " (signature bvec4\n"
+ " (parameters\n"
+ " (declare (in ) vec4 x@0x2237be0)\n"
+ " (declare (in ) vec4 y@0x2237cf0)\n"
+ " )\n"
+ " (\n"
+ " ))\n"
+ "\n"
+ " (signature bvec2\n"
+ " (parameters\n"
+ " (declare (in ) ivec2 x@0x2237ed0)\n"
+ " (declare (in ) ivec2 y@0x2237fe0)\n"
+ " )\n"
+ " (\n"
+ " ))\n"
+ "\n"
+ " (signature bvec3\n"
+ " (parameters\n"
+ " (declare (in ) ivec3 x@0x22381c0)\n"
+ " (declare (in ) ivec3 y@0x22382d0)\n"
+ " )\n"
+ " (\n"
+ " ))\n"
+ "\n"
+ " (signature bvec4\n"
+ " (parameters\n"
+ " (declare (in ) ivec4 x@0x22384b0)\n"
+ " (declare (in ) ivec4 y@0x22385c0)\n"
+ " )\n"
+ " (\n"
+ " ))\n"
+ "\n"
+ ")\n"
+ "\n"
+ "(function lessThanEqual\n"
+ " (signature bvec2\n"
+ " (parameters\n"
+ " (declare (in ) vec2 x@0x22387a0)\n"
+ " (declare (in ) vec2 y@0x22388b0)\n"
+ " )\n"
+ " (\n"
+ " ))\n"
+ "\n"
+ " (signature bvec3\n"
+ " (parameters\n"
+ " (declare (in ) vec3 x@0x2238c70)\n"
+ " (declare (in ) vec3 y@0x2238d80)\n"
+ " )\n"
+ " (\n"
+ " ))\n"
+ "\n"
+ " (signature bvec4\n"
+ " (parameters\n"
+ " (declare (in ) vec4 x@0x2238f60)\n"
+ " (declare (in ) vec4 y@0x2239070)\n"
+ " )\n"
+ " (\n"
+ " ))\n"
+ "\n"
+ " (signature bvec2\n"
+ " (parameters\n"
+ " (declare (in ) ivec2 x@0x2239250)\n"
+ " (declare (in ) ivec2 y@0x2239360)\n"
+ " )\n"
+ " (\n"
+ " ))\n"
+ "\n"
+ " (signature bvec3\n"
+ " (parameters\n"
+ " (declare (in ) ivec3 x@0x2239540)\n"
+ " (declare (in ) ivec3 y@0x2239650)\n"
+ " )\n"
+ " (\n"
+ " ))\n"
+ "\n"
+ " (signature bvec4\n"
+ " (parameters\n"
+ " (declare (in ) ivec4 x@0x2239830)\n"
+ " (declare (in ) ivec4 y@0x2239940)\n"
+ " )\n"
+ " (\n"
+ " ))\n"
+ "\n"
+ ")\n"
+ "\n"
+ "(function greaterThan\n"
+ " (signature bvec2\n"
+ " (parameters\n"
+ " (declare (in ) vec2 x@0x2239b20)\n"
+ " (declare (in ) vec2 y@0x2239c30)\n"
+ " )\n"
+ " (\n"
+ " ))\n"
+ "\n"
+ " (signature bvec3\n"
+ " (parameters\n"
+ " (declare (in ) vec3 x@0x2239ff0)\n"
+ " (declare (in ) vec3 y@0x223a100)\n"
+ " )\n"
+ " (\n"
+ " ))\n"
+ "\n"
+ " (signature bvec4\n"
+ " (parameters\n"
+ " (declare (in ) vec4 x@0x223a2e0)\n"
+ " (declare (in ) vec4 y@0x223a3f0)\n"
+ " )\n"
+ " (\n"
+ " ))\n"
+ "\n"
+ " (signature bvec2\n"
+ " (parameters\n"
+ " (declare (in ) ivec2 x@0x223a5d0)\n"
+ " (declare (in ) ivec2 y@0x223a6e0)\n"
+ " )\n"
+ " (\n"
+ " ))\n"
+ "\n"
+ " (signature bvec3\n"
+ " (parameters\n"
+ " (declare (in ) ivec3 x@0x223a8c0)\n"
+ " (declare (in ) ivec3 y@0x223a9d0)\n"
+ " )\n"
+ " (\n"
+ " ))\n"
+ "\n"
+ " (signature bvec4\n"
+ " (parameters\n"
+ " (declare (in ) ivec4 x@0x223abb0)\n"
+ " (declare (in ) ivec4 y@0x223acc0)\n"
+ " )\n"
+ " (\n"
+ " ))\n"
+ "\n"
+ ")\n"
+ "\n"
+ "(function greaterThanEqual\n"
+ " (signature bvec2\n"
+ " (parameters\n"
+ " (declare (in ) vec2 x@0x223aea0)\n"
+ " (declare (in ) vec2 y@0x223afb0)\n"
+ " )\n"
+ " (\n"
+ " ))\n"
+ "\n"
+ " (signature bvec3\n"
+ " (parameters\n"
+ " (declare (in ) vec3 x@0x223b370)\n"
+ " (declare (in ) vec3 y@0x223b480)\n"
+ " )\n"
+ " (\n"
+ " ))\n"
+ "\n"
+ " (signature bvec4\n"
+ " (parameters\n"
+ " (declare (in ) vec4 x@0x223b660)\n"
+ " (declare (in ) vec4 y@0x223b770)\n"
+ " )\n"
+ " (\n"
+ " ))\n"
+ "\n"
+ " (signature bvec2\n"
+ " (parameters\n"
+ " (declare (in ) ivec2 x@0x223b950)\n"
+ " (declare (in ) ivec2 y@0x223ba60)\n"
+ " )\n"
+ " (\n"
+ " ))\n"
+ "\n"
+ " (signature bvec3\n"
+ " (parameters\n"
+ " (declare (in ) ivec3 x@0x223bc40)\n"
+ " (declare (in ) ivec3 y@0x223bd50)\n"
+ " )\n"
+ " (\n"
+ " ))\n"
+ "\n"
+ " (signature bvec4\n"
+ " (parameters\n"
+ " (declare (in ) ivec4 x@0x223bf30)\n"
+ " (declare (in ) ivec4 y@0x223c040)\n"
+ " )\n"
+ " (\n"
+ " ))\n"
+ "\n"
+ ")\n"
+ "\n"
+ "(function equal\n"
+ " (signature bvec2\n"
+ " (parameters\n"
+ " (declare (in ) vec2 x@0x223c220)\n"
+ " (declare (in ) vec2 y@0x223c330)\n"
+ " )\n"
+ " (\n"
+ " ))\n"
+ "\n"
+ " (signature bvec3\n"
+ " (parameters\n"
+ " (declare (in ) vec3 x@0x223c6e0)\n"
+ " (declare (in ) vec3 y@0x223c7f0)\n"
+ " )\n"
+ " (\n"
+ " ))\n"
+ "\n"
+ " (signature bvec4\n"
+ " (parameters\n"
+ " (declare (in ) vec4 x@0x223c9d0)\n"
+ " (declare (in ) vec4 y@0x223cae0)\n"
+ " )\n"
+ " (\n"
+ " ))\n"
+ "\n"
+ " (signature bvec2\n"
+ " (parameters\n"
+ " (declare (in ) ivec2 x@0x223ccc0)\n"
+ " (declare (in ) ivec2 y@0x223cdd0)\n"
+ " )\n"
+ " (\n"
+ " ))\n"
+ "\n"
+ " (signature bvec3\n"
+ " (parameters\n"
+ " (declare (in ) ivec3 x@0x223cfb0)\n"
+ " (declare (in ) ivec3 y@0x223d0c0)\n"
+ " )\n"
+ " (\n"
+ " ))\n"
+ "\n"
+ " (signature bvec4\n"
+ " (parameters\n"
+ " (declare (in ) ivec4 x@0x223d2a0)\n"
+ " (declare (in ) ivec4 y@0x223d3b0)\n"
+ " )\n"
+ " (\n"
+ " ))\n"
+ "\n"
+ " (signature bvec2\n"
+ " (parameters\n"
+ " (declare (in ) bvec2 x@0x223d590)\n"
+ " (declare (in ) bvec2 y@0x223d6a0)\n"
+ " )\n"
+ " (\n"
+ " ))\n"
+ "\n"
+ " (signature bvec3\n"
+ " (parameters\n"
+ " (declare (in ) bvec3 x@0x223d880)\n"
+ " (declare (in ) bvec3 y@0x223d990)\n"
+ " )\n"
+ " (\n"
+ " ))\n"
+ "\n"
+ " (signature bvec4\n"
+ " (parameters\n"
+ " (declare (in ) bvec4 x@0x223db70)\n"
+ " (declare (in ) bvec4 y@0x223dc80)\n"
+ " )\n"
+ " (\n"
+ " ))\n"
+ "\n"
+ ")\n"
+ "\n"
+ "(function notEqual\n"
+ " (signature bvec2\n"
+ " (parameters\n"
+ " (declare (in ) vec2 x@0x223de60)\n"
+ " (declare (in ) vec2 y@0x223df70)\n"
+ " )\n"
+ " (\n"
+ " ))\n"
+ "\n"
+ " (signature bvec3\n"
+ " (parameters\n"
+ " (declare (in ) vec3 x@0x223e330)\n"
+ " (declare (in ) vec3 y@0x223e440)\n"
+ " )\n"
+ " (\n"
+ " ))\n"
+ "\n"
+ " (signature bvec4\n"
+ " (parameters\n"
+ " (declare (in ) vec4 x@0x223e620)\n"
+ " (declare (in ) vec4 y@0x223e730)\n"
+ " )\n"
+ " (\n"
+ " ))\n"
+ "\n"
+ " (signature bvec2\n"
+ " (parameters\n"
+ " (declare (in ) ivec2 x@0x223e910)\n"
+ " (declare (in ) ivec2 y@0x223ea20)\n"
+ " )\n"
+ " (\n"
+ " ))\n"
+ "\n"
+ " (signature bvec3\n"
+ " (parameters\n"
+ " (declare (in ) ivec3 x@0x223ec00)\n"
+ " (declare (in ) ivec3 y@0x223ed10)\n"
+ " )\n"
+ " (\n"
+ " ))\n"
+ "\n"
+ " (signature bvec4\n"
+ " (parameters\n"
+ " (declare (in ) ivec4 x@0x223eef0)\n"
+ " (declare (in ) ivec4 y@0x223f000)\n"
+ " )\n"
+ " (\n"
+ " ))\n"
+ "\n"
+ " (signature bvec2\n"
+ " (parameters\n"
+ " (declare (in ) bvec2 x@0x223f1e0)\n"
+ " (declare (in ) bvec2 y@0x223f2f0)\n"
+ " )\n"
+ " (\n"
+ " ))\n"
+ "\n"
+ " (signature bvec3\n"
+ " (parameters\n"
+ " (declare (in ) bvec3 x@0x223f4d0)\n"
+ " (declare (in ) bvec3 y@0x223f5e0)\n"
+ " )\n"
+ " (\n"
+ " ))\n"
+ "\n"
+ " (signature bvec4\n"
+ " (parameters\n"
+ " (declare (in ) bvec4 x@0x223f7c0)\n"
+ " (declare (in ) bvec4 y@0x223f8d0)\n"
+ " )\n"
+ " (\n"
+ " ))\n"
+ "\n"
+ ")\n"
+ "\n"
+ "(function any\n"
+ " (signature bool\n"
+ " (parameters\n"
+ " (declare (in ) bvec2 x@0x223fab0)\n"
+ " )\n"
+ " (\n"
+ " ))\n"
+ "\n"
+ " (signature bool\n"
+ " (parameters\n"
+ " (declare (in ) bvec3 x@0x223fe60)\n"
+ " )\n"
+ " (\n"
+ " ))\n"
+ "\n"
+ " (signature bool\n"
+ " (parameters\n"
+ " (declare (in ) bvec4 x@0x2240040)\n"
+ " )\n"
+ " (\n"
+ " ))\n"
+ "\n"
+ ")\n"
+ "\n"
+ "(function all\n"
+ " (signature bool\n"
+ " (parameters\n"
+ " (declare (in ) bvec2 x@0x2240220)\n"
+ " )\n"
+ " (\n"
+ " ))\n"
+ "\n"
+ " (signature bool\n"
+ " (parameters\n"
+ " (declare (in ) bvec3 x@0x22405d0)\n"
+ " )\n"
+ " (\n"
+ " ))\n"
+ "\n"
+ " (signature bool\n"
+ " (parameters\n"
+ " (declare (in ) bvec4 x@0x22407b0)\n"
+ " )\n"
+ " (\n"
+ " ))\n"
+ "\n"
+ ")\n"
+ "\n"
+ "(function not\n"
+ " (signature bvec2\n"
+ " (parameters\n"
+ " (declare (in ) bvec2 x@0x2240990)\n"
+ " )\n"
+ " (\n"
+ " ))\n"
+ "\n"
+ " (signature bvec3\n"
+ " (parameters\n"
+ " (declare (in ) bvec3 x@0x2240d40)\n"
+ " )\n"
+ " (\n"
+ " ))\n"
+ "\n"
+ " (signature bvec4\n"
+ " (parameters\n"
+ " (declare (in ) bvec4 x@0x2240f20)\n"
+ " )\n"
+ " (\n"
+ " ))\n"
+ "\n"
+ ")\n"
+ "\n"
+ "(function texture1D\n"
+ " (signature vec4\n"
+ " (parameters\n"
+ " (declare (in ) sampler1D sampler@0x2241100)\n"
+ " (declare (in ) float coord@0x2241220)\n"
+ " )\n"
+ " (\n"
+ " ))\n"
+ "\n"
+ ")\n"
+ "\n"
+ "(function texture1DProj\n"
+ " (signature vec4\n"
+ " (parameters\n"
+ " (declare (in ) sampler1D sampler@0x22415e0)\n"
+ " (declare (in ) vec2 coord@0x2241700)\n"
+ " )\n"
+ " (\n"
+ " ))\n"
+ "\n"
+ " (signature vec4\n"
+ " (parameters\n"
+ " (declare (in ) sampler1D sampler@0x2241ac0)\n"
+ " (declare (in ) vec4 coord@0x2241be0)\n"
+ " )\n"
+ " (\n"
+ " ))\n"
+ "\n"
+ ")\n"
+ "\n"
+ "(function texture1DLod\n"
+ " (signature vec4\n"
+ " (parameters\n"
+ " (declare (in ) sampler1D sampler@0x2241dc0)\n"
+ " (declare (in ) float coord@0x2241ee0)\n"
+ " (declare (in ) float lod@0x2241ff0)\n"
+ " )\n"
+ " (\n"
+ " ))\n"
+ "\n"
+ ")\n"
+ "\n"
+ "(function texture1DProjLod\n"
+ " (signature vec4\n"
+ " (parameters\n"
+ " (declare (in ) sampler1D sampler@0x22423b0)\n"
+ " (declare (in ) vec2 coord@0x22424d0)\n"
+ " (declare (in ) float lod@0x22425e0)\n"
+ " )\n"
+ " (\n"
+ " ))\n"
+ "\n"
+ " (signature vec4\n"
+ " (parameters\n"
+ " (declare (in ) sampler1D sampler@0x22429a0)\n"
+ " (declare (in ) vec4 coord@0x2242ac0)\n"
+ " (declare (in ) float lod@0x2242bd0)\n"
+ " )\n"
+ " (\n"
+ " ))\n"
+ "\n"
+ ")\n"
+ "\n"
+ "(function texture2D\n"
+ " (signature vec4\n"
+ " (parameters\n"
+ " (declare (in ) sampler2D sampler@0x2242db0)\n"
+ " (declare (in ) vec2 coord@0x2242ed0)\n"
+ " )\n"
+ " (\n"
+ " ))\n"
+ "\n"
+ ")\n"
+ "\n"
+ "(function texture2DProj\n"
+ " (signature vec4\n"
+ " (parameters\n"
+ " (declare (in ) sampler2D sampler@0x2243290)\n"
+ " (declare (in ) vec3 coord@0x22433b0)\n"
+ " )\n"
+ " (\n"
+ " ))\n"
+ "\n"
+ " (signature vec4\n"
+ " (parameters\n"
+ " (declare (in ) sampler2D sampler@0x2243770)\n"
+ " (declare (in ) vec4 coord@0x2243890)\n"
+ " )\n"
+ " (\n"
+ " ))\n"
+ "\n"
+ ")\n"
+ "\n"
+ "(function texture2DLod\n"
+ " (signature vec4\n"
+ " (parameters\n"
+ " (declare (in ) sampler2D sampler@0x2243a70)\n"
+ " (declare (in ) vec2 coord@0x2243b90)\n"
+ " (declare (in ) float lod@0x2243ca0)\n"
+ " )\n"
+ " (\n"
+ " ))\n"
+ "\n"
+ ")\n"
+ "\n"
+ "(function texture2DProjLod\n"
+ " (signature vec4\n"
+ " (parameters\n"
+ " (declare (in ) sampler2D sampler@0x2244060)\n"
+ " (declare (in ) vec3 coord@0x2244180)\n"
+ " (declare (in ) float lod@0x2244290)\n"
+ " )\n"
+ " (\n"
+ " ))\n"
+ "\n"
+ " (signature vec4\n"
+ " (parameters\n"
+ " (declare (in ) sampler2D sampler@0x2244650)\n"
+ " (declare (in ) vec4 coord@0x2244770)\n"
+ " (declare (in ) float lod@0x2244880)\n"
+ " )\n"
+ " (\n"
+ " ))\n"
+ "\n"
+ ")\n"
+ "\n"
+ "(function texture3D\n"
+ " (signature vec4\n"
+ " (parameters\n"
+ " (declare (in ) sampler3D sampler@0x2244a60)\n"
+ " (declare (in ) vec3 coord@0x2244b80)\n"
+ " )\n"
+ " (\n"
+ " ))\n"
+ "\n"
+ ")\n"
+ "\n"
+ "(function texture3DProj\n"
+ " (signature vec4\n"
+ " (parameters\n"
+ " (declare (in ) sampler3D sampler@0x2244f40)\n"
+ " (declare (in ) vec4 coord@0x2245060)\n"
+ " )\n"
+ " (\n"
+ " ))\n"
+ "\n"
+ ")\n"
+ "\n"
+ "(function texture3DLod\n"
+ " (signature vec4\n"
+ " (parameters\n"
+ " (declare (in ) sampler3D sampler@0x2245420)\n"
+ " (declare (in ) vec3 coord@0x2245540)\n"
+ " (declare (in ) float lod@0x2245650)\n"
+ " )\n"
+ " (\n"
+ " ))\n"
+ "\n"
+ ")\n"
+ "\n"
+ "(function texture3DProjLod\n"
+ " (signature vec4\n"
+ " (parameters\n"
+ " (declare (in ) sampler3D sampler@0x2245a10)\n"
+ " (declare (in ) vec4 coord@0x2245b30)\n"
+ " (declare (in ) float lod@0x2245c40)\n"
+ " )\n"
+ " (\n"
+ " ))\n"
+ "\n"
+ ")\n"
+ "\n"
+ "(function textureCube\n"
+ " (signature vec4\n"
+ " (parameters\n"
+ " (declare (in ) samplerCube sampler@0x2246000)\n"
+ " (declare (in ) vec3 coord@0x2246120)\n"
+ " )\n"
+ " (\n"
+ " ))\n"
+ "\n"
+ ")\n"
+ "\n"
+ "(function textureCubeLod\n"
+ " (signature vec4\n"
+ " (parameters\n"
+ " (declare (in ) samplerCube sampler@0x22464e0)\n"
+ " (declare (in ) vec3 coord@0x2246600)\n"
+ " (declare (in ) float lod@0x2246710)\n"
+ " )\n"
+ " (\n"
+ " ))\n"
+ "\n"
+ ")\n"
+ "\n"
+ "(function shadow1D\n"
+ " (signature vec4\n"
+ " (parameters\n"
+ " (declare (in ) sampler1DShadow sampler@0x2246ad0)\n"
+ " (declare (in ) vec3 coord@0x2246bf0)\n"
+ " )\n"
+ " (\n"
+ " ))\n"
+ "\n"
+ ")\n"
+ "\n"
+ "(function shadow2D\n"
+ " (signature vec4\n"
+ " (parameters\n"
+ " (declare (in ) sampler2DShadow sampler@0x2246fb0)\n"
+ " (declare (in ) vec3 coord@0x22470d0)\n"
+ " )\n"
+ " (\n"
+ " ))\n"
+ "\n"
+ ")\n"
+ "\n"
+ "(function shadow1DProj\n"
+ " (signature vec4\n"
+ " (parameters\n"
+ " (declare (in ) sampler1DShadow sampler@0x2247490)\n"
+ " (declare (in ) vec4 coord@0x22475b0)\n"
+ " )\n"
+ " (\n"
+ " ))\n"
+ "\n"
+ ")\n"
+ "\n"
+ "(function shadow2DProj\n"
+ " (signature vec4\n"
+ " (parameters\n"
+ " (declare (in ) sampler2DShadow sampler@0x2247970)\n"
+ " (declare (in ) vec4 coord@0x2247a90)\n"
+ " )\n"
+ " (\n"
+ " ))\n"
+ "\n"
+ ")\n"
+ "\n"
+ "(function shadow1DLod\n"
+ " (signature vec4\n"
+ " (parameters\n"
+ " (declare (in ) sampler1DShadow sampler@0x2247e50)\n"
+ " (declare (in ) vec3 coord@0x2247f70)\n"
+ " (declare (in ) float lod@0x2248080)\n"
+ " )\n"
+ " (\n"
+ " ))\n"
+ "\n"
+ ")\n"
+ "\n"
+ "(function shadow2DLod\n"
+ " (signature vec4\n"
+ " (parameters\n"
+ " (declare (in ) sampler2DShadow sampler@0x2248440)\n"
+ " (declare (in ) vec3 coord@0x2248560)\n"
+ " (declare (in ) float lod@0x2248670)\n"
+ " )\n"
+ " (\n"
+ " ))\n"
+ "\n"
+ ")\n"
+ "\n"
+ "(function shadow1DProjLod\n"
+ " (signature vec4\n"
+ " (parameters\n"
+ " (declare (in ) sampler1DShadow sampler@0x2248a30)\n"
+ " (declare (in ) vec4 coord@0x2248b50)\n"
+ " (declare (in ) float lod@0x2248c60)\n"
+ " )\n"
+ " (\n"
+ " ))\n"
+ "\n"
+ ")\n"
+ "\n"
+ "(function shadow2DProjLod\n"
+ " (signature vec4\n"
+ " (parameters\n"
+ " (declare (in ) sampler2DShadow sampler@0x2249020)\n"
+ " (declare (in ) vec4 coord@0x2249140)\n"
+ " (declare (in ) float lod@0x2249250)\n"
+ " )\n"
+ " (\n"
+ " ))\n"
+ "\n"
+ ")\n"
+ "\n"
+ "(function noise1\n"
+ " (signature float\n"
+ " (parameters\n"
+ " (declare (in ) float x@0x2249610)\n"
+ " )\n"
+ " (\n"
+ " ))\n"
+ "\n"
+ " (signature float\n"
+ " (parameters\n"
+ " (declare (in ) vec2 x@0x22499c0)\n"
+ " )\n"
+ " (\n"
+ " ))\n"
+ "\n"
+ " (signature float\n"
+ " (parameters\n"
+ " (declare (in ) vec3 x@0x2249ba0)\n"
+ " )\n"
+ " (\n"
+ " ))\n"
+ "\n"
+ " (signature float\n"
+ " (parameters\n"
+ " (declare (in ) vec4 x@0x2249d80)\n"
+ " )\n"
+ " (\n"
+ " ))\n"
+ "\n"
+ ")\n"
+ "\n"
+ "(function noise2\n"
+ " (signature vec2\n"
+ " (parameters\n"
+ " (declare (in ) float x@0x2249f60)\n"
+ " )\n"
+ " (\n"
+ " ))\n"
+ "\n"
+ " (signature vec2\n"
+ " (parameters\n"
+ " (declare (in ) vec2 x@0x224a310)\n"
+ " )\n"
+ " (\n"
+ " ))\n"
+ "\n"
+ " (signature vec2\n"
+ " (parameters\n"
+ " (declare (in ) vec3 x@0x224a4f0)\n"
+ " )\n"
+ " (\n"
+ " ))\n"
+ "\n"
+ " (signature vec2\n"
+ " (parameters\n"
+ " (declare (in ) vec4 x@0x224a6d0)\n"
+ " )\n"
+ " (\n"
+ " ))\n"
+ "\n"
+ ")\n"
+ "\n"
+ "(function noise3\n"
+ " (signature vec3\n"
+ " (parameters\n"
+ " (declare (in ) float x@0x224a8b0)\n"
+ " )\n"
+ " (\n"
+ " ))\n"
+ "\n"
+ " (signature vec3\n"
+ " (parameters\n"
+ " (declare (in ) vec2 x@0x224ac60)\n"
+ " )\n"
+ " (\n"
+ " ))\n"
+ "\n"
+ " (signature vec3\n"
+ " (parameters\n"
+ " (declare (in ) vec3 x@0x224ae40)\n"
+ " )\n"
+ " (\n"
+ " ))\n"
+ "\n"
+ " (signature vec3\n"
+ " (parameters\n"
+ " (declare (in ) vec4 x@0x224b020)\n"
+ " )\n"
+ " (\n"
+ " ))\n"
+ "\n"
+ ")\n"
+ "\n"
+ "(function noise4\n"
+ " (signature vec4\n"
+ " (parameters\n"
+ " (declare (in ) float x@0x224b200)\n"
+ " )\n"
+ " (\n"
+ " ))\n"
+ "\n"
+ " (signature vec4\n"
+ " (parameters\n"
+ " (declare (in ) vec2 x@0x224b5b0)\n"
+ " )\n"
+ " (\n"
+ " ))\n"
+ "\n"
+ " (signature vec4\n"
+ " (parameters\n"
+ " (declare (in ) vec3 x@0x224b790)\n"
+ " )\n"
+ " (\n"
+ " ))\n"
+ "\n"
+ " (signature vec4\n"
+ " (parameters\n"
+ " (declare (in ) vec4 x@0x224b970)\n"
+ " )\n"
+ " (\n"
+ " ))\n"
+ "\n"
+ ")\n"
+ "\n"
+ "\n"
+ ")"
+;
+static const char *functions_for_120_vert [] = {
+ builtin_clamp,
+ builtin_matrixCompMult,
+ builtin_shadow2DProjLod,
+ builtin_noise2,
+ builtin_texture3DProjLod,
+ builtin_pow,
+ builtin_texture2DProj,
+ builtin_greaterThanEqual,
+ builtin_sign,
+ builtin_texture3DProj,
+ builtin_texture2D,
+ builtin_equal,
+ builtin_faceforward,
+ builtin_tan,
+ builtin_shadow2DProj,
+ builtin_shadow1DProjLod,
+ builtin_any,
+ builtin_shadow1DProj,
+ builtin_normalize,
+ builtin_asin,
+ builtin_texture1DProj,
+ builtin_log,
+ builtin_floor,
+ builtin_exp2,
+ builtin_lessThan,
+ builtin_cross,
+ builtin_sqrt,
+ builtin_texture3DLod,
+ builtin_fract,
+ builtin_abs,
+ builtin_degrees,
+ builtin_shadow1DLod,
+ builtin_ftransform,
+ builtin_sin,
+ builtin_shadow2D,
+ builtin_shadow2DLod,
+ builtin_all,
+ builtin_log2,
+ builtin_atan,
+ builtin_notEqual,
+ builtin_max,
+ builtin_lessThanEqual,
+ builtin_transpose,
+ builtin_outerProduct,
+ builtin_ceil,
+ builtin_reflect,
+ builtin_textureCubeLod,
+ builtin_step,
+ builtin_texture1D,
+ builtin_greaterThan,
+ builtin_texture3D,
+ builtin_not,
+ builtin_texture2DProjLod,
+ builtin_inversesqrt,
+ builtin_mod,
+ builtin_noise4,
+ builtin_distance,
+ builtin_cos,
+ builtin_shadow1D,
+ builtin_noise1,
+ builtin_refract,
+ builtin_noise3,
+ builtin_texture2DLod,
+ builtin_min,
+ builtin_radians,
+ builtin_smoothstep,
+ builtin_texture1DProjLod,
+ builtin_textureCube,
+ builtin_length,
+ builtin_texture1DLod,
+ builtin_exp,
+ builtin_acos,
+ builtin_mix,
+ builtin_dot,
+};
+static const char *prototypes_for_EXT_texture_array_frag =
+ "(\n"
+ "(function texture1DArray\n"
+ " (signature vec4\n"
+ " (parameters\n"
+ " (declare (in ) sampler1DArray sampler@0xb9bd60)\n"
+ " (declare (in ) vec2 coord@0xb9be80)\n"
+ " )\n"
+ " (\n"
+ " ))\n"
+ "\n"
+ " (signature vec4\n"
+ " (parameters\n"
+ " (declare (in ) sampler1DArray sampler@0xb9c240)\n"
+ " (declare (in ) vec2 coord@0xb9c360)\n"
+ " (declare (in ) float bias@0xb9c470)\n"
+ " )\n"
+ " (\n"
+ " ))\n"
+ "\n"
+ ")\n"
+ "\n"
+ "(function texture2DArray\n"
+ " (signature vec4\n"
+ " (parameters\n"
+ " (declare (in ) sampler1DArray sampler@0xb9c650)\n"
+ " (declare (in ) vec2 coord@0xb9c770)\n"
+ " )\n"
+ " (\n"
+ " ))\n"
+ "\n"
+ " (signature vec4\n"
+ " (parameters\n"
+ " (declare (in ) sampler1DArray sampler@0xb9cb30)\n"
+ " (declare (in ) vec2 coord@0xb9cc50)\n"
+ " (declare (in ) float bias@0xb9cd60)\n"
+ " )\n"
+ " (\n"
+ " ))\n"
+ "\n"
+ ")\n"
+ "\n"
+ "(function shadow1DArray\n"
+ " (signature vec4\n"
+ " (parameters\n"
+ " (declare (in ) sampler1DArrayShadow sampler@0xb9cf40)\n"
+ " (declare (in ) vec3 coord@0xb9d060)\n"
+ " )\n"
+ " (\n"
+ " ))\n"
+ "\n"
+ " (signature vec4\n"
+ " (parameters\n"
+ " (declare (in ) sampler1DArrayShadow sampler@0xb9d420)\n"
+ " (declare (in ) vec3 coord@0xb9d540)\n"
+ " (declare (in ) float bias@0xb9d650)\n"
+ " )\n"
+ " (\n"
+ " ))\n"
+ "\n"
+ ")\n"
+ "\n"
+ "(function shadow2DArray\n"
+ " (signature vec4\n"
+ " (parameters\n"
+ " (declare (in ) sampler2DArrayShadow sampler@0xb9d830)\n"
+ " (declare (in ) vec4 coord@0xb9d950)\n"
+ " )\n"
+ " (\n"
+ " ))\n"
+ "\n"
+ ")\n"
+ "\n"
+ "\n"
+ ")"
+;
+static const char *functions_for_EXT_texture_array_frag [] = {
+ builtin_shadow2DArray,
+ builtin_shadow1DArray,
+ builtin_texture1DArray,
+ builtin_texture2DArray,
+};
+static const char *prototypes_for_110_vert =
+ "(\n"
+ "(function radians\n"
+ " (signature float\n"
+ " (parameters\n"
+ " (declare (in ) float degrees@0x9e3c50)\n"
+ " )\n"
+ " (\n"
+ " ))\n"
+ "\n"
+ " (signature vec2\n"
+ " (parameters\n"
+ " (declare (in ) vec2 degrees@0x9e4020)\n"
+ " )\n"
+ " (\n"
+ " ))\n"
+ "\n"
+ " (signature vec3\n"
+ " (parameters\n"
+ " (declare (in ) vec3 degrees@0x9e4210)\n"
+ " )\n"
+ " (\n"
+ " ))\n"
+ "\n"
+ " (signature vec4\n"
+ " (parameters\n"
+ " (declare (in ) vec4 degrees@0x9e4400)\n"
+ " )\n"
+ " (\n"
+ " ))\n"
+ "\n"
+ ")\n"
+ "\n"
+ "(function degrees\n"
+ " (signature float\n"
+ " (parameters\n"
+ " (declare (in ) float radians@0x9e45f0)\n"
+ " )\n"
+ " (\n"
+ " ))\n"
+ "\n"
+ " (signature vec2\n"
+ " (parameters\n"
+ " (declare (in ) vec2 radians@0x9e49c0)\n"
+ " )\n"
+ " (\n"
+ " ))\n"
+ "\n"
+ " (signature vec3\n"
+ " (parameters\n"
+ " (declare (in ) vec3 radians@0x9e4bb0)\n"
+ " )\n"
+ " (\n"
+ " ))\n"
+ "\n"
+ " (signature vec4\n"
+ " (parameters\n"
+ " (declare (in ) vec4 radians@0x9e4da0)\n"
+ " )\n"
+ " (\n"
+ " ))\n"
+ "\n"
+ ")\n"
+ "\n"
+ "(function sin\n"
+ " (signature float\n"
+ " (parameters\n"
+ " (declare (in ) float angle@0x9e4f90)\n"
+ " )\n"
+ " (\n"
+ " ))\n"
+ "\n"
+ " (signature vec2\n"
+ " (parameters\n"
+ " (declare (in ) vec2 angle@0x9e5340)\n"
+ " )\n"
+ " (\n"
+ " ))\n"
+ "\n"
+ " (signature vec3\n"
+ " (parameters\n"
+ " (declare (in ) vec3 angle@0x9e5520)\n"
+ " )\n"
+ " (\n"
+ " ))\n"
+ "\n"
+ " (signature vec4\n"
+ " (parameters\n"
+ " (declare (in ) vec4 angle@0x9e5700)\n"
+ " )\n"
+ " (\n"
+ " ))\n"
+ "\n"
+ ")\n"
+ "\n"
+ "(function cos\n"
+ " (signature float\n"
+ " (parameters\n"
+ " (declare (in ) float angle@0x9e58e0)\n"
+ " )\n"
+ " (\n"
+ " ))\n"
+ "\n"
+ " (signature vec2\n"
+ " (parameters\n"
+ " (declare (in ) vec2 angle@0x9e5c90)\n"
+ " )\n"
+ " (\n"
+ " ))\n"
+ "\n"
+ " (signature vec3\n"
+ " (parameters\n"
+ " (declare (in ) vec3 angle@0x9e5e70)\n"
+ " )\n"
+ " (\n"
+ " ))\n"
+ "\n"
+ " (signature vec4\n"
+ " (parameters\n"
+ " (declare (in ) vec4 angle@0x9e6050)\n"
+ " )\n"
+ " (\n"
+ " ))\n"
+ "\n"
+ ")\n"
+ "\n"
+ "(function tan\n"
+ " (signature float\n"
+ " (parameters\n"
+ " (declare (in ) float angle@0x9e6230)\n"
+ " )\n"
+ " (\n"
+ " ))\n"
+ "\n"
+ " (signature vec2\n"
+ " (parameters\n"
+ " (declare (in ) vec2 angle@0x9e65e0)\n"
+ " )\n"
+ " (\n"
+ " ))\n"
+ "\n"
+ " (signature vec3\n"
+ " (parameters\n"
+ " (declare (in ) vec3 angle@0x9e67c0)\n"
+ " )\n"
+ " (\n"
+ " ))\n"
+ "\n"
+ " (signature vec4\n"
+ " (parameters\n"
+ " (declare (in ) vec4 angle@0x9e69a0)\n"
+ " )\n"
+ " (\n"
+ " ))\n"
+ "\n"
+ ")\n"
+ "\n"
+ "(function asin\n"
+ " (signature float\n"
+ " (parameters\n"
+ " (declare (in ) float angle@0x9e6b80)\n"
+ " )\n"
+ " (\n"
+ " ))\n"
+ "\n"
+ " (signature vec2\n"
+ " (parameters\n"
+ " (declare (in ) vec2 angle@0x9e6f30)\n"
+ " )\n"
+ " (\n"
+ " ))\n"
+ "\n"
+ " (signature vec3\n"
+ " (parameters\n"
+ " (declare (in ) vec3 angle@0x9e7110)\n"
+ " )\n"
+ " (\n"
+ " ))\n"
+ "\n"
+ " (signature vec4\n"
+ " (parameters\n"
+ " (declare (in ) vec4 angle@0x9e72f0)\n"
+ " )\n"
+ " (\n"
+ " ))\n"
+ "\n"
+ ")\n"
+ "\n"
+ "(function acos\n"
+ " (signature float\n"
+ " (parameters\n"
+ " (declare (in ) float angle@0x9e74d0)\n"
+ " )\n"
+ " (\n"
+ " ))\n"
+ "\n"
+ " (signature vec2\n"
+ " (parameters\n"
+ " (declare (in ) vec2 angle@0x9e7880)\n"
+ " )\n"
+ " (\n"
+ " ))\n"
+ "\n"
+ " (signature vec3\n"
+ " (parameters\n"
+ " (declare (in ) vec3 angle@0x9e7a60)\n"
+ " )\n"
+ " (\n"
+ " ))\n"
+ "\n"
+ " (signature vec4\n"
+ " (parameters\n"
+ " (declare (in ) vec4 angle@0x9e7c40)\n"
+ " )\n"
+ " (\n"
+ " ))\n"
+ "\n"
+ ")\n"
+ "\n"
+ "(function atan\n"
+ " (signature float\n"
+ " (parameters\n"
+ " (declare (in ) float y@0x9e7e20)\n"
+ " (declare (in ) float x@0x9e7f30)\n"
+ " )\n"
+ " (\n"
+ " ))\n"
+ "\n"
+ " (signature vec2\n"
+ " (parameters\n"
+ " (declare (in ) vec2 y@0x9e82e0)\n"
+ " (declare (in ) vec2 x@0x9e83f0)\n"
+ " )\n"
+ " (\n"
+ " ))\n"
+ "\n"
+ " (signature vec3\n"
+ " (parameters\n"
+ " (declare (in ) vec3 y@0x9e85d0)\n"
+ " (declare (in ) vec3 x@0x9e86e0)\n"
+ " )\n"
+ " (\n"
+ " ))\n"
+ "\n"
+ " (signature vec4\n"
+ " (parameters\n"
+ " (declare (in ) vec4 y@0x9e88c0)\n"
+ " (declare (in ) vec4 x@0x9e89d0)\n"
+ " )\n"
+ " (\n"
+ " ))\n"
+ "\n"
+ " (signature float\n"
+ " (parameters\n"
+ " (declare (in ) float y_over_x@0x9e8bb0)\n"
+ " )\n"
+ " (\n"
+ " ))\n"
+ "\n"
+ " (signature vec2\n"
+ " (parameters\n"
+ " (declare (in ) vec2 y_over_x@0x9e8da0)\n"
+ " )\n"
+ " (\n"
+ " ))\n"
+ "\n"
+ " (signature vec3\n"
+ " (parameters\n"
+ " (declare (in ) vec3 y_over_x@0x9e8f90)\n"
+ " )\n"
+ " (\n"
+ " ))\n"
+ "\n"
+ " (signature vec4\n"
+ " (parameters\n"
+ " (declare (in ) vec4 y_over_x@0x9e9180)\n"
+ " )\n"
+ " (\n"
+ " ))\n"
+ "\n"
+ ")\n"
+ "\n"
+ "(function pow\n"
+ " (signature float\n"
+ " (parameters\n"
+ " (declare (in ) float x@0x9e9370)\n"
+ " (declare (in ) float y@0x9e9480)\n"
+ " )\n"
+ " (\n"
+ " ))\n"
+ "\n"
+ " (signature vec2\n"
+ " (parameters\n"
+ " (declare (in ) vec2 x@0x9e9830)\n"
+ " (declare (in ) vec2 y@0x9e9940)\n"
+ " )\n"
+ " (\n"
+ " ))\n"
+ "\n"
+ " (signature vec3\n"
+ " (parameters\n"
+ " (declare (in ) vec3 x@0x9e9b20)\n"
+ " (declare (in ) vec3 y@0x9e9c30)\n"
+ " )\n"
+ " (\n"
+ " ))\n"
+ "\n"
+ " (signature vec4\n"
+ " (parameters\n"
+ " (declare (in ) vec4 x@0x9e9e10)\n"
+ " (declare (in ) vec4 y@0x9e9f20)\n"
+ " )\n"
+ " (\n"
+ " ))\n"
+ "\n"
+ ")\n"
+ "\n"
+ "(function exp\n"
+ " (signature float\n"
+ " (parameters\n"
+ " (declare (in ) float x@0x9ea100)\n"
+ " )\n"
+ " (\n"
+ " ))\n"
+ "\n"
+ " (signature vec2\n"
+ " (parameters\n"
+ " (declare (in ) vec2 x@0x9ea4b0)\n"
+ " )\n"
+ " (\n"
+ " ))\n"
+ "\n"
+ " (signature vec3\n"
+ " (parameters\n"
+ " (declare (in ) vec3 x@0x9ea690)\n"
+ " )\n"
+ " (\n"
+ " ))\n"
+ "\n"
+ " (signature vec4\n"
+ " (parameters\n"
+ " (declare (in ) vec4 x@0x9ea870)\n"
+ " )\n"
+ " (\n"
+ " ))\n"
+ "\n"
+ ")\n"
+ "\n"
+ "(function log\n"
+ " (signature float\n"
+ " (parameters\n"
+ " (declare (in ) float x@0x9eaa50)\n"
+ " )\n"
+ " (\n"
+ " ))\n"
+ "\n"
+ " (signature vec2\n"
+ " (parameters\n"
+ " (declare (in ) vec2 x@0x9eae00)\n"
+ " )\n"
+ " (\n"
+ " ))\n"
+ "\n"
+ " (signature vec3\n"
+ " (parameters\n"
+ " (declare (in ) vec3 x@0x9eafe0)\n"
+ " )\n"
+ " (\n"
+ " ))\n"
+ "\n"
+ " (signature vec4\n"
+ " (parameters\n"
+ " (declare (in ) vec4 x@0x9eb1c0)\n"
+ " )\n"
+ " (\n"
+ " ))\n"
+ "\n"
+ ")\n"
+ "\n"
+ "(function exp2\n"
+ " (signature float\n"
+ " (parameters\n"
+ " (declare (in ) float x@0x9eb3a0)\n"
+ " )\n"
+ " (\n"
+ " ))\n"
+ "\n"
+ " (signature vec2\n"
+ " (parameters\n"
+ " (declare (in ) vec2 x@0x9eb750)\n"
+ " )\n"
+ " (\n"
+ " ))\n"
+ "\n"
+ " (signature vec3\n"
+ " (parameters\n"
+ " (declare (in ) vec3 x@0x9eb930)\n"
+ " )\n"
+ " (\n"
+ " ))\n"
+ "\n"
+ " (signature vec4\n"
+ " (parameters\n"
+ " (declare (in ) vec4 x@0x9ebb10)\n"
+ " )\n"
+ " (\n"
+ " ))\n"
+ "\n"
+ ")\n"
+ "\n"
+ "(function log2\n"
+ " (signature float\n"
+ " (parameters\n"
+ " (declare (in ) float x@0x9ebcf0)\n"
+ " )\n"
+ " (\n"
+ " ))\n"
+ "\n"
+ " (signature vec2\n"
+ " (parameters\n"
+ " (declare (in ) vec2 x@0x9ec0a0)\n"
+ " )\n"
+ " (\n"
+ " ))\n"
+ "\n"
+ " (signature vec3\n"
+ " (parameters\n"
+ " (declare (in ) vec3 x@0x9ec280)\n"
+ " )\n"
+ " (\n"
+ " ))\n"
+ "\n"
+ " (signature vec4\n"
+ " (parameters\n"
+ " (declare (in ) vec4 x@0x9ec460)\n"
+ " )\n"
+ " (\n"
+ " ))\n"
+ "\n"
+ ")\n"
+ "\n"
+ "(function sqrt\n"
+ " (signature float\n"
+ " (parameters\n"
+ " (declare (in ) float x@0x9ec640)\n"
+ " )\n"
+ " (\n"
+ " ))\n"
+ "\n"
+ " (signature vec2\n"
+ " (parameters\n"
+ " (declare (in ) vec2 x@0x9ec9f0)\n"
+ " )\n"
+ " (\n"
+ " ))\n"
+ "\n"
+ " (signature vec3\n"
+ " (parameters\n"
+ " (declare (in ) vec3 x@0x9ecbd0)\n"
+ " )\n"
+ " (\n"
+ " ))\n"
+ "\n"
+ " (signature vec4\n"
+ " (parameters\n"
+ " (declare (in ) vec4 x@0x9ecdb0)\n"
+ " )\n"
+ " (\n"
+ " ))\n"
+ "\n"
+ ")\n"
+ "\n"
+ "(function inversesqrt\n"
+ " (signature float\n"
+ " (parameters\n"
+ " (declare (in ) float x@0x9ecf90)\n"
+ " )\n"
+ " (\n"
+ " ))\n"
+ "\n"
+ " (signature vec2\n"
+ " (parameters\n"
+ " (declare (in ) vec2 x@0x9ed350)\n"
+ " )\n"
+ " (\n"
+ " ))\n"
+ "\n"
+ " (signature vec3\n"
+ " (parameters\n"
+ " (declare (in ) vec3 x@0x9ed530)\n"
+ " )\n"
+ " (\n"
+ " ))\n"
+ "\n"
+ " (signature vec4\n"
+ " (parameters\n"
+ " (declare (in ) vec4 x@0x9ed710)\n"
+ " )\n"
+ " (\n"
+ " ))\n"
+ "\n"
+ ")\n"
+ "\n"
+ "(function abs\n"
+ " (signature float\n"
+ " (parameters\n"
+ " (declare (in ) float x@0x9ed8f0)\n"
+ " )\n"
+ " (\n"
+ " ))\n"
+ "\n"
+ " (signature vec2\n"
+ " (parameters\n"
+ " (declare (in ) vec2 x@0x9edca0)\n"
+ " )\n"
+ " (\n"
+ " ))\n"
+ "\n"
+ " (signature vec3\n"
+ " (parameters\n"
+ " (declare (in ) vec3 x@0x9ede80)\n"
+ " )\n"
+ " (\n"
+ " ))\n"
+ "\n"
+ " (signature vec4\n"
+ " (parameters\n"
+ " (declare (in ) vec4 x@0x9ee060)\n"
+ " )\n"
+ " (\n"
+ " ))\n"
+ "\n"
+ ")\n"
+ "\n"
+ "(function sign\n"
+ " (signature float\n"
+ " (parameters\n"
+ " (declare (in ) float x@0x9ee240)\n"
+ " )\n"
+ " (\n"
+ " ))\n"
+ "\n"
+ " (signature vec2\n"
+ " (parameters\n"
+ " (declare (in ) vec2 x@0x9ee5f0)\n"
+ " )\n"
+ " (\n"
+ " ))\n"
+ "\n"
+ " (signature vec3\n"
+ " (parameters\n"
+ " (declare (in ) vec3 x@0x9ee7d0)\n"
+ " )\n"
+ " (\n"
+ " ))\n"
+ "\n"
+ " (signature vec4\n"
+ " (parameters\n"
+ " (declare (in ) vec4 x@0x9ee9b0)\n"
+ " )\n"
+ " (\n"
+ " ))\n"
+ "\n"
+ ")\n"
+ "\n"
+ "(function floor\n"
+ " (signature float\n"
+ " (parameters\n"
+ " (declare (in ) float x@0x9eeb90)\n"
+ " )\n"
+ " (\n"
+ " ))\n"
+ "\n"
+ " (signature vec2\n"
+ " (parameters\n"
+ " (declare (in ) vec2 x@0x9eef40)\n"
+ " )\n"
+ " (\n"
+ " ))\n"
+ "\n"
+ " (signature vec3\n"
+ " (parameters\n"
+ " (declare (in ) vec3 x@0x9ef120)\n"
+ " )\n"
+ " (\n"
+ " ))\n"
+ "\n"
+ " (signature vec4\n"
+ " (parameters\n"
+ " (declare (in ) vec4 x@0x9ef300)\n"
+ " )\n"
+ " (\n"
+ " ))\n"
+ "\n"
+ ")\n"
+ "\n"
+ "(function ceil\n"
+ " (signature float\n"
+ " (parameters\n"
+ " (declare (in ) float x@0x9ef4e0)\n"
+ " )\n"
+ " (\n"
+ " ))\n"
+ "\n"
+ " (signature vec2\n"
+ " (parameters\n"
+ " (declare (in ) vec2 x@0x9ef890)\n"
+ " )\n"
+ " (\n"
+ " ))\n"
+ "\n"
+ " (signature vec3\n"
+ " (parameters\n"
+ " (declare (in ) vec3 x@0x9efa70)\n"
+ " )\n"
+ " (\n"
+ " ))\n"
+ "\n"
+ " (signature vec4\n"
+ " (parameters\n"
+ " (declare (in ) vec4 x@0x9efc50)\n"
+ " )\n"
+ " (\n"
+ " ))\n"
+ "\n"
+ ")\n"
+ "\n"
+ "(function fract\n"
+ " (signature float\n"
+ " (parameters\n"
+ " (declare (in ) float x@0x9efe30)\n"
+ " )\n"
+ " (\n"
+ " ))\n"
+ "\n"
+ " (signature vec2\n"
+ " (parameters\n"
+ " (declare (in ) vec2 x@0x9f01e0)\n"
+ " )\n"
+ " (\n"
+ " ))\n"
+ "\n"
+ " (signature vec3\n"
+ " (parameters\n"
+ " (declare (in ) vec3 x@0x9f03c0)\n"
+ " )\n"
+ " (\n"
+ " ))\n"
+ "\n"
+ " (signature vec4\n"
+ " (parameters\n"
+ " (declare (in ) vec4 x@0x9f05a0)\n"
+ " )\n"
+ " (\n"
+ " ))\n"
+ "\n"
+ ")\n"
+ "\n"
+ "(function mod\n"
+ " (signature float\n"
+ " (parameters\n"
+ " (declare (in ) float x@0x9f0780)\n"
+ " (declare (in ) float y@0x9f0890)\n"
+ " )\n"
+ " (\n"
+ " ))\n"
+ "\n"
+ " (signature vec2\n"
+ " (parameters\n"
+ " (declare (in ) vec2 x@0x9f0c40)\n"
+ " (declare (in ) float y@0x9f0d50)\n"
+ " )\n"
+ " (\n"
+ " ))\n"
+ "\n"
+ " (signature vec3\n"
+ " (parameters\n"
+ " (declare (in ) vec3 x@0x9f0f30)\n"
+ " (declare (in ) float y@0x9f1040)\n"
+ " )\n"
+ " (\n"
+ " ))\n"
+ "\n"
+ " (signature vec4\n"
+ " (parameters\n"
+ " (declare (in ) vec4 x@0x9f1220)\n"
+ " (declare (in ) float y@0x9f1330)\n"
+ " )\n"
+ " (\n"
+ " ))\n"
+ "\n"
+ " (signature vec2\n"
+ " (parameters\n"
+ " (declare (in ) vec2 x@0x9f1510)\n"
+ " (declare (in ) vec2 y@0x9f1620)\n"
+ " )\n"
+ " (\n"
+ " ))\n"
+ "\n"
+ " (signature vec3\n"
+ " (parameters\n"
+ " (declare (in ) vec3 x@0x9f1800)\n"
+ " (declare (in ) vec3 y@0x9f1910)\n"
+ " )\n"
+ " (\n"
+ " ))\n"
+ "\n"
+ " (signature vec4\n"
+ " (parameters\n"
+ " (declare (in ) vec4 x@0x9f1af0)\n"
+ " (declare (in ) vec4 y@0x9f1c00)\n"
+ " )\n"
+ " (\n"
+ " ))\n"
+ "\n"
+ ")\n"
+ "\n"
+ "(function min\n"
+ " (signature float\n"
+ " (parameters\n"
+ " (declare (in ) float x@0x9f1de0)\n"
+ " (declare (in ) float y@0x9f1ef0)\n"
+ " )\n"
+ " (\n"
+ " ))\n"
+ "\n"
+ " (signature vec2\n"
+ " (parameters\n"
+ " (declare (in ) vec2 x@0x9f22a0)\n"
+ " (declare (in ) vec2 y@0x9f23b0)\n"
+ " )\n"
+ " (\n"
+ " ))\n"
+ "\n"
+ " (signature vec3\n"
+ " (parameters\n"
+ " (declare (in ) vec3 x@0x9f2590)\n"
+ " (declare (in ) vec3 y@0x9f26a0)\n"
+ " )\n"
+ " (\n"
+ " ))\n"
+ "\n"
+ " (signature vec4\n"
+ " (parameters\n"
+ " (declare (in ) vec4 x@0x9f2880)\n"
+ " (declare (in ) vec4 y@0x9f2990)\n"
+ " )\n"
+ " (\n"
+ " ))\n"
+ "\n"
+ " (signature vec2\n"
+ " (parameters\n"
+ " (declare (in ) vec2 x@0x9f2b70)\n"
+ " (declare (in ) float y@0x9f2c80)\n"
+ " )\n"
+ " (\n"
+ " ))\n"
+ "\n"
+ " (signature vec3\n"
+ " (parameters\n"
+ " (declare (in ) vec3 x@0x9f2e60)\n"
+ " (declare (in ) float y@0x9f2f70)\n"
+ " )\n"
+ " (\n"
+ " ))\n"
+ "\n"
+ " (signature vec4\n"
+ " (parameters\n"
+ " (declare (in ) vec4 x@0x9f3150)\n"
+ " (declare (in ) float y@0x9f3260)\n"
+ " )\n"
+ " (\n"
+ " ))\n"
+ "\n"
+ ")\n"
+ "\n"
+ "(function max\n"
+ " (signature float\n"
+ " (parameters\n"
+ " (declare (in ) float x@0x9f3440)\n"
+ " (declare (in ) float y@0x9f3550)\n"
+ " )\n"
+ " (\n"
+ " ))\n"
+ "\n"
+ " (signature vec2\n"
+ " (parameters\n"
+ " (declare (in ) vec2 x@0x9f3900)\n"
+ " (declare (in ) vec2 y@0x9f3a10)\n"
+ " )\n"
+ " (\n"
+ " ))\n"
+ "\n"
+ " (signature vec3\n"
+ " (parameters\n"
+ " (declare (in ) vec3 x@0x9f3bf0)\n"
+ " (declare (in ) vec3 y@0x9f3d00)\n"
+ " )\n"
+ " (\n"
+ " ))\n"
+ "\n"
+ " (signature vec4\n"
+ " (parameters\n"
+ " (declare (in ) vec4 x@0x9f3ee0)\n"
+ " (declare (in ) vec4 y@0x9f3ff0)\n"
+ " )\n"
+ " (\n"
+ " ))\n"
+ "\n"
+ " (signature vec2\n"
+ " (parameters\n"
+ " (declare (in ) vec2 x@0x9f41d0)\n"
+ " (declare (in ) float y@0x9f42e0)\n"
+ " )\n"
+ " (\n"
+ " ))\n"
+ "\n"
+ " (signature vec3\n"
+ " (parameters\n"
+ " (declare (in ) vec3 x@0x9f44c0)\n"
+ " (declare (in ) float y@0x9f45d0)\n"
+ " )\n"
+ " (\n"
+ " ))\n"
+ "\n"
+ " (signature vec4\n"
+ " (parameters\n"
+ " (declare (in ) vec4 x@0x9f47b0)\n"
+ " (declare (in ) float y@0x9f48c0)\n"
+ " )\n"
+ " (\n"
+ " ))\n"
+ "\n"
+ ")\n"
+ "\n"
+ "(function clamp\n"
+ " (signature float\n"
+ " (parameters\n"
+ " (declare (in ) float x@0x9f4aa0)\n"
+ " (declare (in ) float minVal@0x9f4bb0)\n"
+ " (declare (in ) float maxVal@0x9f4cc0)\n"
+ " )\n"
+ " (\n"
+ " ))\n"
+ "\n"
+ " (signature vec2\n"
+ " (parameters\n"
+ " (declare (in ) vec2 x@0x9f5070)\n"
+ " (declare (in ) vec2 minVal@0x9f5180)\n"
+ " (declare (in ) vec2 maxVal@0x9f5290)\n"
+ " )\n"
+ " (\n"
+ " ))\n"
+ "\n"
+ " (signature vec3\n"
+ " (parameters\n"
+ " (declare (in ) vec3 x@0x9f5470)\n"
+ " (declare (in ) vec3 minVal@0x9f5580)\n"
+ " (declare (in ) vec3 maxVal@0x9f5690)\n"
+ " )\n"
+ " (\n"
+ " ))\n"
+ "\n"
+ " (signature vec4\n"
+ " (parameters\n"
+ " (declare (in ) vec4 x@0x9f5870)\n"
+ " (declare (in ) vec4 minVal@0x9f5980)\n"
+ " (declare (in ) vec4 maxVal@0x9f5a90)\n"
+ " )\n"
+ " (\n"
+ " ))\n"
+ "\n"
+ " (signature vec2\n"
+ " (parameters\n"
+ " (declare (in ) vec2 x@0x9f5c70)\n"
+ " (declare (in ) float minVal@0x9f5d80)\n"
+ " (declare (in ) float maxVal@0x9f5e90)\n"
+ " )\n"
+ " (\n"
+ " ))\n"
+ "\n"
+ " (signature vec3\n"
+ " (parameters\n"
+ " (declare (in ) vec3 x@0x9f6070)\n"
+ " (declare (in ) float minVal@0x9f6180)\n"
+ " (declare (in ) float maxVal@0x9f6290)\n"
+ " )\n"
+ " (\n"
+ " ))\n"
+ "\n"
+ " (signature vec4\n"
+ " (parameters\n"
+ " (declare (in ) vec4 x@0x9f6470)\n"
+ " (declare (in ) float minVal@0x9f6580)\n"
+ " (declare (in ) float maxVal@0x9f6690)\n"
+ " )\n"
+ " (\n"
+ " ))\n"
+ "\n"
+ ")\n"
+ "\n"
+ "(function mix\n"
+ " (signature float\n"
+ " (parameters\n"
+ " (declare (in ) float x@0x9f6870)\n"
+ " (declare (in ) float y@0x9f6980)\n"
+ " (declare (in ) float a@0x9f6a90)\n"
+ " )\n"
+ " (\n"
+ " ))\n"
+ "\n"
+ " (signature vec2\n"
+ " (parameters\n"
+ " (declare (in ) vec2 x@0x9f6e40)\n"
+ " (declare (in ) vec2 y@0x9f6f50)\n"
+ " (declare (in ) vec2 a@0x9f7060)\n"
+ " )\n"
+ " (\n"
+ " ))\n"
+ "\n"
+ " (signature vec3\n"
+ " (parameters\n"
+ " (declare (in ) vec3 x@0x9f7240)\n"
+ " (declare (in ) vec3 y@0x9f7350)\n"
+ " (declare (in ) vec3 a@0x9f7460)\n"
+ " )\n"
+ " (\n"
+ " ))\n"
+ "\n"
+ " (signature vec4\n"
+ " (parameters\n"
+ " (declare (in ) vec4 x@0x9f7640)\n"
+ " (declare (in ) vec4 y@0x9f7750)\n"
+ " (declare (in ) vec4 a@0x9f7860)\n"
+ " )\n"
+ " (\n"
+ " ))\n"
+ "\n"
+ " (signature vec2\n"
+ " (parameters\n"
+ " (declare (in ) vec2 x@0x9f7a40)\n"
+ " (declare (in ) vec2 y@0x9f7b50)\n"
+ " (declare (in ) float a@0x9f7c60)\n"
+ " )\n"
+ " (\n"
+ " ))\n"
+ "\n"
+ " (signature vec3\n"
+ " (parameters\n"
+ " (declare (in ) vec3 x@0x9f7e40)\n"
+ " (declare (in ) vec3 y@0x9f7f50)\n"
+ " (declare (in ) float a@0x9f8060)\n"
+ " )\n"
+ " (\n"
+ " ))\n"
+ "\n"
+ " (signature vec4\n"
+ " (parameters\n"
+ " (declare (in ) vec4 x@0x9f8240)\n"
+ " (declare (in ) vec4 y@0x9f8350)\n"
+ " (declare (in ) float a@0x9f8460)\n"
+ " )\n"
+ " (\n"
+ " ))\n"
+ "\n"
+ ")\n"
+ "\n"
+ "(function step\n"
+ " (signature float\n"
+ " (parameters\n"
+ " (declare (in ) float edge@0x9f8640)\n"
+ " (declare (in ) float x@0x9f8750)\n"
+ " )\n"
+ " (\n"
+ " ))\n"
+ "\n"
+ " (signature vec2\n"
+ " (parameters\n"
+ " (declare (in ) vec2 edge@0x9f8b00)\n"
+ " (declare (in ) vec2 x@0x9f8c10)\n"
+ " )\n"
+ " (\n"
+ " ))\n"
+ "\n"
+ " (signature vec3\n"
+ " (parameters\n"
+ " (declare (in ) vec3 edge@0x9f8df0)\n"
+ " (declare (in ) vec3 x@0x9f8f00)\n"
+ " )\n"
+ " (\n"
+ " ))\n"
+ "\n"
+ " (signature vec4\n"
+ " (parameters\n"
+ " (declare (in ) vec4 edge@0x9f90e0)\n"
+ " (declare (in ) vec4 x@0x9f91f0)\n"
+ " )\n"
+ " (\n"
+ " ))\n"
+ "\n"
+ " (signature vec2\n"
+ " (parameters\n"
+ " (declare (in ) float edge@0x9f93d0)\n"
+ " (declare (in ) vec2 x@0x9f94e0)\n"
+ " )\n"
+ " (\n"
+ " ))\n"
+ "\n"
+ " (signature vec3\n"
+ " (parameters\n"
+ " (declare (in ) float edge@0x9f96c0)\n"
+ " (declare (in ) vec3 x@0x9f97d0)\n"
+ " )\n"
+ " (\n"
+ " ))\n"
+ "\n"
+ " (signature vec4\n"
+ " (parameters\n"
+ " (declare (in ) float edge@0x9f99b0)\n"
+ " (declare (in ) vec4 x@0x9f9ac0)\n"
+ " )\n"
+ " (\n"
+ " ))\n"
+ "\n"
+ ")\n"
+ "\n"
+ "(function smoothstep\n"
+ " (signature float\n"
+ " (parameters\n"
+ " (declare (in ) float edge0@0x9f9ca0)\n"
+ " (declare (in ) float edge1@0x9f9db0)\n"
+ " (declare (in ) float x@0x9f9ec0)\n"
+ " )\n"
+ " (\n"
+ " ))\n"
+ "\n"
+ " (signature vec2\n"
+ " (parameters\n"
+ " (declare (in ) vec2 edge0@0x9fa280)\n"
+ " (declare (in ) vec2 edge1@0x9fa390)\n"
+ " (declare (in ) vec2 x@0x9fa4a0)\n"
+ " )\n"
+ " (\n"
+ " ))\n"
+ "\n"
+ " (signature vec3\n"
+ " (parameters\n"
+ " (declare (in ) vec3 edge0@0x9fa680)\n"
+ " (declare (in ) vec3 edge1@0x9fa790)\n"
+ " (declare (in ) vec3 x@0x9fa8a0)\n"
+ " )\n"
+ " (\n"
+ " ))\n"
+ "\n"
+ " (signature vec4\n"
+ " (parameters\n"
+ " (declare (in ) vec4 edge0@0x9faa80)\n"
+ " (declare (in ) vec4 edge1@0x9fab90)\n"
+ " (declare (in ) vec4 x@0x9faca0)\n"
+ " )\n"
+ " (\n"
+ " ))\n"
+ "\n"
+ " (signature vec2\n"
+ " (parameters\n"
+ " (declare (in ) float edge0@0x9fae80)\n"
+ " (declare (in ) float edge1@0x9faf90)\n"
+ " (declare (in ) vec2 x@0x9fb0a0)\n"
+ " )\n"
+ " (\n"
+ " ))\n"
+ "\n"
+ " (signature vec3\n"
+ " (parameters\n"
+ " (declare (in ) float edge0@0x9fb280)\n"
+ " (declare (in ) float edge1@0x9fb390)\n"
+ " (declare (in ) vec3 x@0x9fb4a0)\n"
+ " )\n"
+ " (\n"
+ " ))\n"
+ "\n"
+ " (signature vec4\n"
+ " (parameters\n"
+ " (declare (in ) float edge0@0x9fb680)\n"
+ " (declare (in ) float edge1@0x9fb790)\n"
+ " (declare (in ) vec4 x@0x9fb8a0)\n"
+ " )\n"
+ " (\n"
+ " ))\n"
+ "\n"
+ ")\n"
+ "\n"
+ "(function length\n"
+ " (signature float\n"
+ " (parameters\n"
+ " (declare (in ) float x@0x9fba80)\n"
+ " )\n"
+ " (\n"
+ " ))\n"
+ "\n"
+ " (signature float\n"
+ " (parameters\n"
+ " (declare (in ) vec2 x@0x9fbe30)\n"
+ " )\n"
+ " (\n"
+ " ))\n"
+ "\n"
+ " (signature float\n"
+ " (parameters\n"
+ " (declare (in ) vec3 x@0x9fc010)\n"
+ " )\n"
+ " (\n"
+ " ))\n"
+ "\n"
+ " (signature float\n"
+ " (parameters\n"
+ " (declare (in ) vec4 x@0x9fc1f0)\n"
+ " )\n"
+ " (\n"
+ " ))\n"
+ "\n"
+ ")\n"
+ "\n"
+ "(function distance\n"
+ " (signature float\n"
+ " (parameters\n"
+ " (declare (in ) float p0@0x9fc3d0)\n"
+ " (declare (in ) float p1@0x9fc4e0)\n"
+ " )\n"
+ " (\n"
+ " ))\n"
+ "\n"
+ " (signature float\n"
+ " (parameters\n"
+ " (declare (in ) vec2 p0@0x9fc8a0)\n"
+ " (declare (in ) vec2 p1@0x9fc9b0)\n"
+ " )\n"
+ " (\n"
+ " ))\n"
+ "\n"
+ " (signature float\n"
+ " (parameters\n"
+ " (declare (in ) vec3 p0@0x9fcb90)\n"
+ " (declare (in ) vec3 p1@0x9fcca0)\n"
+ " )\n"
+ " (\n"
+ " ))\n"
+ "\n"
+ " (signature float\n"
+ " (parameters\n"
+ " (declare (in ) vec4 p0@0x9fce80)\n"
+ " (declare (in ) vec4 p1@0x9fcf90)\n"
+ " )\n"
+ " (\n"
+ " ))\n"
+ "\n"
+ ")\n"
+ "\n"
+ "(function dot\n"
+ " (signature float\n"
+ " (parameters\n"
+ " (declare (in ) float x@0x9fd170)\n"
+ " (declare (in ) float y@0x9fd280)\n"
+ " )\n"
+ " (\n"
+ " ))\n"
+ "\n"
+ " (signature float\n"
+ " (parameters\n"
+ " (declare (in ) vec2 x@0x9fd630)\n"
+ " (declare (in ) vec2 y@0x9fd740)\n"
+ " )\n"
+ " (\n"
+ " ))\n"
+ "\n"
+ " (signature float\n"
+ " (parameters\n"
+ " (declare (in ) vec3 x@0x9fd920)\n"
+ " (declare (in ) vec3 y@0x9fda30)\n"
+ " )\n"
+ " (\n"
+ " ))\n"
+ "\n"
+ " (signature float\n"
+ " (parameters\n"
+ " (declare (in ) vec4 x@0x9fdc10)\n"
+ " (declare (in ) vec4 y@0x9fdd20)\n"
+ " )\n"
+ " (\n"
+ " ))\n"
+ "\n"
+ ")\n"
+ "\n"
+ "(function cross\n"
+ " (signature vec3\n"
+ " (parameters\n"
+ " (declare (in ) vec3 x@0x9fdf00)\n"
+ " (declare (in ) vec3 y@0x9fe010)\n"
+ " )\n"
+ " (\n"
+ " ))\n"
+ "\n"
+ ")\n"
+ "\n"
+ "(function normalize\n"
+ " (signature float\n"
+ " (parameters\n"
+ " (declare (in ) float x@0x9fe3c0)\n"
+ " )\n"
+ " (\n"
+ " ))\n"
+ "\n"
+ " (signature vec2\n"
+ " (parameters\n"
+ " (declare (in ) vec2 x@0x9fe780)\n"
+ " )\n"
+ " (\n"
+ " ))\n"
+ "\n"
+ " (signature vec3\n"
+ " (parameters\n"
+ " (declare (in ) vec3 x@0x9fe960)\n"
+ " )\n"
+ " (\n"
+ " ))\n"
+ "\n"
+ " (signature vec4\n"
+ " (parameters\n"
+ " (declare (in ) vec4 x@0x9feb40)\n"
+ " )\n"
+ " (\n"
+ " ))\n"
+ "\n"
+ ")\n"
+ "\n"
+ "(function ftransform\n"
+ " (signature vec4\n"
+ " (parameters\n"
+ " )\n"
+ " (\n"
+ " ))\n"
+ "\n"
+ ")\n"
+ "\n"
+ "(function faceforward\n"
+ " (signature float\n"
+ " (parameters\n"
+ " (declare (in ) float N@0x9fefd0)\n"
+ " (declare (in ) float I@0x9ff0e0)\n"
+ " (declare (in ) float Nref@0x9ff1f0)\n"
+ " )\n"
+ " (\n"
+ " ))\n"
+ "\n"
+ " (signature vec2\n"
+ " (parameters\n"
+ " (declare (in ) vec2 N@0x9ff5b0)\n"
+ " (declare (in ) vec2 I@0x9ff6c0)\n"
+ " (declare (in ) vec2 Nref@0x9ff7d0)\n"
+ " )\n"
+ " (\n"
+ " ))\n"
+ "\n"
+ " (signature vec3\n"
+ " (parameters\n"
+ " (declare (in ) vec3 N@0x9ff9b0)\n"
+ " (declare (in ) vec3 I@0x9ffac0)\n"
+ " (declare (in ) vec3 Nref@0x9ffbd0)\n"
+ " )\n"
+ " (\n"
+ " ))\n"
+ "\n"
+ " (signature vec4\n"
+ " (parameters\n"
+ " (declare (in ) vec4 N@0x9ffdb0)\n"
+ " (declare (in ) vec4 I@0x9ffec0)\n"
+ " (declare (in ) vec4 Nref@0x9fffd0)\n"
+ " )\n"
+ " (\n"
+ " ))\n"
+ "\n"
+ ")\n"
+ "\n"
+ "(function reflect\n"
+ " (signature float\n"
+ " (parameters\n"
+ " (declare (in ) float I@0xa001b0)\n"
+ " (declare (in ) float N@0xa002c0)\n"
+ " )\n"
+ " (\n"
+ " ))\n"
+ "\n"
+ " (signature vec2\n"
+ " (parameters\n"
+ " (declare (in ) vec2 I@0xa00680)\n"
+ " (declare (in ) vec2 N@0xa00790)\n"
+ " )\n"
+ " (\n"
+ " ))\n"
+ "\n"
+ " (signature vec3\n"
+ " (parameters\n"
+ " (declare (in ) vec3 I@0xa00970)\n"
+ " (declare (in ) vec3 N@0xa00a80)\n"
+ " )\n"
+ " (\n"
+ " ))\n"
+ "\n"
+ " (signature vec4\n"
+ " (parameters\n"
+ " (declare (in ) vec4 I@0xa00c60)\n"
+ " (declare (in ) vec4 N@0xa00d70)\n"
+ " )\n"
+ " (\n"
+ " ))\n"
+ "\n"
+ ")\n"
+ "\n"
+ "(function refract\n"
+ " (signature float\n"
+ " (parameters\n"
+ " (declare (in ) float I@0xa00f50)\n"
+ " (declare (in ) float N@0xa01060)\n"
+ " (declare (in ) float eta@0xa01170)\n"
+ " )\n"
+ " (\n"
+ " ))\n"
+ "\n"
+ " (signature vec2\n"
+ " (parameters\n"
+ " (declare (in ) vec2 I@0xa01530)\n"
+ " (declare (in ) vec2 N@0xa01640)\n"
+ " (declare (in ) float eta@0xa01750)\n"
+ " )\n"
+ " (\n"
+ " ))\n"
+ "\n"
+ " (signature vec3\n"
+ " (parameters\n"
+ " (declare (in ) vec3 I@0xa01930)\n"
+ " (declare (in ) vec3 N@0xa01a40)\n"
+ " (declare (in ) float eta@0xa01b50)\n"
+ " )\n"
+ " (\n"
+ " ))\n"
+ "\n"
+ " (signature vec4\n"
+ " (parameters\n"
+ " (declare (in ) vec4 I@0xa01d30)\n"
+ " (declare (in ) vec4 N@0xa01e40)\n"
+ " (declare (in ) float eta@0xa01f50)\n"
+ " )\n"
+ " (\n"
+ " ))\n"
+ "\n"
+ ")\n"
+ "\n"
+ "(function matrixCompMult\n"
+ " (signature mat2\n"
+ " (parameters\n"
+ " (declare (in ) mat2 x@0xa02130)\n"
+ " (declare (in ) mat2 y@0xa02240)\n"
+ " )\n"
+ " (\n"
+ " ))\n"
+ "\n"
+ " (signature mat3\n"
+ " (parameters\n"
+ " (declare (in ) mat3 x@0xa02600)\n"
+ " (declare (in ) mat3 y@0xa02710)\n"
+ " )\n"
+ " (\n"
+ " ))\n"
+ "\n"
+ " (signature mat4\n"
+ " (parameters\n"
+ " (declare (in ) mat4 x@0xa028f0)\n"
+ " (declare (in ) mat4 y@0xa02a00)\n"
+ " )\n"
+ " (\n"
+ " ))\n"
+ "\n"
+ ")\n"
+ "\n"
+ "(function lessThan\n"
+ " (signature bvec2\n"
+ " (parameters\n"
+ " (declare (in ) vec2 x@0xa02be0)\n"
+ " (declare (in ) vec2 y@0xa02cf0)\n"
+ " )\n"
+ " (\n"
+ " ))\n"
+ "\n"
+ " (signature bvec3\n"
+ " (parameters\n"
+ " (declare (in ) vec3 x@0xa030b0)\n"
+ " (declare (in ) vec3 y@0xa031c0)\n"
+ " )\n"
+ " (\n"
+ " ))\n"
+ "\n"
+ " (signature bvec4\n"
+ " (parameters\n"
+ " (declare (in ) vec4 x@0xa033a0)\n"
+ " (declare (in ) vec4 y@0xa034b0)\n"
+ " )\n"
+ " (\n"
+ " ))\n"
+ "\n"
+ " (signature bvec2\n"
+ " (parameters\n"
+ " (declare (in ) ivec2 x@0xa03690)\n"
+ " (declare (in ) ivec2 y@0xa037a0)\n"
+ " )\n"
+ " (\n"
+ " ))\n"
+ "\n"
+ " (signature bvec3\n"
+ " (parameters\n"
+ " (declare (in ) ivec3 x@0xa03980)\n"
+ " (declare (in ) ivec3 y@0xa03a90)\n"
+ " )\n"
+ " (\n"
+ " ))\n"
+ "\n"
+ " (signature bvec4\n"
+ " (parameters\n"
+ " (declare (in ) ivec4 x@0xa03c70)\n"
+ " (declare (in ) ivec4 y@0xa03d80)\n"
+ " )\n"
+ " (\n"
+ " ))\n"
+ "\n"
+ ")\n"
+ "\n"
+ "(function lessThanEqual\n"
+ " (signature bvec2\n"
+ " (parameters\n"
+ " (declare (in ) vec2 x@0xa03f60)\n"
+ " (declare (in ) vec2 y@0xa04070)\n"
+ " )\n"
+ " (\n"
+ " ))\n"
+ "\n"
+ " (signature bvec3\n"
+ " (parameters\n"
+ " (declare (in ) vec3 x@0xa04430)\n"
+ " (declare (in ) vec3 y@0xa04540)\n"
+ " )\n"
+ " (\n"
+ " ))\n"
+ "\n"
+ " (signature bvec4\n"
+ " (parameters\n"
+ " (declare (in ) vec4 x@0xa04720)\n"
+ " (declare (in ) vec4 y@0xa04830)\n"
+ " )\n"
+ " (\n"
+ " ))\n"
+ "\n"
+ " (signature bvec2\n"
+ " (parameters\n"
+ " (declare (in ) ivec2 x@0xa04a10)\n"
+ " (declare (in ) ivec2 y@0xa04b20)\n"
+ " )\n"
+ " (\n"
+ " ))\n"
+ "\n"
+ " (signature bvec3\n"
+ " (parameters\n"
+ " (declare (in ) ivec3 x@0xa04d00)\n"
+ " (declare (in ) ivec3 y@0xa04e10)\n"
+ " )\n"
+ " (\n"
+ " ))\n"
+ "\n"
+ " (signature bvec4\n"
+ " (parameters\n"
+ " (declare (in ) ivec4 x@0xa04ff0)\n"
+ " (declare (in ) ivec4 y@0xa05100)\n"
+ " )\n"
+ " (\n"
+ " ))\n"
+ "\n"
+ ")\n"
+ "\n"
+ "(function greaterThan\n"
+ " (signature bvec2\n"
+ " (parameters\n"
+ " (declare (in ) vec2 x@0xa052e0)\n"
+ " (declare (in ) vec2 y@0xa053f0)\n"
+ " )\n"
+ " (\n"
+ " ))\n"
+ "\n"
+ " (signature bvec3\n"
+ " (parameters\n"
+ " (declare (in ) vec3 x@0xa057b0)\n"
+ " (declare (in ) vec3 y@0xa058c0)\n"
+ " )\n"
+ " (\n"
+ " ))\n"
+ "\n"
+ " (signature bvec4\n"
+ " (parameters\n"
+ " (declare (in ) vec4 x@0xa05aa0)\n"
+ " (declare (in ) vec4 y@0xa05bb0)\n"
+ " )\n"
+ " (\n"
+ " ))\n"
+ "\n"
+ " (signature bvec2\n"
+ " (parameters\n"
+ " (declare (in ) ivec2 x@0xa05d90)\n"
+ " (declare (in ) ivec2 y@0xa05ea0)\n"
+ " )\n"
+ " (\n"
+ " ))\n"
+ "\n"
+ " (signature bvec3\n"
+ " (parameters\n"
+ " (declare (in ) ivec3 x@0xa06080)\n"
+ " (declare (in ) ivec3 y@0xa06190)\n"
+ " )\n"
+ " (\n"
+ " ))\n"
+ "\n"
+ " (signature bvec4\n"
+ " (parameters\n"
+ " (declare (in ) ivec4 x@0xa06370)\n"
+ " (declare (in ) ivec4 y@0xa06480)\n"
+ " )\n"
+ " (\n"
+ " ))\n"
+ "\n"
+ ")\n"
+ "\n"
+ "(function greaterThanEqual\n"
+ " (signature bvec2\n"
+ " (parameters\n"
+ " (declare (in ) vec2 x@0xa06660)\n"
+ " (declare (in ) vec2 y@0xa06770)\n"
+ " )\n"
+ " (\n"
+ " ))\n"
+ "\n"
+ " (signature bvec3\n"
+ " (parameters\n"
+ " (declare (in ) vec3 x@0xa06b30)\n"
+ " (declare (in ) vec3 y@0xa06c40)\n"
+ " )\n"
+ " (\n"
+ " ))\n"
+ "\n"
+ " (signature bvec4\n"
+ " (parameters\n"
+ " (declare (in ) vec4 x@0xa06e20)\n"
+ " (declare (in ) vec4 y@0xa06f30)\n"
+ " )\n"
+ " (\n"
+ " ))\n"
+ "\n"
+ " (signature bvec2\n"
+ " (parameters\n"
+ " (declare (in ) ivec2 x@0xa07110)\n"
+ " (declare (in ) ivec2 y@0xa07220)\n"
+ " )\n"
+ " (\n"
+ " ))\n"
+ "\n"
+ " (signature bvec3\n"
+ " (parameters\n"
+ " (declare (in ) ivec3 x@0xa07400)\n"
+ " (declare (in ) ivec3 y@0xa07510)\n"
+ " )\n"
+ " (\n"
+ " ))\n"
+ "\n"
+ " (signature bvec4\n"
+ " (parameters\n"
+ " (declare (in ) ivec4 x@0xa076f0)\n"
+ " (declare (in ) ivec4 y@0xa07800)\n"
+ " )\n"
+ " (\n"
+ " ))\n"
+ "\n"
+ ")\n"
+ "\n"
+ "(function equal\n"
+ " (signature bvec2\n"
+ " (parameters\n"
+ " (declare (in ) vec2 x@0xa079e0)\n"
+ " (declare (in ) vec2 y@0xa07af0)\n"
+ " )\n"
+ " (\n"
+ " ))\n"
+ "\n"
+ " (signature bvec3\n"
+ " (parameters\n"
+ " (declare (in ) vec3 x@0xa07ea0)\n"
+ " (declare (in ) vec3 y@0xa07fb0)\n"
+ " )\n"
+ " (\n"
+ " ))\n"
+ "\n"
+ " (signature bvec4\n"
+ " (parameters\n"
+ " (declare (in ) vec4 x@0xa08190)\n"
+ " (declare (in ) vec4 y@0xa082a0)\n"
+ " )\n"
+ " (\n"
+ " ))\n"
+ "\n"
+ " (signature bvec2\n"
+ " (parameters\n"
+ " (declare (in ) ivec2 x@0xa08480)\n"
+ " (declare (in ) ivec2 y@0xa08590)\n"
+ " )\n"
+ " (\n"
+ " ))\n"
+ "\n"
+ " (signature bvec3\n"
+ " (parameters\n"
+ " (declare (in ) ivec3 x@0xa08770)\n"
+ " (declare (in ) ivec3 y@0xa08880)\n"
+ " )\n"
+ " (\n"
+ " ))\n"
+ "\n"
+ " (signature bvec4\n"
+ " (parameters\n"
+ " (declare (in ) ivec4 x@0xa08a60)\n"
+ " (declare (in ) ivec4 y@0xa08b70)\n"
+ " )\n"
+ " (\n"
+ " ))\n"
+ "\n"
+ " (signature bvec2\n"
+ " (parameters\n"
+ " (declare (in ) bvec2 x@0xa08d50)\n"
+ " (declare (in ) bvec2 y@0xa08e60)\n"
+ " )\n"
+ " (\n"
+ " ))\n"
+ "\n"
+ " (signature bvec3\n"
+ " (parameters\n"
+ " (declare (in ) bvec3 x@0xa09040)\n"
+ " (declare (in ) bvec3 y@0xa09150)\n"
+ " )\n"
+ " (\n"
+ " ))\n"
+ "\n"
+ " (signature bvec4\n"
+ " (parameters\n"
+ " (declare (in ) bvec4 x@0xa09330)\n"
+ " (declare (in ) bvec4 y@0xa09440)\n"
+ " )\n"
+ " (\n"
+ " ))\n"
+ "\n"
+ ")\n"
+ "\n"
+ "(function notEqual\n"
+ " (signature bvec2\n"
+ " (parameters\n"
+ " (declare (in ) vec2 x@0xa09620)\n"
+ " (declare (in ) vec2 y@0xa09730)\n"
+ " )\n"
+ " (\n"
+ " ))\n"
+ "\n"
+ " (signature bvec3\n"
+ " (parameters\n"
+ " (declare (in ) vec3 x@0xa09af0)\n"
+ " (declare (in ) vec3 y@0xa09c00)\n"
+ " )\n"
+ " (\n"
+ " ))\n"
+ "\n"
+ " (signature bvec4\n"
+ " (parameters\n"
+ " (declare (in ) vec4 x@0xa09de0)\n"
+ " (declare (in ) vec4 y@0xa09ef0)\n"
+ " )\n"
+ " (\n"
+ " ))\n"
+ "\n"
+ " (signature bvec2\n"
+ " (parameters\n"
+ " (declare (in ) ivec2 x@0xa0a0d0)\n"
+ " (declare (in ) ivec2 y@0xa0a1e0)\n"
+ " )\n"
+ " (\n"
+ " ))\n"
+ "\n"
+ " (signature bvec3\n"
+ " (parameters\n"
+ " (declare (in ) ivec3 x@0xa0a3c0)\n"
+ " (declare (in ) ivec3 y@0xa0a4d0)\n"
+ " )\n"
+ " (\n"
+ " ))\n"
+ "\n"
+ " (signature bvec4\n"
+ " (parameters\n"
+ " (declare (in ) ivec4 x@0xa0a6b0)\n"
+ " (declare (in ) ivec4 y@0xa0a7c0)\n"
+ " )\n"
+ " (\n"
+ " ))\n"
+ "\n"
+ " (signature bvec2\n"
+ " (parameters\n"
+ " (declare (in ) bvec2 x@0xa0a9a0)\n"
+ " (declare (in ) bvec2 y@0xa0aab0)\n"
+ " )\n"
+ " (\n"
+ " ))\n"
+ "\n"
+ " (signature bvec3\n"
+ " (parameters\n"
+ " (declare (in ) bvec3 x@0xa0ac90)\n"
+ " (declare (in ) bvec3 y@0xa0ada0)\n"
+ " )\n"
+ " (\n"
+ " ))\n"
+ "\n"
+ " (signature bvec4\n"
+ " (parameters\n"
+ " (declare (in ) bvec4 x@0xa0af80)\n"
+ " (declare (in ) bvec4 y@0xa0b090)\n"
+ " )\n"
+ " (\n"
+ " ))\n"
+ "\n"
+ ")\n"
+ "\n"
+ "(function any\n"
+ " (signature bool\n"
+ " (parameters\n"
+ " (declare (in ) bvec2 x@0xa0b270)\n"
+ " )\n"
+ " (\n"
+ " ))\n"
+ "\n"
+ " (signature bool\n"
+ " (parameters\n"
+ " (declare (in ) bvec3 x@0xa0b620)\n"
+ " )\n"
+ " (\n"
+ " ))\n"
+ "\n"
+ " (signature bool\n"
+ " (parameters\n"
+ " (declare (in ) bvec4 x@0xa0b800)\n"
+ " )\n"
+ " (\n"
+ " ))\n"
+ "\n"
+ ")\n"
+ "\n"
+ "(function all\n"
+ " (signature bool\n"
+ " (parameters\n"
+ " (declare (in ) bvec2 x@0xa0b9e0)\n"
+ " )\n"
+ " (\n"
+ " ))\n"
+ "\n"
+ " (signature bool\n"
+ " (parameters\n"
+ " (declare (in ) bvec3 x@0xa0bd90)\n"
+ " )\n"
+ " (\n"
+ " ))\n"
+ "\n"
+ " (signature bool\n"
+ " (parameters\n"
+ " (declare (in ) bvec4 x@0xa0bf70)\n"
+ " )\n"
+ " (\n"
+ " ))\n"
+ "\n"
+ ")\n"
+ "\n"
+ "(function not\n"
+ " (signature bvec2\n"
+ " (parameters\n"
+ " (declare (in ) bvec2 x@0xa0c150)\n"
+ " )\n"
+ " (\n"
+ " ))\n"
+ "\n"
+ " (signature bvec3\n"
+ " (parameters\n"
+ " (declare (in ) bvec3 x@0xa0c500)\n"
+ " )\n"
+ " (\n"
+ " ))\n"
+ "\n"
+ " (signature bvec4\n"
+ " (parameters\n"
+ " (declare (in ) bvec4 x@0xa0c6e0)\n"
+ " )\n"
+ " (\n"
+ " ))\n"
+ "\n"
+ ")\n"
+ "\n"
+ "(function texture1D\n"
+ " (signature vec4\n"
+ " (parameters\n"
+ " (declare (in ) sampler1D sampler@0xa0c8c0)\n"
+ " (declare (in ) float coord@0xa0c9e0)\n"
+ " )\n"
+ " (\n"
+ " ))\n"
+ "\n"
+ ")\n"
+ "\n"
+ "(function texture1DProj\n"
+ " (signature vec4\n"
+ " (parameters\n"
+ " (declare (in ) sampler1D sampler@0xa0cda0)\n"
+ " (declare (in ) vec2 coord@0xa0cec0)\n"
+ " )\n"
+ " (\n"
+ " ))\n"
+ "\n"
+ " (signature vec4\n"
+ " (parameters\n"
+ " (declare (in ) sampler1D sampler@0xa0d280)\n"
+ " (declare (in ) vec4 coord@0xa0d3a0)\n"
+ " )\n"
+ " (\n"
+ " ))\n"
+ "\n"
+ ")\n"
+ "\n"
+ "(function texture1DLod\n"
+ " (signature vec4\n"
+ " (parameters\n"
+ " (declare (in ) sampler1D sampler@0xa0d580)\n"
+ " (declare (in ) float coord@0xa0d6a0)\n"
+ " (declare (in ) float lod@0xa0d7b0)\n"
+ " )\n"
+ " (\n"
+ " ))\n"
+ "\n"
+ ")\n"
+ "\n"
+ "(function texture1DProjLod\n"
+ " (signature vec4\n"
+ " (parameters\n"
+ " (declare (in ) sampler1D sampler@0xa0db70)\n"
+ " (declare (in ) vec2 coord@0xa0dc90)\n"
+ " (declare (in ) float lod@0xa0dda0)\n"
+ " )\n"
+ " (\n"
+ " ))\n"
+ "\n"
+ " (signature vec4\n"
+ " (parameters\n"
+ " (declare (in ) sampler1D sampler@0xa0e160)\n"
+ " (declare (in ) vec4 coord@0xa0e280)\n"
+ " (declare (in ) float lod@0xa0e390)\n"
+ " )\n"
+ " (\n"
+ " ))\n"
+ "\n"
+ ")\n"
+ "\n"
+ "(function texture2D\n"
+ " (signature vec4\n"
+ " (parameters\n"
+ " (declare (in ) sampler2D sampler@0xa0e570)\n"
+ " (declare (in ) vec2 coord@0xa0e690)\n"
+ " )\n"
+ " (\n"
+ " ))\n"
+ "\n"
+ ")\n"
+ "\n"
+ "(function texture2DProj\n"
+ " (signature vec4\n"
+ " (parameters\n"
+ " (declare (in ) sampler2D sampler@0xa0ea50)\n"
+ " (declare (in ) vec3 coord@0xa0eb70)\n"
+ " )\n"
+ " (\n"
+ " ))\n"
+ "\n"
+ " (signature vec4\n"
+ " (parameters\n"
+ " (declare (in ) sampler2D sampler@0xa0ef30)\n"
+ " (declare (in ) vec4 coord@0xa0f050)\n"
+ " )\n"
+ " (\n"
+ " ))\n"
+ "\n"
+ ")\n"
+ "\n"
+ "(function texture2DLod\n"
+ " (signature vec4\n"
+ " (parameters\n"
+ " (declare (in ) sampler2D sampler@0xa0f230)\n"
+ " (declare (in ) vec2 coord@0xa0f350)\n"
+ " (declare (in ) float lod@0xa0f460)\n"
+ " )\n"
+ " (\n"
+ " ))\n"
+ "\n"
+ ")\n"
+ "\n"
+ "(function texture2DProjLod\n"
+ " (signature vec4\n"
+ " (parameters\n"
+ " (declare (in ) sampler2D sampler@0xa0f820)\n"
+ " (declare (in ) vec3 coord@0xa0f940)\n"
+ " (declare (in ) float lod@0xa0fa50)\n"
+ " )\n"
+ " (\n"
+ " ))\n"
+ "\n"
+ " (signature vec4\n"
+ " (parameters\n"
+ " (declare (in ) sampler2D sampler@0xa0fe10)\n"
+ " (declare (in ) vec4 coord@0xa0ff30)\n"
+ " (declare (in ) float lod@0xa10040)\n"
+ " )\n"
+ " (\n"
+ " ))\n"
+ "\n"
+ ")\n"
+ "\n"
+ "(function texture3D\n"
+ " (signature vec4\n"
+ " (parameters\n"
+ " (declare (in ) sampler3D sampler@0xa10220)\n"
+ " (declare (in ) vec3 coord@0xa10340)\n"
+ " )\n"
+ " (\n"
+ " ))\n"
+ "\n"
+ ")\n"
+ "\n"
+ "(function texture3DProj\n"
+ " (signature vec4\n"
+ " (parameters\n"
+ " (declare (in ) sampler3D sampler@0xa10700)\n"
+ " (declare (in ) vec4 coord@0xa10820)\n"
+ " )\n"
+ " (\n"
+ " ))\n"
+ "\n"
+ ")\n"
+ "\n"
+ "(function texture3DLod\n"
+ " (signature vec4\n"
+ " (parameters\n"
+ " (declare (in ) sampler3D sampler@0xa10be0)\n"
+ " (declare (in ) vec3 coord@0xa10d00)\n"
+ " (declare (in ) float lod@0xa10e10)\n"
+ " )\n"
+ " (\n"
+ " ))\n"
+ "\n"
+ ")\n"
+ "\n"
+ "(function texture3DProjLod\n"
+ " (signature vec4\n"
+ " (parameters\n"
+ " (declare (in ) sampler3D sampler@0xa111d0)\n"
+ " (declare (in ) vec4 coord@0xa112f0)\n"
+ " (declare (in ) float lod@0xa11400)\n"
+ " )\n"
+ " (\n"
+ " ))\n"
+ "\n"
+ ")\n"
+ "\n"
+ "(function textureCube\n"
+ " (signature vec4\n"
+ " (parameters\n"
+ " (declare (in ) samplerCube sampler@0xa117c0)\n"
+ " (declare (in ) vec3 coord@0xa118e0)\n"
+ " )\n"
+ " (\n"
+ " ))\n"
+ "\n"
+ ")\n"
+ "\n"
+ "(function textureCubeLod\n"
+ " (signature vec4\n"
+ " (parameters\n"
+ " (declare (in ) samplerCube sampler@0xa11ca0)\n"
+ " (declare (in ) vec3 coord@0xa11dc0)\n"
+ " (declare (in ) float lod@0xa11ed0)\n"
+ " )\n"
+ " (\n"
+ " ))\n"
+ "\n"
+ ")\n"
+ "\n"
+ "(function shadow1D\n"
+ " (signature vec4\n"
+ " (parameters\n"
+ " (declare (in ) sampler1DShadow sampler@0xa12290)\n"
+ " (declare (in ) vec3 coord@0xa123b0)\n"
+ " )\n"
+ " (\n"
+ " ))\n"
+ "\n"
+ ")\n"
+ "\n"
+ "(function shadow2D\n"
+ " (signature vec4\n"
+ " (parameters\n"
+ " (declare (in ) sampler2DShadow sampler@0xa12770)\n"
+ " (declare (in ) vec3 coord@0xa12890)\n"
+ " )\n"
+ " (\n"
+ " ))\n"
+ "\n"
+ ")\n"
+ "\n"
+ "(function shadow1DProj\n"
+ " (signature vec4\n"
+ " (parameters\n"
+ " (declare (in ) sampler1DShadow sampler@0xa12c50)\n"
+ " (declare (in ) vec4 coord@0xa12d70)\n"
+ " )\n"
+ " (\n"
+ " ))\n"
+ "\n"
+ ")\n"
+ "\n"
+ "(function shadow2DProj\n"
+ " (signature vec4\n"
+ " (parameters\n"
+ " (declare (in ) sampler2DShadow sampler@0xa13130)\n"
+ " (declare (in ) vec4 coord@0xa13250)\n"
+ " )\n"
+ " (\n"
+ " ))\n"
+ "\n"
+ ")\n"
+ "\n"
+ "(function shadow1DLod\n"
+ " (signature vec4\n"
+ " (parameters\n"
+ " (declare (in ) sampler1DShadow sampler@0xa13610)\n"
+ " (declare (in ) vec3 coord@0xa13730)\n"
+ " (declare (in ) float lod@0xa13840)\n"
+ " )\n"
+ " (\n"
+ " ))\n"
+ "\n"
+ ")\n"
+ "\n"
+ "(function shadow2DLod\n"
+ " (signature vec4\n"
+ " (parameters\n"
+ " (declare (in ) sampler2DShadow sampler@0xa13c00)\n"
+ " (declare (in ) vec3 coord@0xa13d20)\n"
+ " (declare (in ) float lod@0xa13e30)\n"
+ " )\n"
+ " (\n"
+ " ))\n"
+ "\n"
+ ")\n"
+ "\n"
+ "(function shadow1DProjLod\n"
+ " (signature vec4\n"
+ " (parameters\n"
+ " (declare (in ) sampler1DShadow sampler@0xa141f0)\n"
+ " (declare (in ) vec4 coord@0xa14310)\n"
+ " (declare (in ) float lod@0xa14420)\n"
+ " )\n"
+ " (\n"
+ " ))\n"
+ "\n"
+ ")\n"
+ "\n"
+ "(function shadow2DProjLod\n"
+ " (signature vec4\n"
+ " (parameters\n"
+ " (declare (in ) sampler2DShadow sampler@0xa147e0)\n"
+ " (declare (in ) vec4 coord@0xa14900)\n"
+ " (declare (in ) float lod@0xa14a10)\n"
+ " )\n"
+ " (\n"
+ " ))\n"
+ "\n"
+ ")\n"
+ "\n"
+ "(function noise1\n"
+ " (signature float\n"
+ " (parameters\n"
+ " (declare (in ) float x@0xa14dd0)\n"
+ " )\n"
+ " (\n"
+ " ))\n"
+ "\n"
+ " (signature float\n"
+ " (parameters\n"
+ " (declare (in ) vec2 x@0xa15180)\n"
+ " )\n"
+ " (\n"
+ " ))\n"
+ "\n"
+ " (signature float\n"
+ " (parameters\n"
+ " (declare (in ) vec3 x@0xa15360)\n"
+ " )\n"
+ " (\n"
+ " ))\n"
+ "\n"
+ " (signature float\n"
+ " (parameters\n"
+ " (declare (in ) vec4 x@0xa15540)\n"
+ " )\n"
+ " (\n"
+ " ))\n"
+ "\n"
+ ")\n"
+ "\n"
+ "(function noise2\n"
+ " (signature vec2\n"
+ " (parameters\n"
+ " (declare (in ) float x@0xa15720)\n"
+ " )\n"
+ " (\n"
+ " ))\n"
+ "\n"
+ " (signature vec2\n"
+ " (parameters\n"
+ " (declare (in ) vec2 x@0xa15ad0)\n"
+ " )\n"
+ " (\n"
+ " ))\n"
+ "\n"
+ " (signature vec2\n"
+ " (parameters\n"
+ " (declare (in ) vec3 x@0xa15cb0)\n"
+ " )\n"
+ " (\n"
+ " ))\n"
+ "\n"
+ " (signature vec2\n"
+ " (parameters\n"
+ " (declare (in ) vec4 x@0xa15e90)\n"
+ " )\n"
+ " (\n"
+ " ))\n"
+ "\n"
+ ")\n"
+ "\n"
+ "(function noise3\n"
+ " (signature vec3\n"
+ " (parameters\n"
+ " (declare (in ) float x@0xa16070)\n"
+ " )\n"
+ " (\n"
+ " ))\n"
+ "\n"
+ " (signature vec3\n"
+ " (parameters\n"
+ " (declare (in ) vec2 x@0xa16420)\n"
+ " )\n"
+ " (\n"
+ " ))\n"
+ "\n"
+ " (signature vec3\n"
+ " (parameters\n"
+ " (declare (in ) vec3 x@0xa16600)\n"
+ " )\n"
+ " (\n"
+ " ))\n"
+ "\n"
+ " (signature vec3\n"
+ " (parameters\n"
+ " (declare (in ) vec4 x@0xa167e0)\n"
+ " )\n"
+ " (\n"
+ " ))\n"
+ "\n"
+ ")\n"
+ "\n"
+ "(function noise4\n"
+ " (signature vec4\n"
+ " (parameters\n"
+ " (declare (in ) float x@0xa169c0)\n"
+ " )\n"
+ " (\n"
+ " ))\n"
+ "\n"
+ " (signature vec4\n"
+ " (parameters\n"
+ " (declare (in ) vec2 x@0xa16d70)\n"
+ " )\n"
+ " (\n"
+ " ))\n"
+ "\n"
+ " (signature vec4\n"
+ " (parameters\n"
+ " (declare (in ) vec3 x@0xa16f50)\n"
+ " )\n"
+ " (\n"
+ " ))\n"
+ "\n"
+ " (signature vec4\n"
+ " (parameters\n"
+ " (declare (in ) vec4 x@0xa17130)\n"
+ " )\n"
+ " (\n"
+ " ))\n"
+ "\n"
+ ")\n"
+ "\n"
+ "\n"
+ ")"
+;
+static const char *functions_for_110_vert [] = {
+ builtin_clamp,
+ builtin_matrixCompMult,
+ builtin_shadow2DProjLod,
+ builtin_noise2,
+ builtin_texture3DProjLod,
+ builtin_pow,
+ builtin_texture2DProj,
+ builtin_greaterThanEqual,
+ builtin_sign,
+ builtin_texture3DProj,
+ builtin_texture2D,
+ builtin_equal,
+ builtin_faceforward,
+ builtin_tan,
+ builtin_shadow2DProj,
+ builtin_shadow1DProjLod,
+ builtin_any,
+ builtin_normalize,
+ builtin_asin,
+ builtin_texture1DProj,
+ builtin_log,
+ builtin_floor,
+ builtin_exp2,
+ builtin_lessThan,
+ builtin_cross,
+ builtin_sqrt,
+ builtin_texture3DLod,
+ builtin_fract,
+ builtin_abs,
+ builtin_degrees,
+ builtin_shadow1DLod,
+ builtin_ftransform,
+ builtin_sin,
+ builtin_shadow2D,
+ builtin_shadow2DLod,
+ builtin_all,
+ builtin_log2,
+ builtin_atan,
+ builtin_notEqual,
+ builtin_max,
+ builtin_lessThanEqual,
+ builtin_shadow1DProj,
+ builtin_ceil,
+ builtin_reflect,
+ builtin_textureCubeLod,
+ builtin_step,
+ builtin_texture1D,
+ builtin_greaterThan,
+ builtin_texture3D,
+ builtin_not,
+ builtin_texture2DProjLod,
+ builtin_inversesqrt,
+ builtin_mod,
+ builtin_noise4,
+ builtin_distance,
+ builtin_cos,
+ builtin_shadow1D,
+ builtin_noise1,
+ builtin_refract,
+ builtin_noise3,
+ builtin_texture2DLod,
+ builtin_min,
+ builtin_radians,
+ builtin_smoothstep,
+ builtin_texture1DProjLod,
+ builtin_textureCube,
+ builtin_length,
+ builtin_texture1DLod,
+ builtin_exp,
+ builtin_acos,
+ builtin_mix,
+ builtin_dot,
+};
+static const char *prototypes_for_110_frag =
+ "(\n"
+ "(function radians\n"
+ " (signature float\n"
+ " (parameters\n"
+ " (declare (in ) float degrees@0x151ee40)\n"
+ " )\n"
+ " (\n"
+ " ))\n"
+ "\n"
+ " (signature vec2\n"
+ " (parameters\n"
+ " (declare (in ) vec2 degrees@0x151f210)\n"
+ " )\n"
+ " (\n"
+ " ))\n"
+ "\n"
+ " (signature vec3\n"
+ " (parameters\n"
+ " (declare (in ) vec3 degrees@0x151f400)\n"
+ " )\n"
+ " (\n"
+ " ))\n"
+ "\n"
+ " (signature vec4\n"
+ " (parameters\n"
+ " (declare (in ) vec4 degrees@0x151f5f0)\n"
+ " )\n"
+ " (\n"
+ " ))\n"
+ "\n"
+ ")\n"
+ "\n"
+ "(function degrees\n"
+ " (signature float\n"
+ " (parameters\n"
+ " (declare (in ) float radians@0x151f7e0)\n"
+ " )\n"
+ " (\n"
+ " ))\n"
+ "\n"
+ " (signature vec2\n"
+ " (parameters\n"
+ " (declare (in ) vec2 radians@0x151fbb0)\n"
+ " )\n"
+ " (\n"
+ " ))\n"
+ "\n"
+ " (signature vec3\n"
+ " (parameters\n"
+ " (declare (in ) vec3 radians@0x151fda0)\n"
+ " )\n"
+ " (\n"
+ " ))\n"
+ "\n"
+ " (signature vec4\n"
+ " (parameters\n"
+ " (declare (in ) vec4 radians@0x151ff90)\n"
+ " )\n"
+ " (\n"
+ " ))\n"
+ "\n"
+ ")\n"
+ "\n"
+ "(function sin\n"
+ " (signature float\n"
+ " (parameters\n"
+ " (declare (in ) float angle@0x1520180)\n"
+ " )\n"
+ " (\n"
+ " ))\n"
+ "\n"
+ " (signature vec2\n"
+ " (parameters\n"
+ " (declare (in ) vec2 angle@0x1520530)\n"
+ " )\n"
+ " (\n"
+ " ))\n"
+ "\n"
+ " (signature vec3\n"
+ " (parameters\n"
+ " (declare (in ) vec3 angle@0x1520710)\n"
+ " )\n"
+ " (\n"
+ " ))\n"
+ "\n"
+ " (signature vec4\n"
+ " (parameters\n"
+ " (declare (in ) vec4 angle@0x15208f0)\n"
+ " )\n"
+ " (\n"
+ " ))\n"
+ "\n"
+ ")\n"
+ "\n"
+ "(function cos\n"
+ " (signature float\n"
+ " (parameters\n"
+ " (declare (in ) float angle@0x1520ad0)\n"
+ " )\n"
+ " (\n"
+ " ))\n"
+ "\n"
+ " (signature vec2\n"
+ " (parameters\n"
+ " (declare (in ) vec2 angle@0x1520e80)\n"
+ " )\n"
+ " (\n"
+ " ))\n"
+ "\n"
+ " (signature vec3\n"
+ " (parameters\n"
+ " (declare (in ) vec3 angle@0x1521060)\n"
+ " )\n"
+ " (\n"
+ " ))\n"
+ "\n"
+ " (signature vec4\n"
+ " (parameters\n"
+ " (declare (in ) vec4 angle@0x1521240)\n"
+ " )\n"
+ " (\n"
+ " ))\n"
+ "\n"
+ ")\n"
+ "\n"
+ "(function tan\n"
+ " (signature float\n"
+ " (parameters\n"
+ " (declare (in ) float angle@0x1521420)\n"
+ " )\n"
+ " (\n"
+ " ))\n"
+ "\n"
+ " (signature vec2\n"
+ " (parameters\n"
+ " (declare (in ) vec2 angle@0x15217d0)\n"
+ " )\n"
+ " (\n"
+ " ))\n"
+ "\n"
+ " (signature vec3\n"
+ " (parameters\n"
+ " (declare (in ) vec3 angle@0x15219b0)\n"
+ " )\n"
+ " (\n"
+ " ))\n"
+ "\n"
+ " (signature vec4\n"
+ " (parameters\n"
+ " (declare (in ) vec4 angle@0x1521b90)\n"
+ " )\n"
+ " (\n"
+ " ))\n"
+ "\n"
+ ")\n"
+ "\n"
+ "(function asin\n"
+ " (signature float\n"
+ " (parameters\n"
+ " (declare (in ) float angle@0x1521d70)\n"
+ " )\n"
+ " (\n"
+ " ))\n"
+ "\n"
+ " (signature vec2\n"
+ " (parameters\n"
+ " (declare (in ) vec2 angle@0x1522120)\n"
+ " )\n"
+ " (\n"
+ " ))\n"
+ "\n"
+ " (signature vec3\n"
+ " (parameters\n"
+ " (declare (in ) vec3 angle@0x1522300)\n"
+ " )\n"
+ " (\n"
+ " ))\n"
+ "\n"
+ " (signature vec4\n"
+ " (parameters\n"
+ " (declare (in ) vec4 angle@0x15224e0)\n"
+ " )\n"
+ " (\n"
+ " ))\n"
+ "\n"
+ ")\n"
+ "\n"
+ "(function acos\n"
+ " (signature float\n"
+ " (parameters\n"
+ " (declare (in ) float angle@0x15226c0)\n"
+ " )\n"
+ " (\n"
+ " ))\n"
+ "\n"
+ " (signature vec2\n"
+ " (parameters\n"
+ " (declare (in ) vec2 angle@0x1522a70)\n"
+ " )\n"
+ " (\n"
+ " ))\n"
+ "\n"
+ " (signature vec3\n"
+ " (parameters\n"
+ " (declare (in ) vec3 angle@0x1522c50)\n"
+ " )\n"
+ " (\n"
+ " ))\n"
+ "\n"
+ " (signature vec4\n"
+ " (parameters\n"
+ " (declare (in ) vec4 angle@0x1522e30)\n"
+ " )\n"
+ " (\n"
+ " ))\n"
+ "\n"
+ ")\n"
+ "\n"
+ "(function atan\n"
+ " (signature float\n"
+ " (parameters\n"
+ " (declare (in ) float y@0x1523010)\n"
+ " (declare (in ) float x@0x1523120)\n"
+ " )\n"
+ " (\n"
+ " ))\n"
+ "\n"
+ " (signature vec2\n"
+ " (parameters\n"
+ " (declare (in ) vec2 y@0x15234d0)\n"
+ " (declare (in ) vec2 x@0x15235e0)\n"
+ " )\n"
+ " (\n"
+ " ))\n"
+ "\n"
+ " (signature vec3\n"
+ " (parameters\n"
+ " (declare (in ) vec3 y@0x15237c0)\n"
+ " (declare (in ) vec3 x@0x15238d0)\n"
+ " )\n"
+ " (\n"
+ " ))\n"
+ "\n"
+ " (signature vec4\n"
+ " (parameters\n"
+ " (declare (in ) vec4 y@0x1523ab0)\n"
+ " (declare (in ) vec4 x@0x1523bc0)\n"
+ " )\n"
+ " (\n"
+ " ))\n"
+ "\n"
+ " (signature float\n"
+ " (parameters\n"
+ " (declare (in ) float y_over_x@0x1523da0)\n"
+ " )\n"
+ " (\n"
+ " ))\n"
+ "\n"
+ " (signature vec2\n"
+ " (parameters\n"
+ " (declare (in ) vec2 y_over_x@0x1523f90)\n"
+ " )\n"
+ " (\n"
+ " ))\n"
+ "\n"
+ " (signature vec3\n"
+ " (parameters\n"
+ " (declare (in ) vec3 y_over_x@0x1524180)\n"
+ " )\n"
+ " (\n"
+ " ))\n"
+ "\n"
+ " (signature vec4\n"
+ " (parameters\n"
+ " (declare (in ) vec4 y_over_x@0x1524370)\n"
+ " )\n"
+ " (\n"
+ " ))\n"
+ "\n"
+ ")\n"
+ "\n"
+ "(function pow\n"
+ " (signature float\n"
+ " (parameters\n"
+ " (declare (in ) float x@0x1524560)\n"
+ " (declare (in ) float y@0x1524670)\n"
+ " )\n"
+ " (\n"
+ " ))\n"
+ "\n"
+ " (signature vec2\n"
+ " (parameters\n"
+ " (declare (in ) vec2 x@0x1524a20)\n"
+ " (declare (in ) vec2 y@0x1524b30)\n"
+ " )\n"
+ " (\n"
+ " ))\n"
+ "\n"
+ " (signature vec3\n"
+ " (parameters\n"
+ " (declare (in ) vec3 x@0x1524d10)\n"
+ " (declare (in ) vec3 y@0x1524e20)\n"
+ " )\n"
+ " (\n"
+ " ))\n"
+ "\n"
+ " (signature vec4\n"
+ " (parameters\n"
+ " (declare (in ) vec4 x@0x1525000)\n"
+ " (declare (in ) vec4 y@0x1525110)\n"
+ " )\n"
+ " (\n"
+ " ))\n"
+ "\n"
+ ")\n"
+ "\n"
+ "(function exp\n"
+ " (signature float\n"
+ " (parameters\n"
+ " (declare (in ) float x@0x15252f0)\n"
+ " )\n"
+ " (\n"
+ " ))\n"
+ "\n"
+ " (signature vec2\n"
+ " (parameters\n"
+ " (declare (in ) vec2 x@0x15256a0)\n"
+ " )\n"
+ " (\n"
+ " ))\n"
+ "\n"
+ " (signature vec3\n"
+ " (parameters\n"
+ " (declare (in ) vec3 x@0x1525880)\n"
+ " )\n"
+ " (\n"
+ " ))\n"
+ "\n"
+ " (signature vec4\n"
+ " (parameters\n"
+ " (declare (in ) vec4 x@0x1525a60)\n"
+ " )\n"
+ " (\n"
+ " ))\n"
+ "\n"
+ ")\n"
+ "\n"
+ "(function log\n"
+ " (signature float\n"
+ " (parameters\n"
+ " (declare (in ) float x@0x1525c40)\n"
+ " )\n"
+ " (\n"
+ " ))\n"
+ "\n"
+ " (signature vec2\n"
+ " (parameters\n"
+ " (declare (in ) vec2 x@0x1525ff0)\n"
+ " )\n"
+ " (\n"
+ " ))\n"
+ "\n"
+ " (signature vec3\n"
+ " (parameters\n"
+ " (declare (in ) vec3 x@0x15261d0)\n"
+ " )\n"
+ " (\n"
+ " ))\n"
+ "\n"
+ " (signature vec4\n"
+ " (parameters\n"
+ " (declare (in ) vec4 x@0x15263b0)\n"
+ " )\n"
+ " (\n"
+ " ))\n"
+ "\n"
+ ")\n"
+ "\n"
+ "(function exp2\n"
+ " (signature float\n"
+ " (parameters\n"
+ " (declare (in ) float x@0x1526590)\n"
+ " )\n"
+ " (\n"
+ " ))\n"
+ "\n"
+ " (signature vec2\n"
+ " (parameters\n"
+ " (declare (in ) vec2 x@0x1526940)\n"
+ " )\n"
+ " (\n"
+ " ))\n"
+ "\n"
+ " (signature vec3\n"
+ " (parameters\n"
+ " (declare (in ) vec3 x@0x1526b20)\n"
+ " )\n"
+ " (\n"
+ " ))\n"
+ "\n"
+ " (signature vec4\n"
+ " (parameters\n"
+ " (declare (in ) vec4 x@0x1526d00)\n"
+ " )\n"
+ " (\n"
+ " ))\n"
+ "\n"
+ ")\n"
+ "\n"
+ "(function log2\n"
+ " (signature float\n"
+ " (parameters\n"
+ " (declare (in ) float x@0x1526ee0)\n"
+ " )\n"
+ " (\n"
+ " ))\n"
+ "\n"
+ " (signature vec2\n"
+ " (parameters\n"
+ " (declare (in ) vec2 x@0x1527290)\n"
+ " )\n"
+ " (\n"
+ " ))\n"
+ "\n"
+ " (signature vec3\n"
+ " (parameters\n"
+ " (declare (in ) vec3 x@0x1527470)\n"
+ " )\n"
+ " (\n"
+ " ))\n"
+ "\n"
+ " (signature vec4\n"
+ " (parameters\n"
+ " (declare (in ) vec4 x@0x1527650)\n"
+ " )\n"
+ " (\n"
+ " ))\n"
+ "\n"
+ ")\n"
+ "\n"
+ "(function sqrt\n"
+ " (signature float\n"
+ " (parameters\n"
+ " (declare (in ) float x@0x1527830)\n"
+ " )\n"
+ " (\n"
+ " ))\n"
+ "\n"
+ " (signature vec2\n"
+ " (parameters\n"
+ " (declare (in ) vec2 x@0x1527be0)\n"
+ " )\n"
+ " (\n"
+ " ))\n"
+ "\n"
+ " (signature vec3\n"
+ " (parameters\n"
+ " (declare (in ) vec3 x@0x1527dc0)\n"
+ " )\n"
+ " (\n"
+ " ))\n"
+ "\n"
+ " (signature vec4\n"
+ " (parameters\n"
+ " (declare (in ) vec4 x@0x1527fa0)\n"
+ " )\n"
+ " (\n"
+ " ))\n"
+ "\n"
+ ")\n"
+ "\n"
+ "(function inversesqrt\n"
+ " (signature float\n"
+ " (parameters\n"
+ " (declare (in ) float x@0x1528180)\n"
+ " )\n"
+ " (\n"
+ " ))\n"
+ "\n"
+ " (signature vec2\n"
+ " (parameters\n"
+ " (declare (in ) vec2 x@0x1528540)\n"
+ " )\n"
+ " (\n"
+ " ))\n"
+ "\n"
+ " (signature vec3\n"
+ " (parameters\n"
+ " (declare (in ) vec3 x@0x1528720)\n"
+ " )\n"
+ " (\n"
+ " ))\n"
+ "\n"
+ " (signature vec4\n"
+ " (parameters\n"
+ " (declare (in ) vec4 x@0x1528900)\n"
+ " )\n"
+ " (\n"
+ " ))\n"
+ "\n"
+ ")\n"
+ "\n"
+ "(function abs\n"
+ " (signature float\n"
+ " (parameters\n"
+ " (declare (in ) float x@0x1528ae0)\n"
+ " )\n"
+ " (\n"
+ " ))\n"
+ "\n"
+ " (signature vec2\n"
+ " (parameters\n"
+ " (declare (in ) vec2 x@0x1528e90)\n"
+ " )\n"
+ " (\n"
+ " ))\n"
+ "\n"
+ " (signature vec3\n"
+ " (parameters\n"
+ " (declare (in ) vec3 x@0x1529070)\n"
+ " )\n"
+ " (\n"
+ " ))\n"
+ "\n"
+ " (signature vec4\n"
+ " (parameters\n"
+ " (declare (in ) vec4 x@0x1529250)\n"
+ " )\n"
+ " (\n"
+ " ))\n"
+ "\n"
+ ")\n"
+ "\n"
+ "(function sign\n"
+ " (signature float\n"
+ " (parameters\n"
+ " (declare (in ) float x@0x1529430)\n"
+ " )\n"
+ " (\n"
+ " ))\n"
+ "\n"
+ " (signature vec2\n"
+ " (parameters\n"
+ " (declare (in ) vec2 x@0x15297e0)\n"
+ " )\n"
+ " (\n"
+ " ))\n"
+ "\n"
+ " (signature vec3\n"
+ " (parameters\n"
+ " (declare (in ) vec3 x@0x15299c0)\n"
+ " )\n"
+ " (\n"
+ " ))\n"
+ "\n"
+ " (signature vec4\n"
+ " (parameters\n"
+ " (declare (in ) vec4 x@0x1529ba0)\n"
+ " )\n"
+ " (\n"
+ " ))\n"
+ "\n"
+ ")\n"
+ "\n"
+ "(function floor\n"
+ " (signature float\n"
+ " (parameters\n"
+ " (declare (in ) float x@0x1529d80)\n"
+ " )\n"
+ " (\n"
+ " ))\n"
+ "\n"
+ " (signature vec2\n"
+ " (parameters\n"
+ " (declare (in ) vec2 x@0x152a130)\n"
+ " )\n"
+ " (\n"
+ " ))\n"
+ "\n"
+ " (signature vec3\n"
+ " (parameters\n"
+ " (declare (in ) vec3 x@0x152a310)\n"
+ " )\n"
+ " (\n"
+ " ))\n"
+ "\n"
+ " (signature vec4\n"
+ " (parameters\n"
+ " (declare (in ) vec4 x@0x152a4f0)\n"
+ " )\n"
+ " (\n"
+ " ))\n"
+ "\n"
+ ")\n"
+ "\n"
+ "(function ceil\n"
+ " (signature float\n"
+ " (parameters\n"
+ " (declare (in ) float x@0x152a6d0)\n"
+ " )\n"
+ " (\n"
+ " ))\n"
+ "\n"
+ " (signature vec2\n"
+ " (parameters\n"
+ " (declare (in ) vec2 x@0x152aa80)\n"
+ " )\n"
+ " (\n"
+ " ))\n"
+ "\n"
+ " (signature vec3\n"
+ " (parameters\n"
+ " (declare (in ) vec3 x@0x152ac60)\n"
+ " )\n"
+ " (\n"
+ " ))\n"
+ "\n"
+ " (signature vec4\n"
+ " (parameters\n"
+ " (declare (in ) vec4 x@0x152ae40)\n"
+ " )\n"
+ " (\n"
+ " ))\n"
+ "\n"
+ ")\n"
+ "\n"
+ "(function fract\n"
+ " (signature float\n"
+ " (parameters\n"
+ " (declare (in ) float x@0x152b020)\n"
+ " )\n"
+ " (\n"
+ " ))\n"
+ "\n"
+ " (signature vec2\n"
+ " (parameters\n"
+ " (declare (in ) vec2 x@0x152b3d0)\n"
+ " )\n"
+ " (\n"
+ " ))\n"
+ "\n"
+ " (signature vec3\n"
+ " (parameters\n"
+ " (declare (in ) vec3 x@0x152b5b0)\n"
+ " )\n"
+ " (\n"
+ " ))\n"
+ "\n"
+ " (signature vec4\n"
+ " (parameters\n"
+ " (declare (in ) vec4 x@0x152b790)\n"
+ " )\n"
+ " (\n"
+ " ))\n"
+ "\n"
+ ")\n"
+ "\n"
+ "(function mod\n"
+ " (signature float\n"
+ " (parameters\n"
+ " (declare (in ) float x@0x152b970)\n"
+ " (declare (in ) float y@0x152ba80)\n"
+ " )\n"
+ " (\n"
+ " ))\n"
+ "\n"
+ " (signature vec2\n"
+ " (parameters\n"
+ " (declare (in ) vec2 x@0x152be30)\n"
+ " (declare (in ) float y@0x152bf40)\n"
+ " )\n"
+ " (\n"
+ " ))\n"
+ "\n"
+ " (signature vec3\n"
+ " (parameters\n"
+ " (declare (in ) vec3 x@0x152c120)\n"
+ " (declare (in ) float y@0x152c230)\n"
+ " )\n"
+ " (\n"
+ " ))\n"
+ "\n"
+ " (signature vec4\n"
+ " (parameters\n"
+ " (declare (in ) vec4 x@0x152c410)\n"
+ " (declare (in ) float y@0x152c520)\n"
+ " )\n"
+ " (\n"
+ " ))\n"
+ "\n"
+ " (signature vec2\n"
+ " (parameters\n"
+ " (declare (in ) vec2 x@0x152c700)\n"
+ " (declare (in ) vec2 y@0x152c810)\n"
+ " )\n"
+ " (\n"
+ " ))\n"
+ "\n"
+ " (signature vec3\n"
+ " (parameters\n"
+ " (declare (in ) vec3 x@0x152c9f0)\n"
+ " (declare (in ) vec3 y@0x152cb00)\n"
+ " )\n"
+ " (\n"
+ " ))\n"
+ "\n"
+ " (signature vec4\n"
+ " (parameters\n"
+ " (declare (in ) vec4 x@0x152cce0)\n"
+ " (declare (in ) vec4 y@0x152cdf0)\n"
+ " )\n"
+ " (\n"
+ " ))\n"
+ "\n"
+ ")\n"
+ "\n"
+ "(function min\n"
+ " (signature float\n"
+ " (parameters\n"
+ " (declare (in ) float x@0x152cfd0)\n"
+ " (declare (in ) float y@0x152d0e0)\n"
+ " )\n"
+ " (\n"
+ " ))\n"
+ "\n"
+ " (signature vec2\n"
+ " (parameters\n"
+ " (declare (in ) vec2 x@0x152d490)\n"
+ " (declare (in ) vec2 y@0x152d5a0)\n"
+ " )\n"
+ " (\n"
+ " ))\n"
+ "\n"
+ " (signature vec3\n"
+ " (parameters\n"
+ " (declare (in ) vec3 x@0x152d780)\n"
+ " (declare (in ) vec3 y@0x152d890)\n"
+ " )\n"
+ " (\n"
+ " ))\n"
+ "\n"
+ " (signature vec4\n"
+ " (parameters\n"
+ " (declare (in ) vec4 x@0x152da70)\n"
+ " (declare (in ) vec4 y@0x152db80)\n"
+ " )\n"
+ " (\n"
+ " ))\n"
+ "\n"
+ " (signature vec2\n"
+ " (parameters\n"
+ " (declare (in ) vec2 x@0x152dd60)\n"
+ " (declare (in ) float y@0x152de70)\n"
+ " )\n"
+ " (\n"
+ " ))\n"
+ "\n"
+ " (signature vec3\n"
+ " (parameters\n"
+ " (declare (in ) vec3 x@0x152e050)\n"
+ " (declare (in ) float y@0x152e160)\n"
+ " )\n"
+ " (\n"
+ " ))\n"
+ "\n"
+ " (signature vec4\n"
+ " (parameters\n"
+ " (declare (in ) vec4 x@0x152e340)\n"
+ " (declare (in ) float y@0x152e450)\n"
+ " )\n"
+ " (\n"
+ " ))\n"
+ "\n"
+ ")\n"
+ "\n"
+ "(function max\n"
+ " (signature float\n"
+ " (parameters\n"
+ " (declare (in ) float x@0x152e630)\n"
+ " (declare (in ) float y@0x152e740)\n"
+ " )\n"
+ " (\n"
+ " ))\n"
+ "\n"
+ " (signature vec2\n"
+ " (parameters\n"
+ " (declare (in ) vec2 x@0x152eaf0)\n"
+ " (declare (in ) vec2 y@0x152ec00)\n"
+ " )\n"
+ " (\n"
+ " ))\n"
+ "\n"
+ " (signature vec3\n"
+ " (parameters\n"
+ " (declare (in ) vec3 x@0x152ede0)\n"
+ " (declare (in ) vec3 y@0x152eef0)\n"
+ " )\n"
+ " (\n"
+ " ))\n"
+ "\n"
+ " (signature vec4\n"
+ " (parameters\n"
+ " (declare (in ) vec4 x@0x152f0d0)\n"
+ " (declare (in ) vec4 y@0x152f1e0)\n"
+ " )\n"
+ " (\n"
+ " ))\n"
+ "\n"
+ " (signature vec2\n"
+ " (parameters\n"
+ " (declare (in ) vec2 x@0x152f3c0)\n"
+ " (declare (in ) float y@0x152f4d0)\n"
+ " )\n"
+ " (\n"
+ " ))\n"
+ "\n"
+ " (signature vec3\n"
+ " (parameters\n"
+ " (declare (in ) vec3 x@0x152f6b0)\n"
+ " (declare (in ) float y@0x152f7c0)\n"
+ " )\n"
+ " (\n"
+ " ))\n"
+ "\n"
+ " (signature vec4\n"
+ " (parameters\n"
+ " (declare (in ) vec4 x@0x152f9a0)\n"
+ " (declare (in ) float y@0x152fab0)\n"
+ " )\n"
+ " (\n"
+ " ))\n"
+ "\n"
+ ")\n"
+ "\n"
+ "(function clamp\n"
+ " (signature float\n"
+ " (parameters\n"
+ " (declare (in ) float x@0x152fc90)\n"
+ " (declare (in ) float minVal@0x152fda0)\n"
+ " (declare (in ) float maxVal@0x152feb0)\n"
+ " )\n"
+ " (\n"
+ " ))\n"
+ "\n"
+ " (signature vec2\n"
+ " (parameters\n"
+ " (declare (in ) vec2 x@0x1530260)\n"
+ " (declare (in ) vec2 minVal@0x1530370)\n"
+ " (declare (in ) vec2 maxVal@0x1530480)\n"
+ " )\n"
+ " (\n"
+ " ))\n"
+ "\n"
+ " (signature vec3\n"
+ " (parameters\n"
+ " (declare (in ) vec3 x@0x1530660)\n"
+ " (declare (in ) vec3 minVal@0x1530770)\n"
+ " (declare (in ) vec3 maxVal@0x1530880)\n"
+ " )\n"
+ " (\n"
+ " ))\n"
+ "\n"
+ " (signature vec4\n"
+ " (parameters\n"
+ " (declare (in ) vec4 x@0x1530a60)\n"
+ " (declare (in ) vec4 minVal@0x1530b70)\n"
+ " (declare (in ) vec4 maxVal@0x1530c80)\n"
+ " )\n"
+ " (\n"
+ " ))\n"
+ "\n"
+ " (signature vec2\n"
+ " (parameters\n"
+ " (declare (in ) vec2 x@0x1530e60)\n"
+ " (declare (in ) float minVal@0x1530f70)\n"
+ " (declare (in ) float maxVal@0x1531080)\n"
+ " )\n"
+ " (\n"
+ " ))\n"
+ "\n"
+ " (signature vec3\n"
+ " (parameters\n"
+ " (declare (in ) vec3 x@0x1531260)\n"
+ " (declare (in ) float minVal@0x1531370)\n"
+ " (declare (in ) float maxVal@0x1531480)\n"
+ " )\n"
+ " (\n"
+ " ))\n"
+ "\n"
+ " (signature vec4\n"
+ " (parameters\n"
+ " (declare (in ) vec4 x@0x1531660)\n"
+ " (declare (in ) float minVal@0x1531770)\n"
+ " (declare (in ) float maxVal@0x1531880)\n"
+ " )\n"
+ " (\n"
+ " ))\n"
+ "\n"
+ ")\n"
+ "\n"
+ "(function mix\n"
+ " (signature float\n"
+ " (parameters\n"
+ " (declare (in ) float x@0x1531a60)\n"
+ " (declare (in ) float y@0x1531b70)\n"
+ " (declare (in ) float a@0x1531c80)\n"
+ " )\n"
+ " (\n"
+ " ))\n"
+ "\n"
+ " (signature vec2\n"
+ " (parameters\n"
+ " (declare (in ) vec2 x@0x1532030)\n"
+ " (declare (in ) vec2 y@0x1532140)\n"
+ " (declare (in ) vec2 a@0x1532250)\n"
+ " )\n"
+ " (\n"
+ " ))\n"
+ "\n"
+ " (signature vec3\n"
+ " (parameters\n"
+ " (declare (in ) vec3 x@0x1532430)\n"
+ " (declare (in ) vec3 y@0x1532540)\n"
+ " (declare (in ) vec3 a@0x1532650)\n"
+ " )\n"
+ " (\n"
+ " ))\n"
+ "\n"
+ " (signature vec4\n"
+ " (parameters\n"
+ " (declare (in ) vec4 x@0x1532830)\n"
+ " (declare (in ) vec4 y@0x1532940)\n"
+ " (declare (in ) vec4 a@0x1532a50)\n"
+ " )\n"
+ " (\n"
+ " ))\n"
+ "\n"
+ " (signature vec2\n"
+ " (parameters\n"
+ " (declare (in ) vec2 x@0x1532c30)\n"
+ " (declare (in ) vec2 y@0x1532d40)\n"
+ " (declare (in ) float a@0x1532e50)\n"
+ " )\n"
+ " (\n"
+ " ))\n"
+ "\n"
+ " (signature vec3\n"
+ " (parameters\n"
+ " (declare (in ) vec3 x@0x1533030)\n"
+ " (declare (in ) vec3 y@0x1533140)\n"
+ " (declare (in ) float a@0x1533250)\n"
+ " )\n"
+ " (\n"
+ " ))\n"
+ "\n"
+ " (signature vec4\n"
+ " (parameters\n"
+ " (declare (in ) vec4 x@0x1533430)\n"
+ " (declare (in ) vec4 y@0x1533540)\n"
+ " (declare (in ) float a@0x1533650)\n"
+ " )\n"
+ " (\n"
+ " ))\n"
+ "\n"
+ ")\n"
+ "\n"
+ "(function step\n"
+ " (signature float\n"
+ " (parameters\n"
+ " (declare (in ) float edge@0x1533830)\n"
+ " (declare (in ) float x@0x1533940)\n"
+ " )\n"
+ " (\n"
+ " ))\n"
+ "\n"
+ " (signature vec2\n"
+ " (parameters\n"
+ " (declare (in ) vec2 edge@0x1533cf0)\n"
+ " (declare (in ) vec2 x@0x1533e00)\n"
+ " )\n"
+ " (\n"
+ " ))\n"
+ "\n"
+ " (signature vec3\n"
+ " (parameters\n"
+ " (declare (in ) vec3 edge@0x1533fe0)\n"
+ " (declare (in ) vec3 x@0x15340f0)\n"
+ " )\n"
+ " (\n"
+ " ))\n"
+ "\n"
+ " (signature vec4\n"
+ " (parameters\n"
+ " (declare (in ) vec4 edge@0x15342d0)\n"
+ " (declare (in ) vec4 x@0x15343e0)\n"
+ " )\n"
+ " (\n"
+ " ))\n"
+ "\n"
+ " (signature vec2\n"
+ " (parameters\n"
+ " (declare (in ) float edge@0x15345c0)\n"
+ " (declare (in ) vec2 x@0x15346d0)\n"
+ " )\n"
+ " (\n"
+ " ))\n"
+ "\n"
+ " (signature vec3\n"
+ " (parameters\n"
+ " (declare (in ) float edge@0x15348b0)\n"
+ " (declare (in ) vec3 x@0x15349c0)\n"
+ " )\n"
+ " (\n"
+ " ))\n"
+ "\n"
+ " (signature vec4\n"
+ " (parameters\n"
+ " (declare (in ) float edge@0x1534ba0)\n"
+ " (declare (in ) vec4 x@0x1534cb0)\n"
+ " )\n"
+ " (\n"
+ " ))\n"
+ "\n"
+ ")\n"
+ "\n"
+ "(function smoothstep\n"
+ " (signature float\n"
+ " (parameters\n"
+ " (declare (in ) float edge0@0x1534e90)\n"
+ " (declare (in ) float edge1@0x1534fa0)\n"
+ " (declare (in ) float x@0x15350b0)\n"
+ " )\n"
+ " (\n"
+ " ))\n"
+ "\n"
+ " (signature vec2\n"
+ " (parameters\n"
+ " (declare (in ) vec2 edge0@0x1535470)\n"
+ " (declare (in ) vec2 edge1@0x1535580)\n"
+ " (declare (in ) vec2 x@0x1535690)\n"
+ " )\n"
+ " (\n"
+ " ))\n"
+ "\n"
+ " (signature vec3\n"
+ " (parameters\n"
+ " (declare (in ) vec3 edge0@0x1535870)\n"
+ " (declare (in ) vec3 edge1@0x1535980)\n"
+ " (declare (in ) vec3 x@0x1535a90)\n"
+ " )\n"
+ " (\n"
+ " ))\n"
+ "\n"
+ " (signature vec4\n"
+ " (parameters\n"
+ " (declare (in ) vec4 edge0@0x1535c70)\n"
+ " (declare (in ) vec4 edge1@0x1535d80)\n"
+ " (declare (in ) vec4 x@0x1535e90)\n"
+ " )\n"
+ " (\n"
+ " ))\n"
+ "\n"
+ " (signature vec2\n"
+ " (parameters\n"
+ " (declare (in ) float edge0@0x1536070)\n"
+ " (declare (in ) float edge1@0x1536180)\n"
+ " (declare (in ) vec2 x@0x1536290)\n"
+ " )\n"
+ " (\n"
+ " ))\n"
+ "\n"
+ " (signature vec3\n"
+ " (parameters\n"
+ " (declare (in ) float edge0@0x1536470)\n"
+ " (declare (in ) float edge1@0x1536580)\n"
+ " (declare (in ) vec3 x@0x1536690)\n"
+ " )\n"
+ " (\n"
+ " ))\n"
+ "\n"
+ " (signature vec4\n"
+ " (parameters\n"
+ " (declare (in ) float edge0@0x1536870)\n"
+ " (declare (in ) float edge1@0x1536980)\n"
+ " (declare (in ) vec4 x@0x1536a90)\n"
+ " )\n"
+ " (\n"
+ " ))\n"
+ "\n"
+ ")\n"
+ "\n"
+ "(function length\n"
+ " (signature float\n"
+ " (parameters\n"
+ " (declare (in ) float x@0x1536c70)\n"
+ " )\n"
+ " (\n"
+ " ))\n"
+ "\n"
+ " (signature float\n"
+ " (parameters\n"
+ " (declare (in ) vec2 x@0x1537020)\n"
+ " )\n"
+ " (\n"
+ " ))\n"
+ "\n"
+ " (signature float\n"
+ " (parameters\n"
+ " (declare (in ) vec3 x@0x1537200)\n"
+ " )\n"
+ " (\n"
+ " ))\n"
+ "\n"
+ " (signature float\n"
+ " (parameters\n"
+ " (declare (in ) vec4 x@0x15373e0)\n"
+ " )\n"
+ " (\n"
+ " ))\n"
+ "\n"
+ ")\n"
+ "\n"
+ "(function distance\n"
+ " (signature float\n"
+ " (parameters\n"
+ " (declare (in ) float p0@0x15375c0)\n"
+ " (declare (in ) float p1@0x15376d0)\n"
+ " )\n"
+ " (\n"
+ " ))\n"
+ "\n"
+ " (signature float\n"
+ " (parameters\n"
+ " (declare (in ) vec2 p0@0x1537a90)\n"
+ " (declare (in ) vec2 p1@0x1537ba0)\n"
+ " )\n"
+ " (\n"
+ " ))\n"
+ "\n"
+ " (signature float\n"
+ " (parameters\n"
+ " (declare (in ) vec3 p0@0x1537d80)\n"
+ " (declare (in ) vec3 p1@0x1537e90)\n"
+ " )\n"
+ " (\n"
+ " ))\n"
+ "\n"
+ " (signature float\n"
+ " (parameters\n"
+ " (declare (in ) vec4 p0@0x1538070)\n"
+ " (declare (in ) vec4 p1@0x1538180)\n"
+ " )\n"
+ " (\n"
+ " ))\n"
+ "\n"
+ ")\n"
+ "\n"
+ "(function dot\n"
+ " (signature float\n"
+ " (parameters\n"
+ " (declare (in ) float x@0x1538360)\n"
+ " (declare (in ) float y@0x1538470)\n"
+ " )\n"
+ " (\n"
+ " ))\n"
+ "\n"
+ " (signature float\n"
+ " (parameters\n"
+ " (declare (in ) vec2 x@0x1538820)\n"
+ " (declare (in ) vec2 y@0x1538930)\n"
+ " )\n"
+ " (\n"
+ " ))\n"
+ "\n"
+ " (signature float\n"
+ " (parameters\n"
+ " (declare (in ) vec3 x@0x1538b10)\n"
+ " (declare (in ) vec3 y@0x1538c20)\n"
+ " )\n"
+ " (\n"
+ " ))\n"
+ "\n"
+ " (signature float\n"
+ " (parameters\n"
+ " (declare (in ) vec4 x@0x1538e00)\n"
+ " (declare (in ) vec4 y@0x1538f10)\n"
+ " )\n"
+ " (\n"
+ " ))\n"
+ "\n"
+ ")\n"
+ "\n"
+ "(function cross\n"
+ " (signature vec3\n"
+ " (parameters\n"
+ " (declare (in ) vec3 x@0x15390f0)\n"
+ " (declare (in ) vec3 y@0x1539200)\n"
+ " )\n"
+ " (\n"
+ " ))\n"
+ "\n"
+ ")\n"
+ "\n"
+ "(function normalize\n"
+ " (signature float\n"
+ " (parameters\n"
+ " (declare (in ) float x@0x15395b0)\n"
+ " )\n"
+ " (\n"
+ " ))\n"
+ "\n"
+ " (signature vec2\n"
+ " (parameters\n"
+ " (declare (in ) vec2 x@0x1539970)\n"
+ " )\n"
+ " (\n"
+ " ))\n"
+ "\n"
+ " (signature vec3\n"
+ " (parameters\n"
+ " (declare (in ) vec3 x@0x1539b50)\n"
+ " )\n"
+ " (\n"
+ " ))\n"
+ "\n"
+ " (signature vec4\n"
+ " (parameters\n"
+ " (declare (in ) vec4 x@0x1539d30)\n"
+ " )\n"
+ " (\n"
+ " ))\n"
+ "\n"
+ ")\n"
+ "\n"
+ "(function faceforward\n"
+ " (signature float\n"
+ " (parameters\n"
+ " (declare (in ) float N@0x1539f10)\n"
+ " (declare (in ) float I@0x153a020)\n"
+ " (declare (in ) float Nref@0x153a130)\n"
+ " )\n"
+ " (\n"
+ " ))\n"
+ "\n"
+ " (signature vec2\n"
+ " (parameters\n"
+ " (declare (in ) vec2 N@0x153a4f0)\n"
+ " (declare (in ) vec2 I@0x153a600)\n"
+ " (declare (in ) vec2 Nref@0x153a710)\n"
+ " )\n"
+ " (\n"
+ " ))\n"
+ "\n"
+ " (signature vec3\n"
+ " (parameters\n"
+ " (declare (in ) vec3 N@0x153a8f0)\n"
+ " (declare (in ) vec3 I@0x153aa00)\n"
+ " (declare (in ) vec3 Nref@0x153ab10)\n"
+ " )\n"
+ " (\n"
+ " ))\n"
+ "\n"
+ " (signature vec4\n"
+ " (parameters\n"
+ " (declare (in ) vec4 N@0x153acf0)\n"
+ " (declare (in ) vec4 I@0x153ae00)\n"
+ " (declare (in ) vec4 Nref@0x153af10)\n"
+ " )\n"
+ " (\n"
+ " ))\n"
+ "\n"
+ ")\n"
+ "\n"
+ "(function reflect\n"
+ " (signature float\n"
+ " (parameters\n"
+ " (declare (in ) float I@0x153b0f0)\n"
+ " (declare (in ) float N@0x153b200)\n"
+ " )\n"
+ " (\n"
+ " ))\n"
+ "\n"
+ " (signature vec2\n"
+ " (parameters\n"
+ " (declare (in ) vec2 I@0x153b5c0)\n"
+ " (declare (in ) vec2 N@0x153b6d0)\n"
+ " )\n"
+ " (\n"
+ " ))\n"
+ "\n"
+ " (signature vec3\n"
+ " (parameters\n"
+ " (declare (in ) vec3 I@0x153b8b0)\n"
+ " (declare (in ) vec3 N@0x153b9c0)\n"
+ " )\n"
+ " (\n"
+ " ))\n"
+ "\n"
+ " (signature vec4\n"
+ " (parameters\n"
+ " (declare (in ) vec4 I@0x153bba0)\n"
+ " (declare (in ) vec4 N@0x153bcb0)\n"
+ " )\n"
+ " (\n"
+ " ))\n"
+ "\n"
+ ")\n"
+ "\n"
+ "(function refract\n"
+ " (signature float\n"
+ " (parameters\n"
+ " (declare (in ) float I@0x153be90)\n"
+ " (declare (in ) float N@0x153bfa0)\n"
+ " (declare (in ) float eta@0x153c0b0)\n"
+ " )\n"
+ " (\n"
+ " ))\n"
+ "\n"
+ " (signature vec2\n"
+ " (parameters\n"
+ " (declare (in ) vec2 I@0x153c470)\n"
+ " (declare (in ) vec2 N@0x153c580)\n"
+ " (declare (in ) float eta@0x153c690)\n"
+ " )\n"
+ " (\n"
+ " ))\n"
+ "\n"
+ " (signature vec3\n"
+ " (parameters\n"
+ " (declare (in ) vec3 I@0x153c870)\n"
+ " (declare (in ) vec3 N@0x153c980)\n"
+ " (declare (in ) float eta@0x153ca90)\n"
+ " )\n"
+ " (\n"
+ " ))\n"
+ "\n"
+ " (signature vec4\n"
+ " (parameters\n"
+ " (declare (in ) vec4 I@0x153cc70)\n"
+ " (declare (in ) vec4 N@0x153cd80)\n"
+ " (declare (in ) float eta@0x153ce90)\n"
+ " )\n"
+ " (\n"
+ " ))\n"
+ "\n"
+ ")\n"
+ "\n"
+ "(function matrixCompMult\n"
+ " (signature mat2\n"
+ " (parameters\n"
+ " (declare (in ) mat2 x@0x153d070)\n"
+ " (declare (in ) mat2 y@0x153d180)\n"
+ " )\n"
+ " (\n"
+ " ))\n"
+ "\n"
+ " (signature mat3\n"
+ " (parameters\n"
+ " (declare (in ) mat3 x@0x153d540)\n"
+ " (declare (in ) mat3 y@0x153d650)\n"
+ " )\n"
+ " (\n"
+ " ))\n"
+ "\n"
+ " (signature mat4\n"
+ " (parameters\n"
+ " (declare (in ) mat4 x@0x153d830)\n"
+ " (declare (in ) mat4 y@0x153d940)\n"
+ " )\n"
+ " (\n"
+ " ))\n"
+ "\n"
+ ")\n"
+ "\n"
+ "(function lessThan\n"
+ " (signature bvec2\n"
+ " (parameters\n"
+ " (declare (in ) vec2 x@0x153db20)\n"
+ " (declare (in ) vec2 y@0x153dc30)\n"
+ " )\n"
+ " (\n"
+ " ))\n"
+ "\n"
+ " (signature bvec3\n"
+ " (parameters\n"
+ " (declare (in ) vec3 x@0x153dff0)\n"
+ " (declare (in ) vec3 y@0x153e100)\n"
+ " )\n"
+ " (\n"
+ " ))\n"
+ "\n"
+ " (signature bvec4\n"
+ " (parameters\n"
+ " (declare (in ) vec4 x@0x153e2e0)\n"
+ " (declare (in ) vec4 y@0x153e3f0)\n"
+ " )\n"
+ " (\n"
+ " ))\n"
+ "\n"
+ " (signature bvec2\n"
+ " (parameters\n"
+ " (declare (in ) ivec2 x@0x153e5d0)\n"
+ " (declare (in ) ivec2 y@0x153e6e0)\n"
+ " )\n"
+ " (\n"
+ " ))\n"
+ "\n"
+ " (signature bvec3\n"
+ " (parameters\n"
+ " (declare (in ) ivec3 x@0x153e8c0)\n"
+ " (declare (in ) ivec3 y@0x153e9d0)\n"
+ " )\n"
+ " (\n"
+ " ))\n"
+ "\n"
+ " (signature bvec4\n"
+ " (parameters\n"
+ " (declare (in ) ivec4 x@0x153ebb0)\n"
+ " (declare (in ) ivec4 y@0x153ecc0)\n"
+ " )\n"
+ " (\n"
+ " ))\n"
+ "\n"
+ ")\n"
+ "\n"
+ "(function lessThanEqual\n"
+ " (signature bvec2\n"
+ " (parameters\n"
+ " (declare (in ) vec2 x@0x153eea0)\n"
+ " (declare (in ) vec2 y@0x153efb0)\n"
+ " )\n"
+ " (\n"
+ " ))\n"
+ "\n"
+ " (signature bvec3\n"
+ " (parameters\n"
+ " (declare (in ) vec3 x@0x153f370)\n"
+ " (declare (in ) vec3 y@0x153f480)\n"
+ " )\n"
+ " (\n"
+ " ))\n"
+ "\n"
+ " (signature bvec4\n"
+ " (parameters\n"
+ " (declare (in ) vec4 x@0x153f660)\n"
+ " (declare (in ) vec4 y@0x153f770)\n"
+ " )\n"
+ " (\n"
+ " ))\n"
+ "\n"
+ " (signature bvec2\n"
+ " (parameters\n"
+ " (declare (in ) ivec2 x@0x153f950)\n"
+ " (declare (in ) ivec2 y@0x153fa60)\n"
+ " )\n"
+ " (\n"
+ " ))\n"
+ "\n"
+ " (signature bvec3\n"
+ " (parameters\n"
+ " (declare (in ) ivec3 x@0x153fc40)\n"
+ " (declare (in ) ivec3 y@0x153fd50)\n"
+ " )\n"
+ " (\n"
+ " ))\n"
+ "\n"
+ " (signature bvec4\n"
+ " (parameters\n"
+ " (declare (in ) ivec4 x@0x153ff30)\n"
+ " (declare (in ) ivec4 y@0x1540040)\n"
+ " )\n"
+ " (\n"
+ " ))\n"
+ "\n"
+ ")\n"
+ "\n"
+ "(function greaterThan\n"
+ " (signature bvec2\n"
+ " (parameters\n"
+ " (declare (in ) vec2 x@0x1540220)\n"
+ " (declare (in ) vec2 y@0x1540330)\n"
+ " )\n"
+ " (\n"
+ " ))\n"
+ "\n"
+ " (signature bvec3\n"
+ " (parameters\n"
+ " (declare (in ) vec3 x@0x15406f0)\n"
+ " (declare (in ) vec3 y@0x1540800)\n"
+ " )\n"
+ " (\n"
+ " ))\n"
+ "\n"
+ " (signature bvec4\n"
+ " (parameters\n"
+ " (declare (in ) vec4 x@0x15409e0)\n"
+ " (declare (in ) vec4 y@0x1540af0)\n"
+ " )\n"
+ " (\n"
+ " ))\n"
+ "\n"
+ " (signature bvec2\n"
+ " (parameters\n"
+ " (declare (in ) ivec2 x@0x1540cd0)\n"
+ " (declare (in ) ivec2 y@0x1540de0)\n"
+ " )\n"
+ " (\n"
+ " ))\n"
+ "\n"
+ " (signature bvec3\n"
+ " (parameters\n"
+ " (declare (in ) ivec3 x@0x1540fc0)\n"
+ " (declare (in ) ivec3 y@0x15410d0)\n"
+ " )\n"
+ " (\n"
+ " ))\n"
+ "\n"
+ " (signature bvec4\n"
+ " (parameters\n"
+ " (declare (in ) ivec4 x@0x15412b0)\n"
+ " (declare (in ) ivec4 y@0x15413c0)\n"
+ " )\n"
+ " (\n"
+ " ))\n"
+ "\n"
+ ")\n"
+ "\n"
+ "(function greaterThanEqual\n"
+ " (signature bvec2\n"
+ " (parameters\n"
+ " (declare (in ) vec2 x@0x15415a0)\n"
+ " (declare (in ) vec2 y@0x15416b0)\n"
+ " )\n"
+ " (\n"
+ " ))\n"
+ "\n"
+ " (signature bvec3\n"
+ " (parameters\n"
+ " (declare (in ) vec3 x@0x1541a70)\n"
+ " (declare (in ) vec3 y@0x1541b80)\n"
+ " )\n"
+ " (\n"
+ " ))\n"
+ "\n"
+ " (signature bvec4\n"
+ " (parameters\n"
+ " (declare (in ) vec4 x@0x1541d60)\n"
+ " (declare (in ) vec4 y@0x1541e70)\n"
+ " )\n"
+ " (\n"
+ " ))\n"
+ "\n"
+ " (signature bvec2\n"
+ " (parameters\n"
+ " (declare (in ) ivec2 x@0x1542050)\n"
+ " (declare (in ) ivec2 y@0x1542160)\n"
+ " )\n"
+ " (\n"
+ " ))\n"
+ "\n"
+ " (signature bvec3\n"
+ " (parameters\n"
+ " (declare (in ) ivec3 x@0x1542340)\n"
+ " (declare (in ) ivec3 y@0x1542450)\n"
+ " )\n"
+ " (\n"
+ " ))\n"
+ "\n"
+ " (signature bvec4\n"
+ " (parameters\n"
+ " (declare (in ) ivec4 x@0x1542630)\n"
+ " (declare (in ) ivec4 y@0x1542740)\n"
+ " )\n"
+ " (\n"
+ " ))\n"
+ "\n"
+ ")\n"
+ "\n"
+ "(function equal\n"
+ " (signature bvec2\n"
+ " (parameters\n"
+ " (declare (in ) vec2 x@0x1542920)\n"
+ " (declare (in ) vec2 y@0x1542a30)\n"
+ " )\n"
+ " (\n"
+ " ))\n"
+ "\n"
+ " (signature bvec3\n"
+ " (parameters\n"
+ " (declare (in ) vec3 x@0x1542de0)\n"
+ " (declare (in ) vec3 y@0x1542ef0)\n"
+ " )\n"
+ " (\n"
+ " ))\n"
+ "\n"
+ " (signature bvec4\n"
+ " (parameters\n"
+ " (declare (in ) vec4 x@0x15430d0)\n"
+ " (declare (in ) vec4 y@0x15431e0)\n"
+ " )\n"
+ " (\n"
+ " ))\n"
+ "\n"
+ " (signature bvec2\n"
+ " (parameters\n"
+ " (declare (in ) ivec2 x@0x15433c0)\n"
+ " (declare (in ) ivec2 y@0x15434d0)\n"
+ " )\n"
+ " (\n"
+ " ))\n"
+ "\n"
+ " (signature bvec3\n"
+ " (parameters\n"
+ " (declare (in ) ivec3 x@0x15436b0)\n"
+ " (declare (in ) ivec3 y@0x15437c0)\n"
+ " )\n"
+ " (\n"
+ " ))\n"
+ "\n"
+ " (signature bvec4\n"
+ " (parameters\n"
+ " (declare (in ) ivec4 x@0x15439a0)\n"
+ " (declare (in ) ivec4 y@0x1543ab0)\n"
+ " )\n"
+ " (\n"
+ " ))\n"
+ "\n"
+ " (signature bvec2\n"
+ " (parameters\n"
+ " (declare (in ) bvec2 x@0x1543c90)\n"
+ " (declare (in ) bvec2 y@0x1543da0)\n"
+ " )\n"
+ " (\n"
+ " ))\n"
+ "\n"
+ " (signature bvec3\n"
+ " (parameters\n"
+ " (declare (in ) bvec3 x@0x1543f80)\n"
+ " (declare (in ) bvec3 y@0x1544090)\n"
+ " )\n"
+ " (\n"
+ " ))\n"
+ "\n"
+ " (signature bvec4\n"
+ " (parameters\n"
+ " (declare (in ) bvec4 x@0x1544270)\n"
+ " (declare (in ) bvec4 y@0x1544380)\n"
+ " )\n"
+ " (\n"
+ " ))\n"
+ "\n"
+ ")\n"
+ "\n"
+ "(function notEqual\n"
+ " (signature bvec2\n"
+ " (parameters\n"
+ " (declare (in ) vec2 x@0x1544560)\n"
+ " (declare (in ) vec2 y@0x1544670)\n"
+ " )\n"
+ " (\n"
+ " ))\n"
+ "\n"
+ " (signature bvec3\n"
+ " (parameters\n"
+ " (declare (in ) vec3 x@0x1544a30)\n"
+ " (declare (in ) vec3 y@0x1544b40)\n"
+ " )\n"
+ " (\n"
+ " ))\n"
+ "\n"
+ " (signature bvec4\n"
+ " (parameters\n"
+ " (declare (in ) vec4 x@0x1544d20)\n"
+ " (declare (in ) vec4 y@0x1544e30)\n"
+ " )\n"
+ " (\n"
+ " ))\n"
+ "\n"
+ " (signature bvec2\n"
+ " (parameters\n"
+ " (declare (in ) ivec2 x@0x1545010)\n"
+ " (declare (in ) ivec2 y@0x1545120)\n"
+ " )\n"
+ " (\n"
+ " ))\n"
+ "\n"
+ " (signature bvec3\n"
+ " (parameters\n"
+ " (declare (in ) ivec3 x@0x1545300)\n"
+ " (declare (in ) ivec3 y@0x1545410)\n"
+ " )\n"
+ " (\n"
+ " ))\n"
+ "\n"
+ " (signature bvec4\n"
+ " (parameters\n"
+ " (declare (in ) ivec4 x@0x15455f0)\n"
+ " (declare (in ) ivec4 y@0x1545700)\n"
+ " )\n"
+ " (\n"
+ " ))\n"
+ "\n"
+ " (signature bvec2\n"
+ " (parameters\n"
+ " (declare (in ) bvec2 x@0x15458e0)\n"
+ " (declare (in ) bvec2 y@0x15459f0)\n"
+ " )\n"
+ " (\n"
+ " ))\n"
+ "\n"
+ " (signature bvec3\n"
+ " (parameters\n"
+ " (declare (in ) bvec3 x@0x1545bd0)\n"
+ " (declare (in ) bvec3 y@0x1545ce0)\n"
+ " )\n"
+ " (\n"
+ " ))\n"
+ "\n"
+ " (signature bvec4\n"
+ " (parameters\n"
+ " (declare (in ) bvec4 x@0x1545ec0)\n"
+ " (declare (in ) bvec4 y@0x1545fd0)\n"
+ " )\n"
+ " (\n"
+ " ))\n"
+ "\n"
+ ")\n"
+ "\n"
+ "(function any\n"
+ " (signature bool\n"
+ " (parameters\n"
+ " (declare (in ) bvec2 x@0x15461b0)\n"
+ " )\n"
+ " (\n"
+ " ))\n"
+ "\n"
+ " (signature bool\n"
+ " (parameters\n"
+ " (declare (in ) bvec3 x@0x1546560)\n"
+ " )\n"
+ " (\n"
+ " ))\n"
+ "\n"
+ " (signature bool\n"
+ " (parameters\n"
+ " (declare (in ) bvec4 x@0x1546740)\n"
+ " )\n"
+ " (\n"
+ " ))\n"
+ "\n"
+ ")\n"
+ "\n"
+ "(function all\n"
+ " (signature bool\n"
+ " (parameters\n"
+ " (declare (in ) bvec2 x@0x1546920)\n"
+ " )\n"
+ " (\n"
+ " ))\n"
+ "\n"
+ " (signature bool\n"
+ " (parameters\n"
+ " (declare (in ) bvec3 x@0x1546cd0)\n"
+ " )\n"
+ " (\n"
+ " ))\n"
+ "\n"
+ " (signature bool\n"
+ " (parameters\n"
+ " (declare (in ) bvec4 x@0x1546eb0)\n"
+ " )\n"
+ " (\n"
+ " ))\n"
+ "\n"
+ ")\n"
+ "\n"
+ "(function not\n"
+ " (signature bvec2\n"
+ " (parameters\n"
+ " (declare (in ) bvec2 x@0x1547090)\n"
+ " )\n"
+ " (\n"
+ " ))\n"
+ "\n"
+ " (signature bvec3\n"
+ " (parameters\n"
+ " (declare (in ) bvec3 x@0x1547440)\n"
+ " )\n"
+ " (\n"
+ " ))\n"
+ "\n"
+ " (signature bvec4\n"
+ " (parameters\n"
+ " (declare (in ) bvec4 x@0x1547620)\n"
+ " )\n"
+ " (\n"
+ " ))\n"
+ "\n"
+ ")\n"
+ "\n"
+ "(function texture1D\n"
+ " (signature vec4\n"
+ " (parameters\n"
+ " (declare (in ) sampler1D sampler@0x1547800)\n"
+ " (declare (in ) float coord@0x1547920)\n"
+ " )\n"
+ " (\n"
+ " ))\n"
+ "\n"
+ " (signature vec4\n"
+ " (parameters\n"
+ " (declare (in ) sampler1D sampler@0x15484c0)\n"
+ " (declare (in ) float coord@0x15485e0)\n"
+ " (declare (in ) float bias@0x15486f0)\n"
+ " )\n"
+ " (\n"
+ " ))\n"
+ "\n"
+ ")\n"
+ "\n"
+ "(function texture1DProj\n"
+ " (signature vec4\n"
+ " (parameters\n"
+ " (declare (in ) sampler1D sampler@0x1547ce0)\n"
+ " (declare (in ) vec2 coord@0x1547e00)\n"
+ " )\n"
+ " (\n"
+ " ))\n"
+ "\n"
+ " (signature vec4\n"
+ " (parameters\n"
+ " (declare (in ) sampler1D sampler@0x15481c0)\n"
+ " (declare (in ) vec4 coord@0x15482e0)\n"
+ " )\n"
+ " (\n"
+ " ))\n"
+ "\n"
+ " (signature vec4\n"
+ " (parameters\n"
+ " (declare (in ) sampler1D sampler@0x15488d0)\n"
+ " (declare (in ) vec2 coord@0x15489f0)\n"
+ " (declare (in ) float bias@0x1548b00)\n"
+ " )\n"
+ " (\n"
+ " ))\n"
+ "\n"
+ " (signature vec4\n"
+ " (parameters\n"
+ " (declare (in ) sampler1D sampler@0x1548ce0)\n"
+ " (declare (in ) vec4 coord@0x1548e00)\n"
+ " (declare (in ) float bias@0x1548f10)\n"
+ " )\n"
+ " (\n"
+ " ))\n"
+ "\n"
+ ")\n"
+ "\n"
+ "(function texture2D\n"
+ " (signature vec4\n"
+ " (parameters\n"
+ " (declare (in ) sampler2D sampler@0x15490f0)\n"
+ " (declare (in ) vec2 coord@0x1549210)\n"
+ " )\n"
+ " (\n"
+ " ))\n"
+ "\n"
+ " (signature vec4\n"
+ " (parameters\n"
+ " (declare (in ) sampler2D sampler@0x1549db0)\n"
+ " (declare (in ) vec2 coord@0x1549ed0)\n"
+ " (declare (in ) float bias@0x1549fe0)\n"
+ " )\n"
+ " (\n"
+ " ))\n"
+ "\n"
+ ")\n"
+ "\n"
+ "(function texture2DProj\n"
+ " (signature vec4\n"
+ " (parameters\n"
+ " (declare (in ) sampler2D sampler@0x15495d0)\n"
+ " (declare (in ) vec3 coord@0x15496f0)\n"
+ " )\n"
+ " (\n"
+ " ))\n"
+ "\n"
+ " (signature vec4\n"
+ " (parameters\n"
+ " (declare (in ) sampler2D sampler@0x1549ab0)\n"
+ " (declare (in ) vec4 coord@0x1549bd0)\n"
+ " )\n"
+ " (\n"
+ " ))\n"
+ "\n"
+ " (signature vec4\n"
+ " (parameters\n"
+ " (declare (in ) sampler2D sampler@0x154a1c0)\n"
+ " (declare (in ) vec3 coord@0x154a2e0)\n"
+ " (declare (in ) float bias@0x154a3f0)\n"
+ " )\n"
+ " (\n"
+ " ))\n"
+ "\n"
+ " (signature vec4\n"
+ " (parameters\n"
+ " (declare (in ) sampler2D sampler@0x154a5d0)\n"
+ " (declare (in ) vec4 coord@0x154a6f0)\n"
+ " (declare (in ) float bias@0x154a800)\n"
+ " )\n"
+ " (\n"
+ " ))\n"
+ "\n"
+ ")\n"
+ "\n"
+ "(function texture3D\n"
+ " (signature vec4\n"
+ " (parameters\n"
+ " (declare (in ) sampler3D sampler@0x154a9e0)\n"
+ " (declare (in ) vec3 coord@0x154ab00)\n"
+ " )\n"
+ " (\n"
+ " ))\n"
+ "\n"
+ " (signature vec4\n"
+ " (parameters\n"
+ " (declare (in ) sampler3D sampler@0x154b3a0)\n"
+ " (declare (in ) vec3 coord@0x154b4c0)\n"
+ " (declare (in ) float bias@0x154b5d0)\n"
+ " )\n"
+ " (\n"
+ " ))\n"
+ "\n"
+ ")\n"
+ "\n"
+ "(function texture3DProj\n"
+ " (signature vec4\n"
+ " (parameters\n"
+ " (declare (in ) sampler3D sampler@0x154aec0)\n"
+ " (declare (in ) vec4 coord@0x154afe0)\n"
+ " )\n"
+ " (\n"
+ " ))\n"
+ "\n"
+ " (signature vec4\n"
+ " (parameters\n"
+ " (declare (in ) sampler3D sampler@0x154b7b0)\n"
+ " (declare (in ) vec4 coord@0x154b8d0)\n"
+ " (declare (in ) float bias@0x154b9e0)\n"
+ " )\n"
+ " (\n"
+ " ))\n"
+ "\n"
+ ")\n"
+ "\n"
+ "(function textureCube\n"
+ " (signature vec4\n"
+ " (parameters\n"
+ " (declare (in ) samplerCube sampler@0x154bbc0)\n"
+ " (declare (in ) vec3 coord@0x154bce0)\n"
+ " )\n"
+ " (\n"
+ " ))\n"
+ "\n"
+ " (signature vec4\n"
+ " (parameters\n"
+ " (declare (in ) samplerCube sampler@0x154c0a0)\n"
+ " (declare (in ) vec3 coord@0x154c1c0)\n"
+ " (declare (in ) float bias@0x154c2d0)\n"
+ " )\n"
+ " (\n"
+ " ))\n"
+ "\n"
+ ")\n"
+ "\n"
+ "(function shadow1D\n"
+ " (signature vec4\n"
+ " (parameters\n"
+ " (declare (in ) sampler1DShadow sampler@0x154c4b0)\n"
+ " (declare (in ) vec3 coord@0x154c5d0)\n"
+ " )\n"
+ " (\n"
+ " ))\n"
+ "\n"
+ " (signature vec4\n"
+ " (parameters\n"
+ " (declare (in ) sampler1DShadow sampler@0x154d830)\n"
+ " (declare (in ) vec3 coord@0x154d950)\n"
+ " (declare (in ) float bias@0x154da60)\n"
+ " )\n"
+ " (\n"
+ " ))\n"
+ "\n"
+ ")\n"
+ "\n"
+ "(function shadow2D\n"
+ " (signature vec4\n"
+ " (parameters\n"
+ " (declare (in ) sampler2DShadow sampler@0x154c990)\n"
+ " (declare (in ) vec3 coord@0x154cab0)\n"
+ " )\n"
+ " (\n"
+ " ))\n"
+ "\n"
+ " (signature vec4\n"
+ " (parameters\n"
+ " (declare (in ) sampler2DShadow sampler@0x154dc40)\n"
+ " (declare (in ) vec3 coord@0x154dd60)\n"
+ " (declare (in ) float bias@0x154de70)\n"
+ " )\n"
+ " (\n"
+ " ))\n"
+ "\n"
+ ")\n"
+ "\n"
+ "(function shadow1DProj\n"
+ " (signature vec4\n"
+ " (parameters\n"
+ " (declare (in ) sampler1DShadow sampler@0x154ce70)\n"
+ " (declare (in ) vec4 coord@0x154cf90)\n"
+ " )\n"
+ " (\n"
+ " ))\n"
+ "\n"
+ " (signature vec4\n"
+ " (parameters\n"
+ " (declare (in ) sampler1DShadow sampler@0x154e050)\n"
+ " (declare (in ) vec4 coord@0x154e170)\n"
+ " (declare (in ) float bias@0x154e280)\n"
+ " )\n"
+ " (\n"
+ " ))\n"
+ "\n"
+ ")\n"
+ "\n"
+ "(function shadow2DProj\n"
+ " (signature vec4\n"
+ " (parameters\n"
+ " (declare (in ) sampler2DShadow sampler@0x154d350)\n"
+ " (declare (in ) vec4 coord@0x154d470)\n"
+ " )\n"
+ " (\n"
+ " ))\n"
+ "\n"
+ " (signature vec4\n"
+ " (parameters\n"
+ " (declare (in ) sampler2DShadow sampler@0x154e460)\n"
+ " (declare (in ) vec4 coord@0x154e580)\n"
+ " (declare (in ) float bias@0x154e690)\n"
+ " )\n"
+ " (\n"
+ " ))\n"
+ "\n"
+ ")\n"
+ "\n"
+ "(function dFdx\n"
+ " (signature float\n"
+ " (parameters\n"
+ " (declare (in ) float p@0x154e870)\n"
+ " )\n"
+ " (\n"
+ " ))\n"
+ "\n"
+ " (signature vec2\n"
+ " (parameters\n"
+ " (declare (in ) vec2 p@0x154ec20)\n"
+ " )\n"
+ " (\n"
+ " ))\n"
+ "\n"
+ " (signature vec3\n"
+ " (parameters\n"
+ " (declare (in ) vec3 p@0x154ee00)\n"
+ " )\n"
+ " (\n"
+ " ))\n"
+ "\n"
+ " (signature vec4\n"
+ " (parameters\n"
+ " (declare (in ) vec4 p@0x154efe0)\n"
+ " )\n"
+ " (\n"
+ " ))\n"
+ "\n"
+ ")\n"
+ "\n"
+ "(function dFdy\n"
+ " (signature float\n"
+ " (parameters\n"
+ " (declare (in ) float p@0x154f1c0)\n"
+ " )\n"
+ " (\n"
+ " ))\n"
+ "\n"
+ " (signature vec2\n"
+ " (parameters\n"
+ " (declare (in ) vec2 p@0x154f570)\n"
+ " )\n"
+ " (\n"
+ " ))\n"
+ "\n"
+ " (signature vec3\n"
+ " (parameters\n"
+ " (declare (in ) vec3 p@0x154f750)\n"
+ " )\n"
+ " (\n"
+ " ))\n"
+ "\n"
+ " (signature vec4\n"
+ " (parameters\n"
+ " (declare (in ) vec4 p@0x154f930)\n"
+ " )\n"
+ " (\n"
+ " ))\n"
+ "\n"
+ ")\n"
+ "\n"
+ "(function fwidth\n"
+ " (signature float\n"
+ " (parameters\n"
+ " (declare (in ) float p@0x154fb10)\n"
+ " )\n"
+ " (\n"
+ " ))\n"
+ "\n"
+ " (signature vec2\n"
+ " (parameters\n"
+ " (declare (in ) vec2 p@0x154fec0)\n"
+ " )\n"
+ " (\n"
+ " ))\n"
+ "\n"
+ " (signature vec3\n"
+ " (parameters\n"
+ " (declare (in ) vec3 p@0x15500a0)\n"
+ " )\n"
+ " (\n"
+ " ))\n"
+ "\n"
+ " (signature vec4\n"
+ " (parameters\n"
+ " (declare (in ) vec4 p@0x1550280)\n"
+ " )\n"
+ " (\n"
+ " ))\n"
+ "\n"
+ ")\n"
+ "\n"
+ "(function noise1\n"
+ " (signature float\n"
+ " (parameters\n"
+ " (declare (in ) float x@0x1550460)\n"
+ " )\n"
+ " (\n"
+ " ))\n"
+ "\n"
+ " (signature float\n"
+ " (parameters\n"
+ " (declare (in ) vec2 x@0x1550810)\n"
+ " )\n"
+ " (\n"
+ " ))\n"
+ "\n"
+ " (signature float\n"
+ " (parameters\n"
+ " (declare (in ) vec3 x@0x15509f0)\n"
+ " )\n"
+ " (\n"
+ " ))\n"
+ "\n"
+ " (signature float\n"
+ " (parameters\n"
+ " (declare (in ) vec4 x@0x1550bd0)\n"
+ " )\n"
+ " (\n"
+ " ))\n"
+ "\n"
+ ")\n"
+ "\n"
+ "(function noise2\n"
+ " (signature vec2\n"
+ " (parameters\n"
+ " (declare (in ) float x@0x1550db0)\n"
+ " )\n"
+ " (\n"
+ " ))\n"
+ "\n"
+ " (signature vec2\n"
+ " (parameters\n"
+ " (declare (in ) vec2 x@0x1551160)\n"
+ " )\n"
+ " (\n"
+ " ))\n"
+ "\n"
+ " (signature vec2\n"
+ " (parameters\n"
+ " (declare (in ) vec3 x@0x1551340)\n"
+ " )\n"
+ " (\n"
+ " ))\n"
+ "\n"
+ " (signature vec2\n"
+ " (parameters\n"
+ " (declare (in ) vec4 x@0x1551520)\n"
+ " )\n"
+ " (\n"
+ " ))\n"
+ "\n"
+ ")\n"
+ "\n"
+ "(function noise3\n"
+ " (signature vec3\n"
+ " (parameters\n"
+ " (declare (in ) float x@0x1551700)\n"
+ " )\n"
+ " (\n"
+ " ))\n"
+ "\n"
+ " (signature vec3\n"
+ " (parameters\n"
+ " (declare (in ) vec2 x@0x1551ab0)\n"
+ " )\n"
+ " (\n"
+ " ))\n"
+ "\n"
+ " (signature vec3\n"
+ " (parameters\n"
+ " (declare (in ) vec3 x@0x1551c90)\n"
+ " )\n"
+ " (\n"
+ " ))\n"
+ "\n"
+ " (signature vec3\n"
+ " (parameters\n"
+ " (declare (in ) vec4 x@0x1551e70)\n"
+ " )\n"
+ " (\n"
+ " ))\n"
+ "\n"
+ ")\n"
+ "\n"
+ "(function noise4\n"
+ " (signature vec4\n"
+ " (parameters\n"
+ " (declare (in ) float x@0x1552050)\n"
+ " )\n"
+ " (\n"
+ " ))\n"
+ "\n"
+ " (signature vec4\n"
+ " (parameters\n"
+ " (declare (in ) vec2 x@0x1552400)\n"
+ " )\n"
+ " (\n"
+ " ))\n"
+ "\n"
+ " (signature vec4\n"
+ " (parameters\n"
+ " (declare (in ) vec3 x@0x15525e0)\n"
+ " )\n"
+ " (\n"
+ " ))\n"
+ "\n"
+ " (signature vec4\n"
+ " (parameters\n"
+ " (declare (in ) vec4 x@0x15527c0)\n"
+ " )\n"
+ " (\n"
+ " ))\n"
+ "\n"
+ ")\n"
+ "\n"
+ "\n"
+ ")"
+;
+static const char *functions_for_110_frag [] = {
+ builtin_clamp,
+ builtin_matrixCompMult,
+ builtin_noise2,
+ builtin_pow,
+ builtin_texture2DProj,
+ builtin_fwidth,
+ builtin_greaterThanEqual,
+ builtin_sign,
+ builtin_texture3DProj,
+ builtin_texture2D,
+ builtin_equal,
+ builtin_faceforward,
+ builtin_tan,
+ builtin_any,
+ builtin_normalize,
+ builtin_asin,
+ builtin_texture1DProj,
+ builtin_log,
+ builtin_floor,
+ builtin_exp2,
+ builtin_lessThan,
+ builtin_cross,
+ builtin_sqrt,
+ builtin_shadow2DProj,
+ builtin_fract,
+ builtin_abs,
+ builtin_degrees,
+ builtin_dFdx,
+ builtin_sin,
+ builtin_shadow2D,
+ builtin_all,
+ builtin_log2,
+ builtin_atan,
+ builtin_notEqual,
+ builtin_max,
+ builtin_lessThanEqual,
+ builtin_shadow1DProj,
+ builtin_ceil,
+ builtin_reflect,
+ builtin_step,
+ builtin_texture1D,
+ builtin_greaterThan,
+ builtin_texture3D,
+ builtin_not,
+ builtin_inversesqrt,
+ builtin_mod,
+ builtin_noise4,
+ builtin_distance,
+ builtin_cos,
+ builtin_shadow1D,
+ builtin_noise1,
+ builtin_refract,
+ builtin_noise3,
+ builtin_min,
+ builtin_radians,
+ builtin_smoothstep,
+ builtin_textureCube,
+ builtin_length,
+ builtin_dFdy,
+ builtin_exp,
+ builtin_acos,
+ builtin_mix,
+ builtin_dot,
+};
+static const char *prototypes_for_EXT_texture_array_vert =
+ "(\n"
+ "(function texture1DArray\n"
+ " (signature vec4\n"
+ " (parameters\n"
+ " (declare (in ) sampler1DArray sampler@0x25ee5c0)\n"
+ " (declare (in ) vec2 coord@0x25ee6e0)\n"
+ " )\n"
+ " (\n"
+ " ))\n"
+ "\n"
+ ")\n"
+ "\n"
+ "(function texture1DArrayLod\n"
+ " (signature vec4\n"
+ " (parameters\n"
+ " (declare (in ) sampler1DArray sampler@0x25eeaa0)\n"
+ " (declare (in ) vec2 coord@0x25eebc0)\n"
+ " (declare (in ) float lod@0x25eecd0)\n"
+ " )\n"
+ " (\n"
+ " ))\n"
+ "\n"
+ ")\n"
+ "\n"
+ "(function texture2DArray\n"
+ " (signature vec4\n"
+ " (parameters\n"
+ " (declare (in ) sampler1DArray sampler@0x25ef090)\n"
+ " (declare (in ) vec2 coord@0x25ef1b0)\n"
+ " )\n"
+ " (\n"
+ " ))\n"
+ "\n"
+ ")\n"
+ "\n"
+ "(function texture2DArrayLod\n"
+ " (signature vec4\n"
+ " (parameters\n"
+ " (declare (in ) sampler1DArray sampler@0x25ef570)\n"
+ " (declare (in ) vec2 coord@0x25ef690)\n"
+ " (declare (in ) float lod@0x25ef7a0)\n"
+ " )\n"
+ " (\n"
+ " ))\n"
+ "\n"
+ ")\n"
+ "\n"
+ "(function shadow1DArray\n"
+ " (signature vec4\n"
+ " (parameters\n"
+ " (declare (in ) sampler1DArrayShadow sampler@0x25efb60)\n"
+ " (declare (in ) vec3 coord@0x25efc80)\n"
+ " )\n"
+ " (\n"
+ " ))\n"
+ "\n"
+ ")\n"
+ "\n"
+ "(function shadow1DArrayLod\n"
+ " (signature vec4\n"
+ " (parameters\n"
+ " (declare (in ) sampler1DArrayShadow sampler@0x25f0040)\n"
+ " (declare (in ) vec3 coord@0x25f0160)\n"
+ " (declare (in ) float lod@0x25f0270)\n"
+ " )\n"
+ " (\n"
+ " ))\n"
+ "\n"
+ ")\n"
+ "\n"
+ "(function shadow2DArray\n"
+ " (signature vec4\n"
+ " (parameters\n"
+ " (declare (in ) sampler2DArrayShadow sampler@0x25f0630)\n"
+ " (declare (in ) vec4 coord@0x25f0750)\n"
+ " )\n"
+ " (\n"
+ " ))\n"
+ "\n"
+ ")\n"
+ "\n"
+ "\n"
+ ")"
+;
+static const char *functions_for_EXT_texture_array_vert [] = {
+ builtin_texture1DArrayLod,
+ builtin_shadow2DArray,
+ builtin_texture2DArrayLod,
+ builtin_shadow1DArrayLod,
+ builtin_shadow1DArray,
+ builtin_texture2DArray,
+ builtin_texture1DArray,
+};
+static const char *prototypes_for_ARB_texture_rectangle_vert =
+ "(\n"
+ "(function texture2DRect\n"
+ " (signature vec4\n"
+ " (parameters\n"
+ " (declare (in ) sampler2DRect sampler@0x1cc28a0)\n"
+ " (declare (in ) vec2 coord@0x1cc29c0)\n"
+ " )\n"
+ " (\n"
+ " ))\n"
+ "\n"
+ ")\n"
+ "\n"
+ "(function texture2DRectProj\n"
+ " (signature vec4\n"
+ " (parameters\n"
+ " (declare (in ) sampler2DRect sampler@0x1cc2d80)\n"
+ " (declare (in ) vec3 coord@0x1cc2ea0)\n"
+ " )\n"
+ " (\n"
+ " ))\n"
+ "\n"
+ " (signature vec4\n"
+ " (parameters\n"
+ " (declare (in ) sampler2DRect sampler@0x1cc3260)\n"
+ " (declare (in ) vec4 coord@0x1cc3380)\n"
+ " )\n"
+ " (\n"
+ " ))\n"
+ "\n"
+ ")\n"
+ "\n"
+ "(function shadow2DRect\n"
+ " (signature vec4\n"
+ " (parameters\n"
+ " (declare (in ) sampler2DRectShadow sampler@0x1cc3560)\n"
+ " (declare (in ) vec3 coord@0x1cc3680)\n"
+ " )\n"
+ " (\n"
+ " ))\n"
+ "\n"
+ ")\n"
+ "\n"
+ "(function shadow2DRectProj\n"
+ " (signature vec4\n"
+ " (parameters\n"
+ " (declare (in ) sampler2DRectShadow sampler@0x1cc3a40)\n"
+ " (declare (in ) vec4 coord@0x1cc3b60)\n"
+ " )\n"
+ " (\n"
+ " ))\n"
+ "\n"
+ ")\n"
+ "\n"
+ "\n"
+ ")"
+;
+static const char *functions_for_ARB_texture_rectangle_vert [] = {
+ builtin_texture2DRect,
+ builtin_shadow2DRectProj,
+ builtin_shadow2DRect,
+ builtin_texture2DRectProj,
+};
+static const char *prototypes_for_ARB_texture_rectangle_frag =
+ "(\n"
+ "(function texture2DRect\n"
+ " (signature vec4\n"
+ " (parameters\n"
+ " (declare (in ) sampler2DRect sampler@0x13d0040)\n"
+ " (declare (in ) vec2 coord@0x13d0160)\n"
+ " )\n"
+ " (\n"
+ " ))\n"
+ "\n"
+ ")\n"
+ "\n"
+ "(function texture2DRectProj\n"
+ " (signature vec4\n"
+ " (parameters\n"
+ " (declare (in ) sampler2DRect sampler@0x13d0520)\n"
+ " (declare (in ) vec3 coord@0x13d0640)\n"
+ " )\n"
+ " (\n"
+ " ))\n"
+ "\n"
+ " (signature vec4\n"
+ " (parameters\n"
+ " (declare (in ) sampler2DRect sampler@0x13d0a00)\n"
+ " (declare (in ) vec4 coord@0x13d0b20)\n"
+ " )\n"
+ " (\n"
+ " ))\n"
+ "\n"
+ ")\n"
+ "\n"
+ "(function shadow2DRect\n"
+ " (signature vec4\n"
+ " (parameters\n"
+ " (declare (in ) sampler2DRectShadow sampler@0x13d0d00)\n"
+ " (declare (in ) vec3 coord@0x13d0e20)\n"
+ " )\n"
+ " (\n"
+ " ))\n"
+ "\n"
+ ")\n"
+ "\n"
+ "(function shadow2DRectProj\n"
+ " (signature vec4\n"
+ " (parameters\n"
+ " (declare (in ) sampler2DRectShadow sampler@0x13d11e0)\n"
+ " (declare (in ) vec4 coord@0x13d1300)\n"
+ " )\n"
+ " (\n"
+ " ))\n"
+ "\n"
+ ")\n"
+ "\n"
+ "\n"
+ ")"
+;
+static const char *functions_for_ARB_texture_rectangle_frag [] = {
+ builtin_texture2DRect,
+ builtin_shadow2DRectProj,
+ builtin_shadow2DRect,
+ builtin_texture2DRectProj,
+};
+static const char *prototypes_for_120_frag =
+ "(\n"
+ "(function radians\n"
+ " (signature float\n"
+ " (parameters\n"
+ " (declare (in ) float degrees@0x8b57e0)\n"
+ " )\n"
+ " (\n"
+ " ))\n"
+ "\n"
+ " (signature vec2\n"
+ " (parameters\n"
+ " (declare (in ) vec2 degrees@0x8b5bb0)\n"
+ " )\n"
+ " (\n"
+ " ))\n"
+ "\n"
+ " (signature vec3\n"
+ " (parameters\n"
+ " (declare (in ) vec3 degrees@0x8b5da0)\n"
+ " )\n"
+ " (\n"
+ " ))\n"
+ "\n"
+ " (signature vec4\n"
+ " (parameters\n"
+ " (declare (in ) vec4 degrees@0x8b5f90)\n"
+ " )\n"
+ " (\n"
+ " ))\n"
+ "\n"
+ ")\n"
+ "\n"
+ "(function degrees\n"
+ " (signature float\n"
+ " (parameters\n"
+ " (declare (in ) float radians@0x8b6180)\n"
+ " )\n"
+ " (\n"
+ " ))\n"
+ "\n"
+ " (signature vec2\n"
+ " (parameters\n"
+ " (declare (in ) vec2 radians@0x8b6550)\n"
+ " )\n"
+ " (\n"
+ " ))\n"
+ "\n"
+ " (signature vec3\n"
+ " (parameters\n"
+ " (declare (in ) vec3 radians@0x8b6740)\n"
+ " )\n"
+ " (\n"
+ " ))\n"
+ "\n"
+ " (signature vec4\n"
+ " (parameters\n"
+ " (declare (in ) vec4 radians@0x8b6930)\n"
+ " )\n"
+ " (\n"
+ " ))\n"
+ "\n"
+ ")\n"
+ "\n"
+ "(function sin\n"
+ " (signature float\n"
+ " (parameters\n"
+ " (declare (in ) float angle@0x8b6b20)\n"
+ " )\n"
+ " (\n"
+ " ))\n"
+ "\n"
+ " (signature vec2\n"
+ " (parameters\n"
+ " (declare (in ) vec2 angle@0x8b6ed0)\n"
+ " )\n"
+ " (\n"
+ " ))\n"
+ "\n"
+ " (signature vec3\n"
+ " (parameters\n"
+ " (declare (in ) vec3 angle@0x8b70b0)\n"
+ " )\n"
+ " (\n"
+ " ))\n"
+ "\n"
+ " (signature vec4\n"
+ " (parameters\n"
+ " (declare (in ) vec4 angle@0x8b7290)\n"
+ " )\n"
+ " (\n"
+ " ))\n"
+ "\n"
+ ")\n"
+ "\n"
+ "(function cos\n"
+ " (signature float\n"
+ " (parameters\n"
+ " (declare (in ) float angle@0x8b7470)\n"
+ " )\n"
+ " (\n"
+ " ))\n"
+ "\n"
+ " (signature vec2\n"
+ " (parameters\n"
+ " (declare (in ) vec2 angle@0x8b7820)\n"
+ " )\n"
+ " (\n"
+ " ))\n"
+ "\n"
+ " (signature vec3\n"
+ " (parameters\n"
+ " (declare (in ) vec3 angle@0x8b7a00)\n"
+ " )\n"
+ " (\n"
+ " ))\n"
+ "\n"
+ " (signature vec4\n"
+ " (parameters\n"
+ " (declare (in ) vec4 angle@0x8b7be0)\n"
+ " )\n"
+ " (\n"
+ " ))\n"
+ "\n"
+ ")\n"
+ "\n"
+ "(function tan\n"
+ " (signature float\n"
+ " (parameters\n"
+ " (declare (in ) float angle@0x8b7dc0)\n"
+ " )\n"
+ " (\n"
+ " ))\n"
+ "\n"
+ " (signature vec2\n"
+ " (parameters\n"
+ " (declare (in ) vec2 angle@0x8b8170)\n"
+ " )\n"
+ " (\n"
+ " ))\n"
+ "\n"
+ " (signature vec3\n"
+ " (parameters\n"
+ " (declare (in ) vec3 angle@0x8b8350)\n"
+ " )\n"
+ " (\n"
+ " ))\n"
+ "\n"
+ " (signature vec4\n"
+ " (parameters\n"
+ " (declare (in ) vec4 angle@0x8b8530)\n"
+ " )\n"
+ " (\n"
+ " ))\n"
+ "\n"
+ ")\n"
+ "\n"
+ "(function asin\n"
+ " (signature float\n"
+ " (parameters\n"
+ " (declare (in ) float angle@0x8b8710)\n"
+ " )\n"
+ " (\n"
+ " ))\n"
+ "\n"
+ " (signature vec2\n"
+ " (parameters\n"
+ " (declare (in ) vec2 angle@0x8b8ac0)\n"
+ " )\n"
+ " (\n"
+ " ))\n"
+ "\n"
+ " (signature vec3\n"
+ " (parameters\n"
+ " (declare (in ) vec3 angle@0x8b8ca0)\n"
+ " )\n"
+ " (\n"
+ " ))\n"
+ "\n"
+ " (signature vec4\n"
+ " (parameters\n"
+ " (declare (in ) vec4 angle@0x8b8e80)\n"
+ " )\n"
+ " (\n"
+ " ))\n"
+ "\n"
+ ")\n"
+ "\n"
+ "(function acos\n"
+ " (signature float\n"
+ " (parameters\n"
+ " (declare (in ) float angle@0x8b9060)\n"
+ " )\n"
+ " (\n"
+ " ))\n"
+ "\n"
+ " (signature vec2\n"
+ " (parameters\n"
+ " (declare (in ) vec2 angle@0x8b9410)\n"
+ " )\n"
+ " (\n"
+ " ))\n"
+ "\n"
+ " (signature vec3\n"
+ " (parameters\n"
+ " (declare (in ) vec3 angle@0x8b95f0)\n"
+ " )\n"
+ " (\n"
+ " ))\n"
+ "\n"
+ " (signature vec4\n"
+ " (parameters\n"
+ " (declare (in ) vec4 angle@0x8b97d0)\n"
+ " )\n"
+ " (\n"
+ " ))\n"
+ "\n"
+ ")\n"
+ "\n"
+ "(function atan\n"
+ " (signature float\n"
+ " (parameters\n"
+ " (declare (in ) float y@0x8b99b0)\n"
+ " (declare (in ) float x@0x8b9ac0)\n"
+ " )\n"
+ " (\n"
+ " ))\n"
+ "\n"
+ " (signature vec2\n"
+ " (parameters\n"
+ " (declare (in ) vec2 y@0x8b9e70)\n"
+ " (declare (in ) vec2 x@0x8b9f80)\n"
+ " )\n"
+ " (\n"
+ " ))\n"
+ "\n"
+ " (signature vec3\n"
+ " (parameters\n"
+ " (declare (in ) vec3 y@0x8ba160)\n"
+ " (declare (in ) vec3 x@0x8ba270)\n"
+ " )\n"
+ " (\n"
+ " ))\n"
+ "\n"
+ " (signature vec4\n"
+ " (parameters\n"
+ " (declare (in ) vec4 y@0x8ba450)\n"
+ " (declare (in ) vec4 x@0x8ba560)\n"
+ " )\n"
+ " (\n"
+ " ))\n"
+ "\n"
+ " (signature float\n"
+ " (parameters\n"
+ " (declare (in ) float y_over_x@0x8ba740)\n"
+ " )\n"
+ " (\n"
+ " ))\n"
+ "\n"
+ " (signature vec2\n"
+ " (parameters\n"
+ " (declare (in ) vec2 y_over_x@0x8ba930)\n"
+ " )\n"
+ " (\n"
+ " ))\n"
+ "\n"
+ " (signature vec3\n"
+ " (parameters\n"
+ " (declare (in ) vec3 y_over_x@0x8bab20)\n"
+ " )\n"
+ " (\n"
+ " ))\n"
+ "\n"
+ " (signature vec4\n"
+ " (parameters\n"
+ " (declare (in ) vec4 y_over_x@0x8bad10)\n"
+ " )\n"
+ " (\n"
+ " ))\n"
+ "\n"
+ ")\n"
+ "\n"
+ "(function pow\n"
+ " (signature float\n"
+ " (parameters\n"
+ " (declare (in ) float x@0x8baf00)\n"
+ " (declare (in ) float y@0x8bb010)\n"
+ " )\n"
+ " (\n"
+ " ))\n"
+ "\n"
+ " (signature vec2\n"
+ " (parameters\n"
+ " (declare (in ) vec2 x@0x8bb3c0)\n"
+ " (declare (in ) vec2 y@0x8bb4d0)\n"
+ " )\n"
+ " (\n"
+ " ))\n"
+ "\n"
+ " (signature vec3\n"
+ " (parameters\n"
+ " (declare (in ) vec3 x@0x8bb6b0)\n"
+ " (declare (in ) vec3 y@0x8bb7c0)\n"
+ " )\n"
+ " (\n"
+ " ))\n"
+ "\n"
+ " (signature vec4\n"
+ " (parameters\n"
+ " (declare (in ) vec4 x@0x8bb9a0)\n"
+ " (declare (in ) vec4 y@0x8bbab0)\n"
+ " )\n"
+ " (\n"
+ " ))\n"
+ "\n"
+ ")\n"
+ "\n"
+ "(function exp\n"
+ " (signature float\n"
+ " (parameters\n"
+ " (declare (in ) float x@0x8bbc90)\n"
+ " )\n"
+ " (\n"
+ " ))\n"
+ "\n"
+ " (signature vec2\n"
+ " (parameters\n"
+ " (declare (in ) vec2 x@0x8bc040)\n"
+ " )\n"
+ " (\n"
+ " ))\n"
+ "\n"
+ " (signature vec3\n"
+ " (parameters\n"
+ " (declare (in ) vec3 x@0x8bc220)\n"
+ " )\n"
+ " (\n"
+ " ))\n"
+ "\n"
+ " (signature vec4\n"
+ " (parameters\n"
+ " (declare (in ) vec4 x@0x8bc400)\n"
+ " )\n"
+ " (\n"
+ " ))\n"
+ "\n"
+ ")\n"
+ "\n"
+ "(function log\n"
+ " (signature float\n"
+ " (parameters\n"
+ " (declare (in ) float x@0x8bc5e0)\n"
+ " )\n"
+ " (\n"
+ " ))\n"
+ "\n"
+ " (signature vec2\n"
+ " (parameters\n"
+ " (declare (in ) vec2 x@0x8bc990)\n"
+ " )\n"
+ " (\n"
+ " ))\n"
+ "\n"
+ " (signature vec3\n"
+ " (parameters\n"
+ " (declare (in ) vec3 x@0x8bcb70)\n"
+ " )\n"
+ " (\n"
+ " ))\n"
+ "\n"
+ " (signature vec4\n"
+ " (parameters\n"
+ " (declare (in ) vec4 x@0x8bcd50)\n"
+ " )\n"
+ " (\n"
+ " ))\n"
+ "\n"
+ ")\n"
+ "\n"
+ "(function exp2\n"
+ " (signature float\n"
+ " (parameters\n"
+ " (declare (in ) float x@0x8bcf30)\n"
+ " )\n"
+ " (\n"
+ " ))\n"
+ "\n"
+ " (signature vec2\n"
+ " (parameters\n"
+ " (declare (in ) vec2 x@0x8bd2e0)\n"
+ " )\n"
+ " (\n"
+ " ))\n"
+ "\n"
+ " (signature vec3\n"
+ " (parameters\n"
+ " (declare (in ) vec3 x@0x8bd4c0)\n"
+ " )\n"
+ " (\n"
+ " ))\n"
+ "\n"
+ " (signature vec4\n"
+ " (parameters\n"
+ " (declare (in ) vec4 x@0x8bd6a0)\n"
+ " )\n"
+ " (\n"
+ " ))\n"
+ "\n"
+ ")\n"
+ "\n"
+ "(function log2\n"
+ " (signature float\n"
+ " (parameters\n"
+ " (declare (in ) float x@0x8bd880)\n"
+ " )\n"
+ " (\n"
+ " ))\n"
+ "\n"
+ " (signature vec2\n"
+ " (parameters\n"
+ " (declare (in ) vec2 x@0x8bdc30)\n"
+ " )\n"
+ " (\n"
+ " ))\n"
+ "\n"
+ " (signature vec3\n"
+ " (parameters\n"
+ " (declare (in ) vec3 x@0x8bde10)\n"
+ " )\n"
+ " (\n"
+ " ))\n"
+ "\n"
+ " (signature vec4\n"
+ " (parameters\n"
+ " (declare (in ) vec4 x@0x8bdff0)\n"
+ " )\n"
+ " (\n"
+ " ))\n"
+ "\n"
+ ")\n"
+ "\n"
+ "(function sqrt\n"
+ " (signature float\n"
+ " (parameters\n"
+ " (declare (in ) float x@0x8be1d0)\n"
+ " )\n"
+ " (\n"
+ " ))\n"
+ "\n"
+ " (signature vec2\n"
+ " (parameters\n"
+ " (declare (in ) vec2 x@0x8be580)\n"
+ " )\n"
+ " (\n"
+ " ))\n"
+ "\n"
+ " (signature vec3\n"
+ " (parameters\n"
+ " (declare (in ) vec3 x@0x8be760)\n"
+ " )\n"
+ " (\n"
+ " ))\n"
+ "\n"
+ " (signature vec4\n"
+ " (parameters\n"
+ " (declare (in ) vec4 x@0x8be940)\n"
+ " )\n"
+ " (\n"
+ " ))\n"
+ "\n"
+ ")\n"
+ "\n"
+ "(function inversesqrt\n"
+ " (signature float\n"
+ " (parameters\n"
+ " (declare (in ) float x@0x8beb20)\n"
+ " )\n"
+ " (\n"
+ " ))\n"
+ "\n"
+ " (signature vec2\n"
+ " (parameters\n"
+ " (declare (in ) vec2 x@0x8beee0)\n"
+ " )\n"
+ " (\n"
+ " ))\n"
+ "\n"
+ " (signature vec3\n"
+ " (parameters\n"
+ " (declare (in ) vec3 x@0x8bf0c0)\n"
+ " )\n"
+ " (\n"
+ " ))\n"
+ "\n"
+ " (signature vec4\n"
+ " (parameters\n"
+ " (declare (in ) vec4 x@0x8bf2a0)\n"
+ " )\n"
+ " (\n"
+ " ))\n"
+ "\n"
+ ")\n"
+ "\n"
+ "(function abs\n"
+ " (signature float\n"
+ " (parameters\n"
+ " (declare (in ) float x@0x8bf480)\n"
+ " )\n"
+ " (\n"
+ " ))\n"
+ "\n"
+ " (signature vec2\n"
+ " (parameters\n"
+ " (declare (in ) vec2 x@0x8bf830)\n"
+ " )\n"
+ " (\n"
+ " ))\n"
+ "\n"
+ " (signature vec3\n"
+ " (parameters\n"
+ " (declare (in ) vec3 x@0x8bfa10)\n"
+ " )\n"
+ " (\n"
+ " ))\n"
+ "\n"
+ " (signature vec4\n"
+ " (parameters\n"
+ " (declare (in ) vec4 x@0x8bfbf0)\n"
+ " )\n"
+ " (\n"
+ " ))\n"
+ "\n"
+ ")\n"
+ "\n"
+ "(function sign\n"
+ " (signature float\n"
+ " (parameters\n"
+ " (declare (in ) float x@0x8bfdd0)\n"
+ " )\n"
+ " (\n"
+ " ))\n"
+ "\n"
+ " (signature vec2\n"
+ " (parameters\n"
+ " (declare (in ) vec2 x@0x8c0180)\n"
+ " )\n"
+ " (\n"
+ " ))\n"
+ "\n"
+ " (signature vec3\n"
+ " (parameters\n"
+ " (declare (in ) vec3 x@0x8c0360)\n"
+ " )\n"
+ " (\n"
+ " ))\n"
+ "\n"
+ " (signature vec4\n"
+ " (parameters\n"
+ " (declare (in ) vec4 x@0x8c0540)\n"
+ " )\n"
+ " (\n"
+ " ))\n"
+ "\n"
+ ")\n"
+ "\n"
+ "(function floor\n"
+ " (signature float\n"
+ " (parameters\n"
+ " (declare (in ) float x@0x8c0720)\n"
+ " )\n"
+ " (\n"
+ " ))\n"
+ "\n"
+ " (signature vec2\n"
+ " (parameters\n"
+ " (declare (in ) vec2 x@0x8c0ad0)\n"
+ " )\n"
+ " (\n"
+ " ))\n"
+ "\n"
+ " (signature vec3\n"
+ " (parameters\n"
+ " (declare (in ) vec3 x@0x8c0cb0)\n"
+ " )\n"
+ " (\n"
+ " ))\n"
+ "\n"
+ " (signature vec4\n"
+ " (parameters\n"
+ " (declare (in ) vec4 x@0x8c0e90)\n"
+ " )\n"
+ " (\n"
+ " ))\n"
+ "\n"
+ ")\n"
+ "\n"
+ "(function ceil\n"
+ " (signature float\n"
+ " (parameters\n"
+ " (declare (in ) float x@0x8c1070)\n"
+ " )\n"
+ " (\n"
+ " ))\n"
+ "\n"
+ " (signature vec2\n"
+ " (parameters\n"
+ " (declare (in ) vec2 x@0x8c1420)\n"
+ " )\n"
+ " (\n"
+ " ))\n"
+ "\n"
+ " (signature vec3\n"
+ " (parameters\n"
+ " (declare (in ) vec3 x@0x8c1600)\n"
+ " )\n"
+ " (\n"
+ " ))\n"
+ "\n"
+ " (signature vec4\n"
+ " (parameters\n"
+ " (declare (in ) vec4 x@0x8c17e0)\n"
+ " )\n"
+ " (\n"
+ " ))\n"
+ "\n"
+ ")\n"
+ "\n"
+ "(function fract\n"
+ " (signature float\n"
+ " (parameters\n"
+ " (declare (in ) float x@0x8c19c0)\n"
+ " )\n"
+ " (\n"
+ " ))\n"
+ "\n"
+ " (signature vec2\n"
+ " (parameters\n"
+ " (declare (in ) vec2 x@0x8c1d70)\n"
+ " )\n"
+ " (\n"
+ " ))\n"
+ "\n"
+ " (signature vec3\n"
+ " (parameters\n"
+ " (declare (in ) vec3 x@0x8c1f50)\n"
+ " )\n"
+ " (\n"
+ " ))\n"
+ "\n"
+ " (signature vec4\n"
+ " (parameters\n"
+ " (declare (in ) vec4 x@0x8c2130)\n"
+ " )\n"
+ " (\n"
+ " ))\n"
+ "\n"
+ ")\n"
+ "\n"
+ "(function mod\n"
+ " (signature float\n"
+ " (parameters\n"
+ " (declare (in ) float x@0x8c2310)\n"
+ " (declare (in ) float y@0x8c2420)\n"
+ " )\n"
+ " (\n"
+ " ))\n"
+ "\n"
+ " (signature vec2\n"
+ " (parameters\n"
+ " (declare (in ) vec2 x@0x8c27d0)\n"
+ " (declare (in ) float y@0x8c28e0)\n"
+ " )\n"
+ " (\n"
+ " ))\n"
+ "\n"
+ " (signature vec3\n"
+ " (parameters\n"
+ " (declare (in ) vec3 x@0x8c2ac0)\n"
+ " (declare (in ) float y@0x8c2bd0)\n"
+ " )\n"
+ " (\n"
+ " ))\n"
+ "\n"
+ " (signature vec4\n"
+ " (parameters\n"
+ " (declare (in ) vec4 x@0x8c2db0)\n"
+ " (declare (in ) float y@0x8c2ec0)\n"
+ " )\n"
+ " (\n"
+ " ))\n"
+ "\n"
+ " (signature vec2\n"
+ " (parameters\n"
+ " (declare (in ) vec2 x@0x8c30a0)\n"
+ " (declare (in ) vec2 y@0x8c31b0)\n"
+ " )\n"
+ " (\n"
+ " ))\n"
+ "\n"
+ " (signature vec3\n"
+ " (parameters\n"
+ " (declare (in ) vec3 x@0x8c3390)\n"
+ " (declare (in ) vec3 y@0x8c34a0)\n"
+ " )\n"
+ " (\n"
+ " ))\n"
+ "\n"
+ " (signature vec4\n"
+ " (parameters\n"
+ " (declare (in ) vec4 x@0x8c3680)\n"
+ " (declare (in ) vec4 y@0x8c3790)\n"
+ " )\n"
+ " (\n"
+ " ))\n"
+ "\n"
+ ")\n"
+ "\n"
+ "(function min\n"
+ " (signature float\n"
+ " (parameters\n"
+ " (declare (in ) float x@0x8c3970)\n"
+ " (declare (in ) float y@0x8c3a80)\n"
+ " )\n"
+ " (\n"
+ " ))\n"
+ "\n"
+ " (signature vec2\n"
+ " (parameters\n"
+ " (declare (in ) vec2 x@0x8c3e30)\n"
+ " (declare (in ) vec2 y@0x8c3f40)\n"
+ " )\n"
+ " (\n"
+ " ))\n"
+ "\n"
+ " (signature vec3\n"
+ " (parameters\n"
+ " (declare (in ) vec3 x@0x8c4120)\n"
+ " (declare (in ) vec3 y@0x8c4230)\n"
+ " )\n"
+ " (\n"
+ " ))\n"
+ "\n"
+ " (signature vec4\n"
+ " (parameters\n"
+ " (declare (in ) vec4 x@0x8c4410)\n"
+ " (declare (in ) vec4 y@0x8c4520)\n"
+ " )\n"
+ " (\n"
+ " ))\n"
+ "\n"
+ " (signature vec2\n"
+ " (parameters\n"
+ " (declare (in ) vec2 x@0x8c4700)\n"
+ " (declare (in ) float y@0x8c4810)\n"
+ " )\n"
+ " (\n"
+ " ))\n"
+ "\n"
+ " (signature vec3\n"
+ " (parameters\n"
+ " (declare (in ) vec3 x@0x8c49f0)\n"
+ " (declare (in ) float y@0x8c4b00)\n"
+ " )\n"
+ " (\n"
+ " ))\n"
+ "\n"
+ " (signature vec4\n"
+ " (parameters\n"
+ " (declare (in ) vec4 x@0x8c4ce0)\n"
+ " (declare (in ) float y@0x8c4df0)\n"
+ " )\n"
+ " (\n"
+ " ))\n"
+ "\n"
+ ")\n"
+ "\n"
+ "(function max\n"
+ " (signature float\n"
+ " (parameters\n"
+ " (declare (in ) float x@0x8c4fd0)\n"
+ " (declare (in ) float y@0x8c50e0)\n"
+ " )\n"
+ " (\n"
+ " ))\n"
+ "\n"
+ " (signature vec2\n"
+ " (parameters\n"
+ " (declare (in ) vec2 x@0x8c5490)\n"
+ " (declare (in ) vec2 y@0x8c55a0)\n"
+ " )\n"
+ " (\n"
+ " ))\n"
+ "\n"
+ " (signature vec3\n"
+ " (parameters\n"
+ " (declare (in ) vec3 x@0x8c5780)\n"
+ " (declare (in ) vec3 y@0x8c5890)\n"
+ " )\n"
+ " (\n"
+ " ))\n"
+ "\n"
+ " (signature vec4\n"
+ " (parameters\n"
+ " (declare (in ) vec4 x@0x8c5a70)\n"
+ " (declare (in ) vec4 y@0x8c5b80)\n"
+ " )\n"
+ " (\n"
+ " ))\n"
+ "\n"
+ " (signature vec2\n"
+ " (parameters\n"
+ " (declare (in ) vec2 x@0x8c5d60)\n"
+ " (declare (in ) float y@0x8c5e70)\n"
+ " )\n"
+ " (\n"
+ " ))\n"
+ "\n"
+ " (signature vec3\n"
+ " (parameters\n"
+ " (declare (in ) vec3 x@0x8c6050)\n"
+ " (declare (in ) float y@0x8c6160)\n"
+ " )\n"
+ " (\n"
+ " ))\n"
+ "\n"
+ " (signature vec4\n"
+ " (parameters\n"
+ " (declare (in ) vec4 x@0x8c6340)\n"
+ " (declare (in ) float y@0x8c6450)\n"
+ " )\n"
+ " (\n"
+ " ))\n"
+ "\n"
+ ")\n"
+ "\n"
+ "(function clamp\n"
+ " (signature float\n"
+ " (parameters\n"
+ " (declare (in ) float x@0x8c6630)\n"
+ " (declare (in ) float minVal@0x8c6740)\n"
+ " (declare (in ) float maxVal@0x8c6850)\n"
+ " )\n"
+ " (\n"
+ " ))\n"
+ "\n"
+ " (signature vec2\n"
+ " (parameters\n"
+ " (declare (in ) vec2 x@0x8c6c00)\n"
+ " (declare (in ) vec2 minVal@0x8c6d10)\n"
+ " (declare (in ) vec2 maxVal@0x8c6e20)\n"
+ " )\n"
+ " (\n"
+ " ))\n"
+ "\n"
+ " (signature vec3\n"
+ " (parameters\n"
+ " (declare (in ) vec3 x@0x8c7000)\n"
+ " (declare (in ) vec3 minVal@0x8c7110)\n"
+ " (declare (in ) vec3 maxVal@0x8c7220)\n"
+ " )\n"
+ " (\n"
+ " ))\n"
+ "\n"
+ " (signature vec4\n"
+ " (parameters\n"
+ " (declare (in ) vec4 x@0x8c7400)\n"
+ " (declare (in ) vec4 minVal@0x8c7510)\n"
+ " (declare (in ) vec4 maxVal@0x8c7620)\n"
+ " )\n"
+ " (\n"
+ " ))\n"
+ "\n"
+ " (signature vec2\n"
+ " (parameters\n"
+ " (declare (in ) vec2 x@0x8c7800)\n"
+ " (declare (in ) float minVal@0x8c7910)\n"
+ " (declare (in ) float maxVal@0x8c7a20)\n"
+ " )\n"
+ " (\n"
+ " ))\n"
+ "\n"
+ " (signature vec3\n"
+ " (parameters\n"
+ " (declare (in ) vec3 x@0x8c7c00)\n"
+ " (declare (in ) float minVal@0x8c7d10)\n"
+ " (declare (in ) float maxVal@0x8c7e20)\n"
+ " )\n"
+ " (\n"
+ " ))\n"
+ "\n"
+ " (signature vec4\n"
+ " (parameters\n"
+ " (declare (in ) vec4 x@0x8c8000)\n"
+ " (declare (in ) float minVal@0x8c8110)\n"
+ " (declare (in ) float maxVal@0x8c8220)\n"
+ " )\n"
+ " (\n"
+ " ))\n"
+ "\n"
+ ")\n"
+ "\n"
+ "(function mix\n"
+ " (signature float\n"
+ " (parameters\n"
+ " (declare (in ) float x@0x8c8400)\n"
+ " (declare (in ) float y@0x8c8510)\n"
+ " (declare (in ) float a@0x8c8620)\n"
+ " )\n"
+ " (\n"
+ " ))\n"
+ "\n"
+ " (signature vec2\n"
+ " (parameters\n"
+ " (declare (in ) vec2 x@0x8c89d0)\n"
+ " (declare (in ) vec2 y@0x8c8ae0)\n"
+ " (declare (in ) vec2 a@0x8c8bf0)\n"
+ " )\n"
+ " (\n"
+ " ))\n"
+ "\n"
+ " (signature vec3\n"
+ " (parameters\n"
+ " (declare (in ) vec3 x@0x8c8dd0)\n"
+ " (declare (in ) vec3 y@0x8c8ee0)\n"
+ " (declare (in ) vec3 a@0x8c8ff0)\n"
+ " )\n"
+ " (\n"
+ " ))\n"
+ "\n"
+ " (signature vec4\n"
+ " (parameters\n"
+ " (declare (in ) vec4 x@0x8c91d0)\n"
+ " (declare (in ) vec4 y@0x8c92e0)\n"
+ " (declare (in ) vec4 a@0x8c93f0)\n"
+ " )\n"
+ " (\n"
+ " ))\n"
+ "\n"
+ " (signature vec2\n"
+ " (parameters\n"
+ " (declare (in ) vec2 x@0x8c95d0)\n"
+ " (declare (in ) vec2 y@0x8c96e0)\n"
+ " (declare (in ) float a@0x8c97f0)\n"
+ " )\n"
+ " (\n"
+ " ))\n"
+ "\n"
+ " (signature vec3\n"
+ " (parameters\n"
+ " (declare (in ) vec3 x@0x8c99d0)\n"
+ " (declare (in ) vec3 y@0x8c9ae0)\n"
+ " (declare (in ) float a@0x8c9bf0)\n"
+ " )\n"
+ " (\n"
+ " ))\n"
+ "\n"
+ " (signature vec4\n"
+ " (parameters\n"
+ " (declare (in ) vec4 x@0x8c9dd0)\n"
+ " (declare (in ) vec4 y@0x8c9ee0)\n"
+ " (declare (in ) float a@0x8c9ff0)\n"
+ " )\n"
+ " (\n"
+ " ))\n"
+ "\n"
+ ")\n"
+ "\n"
+ "(function step\n"
+ " (signature float\n"
+ " (parameters\n"
+ " (declare (in ) float edge@0x8ca1d0)\n"
+ " (declare (in ) float x@0x8ca2e0)\n"
+ " )\n"
+ " (\n"
+ " ))\n"
+ "\n"
+ " (signature vec2\n"
+ " (parameters\n"
+ " (declare (in ) vec2 edge@0x8ca690)\n"
+ " (declare (in ) vec2 x@0x8ca7a0)\n"
+ " )\n"
+ " (\n"
+ " ))\n"
+ "\n"
+ " (signature vec3\n"
+ " (parameters\n"
+ " (declare (in ) vec3 edge@0x8ca980)\n"
+ " (declare (in ) vec3 x@0x8caa90)\n"
+ " )\n"
+ " (\n"
+ " ))\n"
+ "\n"
+ " (signature vec4\n"
+ " (parameters\n"
+ " (declare (in ) vec4 edge@0x8cac70)\n"
+ " (declare (in ) vec4 x@0x8cad80)\n"
+ " )\n"
+ " (\n"
+ " ))\n"
+ "\n"
+ " (signature vec2\n"
+ " (parameters\n"
+ " (declare (in ) float edge@0x8caf60)\n"
+ " (declare (in ) vec2 x@0x8cb070)\n"
+ " )\n"
+ " (\n"
+ " ))\n"
+ "\n"
+ " (signature vec3\n"
+ " (parameters\n"
+ " (declare (in ) float edge@0x8cb250)\n"
+ " (declare (in ) vec3 x@0x8cb360)\n"
+ " )\n"
+ " (\n"
+ " ))\n"
+ "\n"
+ " (signature vec4\n"
+ " (parameters\n"
+ " (declare (in ) float edge@0x8cb540)\n"
+ " (declare (in ) vec4 x@0x8cb650)\n"
+ " )\n"
+ " (\n"
+ " ))\n"
+ "\n"
+ ")\n"
+ "\n"
+ "(function smoothstep\n"
+ " (signature float\n"
+ " (parameters\n"
+ " (declare (in ) float edge0@0x8cb830)\n"
+ " (declare (in ) float edge1@0x8cb940)\n"
+ " (declare (in ) float x@0x8cba50)\n"
+ " )\n"
+ " (\n"
+ " ))\n"
+ "\n"
+ " (signature vec2\n"
+ " (parameters\n"
+ " (declare (in ) vec2 edge0@0x8cbe10)\n"
+ " (declare (in ) vec2 edge1@0x8cbf20)\n"
+ " (declare (in ) vec2 x@0x8cc030)\n"
+ " )\n"
+ " (\n"
+ " ))\n"
+ "\n"
+ " (signature vec3\n"
+ " (parameters\n"
+ " (declare (in ) vec3 edge0@0x8cc210)\n"
+ " (declare (in ) vec3 edge1@0x8cc320)\n"
+ " (declare (in ) vec3 x@0x8cc430)\n"
+ " )\n"
+ " (\n"
+ " ))\n"
+ "\n"
+ " (signature vec4\n"
+ " (parameters\n"
+ " (declare (in ) vec4 edge0@0x8cc610)\n"
+ " (declare (in ) vec4 edge1@0x8cc720)\n"
+ " (declare (in ) vec4 x@0x8cc830)\n"
+ " )\n"
+ " (\n"
+ " ))\n"
+ "\n"
+ " (signature vec2\n"
+ " (parameters\n"
+ " (declare (in ) float edge0@0x8cca10)\n"
+ " (declare (in ) float edge1@0x8ccb20)\n"
+ " (declare (in ) vec2 x@0x8ccc30)\n"
+ " )\n"
+ " (\n"
+ " ))\n"
+ "\n"
+ " (signature vec3\n"
+ " (parameters\n"
+ " (declare (in ) float edge0@0x8cce10)\n"
+ " (declare (in ) float edge1@0x8ccf20)\n"
+ " (declare (in ) vec3 x@0x8cd030)\n"
+ " )\n"
+ " (\n"
+ " ))\n"
+ "\n"
+ " (signature vec4\n"
+ " (parameters\n"
+ " (declare (in ) float edge0@0x8cd210)\n"
+ " (declare (in ) float edge1@0x8cd320)\n"
+ " (declare (in ) vec4 x@0x8cd430)\n"
+ " )\n"
+ " (\n"
+ " ))\n"
+ "\n"
+ ")\n"
+ "\n"
+ "(function length\n"
+ " (signature float\n"
+ " (parameters\n"
+ " (declare (in ) float x@0x8cd610)\n"
+ " )\n"
+ " (\n"
+ " ))\n"
+ "\n"
+ " (signature float\n"
+ " (parameters\n"
+ " (declare (in ) vec2 x@0x8cd9c0)\n"
+ " )\n"
+ " (\n"
+ " ))\n"
+ "\n"
+ " (signature float\n"
+ " (parameters\n"
+ " (declare (in ) vec3 x@0x8cdba0)\n"
+ " )\n"
+ " (\n"
+ " ))\n"
+ "\n"
+ " (signature float\n"
+ " (parameters\n"
+ " (declare (in ) vec4 x@0x8cdd80)\n"
+ " )\n"
+ " (\n"
+ " ))\n"
+ "\n"
+ ")\n"
+ "\n"
+ "(function distance\n"
+ " (signature float\n"
+ " (parameters\n"
+ " (declare (in ) float p0@0x8cdf60)\n"
+ " (declare (in ) float p1@0x8ce070)\n"
+ " )\n"
+ " (\n"
+ " ))\n"
+ "\n"
+ " (signature float\n"
+ " (parameters\n"
+ " (declare (in ) vec2 p0@0x8ce430)\n"
+ " (declare (in ) vec2 p1@0x8ce540)\n"
+ " )\n"
+ " (\n"
+ " ))\n"
+ "\n"
+ " (signature float\n"
+ " (parameters\n"
+ " (declare (in ) vec3 p0@0x8ce720)\n"
+ " (declare (in ) vec3 p1@0x8ce830)\n"
+ " )\n"
+ " (\n"
+ " ))\n"
+ "\n"
+ " (signature float\n"
+ " (parameters\n"
+ " (declare (in ) vec4 p0@0x8cea10)\n"
+ " (declare (in ) vec4 p1@0x8ceb20)\n"
+ " )\n"
+ " (\n"
+ " ))\n"
+ "\n"
+ ")\n"
+ "\n"
+ "(function dot\n"
+ " (signature float\n"
+ " (parameters\n"
+ " (declare (in ) float x@0x8ced00)\n"
+ " (declare (in ) float y@0x8cee10)\n"
+ " )\n"
+ " (\n"
+ " ))\n"
+ "\n"
+ " (signature float\n"
+ " (parameters\n"
+ " (declare (in ) vec2 x@0x8cf1c0)\n"
+ " (declare (in ) vec2 y@0x8cf2d0)\n"
+ " )\n"
+ " (\n"
+ " ))\n"
+ "\n"
+ " (signature float\n"
+ " (parameters\n"
+ " (declare (in ) vec3 x@0x8cf4b0)\n"
+ " (declare (in ) vec3 y@0x8cf5c0)\n"
+ " )\n"
+ " (\n"
+ " ))\n"
+ "\n"
+ " (signature float\n"
+ " (parameters\n"
+ " (declare (in ) vec4 x@0x8cf7a0)\n"
+ " (declare (in ) vec4 y@0x8cf8b0)\n"
+ " )\n"
+ " (\n"
+ " ))\n"
+ "\n"
+ ")\n"
+ "\n"
+ "(function cross\n"
+ " (signature vec3\n"
+ " (parameters\n"
+ " (declare (in ) vec3 x@0x8cfa90)\n"
+ " (declare (in ) vec3 y@0x8cfba0)\n"
+ " )\n"
+ " (\n"
+ " ))\n"
+ "\n"
+ ")\n"
+ "\n"
+ "(function normalize\n"
+ " (signature float\n"
+ " (parameters\n"
+ " (declare (in ) float x@0x8cff50)\n"
+ " )\n"
+ " (\n"
+ " ))\n"
+ "\n"
+ " (signature vec2\n"
+ " (parameters\n"
+ " (declare (in ) vec2 x@0x8d0310)\n"
+ " )\n"
+ " (\n"
+ " ))\n"
+ "\n"
+ " (signature vec3\n"
+ " (parameters\n"
+ " (declare (in ) vec3 x@0x8d04f0)\n"
+ " )\n"
+ " (\n"
+ " ))\n"
+ "\n"
+ " (signature vec4\n"
+ " (parameters\n"
+ " (declare (in ) vec4 x@0x8d06d0)\n"
+ " )\n"
+ " (\n"
+ " ))\n"
+ "\n"
+ ")\n"
+ "\n"
+ "(function faceforward\n"
+ " (signature float\n"
+ " (parameters\n"
+ " (declare (in ) float N@0x8d08b0)\n"
+ " (declare (in ) float I@0x8d09c0)\n"
+ " (declare (in ) float Nref@0x8d0ad0)\n"
+ " )\n"
+ " (\n"
+ " ))\n"
+ "\n"
+ " (signature vec2\n"
+ " (parameters\n"
+ " (declare (in ) vec2 N@0x8d0e90)\n"
+ " (declare (in ) vec2 I@0x8d0fa0)\n"
+ " (declare (in ) vec2 Nref@0x8d10b0)\n"
+ " )\n"
+ " (\n"
+ " ))\n"
+ "\n"
+ " (signature vec3\n"
+ " (parameters\n"
+ " (declare (in ) vec3 N@0x8d1290)\n"
+ " (declare (in ) vec3 I@0x8d13a0)\n"
+ " (declare (in ) vec3 Nref@0x8d14b0)\n"
+ " )\n"
+ " (\n"
+ " ))\n"
+ "\n"
+ " (signature vec4\n"
+ " (parameters\n"
+ " (declare (in ) vec4 N@0x8d1690)\n"
+ " (declare (in ) vec4 I@0x8d17a0)\n"
+ " (declare (in ) vec4 Nref@0x8d18b0)\n"
+ " )\n"
+ " (\n"
+ " ))\n"
+ "\n"
+ ")\n"
+ "\n"
+ "(function reflect\n"
+ " (signature float\n"
+ " (parameters\n"
+ " (declare (in ) float I@0x8d1a90)\n"
+ " (declare (in ) float N@0x8d1ba0)\n"
+ " )\n"
+ " (\n"
+ " ))\n"
+ "\n"
+ " (signature vec2\n"
+ " (parameters\n"
+ " (declare (in ) vec2 I@0x8d1f60)\n"
+ " (declare (in ) vec2 N@0x8d2070)\n"
+ " )\n"
+ " (\n"
+ " ))\n"
+ "\n"
+ " (signature vec3\n"
+ " (parameters\n"
+ " (declare (in ) vec3 I@0x8d2250)\n"
+ " (declare (in ) vec3 N@0x8d2360)\n"
+ " )\n"
+ " (\n"
+ " ))\n"
+ "\n"
+ " (signature vec4\n"
+ " (parameters\n"
+ " (declare (in ) vec4 I@0x8d2540)\n"
+ " (declare (in ) vec4 N@0x8d2650)\n"
+ " )\n"
+ " (\n"
+ " ))\n"
+ "\n"
+ ")\n"
+ "\n"
+ "(function refract\n"
+ " (signature float\n"
+ " (parameters\n"
+ " (declare (in ) float I@0x8d2830)\n"
+ " (declare (in ) float N@0x8d2940)\n"
+ " (declare (in ) float eta@0x8d2a50)\n"
+ " )\n"
+ " (\n"
+ " ))\n"
+ "\n"
+ " (signature vec2\n"
+ " (parameters\n"
+ " (declare (in ) vec2 I@0x8d2e10)\n"
+ " (declare (in ) vec2 N@0x8d2f20)\n"
+ " (declare (in ) float eta@0x8d3030)\n"
+ " )\n"
+ " (\n"
+ " ))\n"
+ "\n"
+ " (signature vec3\n"
+ " (parameters\n"
+ " (declare (in ) vec3 I@0x8d3210)\n"
+ " (declare (in ) vec3 N@0x8d3320)\n"
+ " (declare (in ) float eta@0x8d3430)\n"
+ " )\n"
+ " (\n"
+ " ))\n"
+ "\n"
+ " (signature vec4\n"
+ " (parameters\n"
+ " (declare (in ) vec4 I@0x8d3610)\n"
+ " (declare (in ) vec4 N@0x8d3720)\n"
+ " (declare (in ) float eta@0x8d3830)\n"
+ " )\n"
+ " (\n"
+ " ))\n"
+ "\n"
+ ")\n"
+ "\n"
+ "(function matrixCompMult\n"
+ " (signature mat2\n"
+ " (parameters\n"
+ " (declare (in ) mat2 x@0x8d3a10)\n"
+ " (declare (in ) mat2 y@0x8d3b20)\n"
+ " )\n"
+ " (\n"
+ " ))\n"
+ "\n"
+ " (signature mat3\n"
+ " (parameters\n"
+ " (declare (in ) mat3 x@0x8d3ee0)\n"
+ " (declare (in ) mat3 y@0x8d3ff0)\n"
+ " )\n"
+ " (\n"
+ " ))\n"
+ "\n"
+ " (signature mat4\n"
+ " (parameters\n"
+ " (declare (in ) mat4 x@0x8d41d0)\n"
+ " (declare (in ) mat4 y@0x8d42e0)\n"
+ " )\n"
+ " (\n"
+ " ))\n"
+ "\n"
+ " (signature mat2x3\n"
+ " (parameters\n"
+ " (declare (in ) mat2x3 x@0x8d44c0)\n"
+ " (declare (in ) mat2x3 y@0x8d45d0)\n"
+ " )\n"
+ " (\n"
+ " ))\n"
+ "\n"
+ " (signature mat2x4\n"
+ " (parameters\n"
+ " (declare (in ) mat2x4 x@0x8d47b0)\n"
+ " (declare (in ) mat2x4 y@0x8d48c0)\n"
+ " )\n"
+ " (\n"
+ " ))\n"
+ "\n"
+ " (signature mat3x2\n"
+ " (parameters\n"
+ " (declare (in ) mat3x2 x@0x8d4aa0)\n"
+ " (declare (in ) mat3x2 y@0x8d4bb0)\n"
+ " )\n"
+ " (\n"
+ " ))\n"
+ "\n"
+ " (signature mat3x4\n"
+ " (parameters\n"
+ " (declare (in ) mat3x4 x@0x8d4d90)\n"
+ " (declare (in ) mat3x4 y@0x8d4ea0)\n"
+ " )\n"
+ " (\n"
+ " ))\n"
+ "\n"
+ " (signature mat4x2\n"
+ " (parameters\n"
+ " (declare (in ) mat4x2 x@0x8d5080)\n"
+ " (declare (in ) mat4x2 y@0x8d5190)\n"
+ " )\n"
+ " (\n"
+ " ))\n"
+ "\n"
+ " (signature mat4x3\n"
+ " (parameters\n"
+ " (declare (in ) mat4x3 x@0x8d5370)\n"
+ " (declare (in ) mat4x3 y@0x8d5480)\n"
+ " )\n"
+ " (\n"
+ " ))\n"
+ "\n"
+ ")\n"
+ "\n"
+ "(function outerProduct\n"
+ " (signature mat2\n"
+ " (parameters\n"
+ " (declare (in ) vec2 c@0x8d5660)\n"
+ " (declare (in ) vec2 r@0x8d5770)\n"
+ " )\n"
+ " (\n"
+ " ))\n"
+ "\n"
+ " (signature mat3\n"
+ " (parameters\n"
+ " (declare (in ) vec3 c@0x8d5b30)\n"
+ " (declare (in ) vec3 r@0x8d5c40)\n"
+ " )\n"
+ " (\n"
+ " ))\n"
+ "\n"
+ " (signature mat4\n"
+ " (parameters\n"
+ " (declare (in ) vec4 c@0x8d5e20)\n"
+ " (declare (in ) vec4 r@0x8d5f30)\n"
+ " )\n"
+ " (\n"
+ " ))\n"
+ "\n"
+ " (signature mat2x3\n"
+ " (parameters\n"
+ " (declare (in ) vec3 c@0x8d6110)\n"
+ " (declare (in ) vec2 r@0x8d6220)\n"
+ " )\n"
+ " (\n"
+ " ))\n"
+ "\n"
+ " (signature mat3x2\n"
+ " (parameters\n"
+ " (declare (in ) vec2 c@0x8d6400)\n"
+ " (declare (in ) vec3 r@0x8d6510)\n"
+ " )\n"
+ " (\n"
+ " ))\n"
+ "\n"
+ " (signature mat2x4\n"
+ " (parameters\n"
+ " (declare (in ) vec4 c@0x8d66f0)\n"
+ " (declare (in ) vec2 r@0x8d6800)\n"
+ " )\n"
+ " (\n"
+ " ))\n"
+ "\n"
+ " (signature mat4x2\n"
+ " (parameters\n"
+ " (declare (in ) vec2 c@0x8d69e0)\n"
+ " (declare (in ) vec4 r@0x8d6af0)\n"
+ " )\n"
+ " (\n"
+ " ))\n"
+ "\n"
+ " (signature mat3x4\n"
+ " (parameters\n"
+ " (declare (in ) vec4 c@0x8d6cd0)\n"
+ " (declare (in ) vec3 r@0x8d6de0)\n"
+ " )\n"
+ " (\n"
+ " ))\n"
+ "\n"
+ " (signature mat4x3\n"
+ " (parameters\n"
+ " (declare (in ) vec3 c@0x8d6fc0)\n"
+ " (declare (in ) vec4 r@0x8d70d0)\n"
+ " )\n"
+ " (\n"
+ " ))\n"
+ "\n"
+ ")\n"
+ "\n"
+ "(function transpose\n"
+ " (signature mat2\n"
+ " (parameters\n"
+ " (declare (in ) mat2 m@0x8d72b0)\n"
+ " )\n"
+ " (\n"
+ " ))\n"
+ "\n"
+ " (signature mat3\n"
+ " (parameters\n"
+ " (declare (in ) mat3 m@0x8d7670)\n"
+ " )\n"
+ " (\n"
+ " ))\n"
+ "\n"
+ " (signature mat4\n"
+ " (parameters\n"
+ " (declare (in ) mat4 m@0x8d7850)\n"
+ " )\n"
+ " (\n"
+ " ))\n"
+ "\n"
+ " (signature mat2x3\n"
+ " (parameters\n"
+ " (declare (in ) mat3x2 m@0x8d7a30)\n"
+ " )\n"
+ " (\n"
+ " ))\n"
+ "\n"
+ " (signature mat3x2\n"
+ " (parameters\n"
+ " (declare (in ) mat2x3 m@0x8d7c10)\n"
+ " )\n"
+ " (\n"
+ " ))\n"
+ "\n"
+ " (signature mat2x4\n"
+ " (parameters\n"
+ " (declare (in ) mat4x2 m@0x8d7df0)\n"
+ " )\n"
+ " (\n"
+ " ))\n"
+ "\n"
+ " (signature mat4x2\n"
+ " (parameters\n"
+ " (declare (in ) mat2x4 m@0x8d7fd0)\n"
+ " )\n"
+ " (\n"
+ " ))\n"
+ "\n"
+ " (signature mat3x4\n"
+ " (parameters\n"
+ " (declare (in ) mat4x3 m@0x8d81b0)\n"
+ " )\n"
+ " (\n"
+ " ))\n"
+ "\n"
+ " (signature mat4x3\n"
+ " (parameters\n"
+ " (declare (in ) mat3x4 m@0x8d8390)\n"
+ " )\n"
+ " (\n"
+ " ))\n"
+ "\n"
+ ")\n"
+ "\n"
+ "(function lessThan\n"
+ " (signature bvec2\n"
+ " (parameters\n"
+ " (declare (in ) vec2 x@0x8d8570)\n"
+ " (declare (in ) vec2 y@0x8d8680)\n"
+ " )\n"
+ " (\n"
+ " ))\n"
+ "\n"
+ " (signature bvec3\n"
+ " (parameters\n"
+ " (declare (in ) vec3 x@0x8d8a40)\n"
+ " (declare (in ) vec3 y@0x8d8b50)\n"
+ " )\n"
+ " (\n"
+ " ))\n"
+ "\n"
+ " (signature bvec4\n"
+ " (parameters\n"
+ " (declare (in ) vec4 x@0x8d8d30)\n"
+ " (declare (in ) vec4 y@0x8d8e40)\n"
+ " )\n"
+ " (\n"
+ " ))\n"
+ "\n"
+ " (signature bvec2\n"
+ " (parameters\n"
+ " (declare (in ) ivec2 x@0x8d9020)\n"
+ " (declare (in ) ivec2 y@0x8d9130)\n"
+ " )\n"
+ " (\n"
+ " ))\n"
+ "\n"
+ " (signature bvec3\n"
+ " (parameters\n"
+ " (declare (in ) ivec3 x@0x8d9310)\n"
+ " (declare (in ) ivec3 y@0x8d9420)\n"
+ " )\n"
+ " (\n"
+ " ))\n"
+ "\n"
+ " (signature bvec4\n"
+ " (parameters\n"
+ " (declare (in ) ivec4 x@0x8d9600)\n"
+ " (declare (in ) ivec4 y@0x8d9710)\n"
+ " )\n"
+ " (\n"
+ " ))\n"
+ "\n"
+ ")\n"
+ "\n"
+ "(function lessThanEqual\n"
+ " (signature bvec2\n"
+ " (parameters\n"
+ " (declare (in ) vec2 x@0x8d98f0)\n"
+ " (declare (in ) vec2 y@0x8d9a00)\n"
+ " )\n"
+ " (\n"
+ " ))\n"
+ "\n"
+ " (signature bvec3\n"
+ " (parameters\n"
+ " (declare (in ) vec3 x@0x8d9dc0)\n"
+ " (declare (in ) vec3 y@0x8d9ed0)\n"
+ " )\n"
+ " (\n"
+ " ))\n"
+ "\n"
+ " (signature bvec4\n"
+ " (parameters\n"
+ " (declare (in ) vec4 x@0x8da0b0)\n"
+ " (declare (in ) vec4 y@0x8da1c0)\n"
+ " )\n"
+ " (\n"
+ " ))\n"
+ "\n"
+ " (signature bvec2\n"
+ " (parameters\n"
+ " (declare (in ) ivec2 x@0x8da3a0)\n"
+ " (declare (in ) ivec2 y@0x8da4b0)\n"
+ " )\n"
+ " (\n"
+ " ))\n"
+ "\n"
+ " (signature bvec3\n"
+ " (parameters\n"
+ " (declare (in ) ivec3 x@0x8da690)\n"
+ " (declare (in ) ivec3 y@0x8da7a0)\n"
+ " )\n"
+ " (\n"
+ " ))\n"
+ "\n"
+ " (signature bvec4\n"
+ " (parameters\n"
+ " (declare (in ) ivec4 x@0x8da980)\n"
+ " (declare (in ) ivec4 y@0x8daa90)\n"
+ " )\n"
+ " (\n"
+ " ))\n"
+ "\n"
+ ")\n"
+ "\n"
+ "(function greaterThan\n"
+ " (signature bvec2\n"
+ " (parameters\n"
+ " (declare (in ) vec2 x@0x8dac70)\n"
+ " (declare (in ) vec2 y@0x8dad80)\n"
+ " )\n"
+ " (\n"
+ " ))\n"
+ "\n"
+ " (signature bvec3\n"
+ " (parameters\n"
+ " (declare (in ) vec3 x@0x8db140)\n"
+ " (declare (in ) vec3 y@0x8db250)\n"
+ " )\n"
+ " (\n"
+ " ))\n"
+ "\n"
+ " (signature bvec4\n"
+ " (parameters\n"
+ " (declare (in ) vec4 x@0x8db430)\n"
+ " (declare (in ) vec4 y@0x8db540)\n"
+ " )\n"
+ " (\n"
+ " ))\n"
+ "\n"
+ " (signature bvec2\n"
+ " (parameters\n"
+ " (declare (in ) ivec2 x@0x8db720)\n"
+ " (declare (in ) ivec2 y@0x8db830)\n"
+ " )\n"
+ " (\n"
+ " ))\n"
+ "\n"
+ " (signature bvec3\n"
+ " (parameters\n"
+ " (declare (in ) ivec3 x@0x8dba10)\n"
+ " (declare (in ) ivec3 y@0x8dbb20)\n"
+ " )\n"
+ " (\n"
+ " ))\n"
+ "\n"
+ " (signature bvec4\n"
+ " (parameters\n"
+ " (declare (in ) ivec4 x@0x8dbd00)\n"
+ " (declare (in ) ivec4 y@0x8dbe10)\n"
+ " )\n"
+ " (\n"
+ " ))\n"
+ "\n"
+ ")\n"
+ "\n"
+ "(function greaterThanEqual\n"
+ " (signature bvec2\n"
+ " (parameters\n"
+ " (declare (in ) vec2 x@0x8dbff0)\n"
+ " (declare (in ) vec2 y@0x8dc100)\n"
+ " )\n"
+ " (\n"
+ " ))\n"
+ "\n"
+ " (signature bvec3\n"
+ " (parameters\n"
+ " (declare (in ) vec3 x@0x8dc4c0)\n"
+ " (declare (in ) vec3 y@0x8dc5d0)\n"
+ " )\n"
+ " (\n"
+ " ))\n"
+ "\n"
+ " (signature bvec4\n"
+ " (parameters\n"
+ " (declare (in ) vec4 x@0x8dc7b0)\n"
+ " (declare (in ) vec4 y@0x8dc8c0)\n"
+ " )\n"
+ " (\n"
+ " ))\n"
+ "\n"
+ " (signature bvec2\n"
+ " (parameters\n"
+ " (declare (in ) ivec2 x@0x8dcaa0)\n"
+ " (declare (in ) ivec2 y@0x8dcbb0)\n"
+ " )\n"
+ " (\n"
+ " ))\n"
+ "\n"
+ " (signature bvec3\n"
+ " (parameters\n"
+ " (declare (in ) ivec3 x@0x8dcd90)\n"
+ " (declare (in ) ivec3 y@0x8dcea0)\n"
+ " )\n"
+ " (\n"
+ " ))\n"
+ "\n"
+ " (signature bvec4\n"
+ " (parameters\n"
+ " (declare (in ) ivec4 x@0x8dd080)\n"
+ " (declare (in ) ivec4 y@0x8dd190)\n"
+ " )\n"
+ " (\n"
+ " ))\n"
+ "\n"
+ ")\n"
+ "\n"
+ "(function equal\n"
+ " (signature bvec2\n"
+ " (parameters\n"
+ " (declare (in ) vec2 x@0x8dd370)\n"
+ " (declare (in ) vec2 y@0x8dd480)\n"
+ " )\n"
+ " (\n"
+ " ))\n"
+ "\n"
+ " (signature bvec3\n"
+ " (parameters\n"
+ " (declare (in ) vec3 x@0x8dd830)\n"
+ " (declare (in ) vec3 y@0x8dd940)\n"
+ " )\n"
+ " (\n"
+ " ))\n"
+ "\n"
+ " (signature bvec4\n"
+ " (parameters\n"
+ " (declare (in ) vec4 x@0x8ddb20)\n"
+ " (declare (in ) vec4 y@0x8ddc30)\n"
+ " )\n"
+ " (\n"
+ " ))\n"
+ "\n"
+ " (signature bvec2\n"
+ " (parameters\n"
+ " (declare (in ) ivec2 x@0x8dde10)\n"
+ " (declare (in ) ivec2 y@0x8ddf20)\n"
+ " )\n"
+ " (\n"
+ " ))\n"
+ "\n"
+ " (signature bvec3\n"
+ " (parameters\n"
+ " (declare (in ) ivec3 x@0x8de100)\n"
+ " (declare (in ) ivec3 y@0x8de210)\n"
+ " )\n"
+ " (\n"
+ " ))\n"
+ "\n"
+ " (signature bvec4\n"
+ " (parameters\n"
+ " (declare (in ) ivec4 x@0x8de3f0)\n"
+ " (declare (in ) ivec4 y@0x8de500)\n"
+ " )\n"
+ " (\n"
+ " ))\n"
+ "\n"
+ " (signature bvec2\n"
+ " (parameters\n"
+ " (declare (in ) bvec2 x@0x8de6e0)\n"
+ " (declare (in ) bvec2 y@0x8de7f0)\n"
+ " )\n"
+ " (\n"
+ " ))\n"
+ "\n"
+ " (signature bvec3\n"
+ " (parameters\n"
+ " (declare (in ) bvec3 x@0x8de9d0)\n"
+ " (declare (in ) bvec3 y@0x8deae0)\n"
+ " )\n"
+ " (\n"
+ " ))\n"
+ "\n"
+ " (signature bvec4\n"
+ " (parameters\n"
+ " (declare (in ) bvec4 x@0x8decc0)\n"
+ " (declare (in ) bvec4 y@0x8dedd0)\n"
+ " )\n"
+ " (\n"
+ " ))\n"
+ "\n"
+ ")\n"
+ "\n"
+ "(function notEqual\n"
+ " (signature bvec2\n"
+ " (parameters\n"
+ " (declare (in ) vec2 x@0x8defb0)\n"
+ " (declare (in ) vec2 y@0x8df0c0)\n"
+ " )\n"
+ " (\n"
+ " ))\n"
+ "\n"
+ " (signature bvec3\n"
+ " (parameters\n"
+ " (declare (in ) vec3 x@0x8df480)\n"
+ " (declare (in ) vec3 y@0x8df590)\n"
+ " )\n"
+ " (\n"
+ " ))\n"
+ "\n"
+ " (signature bvec4\n"
+ " (parameters\n"
+ " (declare (in ) vec4 x@0x8df770)\n"
+ " (declare (in ) vec4 y@0x8df880)\n"
+ " )\n"
+ " (\n"
+ " ))\n"
+ "\n"
+ " (signature bvec2\n"
+ " (parameters\n"
+ " (declare (in ) ivec2 x@0x8dfa60)\n"
+ " (declare (in ) ivec2 y@0x8dfb70)\n"
+ " )\n"
+ " (\n"
+ " ))\n"
+ "\n"
+ " (signature bvec3\n"
+ " (parameters\n"
+ " (declare (in ) ivec3 x@0x8dfd50)\n"
+ " (declare (in ) ivec3 y@0x8dfe60)\n"
+ " )\n"
+ " (\n"
+ " ))\n"
+ "\n"
+ " (signature bvec4\n"
+ " (parameters\n"
+ " (declare (in ) ivec4 x@0x8e0040)\n"
+ " (declare (in ) ivec4 y@0x8e0150)\n"
+ " )\n"
+ " (\n"
+ " ))\n"
+ "\n"
+ " (signature bvec2\n"
+ " (parameters\n"
+ " (declare (in ) bvec2 x@0x8e0330)\n"
+ " (declare (in ) bvec2 y@0x8e0440)\n"
+ " )\n"
+ " (\n"
+ " ))\n"
+ "\n"
+ " (signature bvec3\n"
+ " (parameters\n"
+ " (declare (in ) bvec3 x@0x8e0620)\n"
+ " (declare (in ) bvec3 y@0x8e0730)\n"
+ " )\n"
+ " (\n"
+ " ))\n"
+ "\n"
+ " (signature bvec4\n"
+ " (parameters\n"
+ " (declare (in ) bvec4 x@0x8e0910)\n"
+ " (declare (in ) bvec4 y@0x8e0a20)\n"
+ " )\n"
+ " (\n"
+ " ))\n"
+ "\n"
+ ")\n"
+ "\n"
+ "(function any\n"
+ " (signature bool\n"
+ " (parameters\n"
+ " (declare (in ) bvec2 x@0x8e0c00)\n"
+ " )\n"
+ " (\n"
+ " ))\n"
+ "\n"
+ " (signature bool\n"
+ " (parameters\n"
+ " (declare (in ) bvec3 x@0x8e0fb0)\n"
+ " )\n"
+ " (\n"
+ " ))\n"
+ "\n"
+ " (signature bool\n"
+ " (parameters\n"
+ " (declare (in ) bvec4 x@0x8e1190)\n"
+ " )\n"
+ " (\n"
+ " ))\n"
+ "\n"
+ ")\n"
+ "\n"
+ "(function all\n"
+ " (signature bool\n"
+ " (parameters\n"
+ " (declare (in ) bvec2 x@0x8e1370)\n"
+ " )\n"
+ " (\n"
+ " ))\n"
+ "\n"
+ " (signature bool\n"
+ " (parameters\n"
+ " (declare (in ) bvec3 x@0x8e1720)\n"
+ " )\n"
+ " (\n"
+ " ))\n"
+ "\n"
+ " (signature bool\n"
+ " (parameters\n"
+ " (declare (in ) bvec4 x@0x8e1900)\n"
+ " )\n"
+ " (\n"
+ " ))\n"
+ "\n"
+ ")\n"
+ "\n"
+ "(function not\n"
+ " (signature bvec2\n"
+ " (parameters\n"
+ " (declare (in ) bvec2 x@0x8e1ae0)\n"
+ " )\n"
+ " (\n"
+ " ))\n"
+ "\n"
+ " (signature bvec3\n"
+ " (parameters\n"
+ " (declare (in ) bvec3 x@0x8e1e90)\n"
+ " )\n"
+ " (\n"
+ " ))\n"
+ "\n"
+ " (signature bvec4\n"
+ " (parameters\n"
+ " (declare (in ) bvec4 x@0x8e2070)\n"
+ " )\n"
+ " (\n"
+ " ))\n"
+ "\n"
+ ")\n"
+ "\n"
+ "(function texture1D\n"
+ " (signature vec4\n"
+ " (parameters\n"
+ " (declare (in ) sampler1D sampler@0x8e2250)\n"
+ " (declare (in ) float coord@0x8e2370)\n"
+ " )\n"
+ " (\n"
+ " ))\n"
+ "\n"
+ " (signature vec4\n"
+ " (parameters\n"
+ " (declare (in ) sampler1D sampler@0x8e2f10)\n"
+ " (declare (in ) float coord@0x8e3030)\n"
+ " (declare (in ) float bias@0x8e3140)\n"
+ " )\n"
+ " (\n"
+ " ))\n"
+ "\n"
+ ")\n"
+ "\n"
+ "(function texture1DProj\n"
+ " (signature vec4\n"
+ " (parameters\n"
+ " (declare (in ) sampler1D sampler@0x8e2730)\n"
+ " (declare (in ) vec2 coord@0x8e2850)\n"
+ " )\n"
+ " (\n"
+ " ))\n"
+ "\n"
+ " (signature vec4\n"
+ " (parameters\n"
+ " (declare (in ) sampler1D sampler@0x8e2c10)\n"
+ " (declare (in ) vec4 coord@0x8e2d30)\n"
+ " )\n"
+ " (\n"
+ " ))\n"
+ "\n"
+ " (signature vec4\n"
+ " (parameters\n"
+ " (declare (in ) sampler1D sampler@0x8e3320)\n"
+ " (declare (in ) vec2 coord@0x8e3440)\n"
+ " (declare (in ) float bias@0x8e3550)\n"
+ " )\n"
+ " (\n"
+ " ))\n"
+ "\n"
+ " (signature vec4\n"
+ " (parameters\n"
+ " (declare (in ) sampler1D sampler@0x8e3730)\n"
+ " (declare (in ) vec4 coord@0x8e3850)\n"
+ " (declare (in ) float bias@0x8e3960)\n"
+ " )\n"
+ " (\n"
+ " ))\n"
+ "\n"
+ ")\n"
+ "\n"
+ "(function texture2D\n"
+ " (signature vec4\n"
+ " (parameters\n"
+ " (declare (in ) sampler2D sampler@0x8e3b40)\n"
+ " (declare (in ) vec2 coord@0x8e3c60)\n"
+ " )\n"
+ " (\n"
+ " ))\n"
+ "\n"
+ " (signature vec4\n"
+ " (parameters\n"
+ " (declare (in ) sampler2D sampler@0x8e4800)\n"
+ " (declare (in ) vec2 coord@0x8e4920)\n"
+ " (declare (in ) float bias@0x8e4a30)\n"
+ " )\n"
+ " (\n"
+ " ))\n"
+ "\n"
+ ")\n"
+ "\n"
+ "(function texture2DProj\n"
+ " (signature vec4\n"
+ " (parameters\n"
+ " (declare (in ) sampler2D sampler@0x8e4020)\n"
+ " (declare (in ) vec3 coord@0x8e4140)\n"
+ " )\n"
+ " (\n"
+ " ))\n"
+ "\n"
+ " (signature vec4\n"
+ " (parameters\n"
+ " (declare (in ) sampler2D sampler@0x8e4500)\n"
+ " (declare (in ) vec4 coord@0x8e4620)\n"
+ " )\n"
+ " (\n"
+ " ))\n"
+ "\n"
+ " (signature vec4\n"
+ " (parameters\n"
+ " (declare (in ) sampler2D sampler@0x8e4c10)\n"
+ " (declare (in ) vec3 coord@0x8e4d30)\n"
+ " (declare (in ) float bias@0x8e4e40)\n"
+ " )\n"
+ " (\n"
+ " ))\n"
+ "\n"
+ " (signature vec4\n"
+ " (parameters\n"
+ " (declare (in ) sampler2D sampler@0x8e5020)\n"
+ " (declare (in ) vec4 coord@0x8e5140)\n"
+ " (declare (in ) float bias@0x8e5250)\n"
+ " )\n"
+ " (\n"
+ " ))\n"
+ "\n"
+ ")\n"
+ "\n"
+ "(function texture3D\n"
+ " (signature vec4\n"
+ " (parameters\n"
+ " (declare (in ) sampler3D sampler@0x8e5430)\n"
+ " (declare (in ) vec3 coord@0x8e5550)\n"
+ " )\n"
+ " (\n"
+ " ))\n"
+ "\n"
+ " (signature vec4\n"
+ " (parameters\n"
+ " (declare (in ) sampler3D sampler@0x8e5df0)\n"
+ " (declare (in ) vec3 coord@0x8e5f10)\n"
+ " (declare (in ) float bias@0x8e6020)\n"
+ " )\n"
+ " (\n"
+ " ))\n"
+ "\n"
+ ")\n"
+ "\n"
+ "(function texture3DProj\n"
+ " (signature vec4\n"
+ " (parameters\n"
+ " (declare (in ) sampler3D sampler@0x8e5910)\n"
+ " (declare (in ) vec4 coord@0x8e5a30)\n"
+ " )\n"
+ " (\n"
+ " ))\n"
+ "\n"
+ " (signature vec4\n"
+ " (parameters\n"
+ " (declare (in ) sampler3D sampler@0x8e6200)\n"
+ " (declare (in ) vec4 coord@0x8e6320)\n"
+ " (declare (in ) float bias@0x8e6430)\n"
+ " )\n"
+ " (\n"
+ " ))\n"
+ "\n"
+ ")\n"
+ "\n"
+ "(function textureCube\n"
+ " (signature vec4\n"
+ " (parameters\n"
+ " (declare (in ) samplerCube sampler@0x8e6610)\n"
+ " (declare (in ) vec3 coord@0x8e6730)\n"
+ " )\n"
+ " (\n"
+ " ))\n"
+ "\n"
+ " (signature vec4\n"
+ " (parameters\n"
+ " (declare (in ) samplerCube sampler@0x8e6af0)\n"
+ " (declare (in ) vec3 coord@0x8e6c10)\n"
+ " (declare (in ) float bias@0x8e6d20)\n"
+ " )\n"
+ " (\n"
+ " ))\n"
+ "\n"
+ ")\n"
+ "\n"
+ "(function shadow1D\n"
+ " (signature vec4\n"
+ " (parameters\n"
+ " (declare (in ) sampler1DShadow sampler@0x8e6f00)\n"
+ " (declare (in ) vec3 coord@0x8e7020)\n"
+ " )\n"
+ " (\n"
+ " ))\n"
+ "\n"
+ " (signature vec4\n"
+ " (parameters\n"
+ " (declare (in ) sampler1DShadow sampler@0x8e8280)\n"
+ " (declare (in ) vec3 coord@0x8e83a0)\n"
+ " (declare (in ) float bias@0x8e84b0)\n"
+ " )\n"
+ " (\n"
+ " ))\n"
+ "\n"
+ ")\n"
+ "\n"
+ "(function shadow2D\n"
+ " (signature vec4\n"
+ " (parameters\n"
+ " (declare (in ) sampler2DShadow sampler@0x8e73e0)\n"
+ " (declare (in ) vec3 coord@0x8e7500)\n"
+ " )\n"
+ " (\n"
+ " ))\n"
+ "\n"
+ " (signature vec4\n"
+ " (parameters\n"
+ " (declare (in ) sampler2DShadow sampler@0x8e8690)\n"
+ " (declare (in ) vec3 coord@0x8e87b0)\n"
+ " (declare (in ) float bias@0x8e88c0)\n"
+ " )\n"
+ " (\n"
+ " ))\n"
+ "\n"
+ ")\n"
+ "\n"
+ "(function shadow1DProj\n"
+ " (signature vec4\n"
+ " (parameters\n"
+ " (declare (in ) sampler1DShadow sampler@0x8e78c0)\n"
+ " (declare (in ) vec4 coord@0x8e79e0)\n"
+ " )\n"
+ " (\n"
+ " ))\n"
+ "\n"
+ " (signature vec4\n"
+ " (parameters\n"
+ " (declare (in ) sampler1DShadow sampler@0x8e8aa0)\n"
+ " (declare (in ) vec4 coord@0x8e8bc0)\n"
+ " (declare (in ) float bias@0x8e8cd0)\n"
+ " )\n"
+ " (\n"
+ " ))\n"
+ "\n"
+ ")\n"
+ "\n"
+ "(function shadow2DProj\n"
+ " (signature vec4\n"
+ " (parameters\n"
+ " (declare (in ) sampler2DShadow sampler@0x8e7da0)\n"
+ " (declare (in ) vec4 coord@0x8e7ec0)\n"
+ " )\n"
+ " (\n"
+ " ))\n"
+ "\n"
+ " (signature vec4\n"
+ " (parameters\n"
+ " (declare (in ) sampler2DShadow sampler@0x8e8eb0)\n"
+ " (declare (in ) vec4 coord@0x8e8fd0)\n"
+ " (declare (in ) float bias@0x8e90e0)\n"
+ " )\n"
+ " (\n"
+ " ))\n"
+ "\n"
+ ")\n"
+ "\n"
+ "(function dFdx\n"
+ " (signature float\n"
+ " (parameters\n"
+ " (declare (in ) float p@0x8e92c0)\n"
+ " )\n"
+ " (\n"
+ " ))\n"
+ "\n"
+ " (signature vec2\n"
+ " (parameters\n"
+ " (declare (in ) vec2 p@0x8e9670)\n"
+ " )\n"
+ " (\n"
+ " ))\n"
+ "\n"
+ " (signature vec3\n"
+ " (parameters\n"
+ " (declare (in ) vec3 p@0x8e9850)\n"
+ " )\n"
+ " (\n"
+ " ))\n"
+ "\n"
+ " (signature vec4\n"
+ " (parameters\n"
+ " (declare (in ) vec4 p@0x8e9a30)\n"
+ " )\n"
+ " (\n"
+ " ))\n"
+ "\n"
+ ")\n"
+ "\n"
+ "(function dFdy\n"
+ " (signature float\n"
+ " (parameters\n"
+ " (declare (in ) float p@0x8e9c10)\n"
+ " )\n"
+ " (\n"
+ " ))\n"
+ "\n"
+ " (signature vec2\n"
+ " (parameters\n"
+ " (declare (in ) vec2 p@0x8e9fc0)\n"
+ " )\n"
+ " (\n"
+ " ))\n"
+ "\n"
+ " (signature vec3\n"
+ " (parameters\n"
+ " (declare (in ) vec3 p@0x8ea1a0)\n"
+ " )\n"
+ " (\n"
+ " ))\n"
+ "\n"
+ " (signature vec4\n"
+ " (parameters\n"
+ " (declare (in ) vec4 p@0x8ea380)\n"
+ " )\n"
+ " (\n"
+ " ))\n"
+ "\n"
+ ")\n"
+ "\n"
+ "(function fwidth\n"
+ " (signature float\n"
+ " (parameters\n"
+ " (declare (in ) float p@0x8ea560)\n"
+ " )\n"
+ " (\n"
+ " ))\n"
+ "\n"
+ " (signature vec2\n"
+ " (parameters\n"
+ " (declare (in ) vec2 p@0x8ea910)\n"
+ " )\n"
+ " (\n"
+ " ))\n"
+ "\n"
+ " (signature vec3\n"
+ " (parameters\n"
+ " (declare (in ) vec3 p@0x8eaaf0)\n"
+ " )\n"
+ " (\n"
+ " ))\n"
+ "\n"
+ " (signature vec4\n"
+ " (parameters\n"
+ " (declare (in ) vec4 p@0x8eacd0)\n"
+ " )\n"
+ " (\n"
+ " ))\n"
+ "\n"
+ ")\n"
+ "\n"
+ "(function noise1\n"
+ " (signature float\n"
+ " (parameters\n"
+ " (declare (in ) float x@0x8eaeb0)\n"
+ " )\n"
+ " (\n"
+ " ))\n"
+ "\n"
+ " (signature float\n"
+ " (parameters\n"
+ " (declare (in ) vec2 x@0x8eb260)\n"
+ " )\n"
+ " (\n"
+ " ))\n"
+ "\n"
+ " (signature float\n"
+ " (parameters\n"
+ " (declare (in ) vec3 x@0x8eb440)\n"
+ " )\n"
+ " (\n"
+ " ))\n"
+ "\n"
+ " (signature float\n"
+ " (parameters\n"
+ " (declare (in ) vec4 x@0x8eb620)\n"
+ " )\n"
+ " (\n"
+ " ))\n"
+ "\n"
+ ")\n"
+ "\n"
+ "(function noise2\n"
+ " (signature vec2\n"
+ " (parameters\n"
+ " (declare (in ) float x@0x8eb800)\n"
+ " )\n"
+ " (\n"
+ " ))\n"
+ "\n"
+ " (signature vec2\n"
+ " (parameters\n"
+ " (declare (in ) vec2 x@0x8ebbb0)\n"
+ " )\n"
+ " (\n"
+ " ))\n"
+ "\n"
+ " (signature vec2\n"
+ " (parameters\n"
+ " (declare (in ) vec3 x@0x8ebd90)\n"
+ " )\n"
+ " (\n"
+ " ))\n"
+ "\n"
+ " (signature vec2\n"
+ " (parameters\n"
+ " (declare (in ) vec4 x@0x8ebf70)\n"
+ " )\n"
+ " (\n"
+ " ))\n"
+ "\n"
+ ")\n"
+ "\n"
+ "(function noise3\n"
+ " (signature vec3\n"
+ " (parameters\n"
+ " (declare (in ) float x@0x8ec150)\n"
+ " )\n"
+ " (\n"
+ " ))\n"
+ "\n"
+ " (signature vec3\n"
+ " (parameters\n"
+ " (declare (in ) vec2 x@0x8ec500)\n"
+ " )\n"
+ " (\n"
+ " ))\n"
+ "\n"
+ " (signature vec3\n"
+ " (parameters\n"
+ " (declare (in ) vec3 x@0x8ec6e0)\n"
+ " )\n"
+ " (\n"
+ " ))\n"
+ "\n"
+ " (signature vec3\n"
+ " (parameters\n"
+ " (declare (in ) vec4 x@0x8ec8c0)\n"
+ " )\n"
+ " (\n"
+ " ))\n"
+ "\n"
+ ")\n"
+ "\n"
+ "(function noise4\n"
+ " (signature vec4\n"
+ " (parameters\n"
+ " (declare (in ) float x@0x8ecaa0)\n"
+ " )\n"
+ " (\n"
+ " ))\n"
+ "\n"
+ " (signature vec4\n"
+ " (parameters\n"
+ " (declare (in ) vec2 x@0x8ece50)\n"
+ " )\n"
+ " (\n"
+ " ))\n"
+ "\n"
+ " (signature vec4\n"
+ " (parameters\n"
+ " (declare (in ) vec3 x@0x8ed030)\n"
+ " )\n"
+ " (\n"
+ " ))\n"
+ "\n"
+ " (signature vec4\n"
+ " (parameters\n"
+ " (declare (in ) vec4 x@0x8ed210)\n"
+ " )\n"
+ " (\n"
+ " ))\n"
+ "\n"
+ ")\n"
+ "\n"
+ "\n"
+ ")"
+;
+static const char *functions_for_120_frag [] = {
+ builtin_clamp,
+ builtin_matrixCompMult,
+ builtin_noise2,
+ builtin_pow,
+ builtin_texture2DProj,
+ builtin_fwidth,
+ builtin_greaterThanEqual,
+ builtin_sign,
+ builtin_texture3DProj,
+ builtin_texture2D,
+ builtin_equal,
+ builtin_faceforward,
+ builtin_tan,
+ builtin_any,
+ builtin_shadow1DProj,
+ builtin_normalize,
+ builtin_asin,
+ builtin_texture1DProj,
+ builtin_log,
+ builtin_floor,
+ builtin_exp2,
+ builtin_lessThan,
+ builtin_cross,
+ builtin_sqrt,
+ builtin_shadow2DProj,
+ builtin_fract,
+ builtin_abs,
+ builtin_degrees,
+ builtin_dFdx,
+ builtin_sin,
+ builtin_shadow2D,
+ builtin_all,
+ builtin_log2,
+ builtin_atan,
+ builtin_notEqual,
+ builtin_max,
+ builtin_lessThanEqual,
+ builtin_transpose,
+ builtin_outerProduct,
+ builtin_ceil,
+ builtin_reflect,
+ builtin_step,
+ builtin_texture1D,
+ builtin_greaterThan,
+ builtin_texture3D,
+ builtin_not,
+ builtin_inversesqrt,
+ builtin_mod,
+ builtin_noise4,
+ builtin_distance,
+ builtin_cos,
+ builtin_shadow1D,
+ builtin_noise1,
+ builtin_refract,
+ builtin_noise3,
+ builtin_min,
+ builtin_radians,
+ builtin_smoothstep,
+ builtin_textureCube,
+ builtin_length,
+ builtin_dFdy,
+ builtin_exp,
+ builtin_acos,
+ builtin_mix,
+ builtin_dot,
+};
+
+void *builtin_mem_ctx = NULL;
+
+void
+_mesa_glsl_release_functions(void)
+{
+ talloc_free(builtin_mem_ctx);
+}
+
+void
+_mesa_glsl_initialize_functions(exec_list *instructions,
+ struct _mesa_glsl_parse_state *state)
+{
+ if (builtin_mem_ctx == NULL)
+ builtin_mem_ctx = talloc_init("GLSL built-in functions");
+
+ state->num_builtins_to_link = 0;
+
+ if (state->target == vertex_shader && state->language_version == 120) {
+ static gl_shader *sh = NULL;
+ if (sh == NULL) {
+ sh = read_builtins(GL_VERTEX_SHADER,
+ prototypes_for_120_vert,
+ functions_for_120_vert,
+ Elements(functions_for_120_vert ));
+ talloc_steal(builtin_mem_ctx, sh);
+ }
+
+ import_prototypes(sh->ir, instructions, state->symbols,
+ state);
+ state->builtins_to_link[state->num_builtins_to_link] = sh;
+ state->num_builtins_to_link++;
+ }
+
+ if (state->target == fragment_shader && state->EXT_texture_array_enable) {
+ static gl_shader *sh = NULL;
+ if (sh == NULL) {
+ sh = read_builtins(GL_VERTEX_SHADER,
+ prototypes_for_EXT_texture_array_frag,
+ functions_for_EXT_texture_array_frag,
+ Elements(functions_for_EXT_texture_array_frag ));
+ talloc_steal(builtin_mem_ctx, sh);
+ }
+
+ import_prototypes(sh->ir, instructions, state->symbols,
+ state);
+ state->builtins_to_link[state->num_builtins_to_link] = sh;
+ state->num_builtins_to_link++;
+ }
+
+ if (state->target == vertex_shader && state->language_version == 110) {
+ static gl_shader *sh = NULL;
+ if (sh == NULL) {
+ sh = read_builtins(GL_VERTEX_SHADER,
+ prototypes_for_110_vert,
+ functions_for_110_vert,
+ Elements(functions_for_110_vert ));
+ talloc_steal(builtin_mem_ctx, sh);
+ }
+
+ import_prototypes(sh->ir, instructions, state->symbols,
+ state);
+ state->builtins_to_link[state->num_builtins_to_link] = sh;
+ state->num_builtins_to_link++;
+ }
+
+ if (state->target == fragment_shader && state->language_version == 110) {
+ static gl_shader *sh = NULL;
+ if (sh == NULL) {
+ sh = read_builtins(GL_VERTEX_SHADER,
+ prototypes_for_110_frag,
+ functions_for_110_frag,
+ Elements(functions_for_110_frag ));
+ talloc_steal(builtin_mem_ctx, sh);
+ }
+
+ import_prototypes(sh->ir, instructions, state->symbols,
+ state);
+ state->builtins_to_link[state->num_builtins_to_link] = sh;
+ state->num_builtins_to_link++;
+ }
+
+ if (state->target == vertex_shader && state->EXT_texture_array_enable) {
+ static gl_shader *sh = NULL;
+ if (sh == NULL) {
+ sh = read_builtins(GL_VERTEX_SHADER,
+ prototypes_for_EXT_texture_array_vert,
+ functions_for_EXT_texture_array_vert,
+ Elements(functions_for_EXT_texture_array_vert ));
+ talloc_steal(builtin_mem_ctx, sh);
+ }
+
+ import_prototypes(sh->ir, instructions, state->symbols,
+ state);
+ state->builtins_to_link[state->num_builtins_to_link] = sh;
+ state->num_builtins_to_link++;
+ }
+
+ if (state->target == vertex_shader && state->ARB_texture_rectangle_enable) {
+ static gl_shader *sh = NULL;
+ if (sh == NULL) {
+ sh = read_builtins(GL_VERTEX_SHADER,
+ prototypes_for_ARB_texture_rectangle_vert,
+ functions_for_ARB_texture_rectangle_vert,
+ Elements(functions_for_ARB_texture_rectangle_vert ));
+ talloc_steal(builtin_mem_ctx, sh);
+ }
+
+ import_prototypes(sh->ir, instructions, state->symbols,
+ state);
+ state->builtins_to_link[state->num_builtins_to_link] = sh;
+ state->num_builtins_to_link++;
+ }
+
+ if (state->target == fragment_shader && state->ARB_texture_rectangle_enable) {
+ static gl_shader *sh = NULL;
+ if (sh == NULL) {
+ sh = read_builtins(GL_VERTEX_SHADER,
+ prototypes_for_ARB_texture_rectangle_frag,
+ functions_for_ARB_texture_rectangle_frag,
+ Elements(functions_for_ARB_texture_rectangle_frag ));
+ talloc_steal(builtin_mem_ctx, sh);
+ }
+
+ import_prototypes(sh->ir, instructions, state->symbols,
+ state);
+ state->builtins_to_link[state->num_builtins_to_link] = sh;
+ state->num_builtins_to_link++;
+ }
+
+ if (state->target == fragment_shader && state->language_version == 120) {
+ static gl_shader *sh = NULL;
+ if (sh == NULL) {
+ sh = read_builtins(GL_VERTEX_SHADER,
+ prototypes_for_120_frag,
+ functions_for_120_frag,
+ Elements(functions_for_120_frag ));
+ talloc_steal(builtin_mem_ctx, sh);
+ }
+
+ import_prototypes(sh->ir, instructions, state->symbols,
+ state);
+ state->builtins_to_link[state->num_builtins_to_link] = sh;
+ state->num_builtins_to_link++;
+ }
+
+}
diff --git a/src/glsl/builtin_types.h b/src/glsl/builtin_types.h
new file mode 100644
index 00000000000..7b94aac666b
--- /dev/null
+++ b/src/glsl/builtin_types.h
@@ -0,0 +1,290 @@
+/*
+ * Copyright © 2009 Intel Corporation
+ *
+ * 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 (including the next
+ * paragraph) 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
+ * THE AUTHORS OR COPYRIGHT HOLDERS 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.
+ */
+
+const glsl_type glsl_type::_error_type =
+ glsl_type(GL_INVALID_ENUM, GLSL_TYPE_ERROR, 0, 0, "");
+
+const glsl_type glsl_type::void_type =
+ glsl_type(GL_INVALID_ENUM, GLSL_TYPE_VOID, 0, 0, "void");
+
+const glsl_type *const glsl_type::error_type = & glsl_type::_error_type;
+
+/** \name Core built-in types
+ *
+ * These types exist in all versions of GLSL.
+ */
+/*@{*/
+
+const glsl_type glsl_type::builtin_core_types[] = {
+ glsl_type(GL_BOOL, GLSL_TYPE_BOOL, 1, 1, "bool"),
+ glsl_type(GL_BOOL_VEC2, GLSL_TYPE_BOOL, 2, 1, "bvec2"),
+ glsl_type(GL_BOOL_VEC3, GLSL_TYPE_BOOL, 3, 1, "bvec3"),
+ glsl_type(GL_BOOL_VEC4, GLSL_TYPE_BOOL, 4, 1, "bvec4"),
+ glsl_type(GL_INT, GLSL_TYPE_INT, 1, 1, "int"),
+ glsl_type(GL_INT_VEC2, GLSL_TYPE_INT, 2, 1, "ivec2"),
+ glsl_type(GL_INT_VEC3, GLSL_TYPE_INT, 3, 1, "ivec3"),
+ glsl_type(GL_INT_VEC4, GLSL_TYPE_INT, 4, 1, "ivec4"),
+ glsl_type(GL_FLOAT, GLSL_TYPE_FLOAT, 1, 1, "float"),
+ glsl_type(GL_FLOAT_VEC2, GLSL_TYPE_FLOAT, 2, 1, "vec2"),
+ glsl_type(GL_FLOAT_VEC3, GLSL_TYPE_FLOAT, 3, 1, "vec3"),
+ glsl_type(GL_FLOAT_VEC4, GLSL_TYPE_FLOAT, 4, 1, "vec4"),
+ glsl_type(GL_FLOAT_MAT2, GLSL_TYPE_FLOAT, 2, 2, "mat2"),
+ glsl_type(GL_FLOAT_MAT3, GLSL_TYPE_FLOAT, 3, 3, "mat3"),
+ glsl_type(GL_FLOAT_MAT4, GLSL_TYPE_FLOAT, 4, 4, "mat4"),
+ glsl_type(GL_SAMPLER_1D, GLSL_SAMPLER_DIM_1D, 0, 0, GLSL_TYPE_FLOAT,
+ "sampler1D"),
+ glsl_type(GL_SAMPLER_1D_SHADOW, GLSL_SAMPLER_DIM_1D, 1, 0, GLSL_TYPE_FLOAT,
+ "sampler1DShadow"),
+ glsl_type(GL_SAMPLER_2D, GLSL_SAMPLER_DIM_2D, 0, 0, GLSL_TYPE_FLOAT,
+ "sampler2D"),
+ glsl_type(GL_SAMPLER_2D_SHADOW, GLSL_SAMPLER_DIM_2D, 1, 0, GLSL_TYPE_FLOAT,
+ "sampler2DShadow"),
+ glsl_type(GL_SAMPLER_3D, GLSL_SAMPLER_DIM_3D, 0, 0, GLSL_TYPE_FLOAT,
+ "sampler3D"),
+ glsl_type(GL_SAMPLER_CUBE, GLSL_SAMPLER_DIM_CUBE, 0, 0, GLSL_TYPE_FLOAT,
+ "samplerCube"),
+};
+
+const glsl_type *const glsl_type::bool_type = & builtin_core_types[0];
+const glsl_type *const glsl_type::int_type = & builtin_core_types[4];
+const glsl_type *const glsl_type::ivec4_type = & builtin_core_types[7];
+const glsl_type *const glsl_type::float_type = & builtin_core_types[8];
+const glsl_type *const glsl_type::vec2_type = & builtin_core_types[9];
+const glsl_type *const glsl_type::vec3_type = & builtin_core_types[10];
+const glsl_type *const glsl_type::vec4_type = & builtin_core_types[11];
+const glsl_type *const glsl_type::mat2_type = & builtin_core_types[12];
+const glsl_type *const glsl_type::mat3_type = & builtin_core_types[13];
+const glsl_type *const glsl_type::mat4_type = & builtin_core_types[14];
+/*@}*/
+
+/** \name GLSL structures that have not been deprecated.
+ */
+/*@{*/
+
+static const struct glsl_struct_field gl_DepthRangeParameters_fields[] = {
+ { glsl_type::float_type, "near" },
+ { glsl_type::float_type, "far" },
+ { glsl_type::float_type, "diff" },
+};
+
+const glsl_type glsl_type::builtin_structure_types[] = {
+ glsl_type(gl_DepthRangeParameters_fields,
+ Elements(gl_DepthRangeParameters_fields),
+ "gl_DepthRangeParameters"),
+};
+/*@}*/
+
+/** \name GLSL 1.00 / 1.10 structures that are deprecated in GLSL 1.30
+ */
+/*@{*/
+
+static const struct glsl_struct_field gl_PointParameters_fields[] = {
+ { glsl_type::float_type, "size" },
+ { glsl_type::float_type, "sizeMin" },
+ { glsl_type::float_type, "sizeMax" },
+ { glsl_type::float_type, "fadeThresholdSize" },
+ { glsl_type::float_type, "distanceConstantAttenuation" },
+ { glsl_type::float_type, "distanceLinearAttenuation" },
+ { glsl_type::float_type, "distanceQuadraticAttenuation" },
+};
+
+static const struct glsl_struct_field gl_MaterialParameters_fields[] = {
+ { glsl_type::vec4_type, "emission" },
+ { glsl_type::vec4_type, "ambient" },
+ { glsl_type::vec4_type, "diffuse" },
+ { glsl_type::vec4_type, "specular" },
+ { glsl_type::float_type, "shininess" },
+};
+
+static const struct glsl_struct_field gl_LightSourceParameters_fields[] = {
+ { glsl_type::vec4_type, "ambient" },
+ { glsl_type::vec4_type, "diffuse" },
+ { glsl_type::vec4_type, "specular" },
+ { glsl_type::vec4_type, "position" },
+ { glsl_type::vec4_type, "halfVector" },
+ { glsl_type::vec3_type, "spotDirection" },
+ { glsl_type::float_type, "spotExponent" },
+ { glsl_type::float_type, "spotCutoff" },
+ { glsl_type::float_type, "spotCosCutoff" },
+ { glsl_type::float_type, "constantAttenuation" },
+ { glsl_type::float_type, "linearAttenuation" },
+ { glsl_type::float_type, "quadraticAttenuation" },
+};
+
+static const struct glsl_struct_field gl_LightModelParameters_fields[] = {
+ { glsl_type::vec4_type, "ambient" },
+};
+
+static const struct glsl_struct_field gl_LightModelProducts_fields[] = {
+ { glsl_type::vec4_type, "sceneColor" },
+};
+
+static const struct glsl_struct_field gl_LightProducts_fields[] = {
+ { glsl_type::vec4_type, "ambient" },
+ { glsl_type::vec4_type, "diffuse" },
+ { glsl_type::vec4_type, "specular" },
+};
+
+static const struct glsl_struct_field gl_FogParameters_fields[] = {
+ { glsl_type::vec4_type, "color" },
+ { glsl_type::float_type, "density" },
+ { glsl_type::float_type, "start" },
+ { glsl_type::float_type, "end" },
+ { glsl_type::float_type, "scale" },
+};
+
+const glsl_type glsl_type::builtin_110_deprecated_structure_types[] = {
+ glsl_type(gl_PointParameters_fields,
+ Elements(gl_PointParameters_fields),
+ "gl_PointParameters"),
+ glsl_type(gl_MaterialParameters_fields,
+ Elements(gl_MaterialParameters_fields),
+ "gl_MaterialParameters"),
+ glsl_type(gl_LightSourceParameters_fields,
+ Elements(gl_LightSourceParameters_fields),
+ "gl_LightSourceParameters"),
+ glsl_type(gl_LightModelParameters_fields,
+ Elements(gl_LightModelParameters_fields),
+ "gl_LightModelParameters"),
+ glsl_type(gl_LightModelProducts_fields,
+ Elements(gl_LightModelProducts_fields),
+ "gl_LightModelProducts"),
+ glsl_type(gl_LightProducts_fields,
+ Elements(gl_LightProducts_fields),
+ "gl_LightProducts"),
+ glsl_type(gl_FogParameters_fields,
+ Elements(gl_FogParameters_fields),
+ "gl_FogParameters"),
+};
+/*@}*/
+
+/** \name Types added in GLSL 1.20
+ */
+/*@{*/
+
+const glsl_type glsl_type::builtin_120_types[] = {
+ glsl_type(GL_FLOAT_MAT2x3, GLSL_TYPE_FLOAT, 3, 2, "mat2x3"),
+ glsl_type(GL_FLOAT_MAT2x4, GLSL_TYPE_FLOAT, 4, 2, "mat2x4"),
+ glsl_type(GL_FLOAT_MAT3x2, GLSL_TYPE_FLOAT, 2, 3, "mat3x2"),
+ glsl_type(GL_FLOAT_MAT3x4, GLSL_TYPE_FLOAT, 4, 3, "mat3x4"),
+ glsl_type(GL_FLOAT_MAT4x2, GLSL_TYPE_FLOAT, 2, 4, "mat4x2"),
+ glsl_type(GL_FLOAT_MAT4x3, GLSL_TYPE_FLOAT, 3, 4, "mat4x3"),
+};
+const glsl_type *const glsl_type::mat2x3_type = & builtin_120_types[0];
+const glsl_type *const glsl_type::mat2x4_type = & builtin_120_types[1];
+const glsl_type *const glsl_type::mat3x2_type = & builtin_120_types[2];
+const glsl_type *const glsl_type::mat3x4_type = & builtin_120_types[3];
+const glsl_type *const glsl_type::mat4x2_type = & builtin_120_types[4];
+const glsl_type *const glsl_type::mat4x3_type = & builtin_120_types[5];
+/*@}*/
+
+/** \name Types added in GLSL 1.30
+ */
+/*@{*/
+
+const glsl_type glsl_type::builtin_130_types[] = {
+ glsl_type(GL_UNSIGNED_INT, GLSL_TYPE_UINT, 1, 1, "uint"),
+ glsl_type(GL_UNSIGNED_INT_VEC2, GLSL_TYPE_UINT, 2, 1, "uvec2"),
+ glsl_type(GL_UNSIGNED_INT_VEC3, GLSL_TYPE_UINT, 3, 1, "uvec3"),
+ glsl_type(GL_UNSIGNED_INT_VEC4, GLSL_TYPE_UINT, 4, 1, "uvec4"),
+
+ /* 1D and 2D texture arrays - several of these are included only in
+ * builtin_EXT_texture_array_types.
+ */
+ glsl_type(GL_INT_SAMPLER_1D_ARRAY,
+ GLSL_SAMPLER_DIM_1D, 0, 1, GLSL_TYPE_INT, "isampler1DArray"),
+ glsl_type(GL_UNSIGNED_INT_SAMPLER_1D_ARRAY,
+ GLSL_SAMPLER_DIM_1D, 0, 1, GLSL_TYPE_UINT, "usampler1DArray"),
+ glsl_type(GL_INT_SAMPLER_2D_ARRAY,
+ GLSL_SAMPLER_DIM_2D, 0, 1, GLSL_TYPE_INT, "isampler2DArray"),
+ glsl_type(GL_UNSIGNED_INT_SAMPLER_2D_ARRAY,
+ GLSL_SAMPLER_DIM_2D, 0, 1, GLSL_TYPE_UINT, "usampler2DArray"),
+
+ /* cube shadow samplers */
+ glsl_type(GL_SAMPLER_CUBE_SHADOW,
+ GLSL_SAMPLER_DIM_CUBE, 1, 0, GLSL_TYPE_FLOAT, "samplerCubeShadow"),
+
+ /* signed and unsigned integer samplers */
+ glsl_type(GL_INT_SAMPLER_1D,
+ GLSL_SAMPLER_DIM_1D, 0, 0, GLSL_TYPE_INT, "isampler1D"),
+ glsl_type(GL_UNSIGNED_INT_SAMPLER_1D,
+ GLSL_SAMPLER_DIM_1D, 0, 0, GLSL_TYPE_UINT, "usampler1D"),
+ glsl_type(GL_INT_SAMPLER_2D,
+ GLSL_SAMPLER_DIM_2D, 0, 0, GLSL_TYPE_INT, "isampler2D"),
+ glsl_type(GL_UNSIGNED_INT_SAMPLER_2D,
+ GLSL_SAMPLER_DIM_2D, 0, 0, GLSL_TYPE_UINT, "usampler2D"),
+ glsl_type(GL_INT_SAMPLER_3D,
+ GLSL_SAMPLER_DIM_3D, 0, 0, GLSL_TYPE_INT, "isampler3D"),
+ glsl_type(GL_UNSIGNED_INT_SAMPLER_3D,
+ GLSL_SAMPLER_DIM_3D, 0, 0, GLSL_TYPE_UINT, "usampler3D"),
+ glsl_type(GL_INT_SAMPLER_CUBE,
+ GLSL_SAMPLER_DIM_CUBE, 0, 0, GLSL_TYPE_INT, "isamplerCube"),
+ glsl_type(GL_INT_SAMPLER_CUBE,
+ GLSL_SAMPLER_DIM_CUBE, 0, 0, GLSL_TYPE_UINT, "usamplerCube"),
+};
+
+const glsl_type *const glsl_type::uint_type = & builtin_130_types[0];
+const glsl_type *const glsl_type::uvec4_type = & builtin_130_types[3];
+/*@}*/
+
+/** \name Sampler types added by GL_ARB_texture_rectangle
+ */
+/*@{*/
+
+const glsl_type glsl_type::builtin_ARB_texture_rectangle_types[] = {
+ glsl_type(GL_SAMPLER_2D_RECT,
+ GLSL_SAMPLER_DIM_RECT, 0, 0, GLSL_TYPE_FLOAT, "sampler2DRect"),
+ glsl_type(GL_SAMPLER_2D_RECT_SHADOW,
+ GLSL_SAMPLER_DIM_RECT, 1, 0, GLSL_TYPE_FLOAT, "sampler2DRectShadow"),
+};
+/*@}*/
+
+/** \name Sampler types added by GL_EXT_texture_array
+ */
+/*@{*/
+
+const glsl_type glsl_type::builtin_EXT_texture_array_types[] = {
+ glsl_type(GL_SAMPLER_1D_ARRAY,
+ GLSL_SAMPLER_DIM_1D, 0, 1, GLSL_TYPE_FLOAT, "sampler1DArray"),
+ glsl_type(GL_SAMPLER_1D_ARRAY_SHADOW,
+ GLSL_SAMPLER_DIM_2D, 0, 1, GLSL_TYPE_FLOAT, "sampler2DArray"),
+ glsl_type(GL_SAMPLER_2D_ARRAY,
+ GLSL_SAMPLER_DIM_1D, 1, 1, GLSL_TYPE_FLOAT, "sampler1DArrayShadow"),
+ glsl_type(GL_SAMPLER_2D_ARRAY_SHADOW,
+ GLSL_SAMPLER_DIM_2D, 1, 1, GLSL_TYPE_FLOAT, "sampler2DArrayShadow"),
+};
+/*@}*/
+
+/** \name Sampler types added by GL_EXT_texture_buffer_object
+ */
+/*@{*/
+
+const glsl_type glsl_type::builtin_EXT_texture_buffer_object_types[] = {
+ glsl_type(GL_SAMPLER_BUFFER,
+ GLSL_SAMPLER_DIM_BUF, 0, 0, GLSL_TYPE_FLOAT, "samplerBuffer"),
+ glsl_type(GL_INT_SAMPLER_BUFFER,
+ GLSL_SAMPLER_DIM_BUF, 0, 0, GLSL_TYPE_INT, "isamplerBuffer"),
+ glsl_type(GL_UNSIGNED_INT_SAMPLER_BUFFER,
+ GLSL_SAMPLER_DIM_BUF, 0, 0, GLSL_TYPE_UINT, "usamplerBuffer"),
+};
+/*@}*/
diff --git a/src/glsl/builtin_variables.h b/src/glsl/builtin_variables.h
new file mode 100644
index 00000000000..2ec7d621bbf
--- /dev/null
+++ b/src/glsl/builtin_variables.h
@@ -0,0 +1,98 @@
+/*
+ * Copyright © 2010 Intel Corporation
+ *
+ * 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 (including the next
+ * paragraph) 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
+ * THE AUTHORS OR COPYRIGHT HOLDERS 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.
+ */
+
+#include "main/mtypes.h"
+
+struct builtin_variable {
+ enum ir_variable_mode mode;
+ int slot;
+ const char *type;
+ const char *name;
+};
+
+static const builtin_variable builtin_core_vs_variables[] = {
+ { ir_var_out, VERT_RESULT_HPOS, "vec4", "gl_Position" },
+ { ir_var_out, VERT_RESULT_PSIZ, "float", "gl_PointSize" },
+};
+
+static const builtin_variable builtin_core_fs_variables[] = {
+ { ir_var_in, FRAG_ATTRIB_WPOS, "vec4", "gl_FragCoord" },
+ { ir_var_in, FRAG_ATTRIB_FACE, "bool", "gl_FrontFacing" },
+ { ir_var_out, FRAG_RESULT_COLOR, "vec4", "gl_FragColor" },
+ { ir_var_out, FRAG_RESULT_DEPTH, "float", "gl_FragDepth" },
+};
+
+static const builtin_variable builtin_110_deprecated_fs_variables[] = {
+ { ir_var_in, FRAG_ATTRIB_COL0, "vec4", "gl_Color" },
+ { ir_var_in, FRAG_ATTRIB_COL1, "vec4", "gl_SecondaryColor" },
+ { ir_var_in, FRAG_ATTRIB_FOGC, "float", "gl_FogFragCoord" },
+};
+
+static const builtin_variable builtin_110_deprecated_vs_variables[] = {
+ { ir_var_in, VERT_ATTRIB_POS, "vec4", "gl_Vertex" },
+ { ir_var_in, VERT_ATTRIB_NORMAL, "vec3", "gl_Normal" },
+ { ir_var_in, VERT_ATTRIB_COLOR0, "vec4", "gl_Color" },
+ { ir_var_in, VERT_ATTRIB_COLOR1, "vec4", "gl_SecondaryColor" },
+ { ir_var_in, VERT_ATTRIB_TEX0, "vec4", "gl_MultiTexCoord0" },
+ { ir_var_in, VERT_ATTRIB_TEX1, "vec4", "gl_MultiTexCoord1" },
+ { ir_var_in, VERT_ATTRIB_TEX2, "vec4", "gl_MultiTexCoord2" },
+ { ir_var_in, VERT_ATTRIB_TEX3, "vec4", "gl_MultiTexCoord3" },
+ { ir_var_in, VERT_ATTRIB_TEX4, "vec4", "gl_MultiTexCoord4" },
+ { ir_var_in, VERT_ATTRIB_TEX5, "vec4", "gl_MultiTexCoord5" },
+ { ir_var_in, VERT_ATTRIB_TEX6, "vec4", "gl_MultiTexCoord6" },
+ { ir_var_in, VERT_ATTRIB_TEX7, "vec4", "gl_MultiTexCoord7" },
+ { ir_var_in, VERT_ATTRIB_FOG, "float", "gl_FogCoord" },
+ { ir_var_out, VERT_RESULT_HPOS, "vec4", "gl_ClipVertex" },
+ { ir_var_out, VERT_RESULT_COL0, "vec4", "gl_FrontColor" },
+ { ir_var_out, VERT_RESULT_BFC0, "vec4", "gl_BackColor" },
+ { ir_var_out, VERT_RESULT_COL1, "vec4", "gl_FrontSecondaryColor" },
+ { ir_var_out, VERT_RESULT_BFC1, "vec4", "gl_BackSecondaryColor" },
+ { ir_var_out, VERT_RESULT_FOGC, "float", "gl_FogFragCoord" },
+};
+
+static const builtin_variable builtin_120_fs_variables[] = {
+ { ir_var_in, FRAG_ATTRIB_PNTC, "vec2", "gl_PointCoord" },
+};
+
+static const builtin_variable builtin_130_vs_variables[] = {
+ { ir_var_in, -1, "int", "gl_VertexID" },
+};
+
+static const builtin_variable builtin_110_deprecated_uniforms[] = {
+ { ir_var_uniform, -1, "mat4", "gl_ModelViewMatrix" },
+ { ir_var_uniform, -1, "mat4", "gl_ProjectionMatrix" },
+ { ir_var_uniform, -1, "mat4", "gl_ModelViewProjectionMatrix" },
+ { ir_var_uniform, -1, "mat3", "gl_NormalMatrix" },
+ { ir_var_uniform, -1, "mat4", "gl_ModelViewMatrixInverse" },
+ { ir_var_uniform, -1, "mat4", "gl_ProjectionMatrixInverse" },
+ { ir_var_uniform, -1, "mat4", "gl_ModelViewProjectionMatrixInverse" },
+ { ir_var_uniform, -1, "mat4", "gl_ModelViewMatrixTranspose" },
+ { ir_var_uniform, -1, "mat4", "gl_ProjectionMatrixTranspose" },
+ { ir_var_uniform, -1, "mat4", "gl_ModelViewProjectionMatrixTranspose" },
+ { ir_var_uniform, -1, "mat4", "gl_ModelViewMatrixInverseTranspose" },
+ { ir_var_uniform, -1, "mat4", "gl_ProjectionMatrixInverseTranspose" },
+ { ir_var_uniform, -1, "mat4", "gl_ModelViewProjectionMatrixInverseTranspose" },
+ { ir_var_uniform, -1, "float", "gl_NormalScale" },
+ { ir_var_uniform, -1, "gl_LightModelParameters", "gl_LightModel"},
+};
+
diff --git a/src/glsl/builtins/ir/abs b/src/glsl/builtins/ir/abs
new file mode 100644
index 00000000000..904845307c4
--- /dev/null
+++ b/src/glsl/builtins/ir/abs
@@ -0,0 +1,21 @@
+((function abs
+ (signature float
+ (parameters
+ (declare (in) float arg0))
+ ((return (expression float abs (var_ref arg0)))))
+
+ (signature vec2
+ (parameters
+ (declare (in) vec2 arg0))
+ ((return (expression vec2 abs (var_ref arg0)))))
+
+ (signature vec3
+ (parameters
+ (declare (in) vec3 arg0))
+ ((return (expression vec3 abs (var_ref arg0)))))
+
+ (signature vec4
+ (parameters
+ (declare (in) vec4 arg0))
+ ((return (expression vec4 abs (var_ref arg0)))))
+))
diff --git a/src/glsl/builtins/ir/acos b/src/glsl/builtins/ir/acos
new file mode 100644
index 00000000000..d1cfebeff8a
--- /dev/null
+++ b/src/glsl/builtins/ir/acos
@@ -0,0 +1,22 @@
+((function acos
+ (signature float
+ (parameters
+ (declare (in) float x))
+ ((return (expression float - (constant float (1.5707963))
+ (call asin ((var_ref x)))))))
+ (signature vec2
+ (parameters
+ (declare (in) vec2 x))
+ ((return (expression vec2 - (constant float (1.5707963))
+ (call asin ((var_ref x)))))))
+ (signature vec3
+ (parameters
+ (declare (in) vec3 x))
+ ((return (expression vec3 - (constant float (1.5707963))
+ (call asin ((var_ref x)))))))
+ (signature vec4
+ (parameters
+ (declare (in) vec4 x))
+ ((return (expression vec4 - (constant float (1.5707963))
+ (call asin ((var_ref x)))))))
+))
diff --git a/src/glsl/builtins/ir/all b/src/glsl/builtins/ir/all
new file mode 100644
index 00000000000..2cac0dfb684
--- /dev/null
+++ b/src/glsl/builtins/ir/all
@@ -0,0 +1,16 @@
+((function all
+ (signature bool
+ (parameters
+ (declare (in) bvec2 arg0))
+ ((return (expression bool && (swiz x (var_ref arg0))(swiz y (var_ref arg0))))))
+
+ (signature bool
+ (parameters
+ (declare (in) bvec3 arg0))
+ ((return (expression bool && (expression bool && (swiz x (var_ref arg0))(swiz y (var_ref arg0))) (swiz z (var_ref arg0))))))
+
+ (signature bool
+ (parameters
+ (declare (in) bvec4 arg0))
+ ((return (expression bool && (expression bool && (expression bool && (swiz x (var_ref arg0))(swiz y (var_ref arg0))) (swiz z (var_ref arg0))) (swiz w (var_ref arg0))))))
+))
diff --git a/src/glsl/builtins/ir/any b/src/glsl/builtins/ir/any
new file mode 100644
index 00000000000..f10e8a7b478
--- /dev/null
+++ b/src/glsl/builtins/ir/any
@@ -0,0 +1,16 @@
+((function any
+ (signature bool
+ (parameters
+ (declare (in) bvec2 arg0))
+ ((return (expression bool || (swiz x (var_ref arg0))(swiz y (var_ref arg0))))))
+
+ (signature bool
+ (parameters
+ (declare (in) bvec3 arg0))
+ ((return (expression bool || (expression bool || (swiz x (var_ref arg0))(swiz y (var_ref arg0))) (swiz z (var_ref arg0))))))
+
+ (signature bool
+ (parameters
+ (declare (in) bvec4 arg0))
+ ((return (expression bool || (expression bool || (expression bool || (swiz x (var_ref arg0))(swiz y (var_ref arg0))) (swiz z (var_ref arg0))) (swiz w (var_ref arg0))))))
+))
diff --git a/src/glsl/builtins/ir/asin b/src/glsl/builtins/ir/asin
new file mode 100644
index 00000000000..e230ad614ee
--- /dev/null
+++ b/src/glsl/builtins/ir/asin
@@ -0,0 +1,97 @@
+((function asin
+ (signature float
+ (parameters
+ (declare (in) float x))
+ ((return (expression float *
+ (expression float sign (var_ref x))
+ (expression float -
+ (expression float *
+ (constant float (3.1415926))
+ (constant float (0.5)))
+ (expression float *
+ (expression float sqrt
+ (expression float -
+ (constant float (1.0))
+ (expression float abs (var_ref x))))
+ (expression float +
+ (constant float (1.5707288))
+ (expression float *
+ (expression float abs (var_ref x))
+ (expression float +
+ (constant float (-0.2121144))
+ (expression float *
+ (constant float (0.0742610))
+ (expression float abs (var_ref x))))))))))))
+
+ (signature vec2
+ (parameters
+ (declare (in) vec2 x))
+ ((return (expression vec2 *
+ (expression vec2 sign (var_ref x))
+ (expression vec2 -
+ (expression float *
+ (constant float (3.1415926))
+ (constant float (0.5)))
+ (expression vec2 *
+ (expression vec2 sqrt
+ (expression vec2 -
+ (constant float (1.0))
+ (expression vec2 abs (var_ref x))))
+ (expression vec2 +
+ (constant float (1.5707288))
+ (expression vec2 *
+ (expression vec2 abs (var_ref x))
+ (expression vec2 +
+ (constant float (-0.2121144))
+ (expression vec2 *
+ (constant float (0.0742610))
+ (expression vec2 abs (var_ref x))))))))))))
+
+ (signature vec3
+ (parameters
+ (declare (in) vec3 x))
+ ((return (expression vec3 *
+ (expression vec3 sign (var_ref x))
+ (expression vec3 -
+ (expression float *
+ (constant float (3.1415926))
+ (constant float (0.5)))
+ (expression vec3 *
+ (expression vec3 sqrt
+ (expression vec3 -
+ (constant float (1.0))
+ (expression vec3 abs (var_ref x))))
+ (expression vec3 +
+ (constant float (1.5707288))
+ (expression vec3 *
+ (expression vec3 abs (var_ref x))
+ (expression vec3 +
+ (constant float (-0.2121144))
+ (expression vec3 *
+ (constant float (0.0742610))
+ (expression vec3 abs (var_ref x))))))))))))
+
+ (signature vec4
+ (parameters
+ (declare (in) vec4 x))
+ ((return (expression vec4 *
+ (expression vec4 sign (var_ref x))
+ (expression vec4 -
+ (expression float *
+ (constant float (3.1415926))
+ (constant float (0.5)))
+ (expression vec4 *
+ (expression vec4 sqrt
+ (expression vec4 -
+ (constant float (1.0))
+ (expression vec4 abs (var_ref x))))
+ (expression vec4 +
+ (constant float (1.5707288))
+ (expression vec4 *
+ (expression vec4 abs (var_ref x))
+ (expression vec4 +
+ (constant float (-0.2121144))
+ (expression vec4 *
+ (constant float (0.0742610))
+ (expression vec4 abs (var_ref x))))))))))))
+))
diff --git a/src/glsl/builtins/ir/atan b/src/glsl/builtins/ir/atan
new file mode 100644
index 00000000000..84048293870
--- /dev/null
+++ b/src/glsl/builtins/ir/atan
@@ -0,0 +1,154 @@
+((function atan
+ (signature float
+ (parameters
+ (declare (in) float x))
+ ((return (call asin ((expression float *
+ (var_ref x)
+ (expression float rsq
+ (expression float +
+ (expression float *
+ (var_ref x)
+ (var_ref x))
+ (constant float (1.0))))))))))
+
+ (signature vec2
+ (parameters
+ (declare (in) vec2 y_over_x))
+ ((return (call asin ((expression vec2 *
+ (var_ref y_over_x)
+ (expression vec2 rsq
+ (expression vec2 +
+ (expression vec2 *
+ (var_ref y_over_x)
+ (var_ref y_over_x))
+ (constant float (1.0))))))))))
+
+ (signature vec3
+ (parameters
+ (declare (in) vec3 y_over_x))
+ ((return (call asin ((expression vec3 *
+ (var_ref y_over_x)
+ (expression vec3 rsq
+ (expression vec3 +
+ (expression vec3 *
+ (var_ref y_over_x)
+ (var_ref y_over_x))
+ (constant float (1.0))))))))))
+
+ (signature vec4
+ (parameters
+ (declare (in) vec4 y_over_x))
+ ((return (call asin ((expression vec4 *
+ (var_ref y_over_x)
+ (expression vec4 rsq
+ (expression vec4 +
+ (expression vec4 *
+ (var_ref y_over_x)
+ (var_ref y_over_x))
+ (constant float (1.0))))))))))
+
+ (signature float
+ (parameters
+ (declare (in ) float y)
+ (declare (in ) float x)
+ )
+ (
+ (declare () float r)
+ (declare ( ) float abs_retval)
+ (assign (constant bool (1)) (var_ref abs_retval) (call abs ((var_ref x) ))
+)
+ (if (expression bool > (var_ref abs_retval) (constant float (0.000100)) ) (
+ (declare ( ) float atan_retval)
+ (assign (constant bool (1)) (var_ref atan_retval) (call atan ((expression float / (var_ref y) (var_ref x) ) ))
+)
+ (assign (constant bool (1)) (var_ref r) (var_ref atan_retval) )
+ (if (expression bool < (var_ref x) (constant float (0.000000)) ) (
+ (if (expression bool >= (var_ref y) (constant float (0.000000)) ) (
+ (declare ( ) float assignment_tmp)
+ (assign (constant bool (1)) (var_ref assignment_tmp) (expression float + (var_ref r) (constant float (3.141593)) ) )
+ (assign (constant bool (1)) (var_ref r) (var_ref assignment_tmp) )
+ )
+ (
+ (declare ( ) float assignment_tmp)
+ (assign (constant bool (1)) (var_ref assignment_tmp) (expression float - (var_ref r) (constant float (3.141593)) ) )
+ (assign (constant bool (1)) (var_ref r) (var_ref assignment_tmp) )
+ ))
+
+ )
+ (
+ ))
+
+ )
+ (
+ (if (expression bool >= (var_ref y) (constant float (0.000000)) ) (
+ (assign (constant bool (1)) (var_ref r) (constant float (1.570796)) )
+ )
+ (
+ (assign (constant bool (1)) (var_ref r) (constant float (-1.570796)) )
+ ))
+
+ ))
+
+ (return (var_ref r) )
+ ))
+
+
+
+ (signature vec2
+ (parameters
+ (declare (in) vec2 y)
+ (declare (in) vec2 x))
+ ((declare () vec2 r)
+ (assign (constant bool (1))
+ (swiz x (var_ref r))
+ (call atan ((swiz x (var_ref y))
+ (swiz x (var_ref x)))))
+ (assign (constant bool (1))
+ (swiz y (var_ref r))
+ (call atan ((swiz y (var_ref y))
+ (swiz y (var_ref x)))))
+ (return (var_ref r))))
+
+ (signature vec3
+ (parameters
+ (declare (in) vec3 y)
+ (declare (in) vec3 x))
+ ((declare () vec3 r)
+ (assign (constant bool (1))
+ (swiz x (var_ref r))
+ (call atan ((swiz x (var_ref y))
+ (swiz x (var_ref x)))))
+ (assign (constant bool (1))
+ (swiz y (var_ref r))
+ (call atan ((swiz y (var_ref y))
+ (swiz y (var_ref x)))))
+ (assign (constant bool (1))
+ (swiz z (var_ref r))
+ (call atan ((swiz z (var_ref y))
+ (swiz z (var_ref x)))))
+ (return (var_ref r))))
+
+ (signature vec4
+ (parameters
+ (declare (in) vec4 y)
+ (declare (in) vec4 x))
+ ((declare () vec4 r)
+ (assign (constant bool (1))
+ (swiz x (var_ref r))
+ (call atan ((swiz x (var_ref y))
+ (swiz x (var_ref x)))))
+ (assign (constant bool (1))
+ (swiz y (var_ref r))
+ (call atan ((swiz y (var_ref y))
+ (swiz y (var_ref x)))))
+ (assign (constant bool (1))
+ (swiz z (var_ref r))
+ (call atan ((swiz z (var_ref y))
+ (swiz z (var_ref x)))))
+ (assign (constant bool (1))
+ (swiz w (var_ref r))
+ (call atan ((swiz w (var_ref y))
+ (swiz w (var_ref x)))))
+ (return (var_ref r)))))
+
+))
diff --git a/src/glsl/builtins/ir/ceil b/src/glsl/builtins/ir/ceil
new file mode 100644
index 00000000000..a26a7750493
--- /dev/null
+++ b/src/glsl/builtins/ir/ceil
@@ -0,0 +1,21 @@
+((function ceil
+ (signature float
+ (parameters
+ (declare (in) float arg0))
+ ((return (expression float ceil (var_ref arg0)))))
+
+ (signature vec2
+ (parameters
+ (declare (in) vec2 arg0))
+ ((return (expression vec2 ceil (var_ref arg0)))))
+
+ (signature vec3
+ (parameters
+ (declare (in) vec3 arg0))
+ ((return (expression vec3 ceil (var_ref arg0)))))
+
+ (signature vec4
+ (parameters
+ (declare (in) vec4 arg0))
+ ((return (expression vec4 ceil (var_ref arg0)))))
+))
diff --git a/src/glsl/builtins/ir/clamp b/src/glsl/builtins/ir/clamp
new file mode 100644
index 00000000000..2bdc466b269
--- /dev/null
+++ b/src/glsl/builtins/ir/clamp
@@ -0,0 +1,148 @@
+((function clamp
+ (signature float
+ (parameters
+ (declare (in) float arg0)
+ (declare (in) float arg1)
+ (declare (in) float arg2))
+ ((return (expression float max (expression float min (var_ref arg0) (var_ref arg2)) (var_ref arg1)))))
+
+ (signature vec2
+ (parameters
+ (declare (in) vec2 arg0)
+ (declare (in) vec2 arg1)
+ (declare (in) vec2 arg2))
+ ((return (expression vec2 max (expression vec2 min (var_ref arg0) (var_ref arg2)) (var_ref arg1)))))
+
+ (signature vec3
+ (parameters
+ (declare (in) vec3 arg0)
+ (declare (in) vec3 arg1)
+ (declare (in) vec3 arg2))
+ ((return (expression vec3 max (expression vec3 min (var_ref arg0) (var_ref arg2)) (var_ref arg1)))))
+
+ (signature vec4
+ (parameters
+ (declare (in) vec4 arg0)
+ (declare (in) vec4 arg1)
+ (declare (in) vec4 arg2))
+ ((return (expression vec4 max (expression vec4 min (var_ref arg0) (var_ref arg2)) (var_ref arg1)))))
+
+ (signature vec2
+ (parameters
+ (declare (in) vec2 arg0)
+ (declare (in) float arg1)
+ (declare (in) float arg2))
+ ((return (expression vec2 max (expression vec2 min (var_ref arg0) (var_ref arg2)) (var_ref arg1)))))
+
+ (signature vec3
+ (parameters
+ (declare (in) vec3 arg0)
+ (declare (in) float arg1)
+ (declare (in) float arg2))
+ ((return (expression vec3 max (expression vec3 min (var_ref arg0) (var_ref arg2)) (var_ref arg1)))))
+
+ (signature vec4
+ (parameters
+ (declare (in) vec4 arg0)
+ (declare (in) float arg1)
+ (declare (in) float arg2))
+ ((return (expression vec4 max (expression vec4 min (var_ref arg0) (var_ref arg2)) (var_ref arg1)))))
+
+ (signature int
+ (parameters
+ (declare (in) int arg0)
+ (declare (in) int arg1)
+ (declare (in) int arg2))
+ ((return (expression int max (expression int min (var_ref arg0) (var_ref arg2)) (var_ref arg1)))))
+
+ (signature ivec2
+ (parameters
+ (declare (in) ivec2 arg0)
+ (declare (in) ivec2 arg1)
+ (declare (in) ivec2 arg2))
+ ((return (expression ivec2 max (expression ivec2 min (var_ref arg0) (var_ref arg2)) (var_ref arg1)))))
+
+ (signature ivec3
+ (parameters
+ (declare (in) ivec3 arg0)
+ (declare (in) ivec3 arg1)
+ (declare (in) ivec3 arg2))
+ ((return (expression ivec3 max (expression ivec3 min (var_ref arg0) (var_ref arg2)) (var_ref arg1)))))
+
+ (signature ivec4
+ (parameters
+ (declare (in) ivec4 arg0)
+ (declare (in) ivec4 arg1)
+ (declare (in) ivec4 arg2))
+ ((return (expression ivec4 max (expression ivec4 min (var_ref arg0) (var_ref arg2)) (var_ref arg1)))))
+
+ (signature ivec2
+ (parameters
+ (declare (in) ivec2 arg0)
+ (declare (in) int arg1)
+ (declare (in) int arg2))
+ ((return (expression ivec2 max (expression ivec2 min (var_ref arg0) (var_ref arg2)) (var_ref arg1)))))
+
+ (signature ivec3
+ (parameters
+ (declare (in) ivec3 arg0)
+ (declare (in) int arg1)
+ (declare (in) int arg2))
+ ((return (expression ivec3 max (expression ivec3 min (var_ref arg0) (var_ref arg2)) (var_ref arg1)))))
+
+ (signature ivec4
+ (parameters
+ (declare (in) ivec4 arg0)
+ (declare (in) int arg1)
+ (declare (in) int arg2))
+ ((return (expression ivec4 max (expression ivec4 min (var_ref arg0) (var_ref arg2)) (var_ref arg1)))))
+
+ (signature uint
+ (parameters
+ (declare (in) uint arg0)
+ (declare (in) uint arg1)
+ (declare (in) uint arg2))
+ ((return (expression uint max (expression uint min (var_ref arg0) (var_ref arg2)) (var_ref arg1)))))
+
+ (signature uvec2
+ (parameters
+ (declare (in) uvec2 arg0)
+ (declare (in) uvec2 arg1)
+ (declare (in) uvec2 arg2))
+ ((return (expression uvec2 max (expression uvec2 min (var_ref arg0) (var_ref arg2)) (var_ref arg1)))))
+
+ (signature uvec3
+ (parameters
+ (declare (in) uvec3 arg0)
+ (declare (in) uvec3 arg1)
+ (declare (in) uvec3 arg2))
+ ((return (expression uvec3 max (expression uvec3 min (var_ref arg0) (var_ref arg2)) (var_ref arg1)))))
+
+ (signature uvec4
+ (parameters
+ (declare (in) uvec4 arg0)
+ (declare (in) uvec4 arg1)
+ (declare (in) uvec4 arg2))
+ ((return (expression uvec4 max (expression uvec4 min (var_ref arg0) (var_ref arg2)) (var_ref arg1)))))
+
+ (signature uvec2
+ (parameters
+ (declare (in) uvec2 arg0)
+ (declare (in) uint arg1)
+ (declare (in) uint arg2))
+ ((return (expression uvec2 max (expression uvec2 min (var_ref arg0) (var_ref arg2)) (var_ref arg1)))))
+
+ (signature uvec3
+ (parameters
+ (declare (in) uvec3 arg0)
+ (declare (in) uint arg1)
+ (declare (in) uint arg2))
+ ((return (expression uvec3 max (expression uvec3 min (var_ref arg0) (var_ref arg2)) (var_ref arg1)))))
+
+ (signature uvec4
+ (parameters
+ (declare (in) uvec4 arg0)
+ (declare (in) uint arg1)
+ (declare (in) uint arg2))
+ ((return (expression uvec4 max (expression uvec4 min (var_ref arg0) (var_ref arg2)) (var_ref arg1)))))
+))
diff --git a/src/glsl/builtins/ir/cos b/src/glsl/builtins/ir/cos
new file mode 100644
index 00000000000..88f266eccbe
--- /dev/null
+++ b/src/glsl/builtins/ir/cos
@@ -0,0 +1,21 @@
+((function cos
+ (signature float
+ (parameters
+ (declare (in) float angle))
+ ((return (expression float cos (var_ref angle)))))
+
+ (signature vec2
+ (parameters
+ (declare (in) vec2 angle))
+ ((return (expression vec2 cos (var_ref angle)))))
+
+ (signature vec3
+ (parameters
+ (declare (in) vec3 angle))
+ ((return (expression vec3 cos (var_ref angle)))))
+
+ (signature vec4
+ (parameters
+ (declare (in) vec4 angle))
+ ((return (expression vec4 cos (var_ref angle)))))
+))
diff --git a/src/glsl/builtins/ir/cosh b/src/glsl/builtins/ir/cosh
new file mode 100644
index 00000000000..45e0ae427d6
--- /dev/null
+++ b/src/glsl/builtins/ir/cosh
@@ -0,0 +1,30 @@
+((function cosh
+ (signature float
+ (parameters
+ (declare (in) float x))
+ ((return (expression float * (constant float (0.5))
+ (expression float +
+ (expression float exp (var_ref x))
+ (expression float exp (expression float neg (var_ref x))))))))
+ (signature vec2
+ (parameters
+ (declare (in) vec2 x))
+ ((return (expression vec2 * (constant vec2 (0.5))
+ (expression vec2 +
+ (expression vec2 exp (var_ref x))
+ (expression vec2 exp (expression vec2 neg (var_ref x))))))))
+ (signature vec3
+ (parameters
+ (declare (in) vec3 x))
+ ((return (expression vec3 * (constant vec3 (0.5))
+ (expression vec3 +
+ (expression vec3 exp (var_ref x))
+ (expression vec3 exp (expression vec3 neg (var_ref x))))))))
+ (signature vec4
+ (parameters
+ (declare (in) vec4 x))
+ ((return (expression vec4 * (constant vec4 (0.5))
+ (expression vec4 +
+ (expression vec4 exp (var_ref x))
+ (expression vec4 exp (expression vec4 neg (var_ref x))))))))
+))
diff --git a/src/glsl/builtins/ir/cross b/src/glsl/builtins/ir/cross
new file mode 100644
index 00000000000..24717a2183d
--- /dev/null
+++ b/src/glsl/builtins/ir/cross
@@ -0,0 +1,7 @@
+((function cross
+ (signature vec3
+ (parameters
+ (declare (in) vec3 arg0)
+ (declare (in) vec3 arg1))
+ ((return (expression vec3 cross (var_ref arg0) (var_ref arg1)))))
+))
diff --git a/src/glsl/builtins/ir/dFdx b/src/glsl/builtins/ir/dFdx
new file mode 100644
index 00000000000..30594d33c74
--- /dev/null
+++ b/src/glsl/builtins/ir/dFdx
@@ -0,0 +1,21 @@
+((function dFdx
+ (signature float
+ (parameters
+ (declare (in) float p))
+ ((return (expression float dFdx (var_ref p)))))
+
+ (signature vec2
+ (parameters
+ (declare (in) vec2 p))
+ ((return (expression vec2 dFdx (var_ref p)))))
+
+ (signature vec3
+ (parameters
+ (declare (in) vec3 p))
+ ((return (expression vec3 dFdx (var_ref p)))))
+
+ (signature vec4
+ (parameters
+ (declare (in) vec4 p))
+ ((return (expression vec4 dFdx (var_ref p)))))
+))
diff --git a/src/glsl/builtins/ir/dFdy b/src/glsl/builtins/ir/dFdy
new file mode 100644
index 00000000000..fb5798d3cbe
--- /dev/null
+++ b/src/glsl/builtins/ir/dFdy
@@ -0,0 +1,21 @@
+((function dFdy
+ (signature float
+ (parameters
+ (declare (in) float p))
+ ((return (expression float dFdy (var_ref p)))))
+
+ (signature vec2
+ (parameters
+ (declare (in) vec2 p))
+ ((return (expression vec2 dFdy (var_ref p)))))
+
+ (signature vec3
+ (parameters
+ (declare (in) vec3 p))
+ ((return (expression vec3 dFdy (var_ref p)))))
+
+ (signature vec4
+ (parameters
+ (declare (in) vec4 p))
+ ((return (expression vec4 dFdy (var_ref p)))))
+))
diff --git a/src/glsl/builtins/ir/degrees b/src/glsl/builtins/ir/degrees
new file mode 100644
index 00000000000..dc0d7b9e20d
--- /dev/null
+++ b/src/glsl/builtins/ir/degrees
@@ -0,0 +1,21 @@
+((function degrees
+ (signature float
+ (parameters
+ (declare (in) float arg0))
+ ((return (expression float * (var_ref arg0) (constant float (57.295780))))))
+
+ (signature vec2
+ (parameters
+ (declare (in) vec2 arg0))
+ ((return (expression vec2 * (var_ref arg0) (constant float (57.295780))))))
+
+ (signature vec3
+ (parameters
+ (declare (in) vec3 arg0))
+ ((return (expression vec3 * (var_ref arg0) (constant float (57.295780))))))
+
+ (signature vec4
+ (parameters
+ (declare (in) vec4 arg0))
+ ((return (expression vec4 * (var_ref arg0) (constant float (57.295780))))))
+))
diff --git a/src/glsl/builtins/ir/distance b/src/glsl/builtins/ir/distance
new file mode 100644
index 00000000000..a2309c484f9
--- /dev/null
+++ b/src/glsl/builtins/ir/distance
@@ -0,0 +1,33 @@
+((function distance
+ (signature float
+ (parameters
+ (declare (in) float p0)
+ (declare (in) float p1))
+ ((declare () float p)
+ (assign (constant bool (1)) (var_ref p) (expression float - (var_ref p0) (var_ref p1)))
+ (return (expression float sqrt (expression float dot (var_ref p) (var_ref p))))))
+
+ (signature float
+ (parameters
+ (declare (in) vec2 p0)
+ (declare (in) vec2 p1))
+ ((declare () vec2 p)
+ (assign (constant bool (1)) (var_ref p) (expression vec2 - (var_ref p0) (var_ref p1)))
+ (return (expression float sqrt (expression float dot (var_ref p) (var_ref p))))))
+
+ (signature float
+ (parameters
+ (declare (in) vec3 p0)
+ (declare (in) vec3 p1))
+ ((declare () vec3 p)
+ (assign (constant bool (1)) (var_ref p) (expression vec3 - (var_ref p0) (var_ref p1)))
+ (return (expression float sqrt (expression float dot (var_ref p) (var_ref p))))))
+
+ (signature float
+ (parameters
+ (declare (in) vec4 p0)
+ (declare (in) vec4 p1))
+ ((declare () vec4 p)
+ (assign (constant bool (1)) (var_ref p) (expression vec4 - (var_ref p0) (var_ref p1)))
+ (return (expression float sqrt (expression float dot (var_ref p) (var_ref p))))))
+))
diff --git a/src/glsl/builtins/ir/dot b/src/glsl/builtins/ir/dot
new file mode 100644
index 00000000000..a91a6d2c56d
--- /dev/null
+++ b/src/glsl/builtins/ir/dot
@@ -0,0 +1,25 @@
+((function dot
+ (signature float
+ (parameters
+ (declare (in) float arg0)
+ (declare (in) float arg1))
+ ((return (expression float dot (var_ref arg0) (var_ref arg1)))))
+
+ (signature float
+ (parameters
+ (declare (in) vec2 arg0)
+ (declare (in) vec2 arg1))
+ ((return (expression float dot (var_ref arg0) (var_ref arg1)))))
+
+ (signature float
+ (parameters
+ (declare (in) vec3 arg0)
+ (declare (in) vec3 arg1))
+ ((return (expression float dot (var_ref arg0) (var_ref arg1)))))
+
+ (signature float
+ (parameters
+ (declare (in) vec4 arg0)
+ (declare (in) vec4 arg1))
+ ((return (expression float dot (var_ref arg0) (var_ref arg1)))))
+))
diff --git a/src/glsl/builtins/ir/equal b/src/glsl/builtins/ir/equal
new file mode 100644
index 00000000000..d7a4bc6063f
--- /dev/null
+++ b/src/glsl/builtins/ir/equal
@@ -0,0 +1,91 @@
+((function equal
+ (signature bvec2
+ (parameters
+ (declare (in) vec2 arg0)
+ (declare (in) vec2 arg1))
+ ((declare () bvec2 temp)
+ (assign (constant bool (1)) (swiz x (var_ref temp)) (expression bool == (swiz x (var_ref arg0))(swiz x (var_ref arg1))))
+ (assign (constant bool (1)) (swiz y (var_ref temp)) (expression bool == (swiz y (var_ref arg0))(swiz y (var_ref arg1))))
+ (return (var_ref temp))))
+
+ (signature bvec3
+ (parameters
+ (declare (in) vec3 arg0)
+ (declare (in) vec3 arg1))
+ ((declare () bvec3 temp)
+ (assign (constant bool (1)) (swiz x (var_ref temp)) (expression bool == (swiz x (var_ref arg0))(swiz x (var_ref arg1))))
+ (assign (constant bool (1)) (swiz y (var_ref temp)) (expression bool == (swiz y (var_ref arg0))(swiz y (var_ref arg1))))
+ (assign (constant bool (1)) (swiz z (var_ref temp)) (expression bool == (swiz z (var_ref arg0))(swiz z (var_ref arg1))))
+ (return (var_ref temp))))
+
+ (signature bvec4
+ (parameters
+ (declare (in) vec4 arg0)
+ (declare (in) vec4 arg1))
+ ((declare () bvec4 temp)
+ (assign (constant bool (1)) (swiz x (var_ref temp)) (expression bool == (swiz x (var_ref arg0))(swiz x (var_ref arg1))))
+ (assign (constant bool (1)) (swiz y (var_ref temp)) (expression bool == (swiz y (var_ref arg0))(swiz y (var_ref arg1))))
+ (assign (constant bool (1)) (swiz z (var_ref temp)) (expression bool == (swiz z (var_ref arg0))(swiz z (var_ref arg1))))
+ (assign (constant bool (1)) (swiz w (var_ref temp)) (expression bool == (swiz w (var_ref arg0))(swiz w (var_ref arg1))))
+ (return (var_ref temp))))
+
+ (signature bvec2
+ (parameters
+ (declare (in) ivec2 arg0)
+ (declare (in) ivec2 arg1))
+ ((declare () bvec2 temp)
+ (assign (constant bool (1)) (swiz x (var_ref temp)) (expression bool == (swiz x (var_ref arg0))(swiz x (var_ref arg1))))
+ (assign (constant bool (1)) (swiz y (var_ref temp)) (expression bool == (swiz y (var_ref arg0))(swiz y (var_ref arg1))))
+ (return (var_ref temp))))
+
+ (signature bvec3
+ (parameters
+ (declare (in) ivec3 arg0)
+ (declare (in) ivec3 arg1))
+ ((declare () bvec3 temp)
+ (assign (constant bool (1)) (swiz x (var_ref temp)) (expression bool == (swiz x (var_ref arg0))(swiz x (var_ref arg1))))
+ (assign (constant bool (1)) (swiz y (var_ref temp)) (expression bool == (swiz y (var_ref arg0))(swiz y (var_ref arg1))))
+ (assign (constant bool (1)) (swiz z (var_ref temp)) (expression bool == (swiz z (var_ref arg0))(swiz z (var_ref arg1))))
+ (return (var_ref temp))))
+
+ (signature bvec4
+ (parameters
+ (declare (in) ivec4 arg0)
+ (declare (in) ivec4 arg1))
+ ((declare () bvec4 temp)
+ (assign (constant bool (1)) (swiz x (var_ref temp)) (expression bool == (swiz x (var_ref arg0))(swiz x (var_ref arg1))))
+ (assign (constant bool (1)) (swiz y (var_ref temp)) (expression bool == (swiz y (var_ref arg0))(swiz y (var_ref arg1))))
+ (assign (constant bool (1)) (swiz z (var_ref temp)) (expression bool == (swiz z (var_ref arg0))(swiz z (var_ref arg1))))
+ (assign (constant bool (1)) (swiz w (var_ref temp)) (expression bool == (swiz w (var_ref arg0))(swiz w (var_ref arg1))))
+ (return (var_ref temp))))
+
+ (signature bvec2
+ (parameters
+ (declare (in) uvec2 arg0)
+ (declare (in) uvec2 arg1))
+ ((declare () bvec2 temp)
+ (assign (constant bool (1)) (swiz x (var_ref temp)) (expression bool == (swiz x (var_ref arg0))(swiz x (var_ref arg1))))
+ (assign (constant bool (1)) (swiz y (var_ref temp)) (expression bool == (swiz y (var_ref arg0))(swiz y (var_ref arg1))))
+ (return (var_ref temp))))
+
+ (signature bvec3
+ (parameters
+ (declare (in) uvec3 arg0)
+ (declare (in) uvec3 arg1))
+ ((declare () bvec3 temp)
+ (assign (constant bool (1)) (swiz x (var_ref temp)) (expression bool == (swiz x (var_ref arg0))(swiz x (var_ref arg1))))
+ (assign (constant bool (1)) (swiz y (var_ref temp)) (expression bool == (swiz y (var_ref arg0))(swiz y (var_ref arg1))))
+ (assign (constant bool (1)) (swiz z (var_ref temp)) (expression bool == (swiz z (var_ref arg0))(swiz z (var_ref arg1))))
+ (return (var_ref temp))))
+
+ (signature bvec4
+ (parameters
+ (declare (in) uvec4 arg0)
+ (declare (in) uvec4 arg1))
+ ((declare () bvec4 temp)
+ (assign (constant bool (1)) (swiz x (var_ref temp)) (expression bool == (swiz x (var_ref arg0))(swiz x (var_ref arg1))))
+ (assign (constant bool (1)) (swiz y (var_ref temp)) (expression bool == (swiz y (var_ref arg0))(swiz y (var_ref arg1))))
+ (assign (constant bool (1)) (swiz z (var_ref temp)) (expression bool == (swiz z (var_ref arg0))(swiz z (var_ref arg1))))
+ (assign (constant bool (1)) (swiz w (var_ref temp)) (expression bool == (swiz w (var_ref arg0))(swiz w (var_ref arg1))))
+ (return (var_ref temp))))
+))
diff --git a/src/glsl/builtins/ir/exp b/src/glsl/builtins/ir/exp
new file mode 100644
index 00000000000..a73bd6a7f84
--- /dev/null
+++ b/src/glsl/builtins/ir/exp
@@ -0,0 +1,21 @@
+((function exp
+ (signature float
+ (parameters
+ (declare (in) float arg0))
+ ((return (expression float exp (var_ref arg0)))))
+
+ (signature vec2
+ (parameters
+ (declare (in) vec2 arg0))
+ ((return (expression vec2 exp (var_ref arg0)))))
+
+ (signature vec3
+ (parameters
+ (declare (in) vec3 arg0))
+ ((return (expression vec3 exp (var_ref arg0)))))
+
+ (signature vec4
+ (parameters
+ (declare (in) vec4 arg0))
+ ((return (expression vec4 exp (var_ref arg0)))))
+))
diff --git a/src/glsl/builtins/ir/exp2 b/src/glsl/builtins/ir/exp2
new file mode 100644
index 00000000000..a842d3fe65b
--- /dev/null
+++ b/src/glsl/builtins/ir/exp2
@@ -0,0 +1,21 @@
+((function exp2
+ (signature float
+ (parameters
+ (declare (in) float arg0))
+ ((return (expression float exp2 (var_ref arg0)))))
+
+ (signature vec2
+ (parameters
+ (declare (in) vec2 arg0))
+ ((return (expression vec2 exp2 (var_ref arg0)))))
+
+ (signature vec3
+ (parameters
+ (declare (in) vec3 arg0))
+ ((return (expression vec3 exp2 (var_ref arg0)))))
+
+ (signature vec4
+ (parameters
+ (declare (in) vec4 arg0))
+ ((return (expression vec4 exp2 (var_ref arg0)))))
+))
diff --git a/src/glsl/builtins/ir/faceforward b/src/glsl/builtins/ir/faceforward
new file mode 100644
index 00000000000..d1703972388
--- /dev/null
+++ b/src/glsl/builtins/ir/faceforward
@@ -0,0 +1,37 @@
+((function faceforward
+ (signature float
+ (parameters
+ (declare (in) float N)
+ (declare (in) float I)
+ (declare (in) float Nref))
+ ((if (expression bool < (expression float dot (var_ref Nref) (var_ref I)) (constant float (0)))
+ ((return (var_ref N)))
+ ((return (expression float neg (var_ref N)))))))
+
+ (signature vec2
+ (parameters
+ (declare (in) vec2 N)
+ (declare (in) vec2 I)
+ (declare (in) vec2 Nref))
+ ((if (expression bool < (expression float dot (var_ref Nref) (var_ref I)) (constant float (0)))
+ ((return (var_ref N)))
+ ((return (expression vec2 neg (var_ref N)))))))
+
+ (signature vec3
+ (parameters
+ (declare (in) vec3 N)
+ (declare (in) vec3 I)
+ (declare (in) vec3 Nref))
+ ((if (expression bool < (expression float dot (var_ref Nref) (var_ref I)) (constant float (0)))
+ ((return (var_ref N)))
+ ((return (expression vec3 neg (var_ref N)))))))
+
+ (signature vec4
+ (parameters
+ (declare (in) vec4 N)
+ (declare (in) vec4 I)
+ (declare (in) vec4 Nref))
+ ((if (expression bool < (expression float dot (var_ref Nref) (var_ref I)) (constant float (0)))
+ ((return (var_ref N)))
+ ((return (expression vec4 neg (var_ref N)))))))
+))
diff --git a/src/glsl/builtins/ir/floor b/src/glsl/builtins/ir/floor
new file mode 100644
index 00000000000..8dd8052799b
--- /dev/null
+++ b/src/glsl/builtins/ir/floor
@@ -0,0 +1,21 @@
+((function floor
+ (signature float
+ (parameters
+ (declare (in) float arg0))
+ ((return (expression float floor (var_ref arg0)))))
+
+ (signature vec2
+ (parameters
+ (declare (in) vec2 arg0))
+ ((return (expression vec2 floor (var_ref arg0)))))
+
+ (signature vec3
+ (parameters
+ (declare (in) vec3 arg0))
+ ((return (expression vec3 floor (var_ref arg0)))))
+
+ (signature vec4
+ (parameters
+ (declare (in) vec4 arg0))
+ ((return (expression vec4 floor (var_ref arg0)))))
+))
diff --git a/src/glsl/builtins/ir/fract b/src/glsl/builtins/ir/fract
new file mode 100644
index 00000000000..3f0763d1b3e
--- /dev/null
+++ b/src/glsl/builtins/ir/fract
@@ -0,0 +1,22 @@
+((function fract
+ (signature float
+ (parameters
+ (declare (in) float x))
+ ((return (expression float fract (var_ref x)))))
+
+ (signature vec2
+ (parameters
+ (declare (in) vec2 x))
+ ((return (expression vec2 fract (var_ref x)))))
+
+ (signature vec3
+ (parameters
+ (declare (in) vec3 x))
+ ((return (expression vec3 fract (var_ref x)))))
+
+ (signature vec4
+ (parameters
+ (declare (in) vec4 x))
+ ((return (expression vec4 fract (var_ref x)))))
+))
+
diff --git a/src/glsl/builtins/ir/ftransform b/src/glsl/builtins/ir/ftransform
new file mode 100644
index 00000000000..9ca63dc1e34
--- /dev/null
+++ b/src/glsl/builtins/ir/ftransform
@@ -0,0 +1,9 @@
+((declare (uniform) mat4 gl_ModelViewProjectionMatrix)
+ (declare (in) vec4 gl_Vertex)
+ (function ftransform
+ (signature vec4
+ (parameters)
+ ((return (expression vec4 *
+ (var_ref gl_ModelViewProjectionMatrix)
+ (var_ref gl_Vertex)))))
+))
diff --git a/src/glsl/builtins/ir/fwidth b/src/glsl/builtins/ir/fwidth
new file mode 100644
index 00000000000..385e05d6a1a
--- /dev/null
+++ b/src/glsl/builtins/ir/fwidth
@@ -0,0 +1,29 @@
+((function fwidth
+ (signature float
+ (parameters
+ (declare (in) float p))
+ ((return (expression float +
+ (expression float abs (expression float dFdx (var_ref p)))
+ (expression float abs (expression float dFdy (var_ref p)))))))
+
+ (signature vec2
+ (parameters
+ (declare (in) vec2 p))
+ ((return (expression vec2 +
+ (expression vec2 abs (expression vec2 dFdx (var_ref p)))
+ (expression vec2 abs (expression vec2 dFdy (var_ref p)))))))
+
+ (signature vec3
+ (parameters
+ (declare (in) vec3 p))
+ ((return (expression vec3 +
+ (expression vec3 abs (expression vec3 dFdx (var_ref p)))
+ (expression vec3 abs (expression vec3 dFdy (var_ref p)))))))
+
+ (signature vec4
+ (parameters
+ (declare (in) vec4 p))
+ ((return (expression vec4 +
+ (expression vec4 abs (expression vec4 dFdx (var_ref p)))
+ (expression vec4 abs (expression vec4 dFdy (var_ref p)))))))
+))
diff --git a/src/glsl/builtins/ir/greaterThan b/src/glsl/builtins/ir/greaterThan
new file mode 100644
index 00000000000..ce7bd29bed8
--- /dev/null
+++ b/src/glsl/builtins/ir/greaterThan
@@ -0,0 +1,91 @@
+((function greaterThan
+ (signature bvec2
+ (parameters
+ (declare (in) vec2 arg0)
+ (declare (in) vec2 arg1))
+ ((declare () bvec2 temp)
+ (assign (constant bool (1)) (swiz x (var_ref temp)) (expression bool > (swiz x (var_ref arg0))(swiz x (var_ref arg1))))
+ (assign (constant bool (1)) (swiz y (var_ref temp)) (expression bool > (swiz y (var_ref arg0))(swiz y (var_ref arg1))))
+ (return (var_ref temp))))
+
+ (signature bvec3
+ (parameters
+ (declare (in) vec3 arg0)
+ (declare (in) vec3 arg1))
+ ((declare () bvec3 temp)
+ (assign (constant bool (1)) (swiz x (var_ref temp)) (expression bool > (swiz x (var_ref arg0))(swiz x (var_ref arg1))))
+ (assign (constant bool (1)) (swiz y (var_ref temp)) (expression bool > (swiz y (var_ref arg0))(swiz y (var_ref arg1))))
+ (assign (constant bool (1)) (swiz z (var_ref temp)) (expression bool > (swiz z (var_ref arg0))(swiz z (var_ref arg1))))
+ (return (var_ref temp))))
+
+ (signature bvec4
+ (parameters
+ (declare (in) vec4 arg0)
+ (declare (in) vec4 arg1))
+ ((declare () bvec4 temp)
+ (assign (constant bool (1)) (swiz x (var_ref temp)) (expression bool > (swiz x (var_ref arg0))(swiz x (var_ref arg1))))
+ (assign (constant bool (1)) (swiz y (var_ref temp)) (expression bool > (swiz y (var_ref arg0))(swiz y (var_ref arg1))))
+ (assign (constant bool (1)) (swiz z (var_ref temp)) (expression bool > (swiz z (var_ref arg0))(swiz z (var_ref arg1))))
+ (assign (constant bool (1)) (swiz w (var_ref temp)) (expression bool > (swiz w (var_ref arg0))(swiz w (var_ref arg1))))
+ (return (var_ref temp))))
+
+ (signature bvec2
+ (parameters
+ (declare (in) ivec2 arg0)
+ (declare (in) ivec2 arg1))
+ ((declare () bvec2 temp)
+ (assign (constant bool (1)) (swiz x (var_ref temp)) (expression bool > (swiz x (var_ref arg0))(swiz x (var_ref arg1))))
+ (assign (constant bool (1)) (swiz y (var_ref temp)) (expression bool > (swiz y (var_ref arg0))(swiz y (var_ref arg1))))
+ (return (var_ref temp))))
+
+ (signature bvec3
+ (parameters
+ (declare (in) ivec3 arg0)
+ (declare (in) ivec3 arg1))
+ ((declare () bvec3 temp)
+ (assign (constant bool (1)) (swiz x (var_ref temp)) (expression bool > (swiz x (var_ref arg0))(swiz x (var_ref arg1))))
+ (assign (constant bool (1)) (swiz y (var_ref temp)) (expression bool > (swiz y (var_ref arg0))(swiz y (var_ref arg1))))
+ (assign (constant bool (1)) (swiz z (var_ref temp)) (expression bool > (swiz z (var_ref arg0))(swiz z (var_ref arg1))))
+ (return (var_ref temp))))
+
+ (signature bvec4
+ (parameters
+ (declare (in) ivec4 arg0)
+ (declare (in) ivec4 arg1))
+ ((declare () bvec4 temp)
+ (assign (constant bool (1)) (swiz x (var_ref temp)) (expression bool > (swiz x (var_ref arg0))(swiz x (var_ref arg1))))
+ (assign (constant bool (1)) (swiz y (var_ref temp)) (expression bool > (swiz y (var_ref arg0))(swiz y (var_ref arg1))))
+ (assign (constant bool (1)) (swiz z (var_ref temp)) (expression bool > (swiz z (var_ref arg0))(swiz z (var_ref arg1))))
+ (assign (constant bool (1)) (swiz w (var_ref temp)) (expression bool > (swiz w (var_ref arg0))(swiz w (var_ref arg1))))
+ (return (var_ref temp))))
+
+ (signature bvec2
+ (parameters
+ (declare (in) uvec2 arg0)
+ (declare (in) uvec2 arg1))
+ ((declare () bvec2 temp)
+ (assign (constant bool (1)) (swiz x (var_ref temp)) (expression bool > (swiz x (var_ref arg0))(swiz x (var_ref arg1))))
+ (assign (constant bool (1)) (swiz y (var_ref temp)) (expression bool > (swiz y (var_ref arg0))(swiz y (var_ref arg1))))
+ (return (var_ref temp))))
+
+ (signature bvec3
+ (parameters
+ (declare (in) uvec3 arg0)
+ (declare (in) uvec3 arg1))
+ ((declare () bvec3 temp)
+ (assign (constant bool (1)) (swiz x (var_ref temp)) (expression bool > (swiz x (var_ref arg0))(swiz x (var_ref arg1))))
+ (assign (constant bool (1)) (swiz y (var_ref temp)) (expression bool > (swiz y (var_ref arg0))(swiz y (var_ref arg1))))
+ (assign (constant bool (1)) (swiz z (var_ref temp)) (expression bool > (swiz z (var_ref arg0))(swiz z (var_ref arg1))))
+ (return (var_ref temp))))
+
+ (signature bvec4
+ (parameters
+ (declare (in) uvec4 arg0)
+ (declare (in) uvec4 arg1))
+ ((declare () bvec4 temp)
+ (assign (constant bool (1)) (swiz x (var_ref temp)) (expression bool > (swiz x (var_ref arg0))(swiz x (var_ref arg1))))
+ (assign (constant bool (1)) (swiz y (var_ref temp)) (expression bool > (swiz y (var_ref arg0))(swiz y (var_ref arg1))))
+ (assign (constant bool (1)) (swiz z (var_ref temp)) (expression bool > (swiz z (var_ref arg0))(swiz z (var_ref arg1))))
+ (assign (constant bool (1)) (swiz w (var_ref temp)) (expression bool > (swiz w (var_ref arg0))(swiz w (var_ref arg1))))
+ (return (var_ref temp))))
+))
diff --git a/src/glsl/builtins/ir/greaterThanEqual b/src/glsl/builtins/ir/greaterThanEqual
new file mode 100644
index 00000000000..de1a9f9516e
--- /dev/null
+++ b/src/glsl/builtins/ir/greaterThanEqual
@@ -0,0 +1,91 @@
+((function greaterThanEqual
+ (signature bvec2
+ (parameters
+ (declare (in) vec2 arg0)
+ (declare (in) vec2 arg1))
+ ((declare () bvec2 temp)
+ (assign (constant bool (1)) (swiz x (var_ref temp)) (expression bool >= (swiz x (var_ref arg0))(swiz x (var_ref arg1))))
+ (assign (constant bool (1)) (swiz y (var_ref temp)) (expression bool >= (swiz y (var_ref arg0))(swiz y (var_ref arg1))))
+ (return (var_ref temp))))
+
+ (signature bvec3
+ (parameters
+ (declare (in) vec3 arg0)
+ (declare (in) vec3 arg1))
+ ((declare () bvec3 temp)
+ (assign (constant bool (1)) (swiz x (var_ref temp)) (expression bool >= (swiz x (var_ref arg0))(swiz x (var_ref arg1))))
+ (assign (constant bool (1)) (swiz y (var_ref temp)) (expression bool >= (swiz y (var_ref arg0))(swiz y (var_ref arg1))))
+ (assign (constant bool (1)) (swiz z (var_ref temp)) (expression bool >= (swiz z (var_ref arg0))(swiz z (var_ref arg1))))
+ (return (var_ref temp))))
+
+ (signature bvec4
+ (parameters
+ (declare (in) vec4 arg0)
+ (declare (in) vec4 arg1))
+ ((declare () bvec4 temp)
+ (assign (constant bool (1)) (swiz x (var_ref temp)) (expression bool >= (swiz x (var_ref arg0))(swiz x (var_ref arg1))))
+ (assign (constant bool (1)) (swiz y (var_ref temp)) (expression bool >= (swiz y (var_ref arg0))(swiz y (var_ref arg1))))
+ (assign (constant bool (1)) (swiz z (var_ref temp)) (expression bool >= (swiz z (var_ref arg0))(swiz z (var_ref arg1))))
+ (assign (constant bool (1)) (swiz w (var_ref temp)) (expression bool >= (swiz w (var_ref arg0))(swiz w (var_ref arg1))))
+ (return (var_ref temp))))
+
+ (signature bvec2
+ (parameters
+ (declare (in) ivec2 arg0)
+ (declare (in) ivec2 arg1))
+ ((declare () bvec2 temp)
+ (assign (constant bool (1)) (swiz x (var_ref temp)) (expression bool >= (swiz x (var_ref arg0))(swiz x (var_ref arg1))))
+ (assign (constant bool (1)) (swiz y (var_ref temp)) (expression bool >= (swiz y (var_ref arg0))(swiz y (var_ref arg1))))
+ (return (var_ref temp))))
+
+ (signature bvec3
+ (parameters
+ (declare (in) ivec3 arg0)
+ (declare (in) ivec3 arg1))
+ ((declare () bvec3 temp)
+ (assign (constant bool (1)) (swiz x (var_ref temp)) (expression bool >= (swiz x (var_ref arg0))(swiz x (var_ref arg1))))
+ (assign (constant bool (1)) (swiz y (var_ref temp)) (expression bool >= (swiz y (var_ref arg0))(swiz y (var_ref arg1))))
+ (assign (constant bool (1)) (swiz z (var_ref temp)) (expression bool >= (swiz z (var_ref arg0))(swiz z (var_ref arg1))))
+ (return (var_ref temp))))
+
+ (signature bvec4
+ (parameters
+ (declare (in) ivec4 arg0)
+ (declare (in) ivec4 arg1))
+ ((declare () bvec4 temp)
+ (assign (constant bool (1)) (swiz x (var_ref temp)) (expression bool >= (swiz x (var_ref arg0))(swiz x (var_ref arg1))))
+ (assign (constant bool (1)) (swiz y (var_ref temp)) (expression bool >= (swiz y (var_ref arg0))(swiz y (var_ref arg1))))
+ (assign (constant bool (1)) (swiz z (var_ref temp)) (expression bool >= (swiz z (var_ref arg0))(swiz z (var_ref arg1))))
+ (assign (constant bool (1)) (swiz w (var_ref temp)) (expression bool >= (swiz w (var_ref arg0))(swiz w (var_ref arg1))))
+ (return (var_ref temp))))
+
+ (signature bvec2
+ (parameters
+ (declare (in) uvec2 arg0)
+ (declare (in) uvec2 arg1))
+ ((declare () bvec2 temp)
+ (assign (constant bool (1)) (swiz x (var_ref temp)) (expression bool >= (swiz x (var_ref arg0))(swiz x (var_ref arg1))))
+ (assign (constant bool (1)) (swiz y (var_ref temp)) (expression bool >= (swiz y (var_ref arg0))(swiz y (var_ref arg1))))
+ (return (var_ref temp))))
+
+ (signature bvec3
+ (parameters
+ (declare (in) uvec3 arg0)
+ (declare (in) uvec3 arg1))
+ ((declare () bvec3 temp)
+ (assign (constant bool (1)) (swiz x (var_ref temp)) (expression bool >= (swiz x (var_ref arg0))(swiz x (var_ref arg1))))
+ (assign (constant bool (1)) (swiz y (var_ref temp)) (expression bool >= (swiz y (var_ref arg0))(swiz y (var_ref arg1))))
+ (assign (constant bool (1)) (swiz z (var_ref temp)) (expression bool >= (swiz z (var_ref arg0))(swiz z (var_ref arg1))))
+ (return (var_ref temp))))
+
+ (signature bvec4
+ (parameters
+ (declare (in) uvec4 arg0)
+ (declare (in) uvec4 arg1))
+ ((declare () bvec4 temp)
+ (assign (constant bool (1)) (swiz x (var_ref temp)) (expression bool >= (swiz x (var_ref arg0))(swiz x (var_ref arg1))))
+ (assign (constant bool (1)) (swiz y (var_ref temp)) (expression bool >= (swiz y (var_ref arg0))(swiz y (var_ref arg1))))
+ (assign (constant bool (1)) (swiz z (var_ref temp)) (expression bool >= (swiz z (var_ref arg0))(swiz z (var_ref arg1))))
+ (assign (constant bool (1)) (swiz w (var_ref temp)) (expression bool >= (swiz w (var_ref arg0))(swiz w (var_ref arg1))))
+ (return (var_ref temp))))
+))
diff --git a/src/glsl/builtins/ir/inversesqrt b/src/glsl/builtins/ir/inversesqrt
new file mode 100644
index 00000000000..5b66d2b3695
--- /dev/null
+++ b/src/glsl/builtins/ir/inversesqrt
@@ -0,0 +1,21 @@
+((function inversesqrt
+ (signature float
+ (parameters
+ (declare (in) float arg0))
+ ((return (expression float rsq (var_ref arg0)))))
+
+ (signature vec2
+ (parameters
+ (declare (in) vec2 arg0))
+ ((return (expression vec2 rsq (var_ref arg0)))))
+
+ (signature vec3
+ (parameters
+ (declare (in) vec3 arg0))
+ ((return (expression vec3 rsq (var_ref arg0)))))
+
+ (signature vec4
+ (parameters
+ (declare (in) vec4 arg0))
+ ((return (expression vec4 rsq (var_ref arg0)))))
+))
diff --git a/src/glsl/builtins/ir/length b/src/glsl/builtins/ir/length
new file mode 100644
index 00000000000..89ff7f3ef12
--- /dev/null
+++ b/src/glsl/builtins/ir/length
@@ -0,0 +1,21 @@
+((function length
+ (signature float
+ (parameters
+ (declare (in) float arg0))
+ ((return (expression float sqrt (expression float dot (var_ref arg0) (var_ref arg0))))))
+
+ (signature float
+ (parameters
+ (declare (in) vec2 arg0))
+ ((return (expression float sqrt (expression float dot (var_ref arg0) (var_ref arg0))))))
+
+ (signature float
+ (parameters
+ (declare (in) vec3 arg0))
+ ((return (expression float sqrt (expression float dot (var_ref arg0) (var_ref arg0))))))
+
+ (signature float
+ (parameters
+ (declare (in) vec4 arg0))
+ ((return (expression float sqrt (expression float dot (var_ref arg0) (var_ref arg0))))))
+))
diff --git a/src/glsl/builtins/ir/lessThan b/src/glsl/builtins/ir/lessThan
new file mode 100644
index 00000000000..52113b70466
--- /dev/null
+++ b/src/glsl/builtins/ir/lessThan
@@ -0,0 +1,91 @@
+((function lessThan
+ (signature bvec2
+ (parameters
+ (declare (in) vec2 arg0)
+ (declare (in) vec2 arg1))
+ ((declare () bvec2 temp)
+ (assign (constant bool (1)) (swiz x (var_ref temp)) (expression bool < (swiz x (var_ref arg0))(swiz x (var_ref arg1))))
+ (assign (constant bool (1)) (swiz y (var_ref temp)) (expression bool < (swiz y (var_ref arg0))(swiz y (var_ref arg1))))
+ (return (var_ref temp))))
+
+ (signature bvec3
+ (parameters
+ (declare (in) vec3 arg0)
+ (declare (in) vec3 arg1))
+ ((declare () bvec3 temp)
+ (assign (constant bool (1)) (swiz x (var_ref temp)) (expression bool < (swiz x (var_ref arg0))(swiz x (var_ref arg1))))
+ (assign (constant bool (1)) (swiz y (var_ref temp)) (expression bool < (swiz y (var_ref arg0))(swiz y (var_ref arg1))))
+ (assign (constant bool (1)) (swiz z (var_ref temp)) (expression bool < (swiz z (var_ref arg0))(swiz z (var_ref arg1))))
+ (return (var_ref temp))))
+
+ (signature bvec4
+ (parameters
+ (declare (in) vec4 arg0)
+ (declare (in) vec4 arg1))
+ ((declare () bvec4 temp)
+ (assign (constant bool (1)) (swiz x (var_ref temp)) (expression bool < (swiz x (var_ref arg0))(swiz x (var_ref arg1))))
+ (assign (constant bool (1)) (swiz y (var_ref temp)) (expression bool < (swiz y (var_ref arg0))(swiz y (var_ref arg1))))
+ (assign (constant bool (1)) (swiz z (var_ref temp)) (expression bool < (swiz z (var_ref arg0))(swiz z (var_ref arg1))))
+ (assign (constant bool (1)) (swiz w (var_ref temp)) (expression bool < (swiz w (var_ref arg0))(swiz w (var_ref arg1))))
+ (return (var_ref temp))))
+
+ (signature bvec2
+ (parameters
+ (declare (in) ivec2 arg0)
+ (declare (in) ivec2 arg1))
+ ((declare () bvec2 temp)
+ (assign (constant bool (1)) (swiz x (var_ref temp)) (expression bool < (swiz x (var_ref arg0))(swiz x (var_ref arg1))))
+ (assign (constant bool (1)) (swiz y (var_ref temp)) (expression bool < (swiz y (var_ref arg0))(swiz y (var_ref arg1))))
+ (return (var_ref temp))))
+
+ (signature bvec3
+ (parameters
+ (declare (in) ivec3 arg0)
+ (declare (in) ivec3 arg1))
+ ((declare () bvec3 temp)
+ (assign (constant bool (1)) (swiz x (var_ref temp)) (expression bool < (swiz x (var_ref arg0))(swiz x (var_ref arg1))))
+ (assign (constant bool (1)) (swiz y (var_ref temp)) (expression bool < (swiz y (var_ref arg0))(swiz y (var_ref arg1))))
+ (assign (constant bool (1)) (swiz z (var_ref temp)) (expression bool < (swiz z (var_ref arg0))(swiz z (var_ref arg1))))
+ (return (var_ref temp))))
+
+ (signature bvec4
+ (parameters
+ (declare (in) ivec4 arg0)
+ (declare (in) ivec4 arg1))
+ ((declare () bvec4 temp)
+ (assign (constant bool (1)) (swiz x (var_ref temp)) (expression bool < (swiz x (var_ref arg0))(swiz x (var_ref arg1))))
+ (assign (constant bool (1)) (swiz y (var_ref temp)) (expression bool < (swiz y (var_ref arg0))(swiz y (var_ref arg1))))
+ (assign (constant bool (1)) (swiz z (var_ref temp)) (expression bool < (swiz z (var_ref arg0))(swiz z (var_ref arg1))))
+ (assign (constant bool (1)) (swiz w (var_ref temp)) (expression bool < (swiz w (var_ref arg0))(swiz w (var_ref arg1))))
+ (return (var_ref temp))))
+
+ (signature bvec2
+ (parameters
+ (declare (in) uvec2 arg0)
+ (declare (in) uvec2 arg1))
+ ((declare () bvec2 temp)
+ (assign (constant bool (1)) (swiz x (var_ref temp)) (expression bool < (swiz x (var_ref arg0))(swiz x (var_ref arg1))))
+ (assign (constant bool (1)) (swiz y (var_ref temp)) (expression bool < (swiz y (var_ref arg0))(swiz y (var_ref arg1))))
+ (return (var_ref temp))))
+
+ (signature bvec3
+ (parameters
+ (declare (in) uvec3 arg0)
+ (declare (in) uvec3 arg1))
+ ((declare () bvec3 temp)
+ (assign (constant bool (1)) (swiz x (var_ref temp)) (expression bool < (swiz x (var_ref arg0))(swiz x (var_ref arg1))))
+ (assign (constant bool (1)) (swiz y (var_ref temp)) (expression bool < (swiz y (var_ref arg0))(swiz y (var_ref arg1))))
+ (assign (constant bool (1)) (swiz z (var_ref temp)) (expression bool < (swiz z (var_ref arg0))(swiz z (var_ref arg1))))
+ (return (var_ref temp))))
+
+ (signature bvec4
+ (parameters
+ (declare (in) uvec4 arg0)
+ (declare (in) uvec4 arg1))
+ ((declare () bvec4 temp)
+ (assign (constant bool (1)) (swiz x (var_ref temp)) (expression bool < (swiz x (var_ref arg0))(swiz x (var_ref arg1))))
+ (assign (constant bool (1)) (swiz y (var_ref temp)) (expression bool < (swiz y (var_ref arg0))(swiz y (var_ref arg1))))
+ (assign (constant bool (1)) (swiz z (var_ref temp)) (expression bool < (swiz z (var_ref arg0))(swiz z (var_ref arg1))))
+ (assign (constant bool (1)) (swiz w (var_ref temp)) (expression bool < (swiz w (var_ref arg0))(swiz w (var_ref arg1))))
+ (return (var_ref temp))))
+))
diff --git a/src/glsl/builtins/ir/lessThanEqual b/src/glsl/builtins/ir/lessThanEqual
new file mode 100644
index 00000000000..4b240be5d19
--- /dev/null
+++ b/src/glsl/builtins/ir/lessThanEqual
@@ -0,0 +1,91 @@
+((function lessThanEqual
+ (signature bvec2
+ (parameters
+ (declare (in) vec2 arg0)
+ (declare (in) vec2 arg1))
+ ((declare () bvec2 temp)
+ (assign (constant bool (1)) (swiz x (var_ref temp)) (expression bool <= (swiz x (var_ref arg0))(swiz x (var_ref arg1))))
+ (assign (constant bool (1)) (swiz y (var_ref temp)) (expression bool <= (swiz y (var_ref arg0))(swiz y (var_ref arg1))))
+ (return (var_ref temp))))
+
+ (signature bvec3
+ (parameters
+ (declare (in) vec3 arg0)
+ (declare (in) vec3 arg1))
+ ((declare () bvec3 temp)
+ (assign (constant bool (1)) (swiz x (var_ref temp)) (expression bool <= (swiz x (var_ref arg0))(swiz x (var_ref arg1))))
+ (assign (constant bool (1)) (swiz y (var_ref temp)) (expression bool <= (swiz y (var_ref arg0))(swiz y (var_ref arg1))))
+ (assign (constant bool (1)) (swiz z (var_ref temp)) (expression bool <= (swiz z (var_ref arg0))(swiz z (var_ref arg1))))
+ (return (var_ref temp))))
+
+ (signature bvec4
+ (parameters
+ (declare (in) vec4 arg0)
+ (declare (in) vec4 arg1))
+ ((declare () bvec4 temp)
+ (assign (constant bool (1)) (swiz x (var_ref temp)) (expression bool <= (swiz x (var_ref arg0))(swiz x (var_ref arg1))))
+ (assign (constant bool (1)) (swiz y (var_ref temp)) (expression bool <= (swiz y (var_ref arg0))(swiz y (var_ref arg1))))
+ (assign (constant bool (1)) (swiz z (var_ref temp)) (expression bool <= (swiz z (var_ref arg0))(swiz z (var_ref arg1))))
+ (assign (constant bool (1)) (swiz w (var_ref temp)) (expression bool <= (swiz w (var_ref arg0))(swiz w (var_ref arg1))))
+ (return (var_ref temp))))
+
+ (signature bvec2
+ (parameters
+ (declare (in) ivec2 arg0)
+ (declare (in) ivec2 arg1))
+ ((declare () bvec2 temp)
+ (assign (constant bool (1)) (swiz x (var_ref temp)) (expression bool <= (swiz x (var_ref arg0))(swiz x (var_ref arg1))))
+ (assign (constant bool (1)) (swiz y (var_ref temp)) (expression bool <= (swiz y (var_ref arg0))(swiz y (var_ref arg1))))
+ (return (var_ref temp))))
+
+ (signature bvec3
+ (parameters
+ (declare (in) ivec3 arg0)
+ (declare (in) ivec3 arg1))
+ ((declare () bvec3 temp)
+ (assign (constant bool (1)) (swiz x (var_ref temp)) (expression bool <= (swiz x (var_ref arg0))(swiz x (var_ref arg1))))
+ (assign (constant bool (1)) (swiz y (var_ref temp)) (expression bool <= (swiz y (var_ref arg0))(swiz y (var_ref arg1))))
+ (assign (constant bool (1)) (swiz z (var_ref temp)) (expression bool <= (swiz z (var_ref arg0))(swiz z (var_ref arg1))))
+ (return (var_ref temp))))
+
+ (signature bvec4
+ (parameters
+ (declare (in) ivec4 arg0)
+ (declare (in) ivec4 arg1))
+ ((declare () bvec4 temp)
+ (assign (constant bool (1)) (swiz x (var_ref temp)) (expression bool <= (swiz x (var_ref arg0))(swiz x (var_ref arg1))))
+ (assign (constant bool (1)) (swiz y (var_ref temp)) (expression bool <= (swiz y (var_ref arg0))(swiz y (var_ref arg1))))
+ (assign (constant bool (1)) (swiz z (var_ref temp)) (expression bool <= (swiz z (var_ref arg0))(swiz z (var_ref arg1))))
+ (assign (constant bool (1)) (swiz w (var_ref temp)) (expression bool <= (swiz w (var_ref arg0))(swiz w (var_ref arg1))))
+ (return (var_ref temp))))
+
+ (signature bvec2
+ (parameters
+ (declare (in) uvec2 arg0)
+ (declare (in) uvec2 arg1))
+ ((declare () bvec2 temp)
+ (assign (constant bool (1)) (swiz x (var_ref temp)) (expression bool <= (swiz x (var_ref arg0))(swiz x (var_ref arg1))))
+ (assign (constant bool (1)) (swiz y (var_ref temp)) (expression bool <= (swiz y (var_ref arg0))(swiz y (var_ref arg1))))
+ (return (var_ref temp))))
+
+ (signature bvec3
+ (parameters
+ (declare (in) uvec3 arg0)
+ (declare (in) uvec3 arg1))
+ ((declare () bvec3 temp)
+ (assign (constant bool (1)) (swiz x (var_ref temp)) (expression bool <= (swiz x (var_ref arg0))(swiz x (var_ref arg1))))
+ (assign (constant bool (1)) (swiz y (var_ref temp)) (expression bool <= (swiz y (var_ref arg0))(swiz y (var_ref arg1))))
+ (assign (constant bool (1)) (swiz z (var_ref temp)) (expression bool <= (swiz z (var_ref arg0))(swiz z (var_ref arg1))))
+ (return (var_ref temp))))
+
+ (signature bvec4
+ (parameters
+ (declare (in) uvec4 arg0)
+ (declare (in) uvec4 arg1))
+ ((declare () bvec4 temp)
+ (assign (constant bool (1)) (swiz x (var_ref temp)) (expression bool <= (swiz x (var_ref arg0))(swiz x (var_ref arg1))))
+ (assign (constant bool (1)) (swiz y (var_ref temp)) (expression bool <= (swiz y (var_ref arg0))(swiz y (var_ref arg1))))
+ (assign (constant bool (1)) (swiz z (var_ref temp)) (expression bool <= (swiz z (var_ref arg0))(swiz z (var_ref arg1))))
+ (assign (constant bool (1)) (swiz w (var_ref temp)) (expression bool <= (swiz w (var_ref arg0))(swiz w (var_ref arg1))))
+ (return (var_ref temp))))
+))
diff --git a/src/glsl/builtins/ir/log b/src/glsl/builtins/ir/log
new file mode 100644
index 00000000000..d168abb5a73
--- /dev/null
+++ b/src/glsl/builtins/ir/log
@@ -0,0 +1,21 @@
+((function log
+ (signature float
+ (parameters
+ (declare (in) float arg0))
+ ((return (expression float log (var_ref arg0)))))
+
+ (signature vec2
+ (parameters
+ (declare (in) vec2 arg0))
+ ((return (expression vec2 log (var_ref arg0)))))
+
+ (signature vec3
+ (parameters
+ (declare (in) vec3 arg0))
+ ((return (expression vec3 log (var_ref arg0)))))
+
+ (signature vec4
+ (parameters
+ (declare (in) vec4 arg0))
+ ((return (expression vec4 log (var_ref arg0)))))
+))
diff --git a/src/glsl/builtins/ir/log2 b/src/glsl/builtins/ir/log2
new file mode 100644
index 00000000000..b96c6276f0a
--- /dev/null
+++ b/src/glsl/builtins/ir/log2
@@ -0,0 +1,21 @@
+((function log2
+ (signature float
+ (parameters
+ (declare (in) float arg0))
+ ((return (expression float log2 (var_ref arg0)))))
+
+ (signature vec2
+ (parameters
+ (declare (in) vec2 arg0))
+ ((return (expression vec2 log2 (var_ref arg0)))))
+
+ (signature vec3
+ (parameters
+ (declare (in) vec3 arg0))
+ ((return (expression vec3 log2 (var_ref arg0)))))
+
+ (signature vec4
+ (parameters
+ (declare (in) vec4 arg0))
+ ((return (expression vec4 log2 (var_ref arg0)))))
+))
diff --git a/src/glsl/builtins/ir/matrixCompMult b/src/glsl/builtins/ir/matrixCompMult
new file mode 100644
index 00000000000..538da18a794
--- /dev/null
+++ b/src/glsl/builtins/ir/matrixCompMult
@@ -0,0 +1,91 @@
+((function matrixCompMult
+ (signature mat2
+ (parameters
+ (declare (in) mat2 x)
+ (declare (in) mat2 y))
+ ((declare () mat2 z)
+ (assign (constant bool (1)) (array_ref (var_ref z) (constant int (0))) (expression vec2 * (array_ref (var_ref x) (constant int (0))) (array_ref (var_ref y) (constant int (0)))))
+ (assign (constant bool (1)) (array_ref (var_ref z) (constant int (1))) (expression vec2 * (array_ref (var_ref x) (constant int (1))) (array_ref (var_ref y) (constant int (1)))))
+(return (var_ref z))))
+
+ (signature mat3
+ (parameters
+ (declare (in) mat3 x)
+ (declare (in) mat3 y))
+ ((declare () mat3 z)
+ (assign (constant bool (1)) (array_ref (var_ref z) (constant int (0))) (expression vec3 * (array_ref (var_ref x) (constant int (0))) (array_ref (var_ref y) (constant int (0)))))
+ (assign (constant bool (1)) (array_ref (var_ref z) (constant int (1))) (expression vec3 * (array_ref (var_ref x) (constant int (1))) (array_ref (var_ref y) (constant int (1)))))
+ (assign (constant bool (1)) (array_ref (var_ref z) (constant int (2))) (expression vec3 * (array_ref (var_ref x) (constant int (2))) (array_ref (var_ref y) (constant int (2)))))
+(return (var_ref z))))
+
+ (signature mat4
+ (parameters
+ (declare (in) mat4 x)
+ (declare (in) mat4 y))
+ ((declare () mat4 z)
+ (assign (constant bool (1)) (array_ref (var_ref z) (constant int (0))) (expression vec4 * (array_ref (var_ref x) (constant int (0))) (array_ref (var_ref y) (constant int (0)))))
+ (assign (constant bool (1)) (array_ref (var_ref z) (constant int (1))) (expression vec4 * (array_ref (var_ref x) (constant int (1))) (array_ref (var_ref y) (constant int (1)))))
+ (assign (constant bool (1)) (array_ref (var_ref z) (constant int (2))) (expression vec4 * (array_ref (var_ref x) (constant int (2))) (array_ref (var_ref y) (constant int (2)))))
+ (assign (constant bool (1)) (array_ref (var_ref z) (constant int (3))) (expression vec4 * (array_ref (var_ref x) (constant int (3))) (array_ref (var_ref y) (constant int (3)))))
+(return (var_ref z))))
+
+ (signature mat2x3
+ (parameters
+ (declare (in) mat2x3 x)
+ (declare (in) mat2x3 y))
+ ((declare () mat2x3 z)
+ (assign (constant bool (1)) (array_ref (var_ref z) (constant int (0))) (expression vec3 * (array_ref (var_ref x) (constant int (0))) (array_ref (var_ref y) (constant int (0)))))
+ (assign (constant bool (1)) (array_ref (var_ref z) (constant int (1))) (expression vec3 * (array_ref (var_ref x) (constant int (1))) (array_ref (var_ref y) (constant int (1)))))
+(return (var_ref z))))
+
+ (signature mat3x2
+ (parameters
+ (declare (in) mat3x2 x)
+ (declare (in) mat3x2 y))
+ ((declare () mat3x2 z)
+ (assign (constant bool (1)) (array_ref (var_ref z) (constant int (0))) (expression vec2 * (array_ref (var_ref x) (constant int (0))) (array_ref (var_ref y) (constant int (0)))))
+ (assign (constant bool (1)) (array_ref (var_ref z) (constant int (1))) (expression vec2 * (array_ref (var_ref x) (constant int (1))) (array_ref (var_ref y) (constant int (1)))))
+ (assign (constant bool (1)) (array_ref (var_ref z) (constant int (2))) (expression vec2 * (array_ref (var_ref x) (constant int (2))) (array_ref (var_ref y) (constant int (2)))))
+(return (var_ref z))))
+
+ (signature mat2x4
+ (parameters
+ (declare (in) mat2x4 x)
+ (declare (in) mat2x4 y))
+ ((declare () mat2x4 z)
+ (assign (constant bool (1)) (array_ref (var_ref z) (constant int (0))) (expression vec4 * (array_ref (var_ref x) (constant int (0))) (array_ref (var_ref y) (constant int (0)))))
+ (assign (constant bool (1)) (array_ref (var_ref z) (constant int (1))) (expression vec4 * (array_ref (var_ref x) (constant int (1))) (array_ref (var_ref y) (constant int (1)))))
+(return (var_ref z))))
+
+ (signature mat4x2
+ (parameters
+ (declare (in) mat4x2 x)
+ (declare (in) mat4x2 y))
+ ((declare () mat4x2 z)
+ (assign (constant bool (1)) (array_ref (var_ref z) (constant int (0))) (expression vec2 * (array_ref (var_ref x) (constant int (0))) (array_ref (var_ref y) (constant int (0)))))
+ (assign (constant bool (1)) (array_ref (var_ref z) (constant int (1))) (expression vec2 * (array_ref (var_ref x) (constant int (1))) (array_ref (var_ref y) (constant int (1)))))
+ (assign (constant bool (1)) (array_ref (var_ref z) (constant int (2))) (expression vec2 * (array_ref (var_ref x) (constant int (2))) (array_ref (var_ref y) (constant int (2)))))
+ (assign (constant bool (1)) (array_ref (var_ref z) (constant int (3))) (expression vec2 * (array_ref (var_ref x) (constant int (3))) (array_ref (var_ref y) (constant int (3)))))
+(return (var_ref z))))
+
+ (signature mat3x4
+ (parameters
+ (declare (in) mat3x4 x)
+ (declare (in) mat3x4 y))
+ ((declare () mat3x4 z)
+ (assign (constant bool (1)) (array_ref (var_ref z) (constant int (0))) (expression vec4 * (array_ref (var_ref x) (constant int (0))) (array_ref (var_ref y) (constant int (0)))))
+ (assign (constant bool (1)) (array_ref (var_ref z) (constant int (1))) (expression vec4 * (array_ref (var_ref x) (constant int (1))) (array_ref (var_ref y) (constant int (1)))))
+ (assign (constant bool (1)) (array_ref (var_ref z) (constant int (2))) (expression vec4 * (array_ref (var_ref x) (constant int (2))) (array_ref (var_ref y) (constant int (2)))))
+(return (var_ref z))))
+
+ (signature mat4x3
+ (parameters
+ (declare (in) mat4x3 x)
+ (declare (in) mat4x3 y))
+ ((declare () mat4x3 z)
+ (assign (constant bool (1)) (array_ref (var_ref z) (constant int (0))) (expression vec3 * (array_ref (var_ref x) (constant int (0))) (array_ref (var_ref y) (constant int (0)))))
+ (assign (constant bool (1)) (array_ref (var_ref z) (constant int (1))) (expression vec3 * (array_ref (var_ref x) (constant int (1))) (array_ref (var_ref y) (constant int (1)))))
+ (assign (constant bool (1)) (array_ref (var_ref z) (constant int (2))) (expression vec3 * (array_ref (var_ref x) (constant int (2))) (array_ref (var_ref y) (constant int (2)))))
+ (assign (constant bool (1)) (array_ref (var_ref z) (constant int (3))) (expression vec3 * (array_ref (var_ref x) (constant int (3))) (array_ref (var_ref y) (constant int (3)))))
+(return (var_ref z))))
+))
diff --git a/src/glsl/builtins/ir/max b/src/glsl/builtins/ir/max
new file mode 100644
index 00000000000..2b5a02868cc
--- /dev/null
+++ b/src/glsl/builtins/ir/max
@@ -0,0 +1,127 @@
+((function max
+ (signature float
+ (parameters
+ (declare (in) float arg0)
+ (declare (in) float arg1))
+ ((return (expression float max (var_ref arg0) (var_ref arg1)))))
+
+ (signature vec2
+ (parameters
+ (declare (in) vec2 arg0)
+ (declare (in) vec2 arg1))
+ ((return (expression vec2 max (var_ref arg0) (var_ref arg1)))))
+
+ (signature vec3
+ (parameters
+ (declare (in) vec3 arg0)
+ (declare (in) vec3 arg1))
+ ((return (expression vec3 max (var_ref arg0) (var_ref arg1)))))
+
+ (signature vec4
+ (parameters
+ (declare (in) vec4 arg0)
+ (declare (in) vec4 arg1))
+ ((return (expression vec4 max (var_ref arg0) (var_ref arg1)))))
+
+ (signature vec2
+ (parameters
+ (declare (in) vec2 arg0)
+ (declare (in) float arg1))
+ ((return (expression vec2 max (var_ref arg0) (var_ref arg1)))))
+
+ (signature vec3
+ (parameters
+ (declare (in) vec3 arg0)
+ (declare (in) float arg1))
+ ((return (expression vec3 max (var_ref arg0) (var_ref arg1)))))
+
+ (signature vec4
+ (parameters
+ (declare (in) vec4 arg0)
+ (declare (in) float arg1))
+ ((return (expression vec4 max (var_ref arg0) (var_ref arg1)))))
+
+ (signature int
+ (parameters
+ (declare (in) int arg0)
+ (declare (in) int arg1))
+ ((return (expression int max (var_ref arg0) (var_ref arg1)))))
+
+ (signature ivec2
+ (parameters
+ (declare (in) ivec2 arg0)
+ (declare (in) ivec2 arg1))
+ ((return (expression ivec2 max (var_ref arg0) (var_ref arg1)))))
+
+ (signature ivec3
+ (parameters
+ (declare (in) ivec3 arg0)
+ (declare (in) ivec3 arg1))
+ ((return (expression ivec3 max (var_ref arg0) (var_ref arg1)))))
+
+ (signature ivec4
+ (parameters
+ (declare (in) ivec4 arg0)
+ (declare (in) ivec4 arg1))
+ ((return (expression ivec4 max (var_ref arg0) (var_ref arg1)))))
+
+ (signature ivec2
+ (parameters
+ (declare (in) ivec2 arg0)
+ (declare (in) int arg1))
+ ((return (expression ivec2 max (var_ref arg0) (var_ref arg1)))))
+
+ (signature ivec3
+ (parameters
+ (declare (in) ivec3 arg0)
+ (declare (in) int arg1))
+ ((return (expression ivec3 max (var_ref arg0) (var_ref arg1)))))
+
+ (signature ivec4
+ (parameters
+ (declare (in) ivec4 arg0)
+ (declare (in) int arg1))
+ ((return (expression ivec4 max (var_ref arg0) (var_ref arg1)))))
+
+ (signature uint
+ (parameters
+ (declare (in) uint arg0)
+ (declare (in) uint arg1))
+ ((return (expression uint max (var_ref arg0) (var_ref arg1)))))
+
+ (signature uvec2
+ (parameters
+ (declare (in) uvec2 arg0)
+ (declare (in) uvec2 arg1))
+ ((return (expression uvec2 max (var_ref arg0) (var_ref arg1)))))
+
+ (signature uvec3
+ (parameters
+ (declare (in) uvec3 arg0)
+ (declare (in) uvec3 arg1))
+ ((return (expression uvec3 max (var_ref arg0) (var_ref arg1)))))
+
+ (signature uvec4
+ (parameters
+ (declare (in) uvec4 arg0)
+ (declare (in) uvec4 arg1))
+ ((return (expression uvec4 max (var_ref arg0) (var_ref arg1)))))
+
+ (signature uvec2
+ (parameters
+ (declare (in) uvec2 arg0)
+ (declare (in) uint arg1))
+ ((return (expression uvec2 max (var_ref arg0) (var_ref arg1)))))
+
+ (signature uvec3
+ (parameters
+ (declare (in) uvec3 arg0)
+ (declare (in) uint arg1))
+ ((return (expression uvec3 max (var_ref arg0) (var_ref arg1)))))
+
+ (signature uvec4
+ (parameters
+ (declare (in) uvec4 arg0)
+ (declare (in) uint arg1))
+ ((return (expression uvec4 max (var_ref arg0) (var_ref arg1)))))
+))
diff --git a/src/glsl/builtins/ir/min b/src/glsl/builtins/ir/min
new file mode 100644
index 00000000000..2deef1118a7
--- /dev/null
+++ b/src/glsl/builtins/ir/min
@@ -0,0 +1,127 @@
+((function min
+ (signature float
+ (parameters
+ (declare (in) float arg0)
+ (declare (in) float arg1))
+ ((return (expression float min (var_ref arg0) (var_ref arg1)))))
+
+ (signature vec2
+ (parameters
+ (declare (in) vec2 arg0)
+ (declare (in) vec2 arg1))
+ ((return (expression vec2 min (var_ref arg0) (var_ref arg1)))))
+
+ (signature vec3
+ (parameters
+ (declare (in) vec3 arg0)
+ (declare (in) vec3 arg1))
+ ((return (expression vec3 min (var_ref arg0) (var_ref arg1)))))
+
+ (signature vec4
+ (parameters
+ (declare (in) vec4 arg0)
+ (declare (in) vec4 arg1))
+ ((return (expression vec4 min (var_ref arg0) (var_ref arg1)))))
+
+ (signature vec2
+ (parameters
+ (declare (in) vec2 arg0)
+ (declare (in) float arg1))
+ ((return (expression vec2 min (var_ref arg0) (var_ref arg1)))))
+
+ (signature vec3
+ (parameters
+ (declare (in) vec3 arg0)
+ (declare (in) float arg1))
+ ((return (expression vec3 min (var_ref arg0) (var_ref arg1)))))
+
+ (signature vec4
+ (parameters
+ (declare (in) vec4 arg0)
+ (declare (in) float arg1))
+ ((return (expression vec4 min (var_ref arg0) (var_ref arg1)))))
+
+ (signature int
+ (parameters
+ (declare (in) int arg0)
+ (declare (in) int arg1))
+ ((return (expression int min (var_ref arg0) (var_ref arg1)))))
+
+ (signature ivec2
+ (parameters
+ (declare (in) ivec2 arg0)
+ (declare (in) ivec2 arg1))
+ ((return (expression ivec2 min (var_ref arg0) (var_ref arg1)))))
+
+ (signature ivec3
+ (parameters
+ (declare (in) ivec3 arg0)
+ (declare (in) ivec3 arg1))
+ ((return (expression ivec3 min (var_ref arg0) (var_ref arg1)))))
+
+ (signature ivec4
+ (parameters
+ (declare (in) ivec4 arg0)
+ (declare (in) ivec4 arg1))
+ ((return (expression ivec4 min (var_ref arg0) (var_ref arg1)))))
+
+ (signature ivec2
+ (parameters
+ (declare (in) ivec2 arg0)
+ (declare (in) int arg1))
+ ((return (expression ivec2 min (var_ref arg0) (var_ref arg1)))))
+
+ (signature ivec3
+ (parameters
+ (declare (in) ivec3 arg0)
+ (declare (in) int arg1))
+ ((return (expression ivec3 min (var_ref arg0) (var_ref arg1)))))
+
+ (signature ivec4
+ (parameters
+ (declare (in) ivec4 arg0)
+ (declare (in) int arg1))
+ ((return (expression ivec4 min (var_ref arg0) (var_ref arg1)))))
+
+ (signature uint
+ (parameters
+ (declare (in) uint arg0)
+ (declare (in) uint arg1))
+ ((return (expression uint min (var_ref arg0) (var_ref arg1)))))
+
+ (signature uvec2
+ (parameters
+ (declare (in) uvec2 arg0)
+ (declare (in) uvec2 arg1))
+ ((return (expression uvec2 min (var_ref arg0) (var_ref arg1)))))
+
+ (signature uvec3
+ (parameters
+ (declare (in) uvec3 arg0)
+ (declare (in) uvec3 arg1))
+ ((return (expression uvec3 min (var_ref arg0) (var_ref arg1)))))
+
+ (signature uvec4
+ (parameters
+ (declare (in) uvec4 arg0)
+ (declare (in) uvec4 arg1))
+ ((return (expression uvec4 min (var_ref arg0) (var_ref arg1)))))
+
+ (signature uvec2
+ (parameters
+ (declare (in) uvec2 arg0)
+ (declare (in) uint arg1))
+ ((return (expression uvec2 min (var_ref arg0) (var_ref arg1)))))
+
+ (signature uvec3
+ (parameters
+ (declare (in) uvec3 arg0)
+ (declare (in) uint arg1))
+ ((return (expression uvec3 min (var_ref arg0) (var_ref arg1)))))
+
+ (signature uvec4
+ (parameters
+ (declare (in) uvec4 arg0)
+ (declare (in) uint arg1))
+ ((return (expression uvec4 min (var_ref arg0) (var_ref arg1)))))
+))
diff --git a/src/glsl/builtins/ir/mix b/src/glsl/builtins/ir/mix
new file mode 100644
index 00000000000..6bc6f0a43e8
--- /dev/null
+++ b/src/glsl/builtins/ir/mix
@@ -0,0 +1,88 @@
+((function mix
+ (signature float
+ (parameters
+ (declare (in) float arg0)
+ (declare (in) float arg1)
+ (declare (in) float arg2))
+ ((return (expression float + (expression float * (var_ref arg0) (expression float - (constant float (1.000000)) (var_ref arg2))) (expression float * (var_ref arg1) (var_ref arg2))))))
+
+ (signature vec2
+ (parameters
+ (declare (in) vec2 arg0)
+ (declare (in) vec2 arg1)
+ (declare (in) vec2 arg2))
+ ((return (expression vec2 + (expression vec2 * (var_ref arg0) (expression vec2 - (constant float (1.000000)) (var_ref arg2))) (expression vec2 * (var_ref arg1) (var_ref arg2))))))
+
+ (signature vec3
+ (parameters
+ (declare (in) vec3 arg0)
+ (declare (in) vec3 arg1)
+ (declare (in) vec3 arg2))
+ ((return (expression vec3 + (expression vec3 * (var_ref arg0) (expression vec3 - (constant float (1.000000)) (var_ref arg2))) (expression vec3 * (var_ref arg1) (var_ref arg2))))))
+
+ (signature vec4
+ (parameters
+ (declare (in) vec4 arg0)
+ (declare (in) vec4 arg1)
+ (declare (in) vec4 arg2))
+ ((return (expression vec4 + (expression vec4 * (var_ref arg0) (expression vec4 - (constant float (1.000000)) (var_ref arg2))) (expression vec4 * (var_ref arg1) (var_ref arg2))))))
+
+ (signature vec2
+ (parameters
+ (declare (in) vec2 arg0)
+ (declare (in) vec2 arg1)
+ (declare (in) float arg2))
+ ((return (expression vec2 + (expression vec2 * (var_ref arg0) (expression float - (constant float (1.000000)) (var_ref arg2))) (expression vec2 * (var_ref arg1) (var_ref arg2))))))
+
+ (signature vec3
+ (parameters
+ (declare (in) vec3 arg0)
+ (declare (in) vec3 arg1)
+ (declare (in) float arg2))
+ ((return (expression vec3 + (expression vec3 * (var_ref arg0) (expression float - (constant float (1.000000)) (var_ref arg2))) (expression vec3 * (var_ref arg1) (var_ref arg2))))))
+
+ (signature vec4
+ (parameters
+ (declare (in) vec4 arg0)
+ (declare (in) vec4 arg1)
+ (declare (in) float arg2))
+ ((return (expression vec4 + (expression vec4 * (var_ref arg0) (expression float - (constant float (1.000000)) (var_ref arg2))) (expression vec4 * (var_ref arg1) (var_ref arg2))))))
+
+ (signature float
+ (parameters
+ (declare (in) float v1)
+ (declare (in) float v2)
+ (declare (in) bool a))
+ ((assign (var_ref a) (var_ref v1) (var_ref v2))
+ (return (var_ref v1))))
+
+ (signature vec2
+ (parameters
+ (declare (in) vec2 v1)
+ (declare (in) vec2 v2)
+ (declare (in) bvec2 a))
+ ((assign (swiz x (var_ref a)) (swiz x (var_ref v1)) (swiz x (var_ref v2)))
+ (assign (swiz y (var_ref a)) (swiz y (var_ref v1)) (swiz y (var_ref v2)))
+ (return (var_ref v1))))
+
+ (signature vec3
+ (parameters
+ (declare (in) vec3 v1)
+ (declare (in) vec3 v2)
+ (declare (in) bvec3 a))
+ ((assign (swiz x (var_ref a)) (swiz x (var_ref v1)) (swiz x (var_ref v2)))
+ (assign (swiz y (var_ref a)) (swiz y (var_ref v1)) (swiz y (var_ref v2)))
+ (assign (swiz z (var_ref a)) (swiz z (var_ref v1)) (swiz z (var_ref v2)))
+ (return (var_ref v1))))
+
+ (signature vec4
+ (parameters
+ (declare (in) vec4 v1)
+ (declare (in) vec4 v2)
+ (declare (in) bvec4 a))
+ ((assign (swiz x (var_ref a)) (swiz x (var_ref v1)) (swiz x (var_ref v2)))
+ (assign (swiz y (var_ref a)) (swiz y (var_ref v1)) (swiz y (var_ref v2)))
+ (assign (swiz z (var_ref a)) (swiz z (var_ref v1)) (swiz z (var_ref v2)))
+ (assign (swiz w (var_ref a)) (swiz w (var_ref v1)) (swiz w (var_ref v2)))
+ (return (var_ref v1))))
+))
diff --git a/src/glsl/builtins/ir/mod b/src/glsl/builtins/ir/mod
new file mode 100644
index 00000000000..aeaea240e2d
--- /dev/null
+++ b/src/glsl/builtins/ir/mod
@@ -0,0 +1,43 @@
+((function mod
+ (signature float
+ (parameters
+ (declare (in) float arg0)
+ (declare (in) float arg1))
+ ((return (expression float % (var_ref arg0) (var_ref arg1)))))
+
+ (signature vec2
+ (parameters
+ (declare (in) vec2 arg0)
+ (declare (in) vec2 arg1))
+ ((return (expression vec2 % (var_ref arg0) (var_ref arg1)))))
+
+ (signature vec3
+ (parameters
+ (declare (in) vec3 arg0)
+ (declare (in) vec3 arg1))
+ ((return (expression vec3 % (var_ref arg0) (var_ref arg1)))))
+
+ (signature vec4
+ (parameters
+ (declare (in) vec4 arg0)
+ (declare (in) vec4 arg1))
+ ((return (expression vec4 % (var_ref arg0) (var_ref arg1)))))
+
+ (signature vec2
+ (parameters
+ (declare (in) vec2 arg0)
+ (declare (in) float arg1))
+ ((return (expression vec2 % (var_ref arg0) (var_ref arg1)))))
+
+ (signature vec3
+ (parameters
+ (declare (in) vec3 arg0)
+ (declare (in) float arg1))
+ ((return (expression vec3 % (var_ref arg0) (var_ref arg1)))))
+
+ (signature vec4
+ (parameters
+ (declare (in) vec4 arg0)
+ (declare (in) float arg1))
+ ((return (expression vec4 % (var_ref arg0) (var_ref arg1)))))
+))
diff --git a/src/glsl/builtins/ir/noise1 b/src/glsl/builtins/ir/noise1
new file mode 100644
index 00000000000..eb7be358575
--- /dev/null
+++ b/src/glsl/builtins/ir/noise1
@@ -0,0 +1,18 @@
+((function noise1
+ (signature float
+ (parameters
+ (declare (in) float x))
+ ((return (constant float (0)))))
+ (signature float
+ (parameters
+ (declare (in) vec2 x))
+ ((return (constant float (0)))))
+ (signature float
+ (parameters
+ (declare (in) vec3 x))
+ ((return (constant float (0)))))
+ (signature float
+ (parameters
+ (declare (in) vec4 x))
+ ((return (constant float (0)))))
+))
diff --git a/src/glsl/builtins/ir/noise2 b/src/glsl/builtins/ir/noise2
new file mode 100644
index 00000000000..ae4443a704a
--- /dev/null
+++ b/src/glsl/builtins/ir/noise2
@@ -0,0 +1,18 @@
+((function noise2
+ (signature vec2
+ (parameters
+ (declare (in) float x))
+ ((return (constant vec2 (0 0)))))
+ (signature vec2
+ (parameters
+ (declare (in) vec2 x))
+ ((return (constant vec2 (0 0)))))
+ (signature vec2
+ (parameters
+ (declare (in) vec3 x))
+ ((return (constant vec2 (0 0)))))
+ (signature vec2
+ (parameters
+ (declare (in) vec4 x))
+ ((return (constant vec2 (0 0)))))
+))
diff --git a/src/glsl/builtins/ir/noise3 b/src/glsl/builtins/ir/noise3
new file mode 100644
index 00000000000..30d9681890e
--- /dev/null
+++ b/src/glsl/builtins/ir/noise3
@@ -0,0 +1,18 @@
+((function noise3
+ (signature vec3
+ (parameters
+ (declare (in) float x))
+ ((return (constant vec3 (0 0 0)))))
+ (signature vec3
+ (parameters
+ (declare (in) vec2 x))
+ ((return (constant vec3 (0 0 0)))))
+ (signature vec3
+ (parameters
+ (declare (in) vec3 x))
+ ((return (constant vec3 (0 0 0)))))
+ (signature vec3
+ (parameters
+ (declare (in) vec4 x))
+ ((return (constant vec3 (0 0 0)))))
+))
diff --git a/src/glsl/builtins/ir/noise4 b/src/glsl/builtins/ir/noise4
new file mode 100644
index 00000000000..913bef2aa1b
--- /dev/null
+++ b/src/glsl/builtins/ir/noise4
@@ -0,0 +1,18 @@
+((function noise4
+ (signature vec4
+ (parameters
+ (declare (in) float x))
+ ((return (constant vec4 (0 0 0 0)))))
+ (signature vec4
+ (parameters
+ (declare (in) vec2 x))
+ ((return (constant vec4 (0 0 0 0)))))
+ (signature vec4
+ (parameters
+ (declare (in) vec3 x))
+ ((return (constant vec4 (0 0 0 0)))))
+ (signature vec4
+ (parameters
+ (declare (in) vec4 x))
+ ((return (constant vec4 (0 0 0 0)))))
+))
diff --git a/src/glsl/builtins/ir/normalize b/src/glsl/builtins/ir/normalize
new file mode 100644
index 00000000000..be88a9830d1
--- /dev/null
+++ b/src/glsl/builtins/ir/normalize
@@ -0,0 +1,21 @@
+((function normalize
+ (signature float
+ (parameters
+ (declare (in) float arg0))
+ ((return (expression float * (var_ref arg0) (expression float rsq (expression float dot (var_ref arg0) (var_ref arg0)))))))
+
+ (signature vec2
+ (parameters
+ (declare (in) vec2 arg0))
+ ((return (expression vec2 * (var_ref arg0) (expression float rsq (expression float dot (var_ref arg0) (var_ref arg0)))))))
+
+ (signature vec3
+ (parameters
+ (declare (in) vec3 arg0))
+ ((return (expression vec3 * (var_ref arg0) (expression float rsq (expression float dot (var_ref arg0) (var_ref arg0)))))))
+
+ (signature vec4
+ (parameters
+ (declare (in) vec4 arg0))
+ ((return (expression vec4 * (var_ref arg0) (expression float rsq (expression float dot (var_ref arg0) (var_ref arg0)))))))
+))
diff --git a/src/glsl/builtins/ir/not b/src/glsl/builtins/ir/not
new file mode 100644
index 00000000000..b696b06557f
--- /dev/null
+++ b/src/glsl/builtins/ir/not
@@ -0,0 +1,16 @@
+((function not
+ (signature bvec2
+ (parameters
+ (declare (in) bvec2 arg0))
+ ((return (expression bvec2 ! (var_ref arg0)))))
+
+ (signature bvec3
+ (parameters
+ (declare (in) bvec3 arg0))
+ ((return (expression bvec3 ! (var_ref arg0)))))
+
+ (signature bvec4
+ (parameters
+ (declare (in) bvec4 arg0))
+ ((return (expression bvec4 ! (var_ref arg0)))))
+))
diff --git a/src/glsl/builtins/ir/notEqual b/src/glsl/builtins/ir/notEqual
new file mode 100644
index 00000000000..bcc7339bb6e
--- /dev/null
+++ b/src/glsl/builtins/ir/notEqual
@@ -0,0 +1,91 @@
+((function notEqual
+ (signature bvec2
+ (parameters
+ (declare (in) vec2 arg0)
+ (declare (in) vec2 arg1))
+ ((declare () bvec2 temp)
+ (assign (constant bool (1)) (swiz x (var_ref temp)) (expression bool != (swiz x (var_ref arg0))(swiz x (var_ref arg1))))
+ (assign (constant bool (1)) (swiz y (var_ref temp)) (expression bool != (swiz y (var_ref arg0))(swiz y (var_ref arg1))))
+ (return (var_ref temp))))
+
+ (signature bvec3
+ (parameters
+ (declare (in) vec3 arg0)
+ (declare (in) vec3 arg1))
+ ((declare () bvec3 temp)
+ (assign (constant bool (1)) (swiz x (var_ref temp)) (expression bool != (swiz x (var_ref arg0))(swiz x (var_ref arg1))))
+ (assign (constant bool (1)) (swiz y (var_ref temp)) (expression bool != (swiz y (var_ref arg0))(swiz y (var_ref arg1))))
+ (assign (constant bool (1)) (swiz z (var_ref temp)) (expression bool != (swiz z (var_ref arg0))(swiz z (var_ref arg1))))
+ (return (var_ref temp))))
+
+ (signature bvec4
+ (parameters
+ (declare (in) vec4 arg0)
+ (declare (in) vec4 arg1))
+ ((declare () bvec4 temp)
+ (assign (constant bool (1)) (swiz x (var_ref temp)) (expression bool != (swiz x (var_ref arg0))(swiz x (var_ref arg1))))
+ (assign (constant bool (1)) (swiz y (var_ref temp)) (expression bool != (swiz y (var_ref arg0))(swiz y (var_ref arg1))))
+ (assign (constant bool (1)) (swiz z (var_ref temp)) (expression bool != (swiz z (var_ref arg0))(swiz z (var_ref arg1))))
+ (assign (constant bool (1)) (swiz w (var_ref temp)) (expression bool != (swiz w (var_ref arg0))(swiz w (var_ref arg1))))
+ (return (var_ref temp))))
+
+ (signature bvec2
+ (parameters
+ (declare (in) ivec2 arg0)
+ (declare (in) ivec2 arg1))
+ ((declare () bvec2 temp)
+ (assign (constant bool (1)) (swiz x (var_ref temp)) (expression bool != (swiz x (var_ref arg0))(swiz x (var_ref arg1))))
+ (assign (constant bool (1)) (swiz y (var_ref temp)) (expression bool != (swiz y (var_ref arg0))(swiz y (var_ref arg1))))
+ (return (var_ref temp))))
+
+ (signature bvec3
+ (parameters
+ (declare (in) ivec3 arg0)
+ (declare (in) ivec3 arg1))
+ ((declare () bvec3 temp)
+ (assign (constant bool (1)) (swiz x (var_ref temp)) (expression bool != (swiz x (var_ref arg0))(swiz x (var_ref arg1))))
+ (assign (constant bool (1)) (swiz y (var_ref temp)) (expression bool != (swiz y (var_ref arg0))(swiz y (var_ref arg1))))
+ (assign (constant bool (1)) (swiz z (var_ref temp)) (expression bool != (swiz z (var_ref arg0))(swiz z (var_ref arg1))))
+ (return (var_ref temp))))
+
+ (signature bvec4
+ (parameters
+ (declare (in) ivec4 arg0)
+ (declare (in) ivec4 arg1))
+ ((declare () bvec4 temp)
+ (assign (constant bool (1)) (swiz x (var_ref temp)) (expression bool != (swiz x (var_ref arg0))(swiz x (var_ref arg1))))
+ (assign (constant bool (1)) (swiz y (var_ref temp)) (expression bool != (swiz y (var_ref arg0))(swiz y (var_ref arg1))))
+ (assign (constant bool (1)) (swiz z (var_ref temp)) (expression bool != (swiz z (var_ref arg0))(swiz z (var_ref arg1))))
+ (assign (constant bool (1)) (swiz w (var_ref temp)) (expression bool != (swiz w (var_ref arg0))(swiz w (var_ref arg1))))
+ (return (var_ref temp))))
+
+ (signature bvec2
+ (parameters
+ (declare (in) uvec2 arg0)
+ (declare (in) uvec2 arg1))
+ ((declare () bvec2 temp)
+ (assign (constant bool (1)) (swiz x (var_ref temp)) (expression bool != (swiz x (var_ref arg0))(swiz x (var_ref arg1))))
+ (assign (constant bool (1)) (swiz y (var_ref temp)) (expression bool != (swiz y (var_ref arg0))(swiz y (var_ref arg1))))
+ (return (var_ref temp))))
+
+ (signature bvec3
+ (parameters
+ (declare (in) uvec3 arg0)
+ (declare (in) uvec3 arg1))
+ ((declare () bvec3 temp)
+ (assign (constant bool (1)) (swiz x (var_ref temp)) (expression bool != (swiz x (var_ref arg0))(swiz x (var_ref arg1))))
+ (assign (constant bool (1)) (swiz y (var_ref temp)) (expression bool != (swiz y (var_ref arg0))(swiz y (var_ref arg1))))
+ (assign (constant bool (1)) (swiz z (var_ref temp)) (expression bool != (swiz z (var_ref arg0))(swiz z (var_ref arg1))))
+ (return (var_ref temp))))
+
+ (signature bvec4
+ (parameters
+ (declare (in) uvec4 arg0)
+ (declare (in) uvec4 arg1))
+ ((declare () bvec4 temp)
+ (assign (constant bool (1)) (swiz x (var_ref temp)) (expression bool != (swiz x (var_ref arg0))(swiz x (var_ref arg1))))
+ (assign (constant bool (1)) (swiz y (var_ref temp)) (expression bool != (swiz y (var_ref arg0))(swiz y (var_ref arg1))))
+ (assign (constant bool (1)) (swiz z (var_ref temp)) (expression bool != (swiz z (var_ref arg0))(swiz z (var_ref arg1))))
+ (assign (constant bool (1)) (swiz w (var_ref temp)) (expression bool != (swiz w (var_ref arg0))(swiz w (var_ref arg1))))
+ (return (var_ref temp))))
+))
diff --git a/src/glsl/builtins/ir/outerProduct b/src/glsl/builtins/ir/outerProduct
new file mode 100644
index 00000000000..69ae741e176
--- /dev/null
+++ b/src/glsl/builtins/ir/outerProduct
@@ -0,0 +1,92 @@
+((function outerProduct
+ (signature mat2
+ (parameters
+ (declare (in) vec2 u)
+ (declare (in) vec2 v))
+ ((declare () mat2 m)
+ (assign (constant bool (1)) (array_ref (var_ref m) (constant int (0))) (expression vec2 * (var_ref u) (swiz x (var_ref v))))
+ (assign (constant bool (1)) (array_ref (var_ref m) (constant int (1))) (expression vec2 * (var_ref u) (swiz y (var_ref v))))
+ (return (var_ref m))))
+
+ (signature mat2x3
+ (parameters
+ (declare (in) vec3 u)
+ (declare (in) vec2 v))
+ ((declare () mat2x3 m)
+ (assign (constant bool (1)) (array_ref (var_ref m) (constant int (0))) (expression vec3 * (var_ref u) (swiz x (var_ref v))))
+ (assign (constant bool (1)) (array_ref (var_ref m) (constant int (1))) (expression vec3 * (var_ref u) (swiz y (var_ref v))))
+ (return (var_ref m))))
+
+ (signature mat2x4
+ (parameters
+ (declare (in) vec4 u)
+ (declare (in) vec2 v))
+ ((declare () mat2x4 m)
+ (assign (constant bool (1)) (array_ref (var_ref m) (constant int (0))) (expression vec4 * (var_ref u) (swiz x (var_ref v))))
+ (assign (constant bool (1)) (array_ref (var_ref m) (constant int (1))) (expression vec4 * (var_ref u) (swiz y (var_ref v))))
+ (return (var_ref m))))
+
+ (signature mat3x2
+ (parameters
+ (declare (in) vec2 u)
+ (declare (in) vec3 v))
+ ((declare () mat3x2 m)
+ (assign (constant bool (1)) (array_ref (var_ref m) (constant int (0))) (expression vec2 * (var_ref u) (swiz x (var_ref v))))
+ (assign (constant bool (1)) (array_ref (var_ref m) (constant int (1))) (expression vec2 * (var_ref u) (swiz y (var_ref v))))
+ (assign (constant bool (1)) (array_ref (var_ref m) (constant int (2))) (expression vec2 * (var_ref u) (swiz z (var_ref v))))
+ (return (var_ref m))
+ ))
+
+ (signature mat3
+ (parameters
+ (declare (in) vec3 u)
+ (declare (in) vec3 v))
+ ((declare () mat3 m)
+ (assign (constant bool (1)) (array_ref (var_ref m) (constant int (0))) (expression vec3 * (var_ref u) (swiz x (var_ref v))))
+ (assign (constant bool (1)) (array_ref (var_ref m) (constant int (1))) (expression vec3 * (var_ref u) (swiz y (var_ref v))))
+ (assign (constant bool (1)) (array_ref (var_ref m) (constant int (2))) (expression vec3 * (var_ref u) (swiz z (var_ref v))))
+ (return (var_ref m))))
+
+ (signature mat3x4
+ (parameters
+ (declare (in) vec4 u)
+ (declare (in) vec3 v))
+ ((declare () mat3x4 m)
+ (assign (constant bool (1)) (array_ref (var_ref m) (constant int (0))) (expression vec4 * (var_ref u) (swiz x (var_ref v))))
+ (assign (constant bool (1)) (array_ref (var_ref m) (constant int (1))) (expression vec4 * (var_ref u) (swiz y (var_ref v))))
+ (assign (constant bool (1)) (array_ref (var_ref m) (constant int (2))) (expression vec4 * (var_ref u) (swiz z (var_ref v))))
+ (return (var_ref m))))
+
+ (signature mat4x2
+ (parameters
+ (declare (in) vec2 u)
+ (declare (in) vec4 v))
+ ((declare () mat4x2 m)
+ (assign (constant bool (1)) (array_ref (var_ref m) (constant int (0))) (expression vec2 * (var_ref u) (swiz x (var_ref v))))
+ (assign (constant bool (1)) (array_ref (var_ref m) (constant int (1))) (expression vec2 * (var_ref u) (swiz y (var_ref v))))
+ (assign (constant bool (1)) (array_ref (var_ref m) (constant int (2))) (expression vec2 * (var_ref u) (swiz z (var_ref v))))
+ (assign (constant bool (1)) (array_ref (var_ref m) (constant int (3))) (expression vec2 * (var_ref u) (swiz w (var_ref v))))
+ (return (var_ref m))))
+
+ (signature mat4x3
+ (parameters
+ (declare (in) vec3 u)
+ (declare (in) vec4 v))
+ ((declare () mat4x3 m)
+ (assign (constant bool (1)) (array_ref (var_ref m) (constant int (0))) (expression vec3 * (var_ref u) (swiz x (var_ref v))))
+ (assign (constant bool (1)) (array_ref (var_ref m) (constant int (1))) (expression vec3 * (var_ref u) (swiz y (var_ref v))))
+ (assign (constant bool (1)) (array_ref (var_ref m) (constant int (2))) (expression vec3 * (var_ref u) (swiz z (var_ref v))))
+ (assign (constant bool (1)) (array_ref (var_ref m) (constant int (3))) (expression vec3 * (var_ref u) (swiz w (var_ref v))))
+ (return (var_ref m))))
+
+ (signature mat4
+ (parameters
+ (declare (in) vec4 u)
+ (declare (in) vec4 v))
+ ((declare () mat4 m)
+ (assign (constant bool (1)) (array_ref (var_ref m) (constant int (0))) (expression vec4 * (var_ref u) (swiz x (var_ref v))))
+ (assign (constant bool (1)) (array_ref (var_ref m) (constant int (1))) (expression vec4 * (var_ref u) (swiz y (var_ref v))))
+ (assign (constant bool (1)) (array_ref (var_ref m) (constant int (2))) (expression vec4 * (var_ref u) (swiz z (var_ref v))))
+ (assign (constant bool (1)) (array_ref (var_ref m) (constant int (3))) (expression vec4 * (var_ref u) (swiz w (var_ref v))))
+ (return (var_ref m))))
+))
diff --git a/src/glsl/builtins/ir/pow b/src/glsl/builtins/ir/pow
new file mode 100644
index 00000000000..a61bc4418e3
--- /dev/null
+++ b/src/glsl/builtins/ir/pow
@@ -0,0 +1,25 @@
+((function pow
+ (signature float
+ (parameters
+ (declare (in) float arg0)
+ (declare (in) float arg1))
+ ((return (expression float pow (var_ref arg0) (var_ref arg1)))))
+
+ (signature vec2
+ (parameters
+ (declare (in) vec2 arg0)
+ (declare (in) vec2 arg1))
+ ((return (expression vec2 pow (var_ref arg0) (var_ref arg1)))))
+
+ (signature vec3
+ (parameters
+ (declare (in) vec3 arg0)
+ (declare (in) vec3 arg1))
+ ((return (expression vec3 pow (var_ref arg0) (var_ref arg1)))))
+
+ (signature vec4
+ (parameters
+ (declare (in) vec4 arg0)
+ (declare (in) vec4 arg1))
+ ((return (expression vec4 pow (var_ref arg0) (var_ref arg1)))))
+))
diff --git a/src/glsl/builtins/ir/radians b/src/glsl/builtins/ir/radians
new file mode 100644
index 00000000000..6a0f5d2e219
--- /dev/null
+++ b/src/glsl/builtins/ir/radians
@@ -0,0 +1,21 @@
+((function radians
+ (signature float
+ (parameters
+ (declare (in) float arg0))
+ ((return (expression float * (var_ref arg0) (constant float (0.017453))))))
+
+ (signature vec2
+ (parameters
+ (declare (in) vec2 arg0))
+ ((return (expression vec2 * (var_ref arg0) (constant float (0.017453))))))
+
+ (signature vec3
+ (parameters
+ (declare (in) vec3 arg0))
+ ((return (expression vec3 * (var_ref arg0) (constant float (0.017453))))))
+
+ (signature vec4
+ (parameters
+ (declare (in) vec4 arg0))
+ ((return (expression vec4 * (var_ref arg0) (constant float (0.017453))))))
+))
diff --git a/src/glsl/builtins/ir/reflect b/src/glsl/builtins/ir/reflect
new file mode 100644
index 00000000000..8238fdc93fd
--- /dev/null
+++ b/src/glsl/builtins/ir/reflect
@@ -0,0 +1,58 @@
+((function reflect
+ (signature float
+ (parameters
+ (declare (in) float i)
+ (declare (in) float n))
+ ((return (expression float -
+ (var_ref i)
+ (expression float *
+ (constant float (2.0))
+ (expression float *
+ (expression float dot
+ (var_ref n)
+ (var_ref i))
+ (var_ref n)))))))
+
+ (signature vec2
+ (parameters
+ (declare (in) vec2 i)
+ (declare (in) vec2 n))
+ ((return (expression vec2 -
+ (var_ref i)
+ (expression vec2 *
+ (constant float (2.0))
+ (expression vec2 *
+ (expression float dot
+ (var_ref n)
+ (var_ref i))
+ (var_ref n)))))))
+
+ (signature vec3
+ (parameters
+ (declare (in) vec3 i)
+ (declare (in) vec3 n))
+ ((return (expression vec3 -
+ (var_ref i)
+ (expression vec3 *
+ (constant float (2.0))
+ (expression vec3 *
+ (expression float dot
+ (var_ref n)
+ (var_ref i))
+ (var_ref n)))))))
+
+ (signature vec4
+ (parameters
+ (declare (in) vec4 i)
+ (declare (in) vec4 n))
+ ((return (expression vec4 -
+ (var_ref i)
+ (expression vec4 *
+ (constant float (2.0))
+ (expression vec4 *
+ (expression float dot
+ (var_ref n)
+ (var_ref i))
+ (var_ref n)))))))
+
+))
diff --git a/src/glsl/builtins/ir/refract b/src/glsl/builtins/ir/refract
new file mode 100644
index 00000000000..522ab411734
--- /dev/null
+++ b/src/glsl/builtins/ir/refract
@@ -0,0 +1,102 @@
+((function refract
+ (signature float
+ (parameters
+ (declare (in) float i)
+ (declare (in) float n)
+ (declare (in) float eta))
+ ((declare () float k)
+ (assign (constant bool (1)) (var_ref k)
+ (expression float - (constant float (1.0))
+ (expression float * (var_ref eta)
+ (expression float * (var_ref eta)
+ (expression float - (constant float (1.0))
+ (expression float *
+ (expression float dot (var_ref n) (var_ref i))
+ (expression float dot (var_ref n) (var_ref i))))))))
+ (if (expression bool < (var_ref k) (constant float (0.0)))
+ ((return (constant float (0.0))))
+ ((return (expression float -
+ (expression float * (var_ref eta) (var_ref i))
+ (expression float *
+ (expression float +
+ (expression float * (var_ref eta)
+ (expression float dot (var_ref n) (var_ref i)))
+ (expression float sqrt (var_ref k)))
+ (var_ref n))))))))
+
+ (signature vec2
+ (parameters
+ (declare (in) vec2 i)
+ (declare (in) vec2 n)
+ (declare (in) float eta))
+ ((declare () float k)
+ (assign (constant bool (1)) (var_ref k)
+ (expression float - (constant float (1.0))
+ (expression float * (var_ref eta)
+ (expression float * (var_ref eta)
+ (expression float - (constant float (1.0))
+ (expression float *
+ (expression float dot (var_ref n) (var_ref i))
+ (expression float dot (var_ref n) (var_ref i))))))))
+ (if (expression bool < (var_ref k) (constant float (0.0)))
+ ((return (constant vec2 (0.0 0.0))))
+ ((return (expression vec2 -
+ (expression vec2 * (var_ref eta) (var_ref i))
+ (expression vec2 *
+ (expression float +
+ (expression float * (var_ref eta)
+ (expression float dot (var_ref n) (var_ref i)))
+ (expression float sqrt (var_ref k)))
+ (var_ref n))))))))
+
+ (signature vec3
+ (parameters
+ (declare (in) vec3 i)
+ (declare (in) vec3 n)
+ (declare (in) float eta))
+ ((declare () float k)
+ (assign (constant bool (1)) (var_ref k)
+ (expression float - (constant float (1.0))
+ (expression float * (var_ref eta)
+ (expression float * (var_ref eta)
+ (expression float - (constant float (1.0))
+ (expression float *
+ (expression float dot (var_ref n) (var_ref i))
+ (expression float dot (var_ref n) (var_ref i))))))))
+ (if (expression bool < (var_ref k) (constant float (0.0)))
+ ((return (constant vec3 (0.0 0.0 0.0))))
+ ((return (expression vec3 -
+ (expression vec3 * (var_ref eta) (var_ref i))
+ (expression vec3 *
+ (expression float +
+ (expression float * (var_ref eta)
+ (expression float dot (var_ref n) (var_ref i)))
+ (expression float sqrt (var_ref k)))
+ (var_ref n))))))))
+
+ (signature vec4
+ (parameters
+ (declare (in) vec4 i)
+ (declare (in) vec4 n)
+ (declare (in) float eta))
+ ((declare () float k)
+ (assign (constant bool (1)) (var_ref k)
+ (expression float - (constant float (1.0))
+ (expression float * (var_ref eta)
+ (expression float * (var_ref eta)
+ (expression float - (constant float (1.0))
+ (expression float *
+ (expression float dot (var_ref n) (var_ref i))
+ (expression float dot (var_ref n) (var_ref i))))))))
+ (if (expression bool < (var_ref k) (constant float (0.0)))
+ ((return (constant vec4 (0.0 0.0 0.0 0.0))))
+ ((return (expression vec4 -
+ (expression vec4 * (var_ref eta) (var_ref i))
+ (expression vec4 *
+ (expression float +
+ (expression float * (var_ref eta)
+ (expression float dot (var_ref n) (var_ref i)))
+ (expression float sqrt (var_ref k)))
+ (var_ref n))))))))
+
+))
diff --git a/src/glsl/builtins/ir/sign b/src/glsl/builtins/ir/sign
new file mode 100644
index 00000000000..1f51718dab1
--- /dev/null
+++ b/src/glsl/builtins/ir/sign
@@ -0,0 +1,42 @@
+((function sign
+ (signature float
+ (parameters
+ (declare (in) float x))
+ ((return (expression float sign (var_ref x)))))
+
+ (signature vec2
+ (parameters
+ (declare (in) vec2 x))
+ ((return (expression vec2 sign (var_ref x)))))
+
+ (signature vec3
+ (parameters
+ (declare (in) vec3 x))
+ ((return (expression vec3 sign (var_ref x)))))
+
+ (signature vec4
+ (parameters
+ (declare (in) vec4 x))
+ ((return (expression vec4 sign (var_ref x)))))
+
+ (signature int
+ (parameters
+ (declare (in) int x))
+ ((return (expression int sign (var_ref x)))))
+
+ (signature ivec2
+ (parameters
+ (declare (in) ivec2 x))
+ ((return (expression ivec2 sign (var_ref x)))))
+
+ (signature ivec3
+ (parameters
+ (declare (in) ivec3 x))
+ ((return (expression ivec3 sign (var_ref x)))))
+
+ (signature ivec4
+ (parameters
+ (declare (in) ivec4 x))
+ ((return (expression ivec4 sign (var_ref x)))))
+))
+
diff --git a/src/glsl/builtins/ir/sin b/src/glsl/builtins/ir/sin
new file mode 100644
index 00000000000..e6009d8ef12
--- /dev/null
+++ b/src/glsl/builtins/ir/sin
@@ -0,0 +1,21 @@
+((function sin
+ (signature float
+ (parameters
+ (declare (in) float angle))
+ ((return (expression float sin (var_ref angle)))))
+
+ (signature vec2
+ (parameters
+ (declare (in) vec2 angle))
+ ((return (expression vec2 sin (var_ref angle)))))
+
+ (signature vec3
+ (parameters
+ (declare (in) vec3 angle))
+ ((return (expression vec3 sin (var_ref angle)))))
+
+ (signature vec4
+ (parameters
+ (declare (in) vec4 angle))
+ ((return (expression vec4 sin (var_ref angle)))))
+))
diff --git a/src/glsl/builtins/ir/sinh b/src/glsl/builtins/ir/sinh
new file mode 100644
index 00000000000..7ad4f58e204
--- /dev/null
+++ b/src/glsl/builtins/ir/sinh
@@ -0,0 +1,30 @@
+((function sinh
+ (signature float
+ (parameters
+ (declare (in) float x))
+ ((return (expression float * (constant float (0.5))
+ (expression float -
+ (expression float exp (var_ref x))
+ (expression float exp (expression float neg (var_ref x))))))))
+ (signature vec2
+ (parameters
+ (declare (in) vec2 x))
+ ((return (expression vec2 * (constant vec2 (0.5))
+ (expression vec2 -
+ (expression vec2 exp (var_ref x))
+ (expression vec2 exp (expression vec2 neg (var_ref x))))))))
+ (signature vec3
+ (parameters
+ (declare (in) vec3 x))
+ ((return (expression vec3 * (constant vec3 (0.5))
+ (expression vec3 -
+ (expression vec3 exp (var_ref x))
+ (expression vec3 exp (expression vec3 neg (var_ref x))))))))
+ (signature vec4
+ (parameters
+ (declare (in) vec4 x))
+ ((return (expression vec4 * (constant vec4 (0.5))
+ (expression vec4 -
+ (expression vec4 exp (var_ref x))
+ (expression vec4 exp (expression vec4 neg (var_ref x))))))))
+))
diff --git a/src/glsl/builtins/ir/smoothstep b/src/glsl/builtins/ir/smoothstep
new file mode 100644
index 00000000000..663eec63419
--- /dev/null
+++ b/src/glsl/builtins/ir/smoothstep
@@ -0,0 +1,153 @@
+((function smoothstep
+ (signature float
+ (parameters
+ (declare (in) float edge0)
+ (declare (in) float edge1)
+ (declare (in) float x))
+ ((declare () float t)
+
+ (assign (constant bool (1)) (var_ref t)
+ (expression float max
+ (expression float min
+ (expression float / (expression float - (var_ref x) (var_ref edge0)) (expression float - (var_ref edge1) (var_ref edge0)))
+ (constant float (1.0)))
+ (constant float (0.0))))
+ (return (expression float * (var_ref t) (expression float * (var_ref t) (expression float - (constant float (3.000000)) (expression float * (constant float (2.000000)) (var_ref t))))))))
+
+ (signature vec2
+ (parameters
+ (declare (in) float edge0)
+ (declare (in) float edge1)
+ (declare (in) vec2 x))
+ ((declare () vec2 t)
+ (declare () vec2 retval)
+
+ (assign (constant bool (1)) (swiz x (var_ref t))
+ (expression float max
+ (expression float min
+ (expression float / (expression float - (swiz x (var_ref x)) (var_ref edge0)) (expression float - (var_ref edge1) (var_ref edge0)))
+ (constant float (1.0)))
+ (constant float (0.0))))
+ (assign (constant bool (1)) (swiz x (var_ref retval)) (expression float * (swiz x (var_ref t)) (expression float * (swiz x (var_ref t)) (expression float - (constant float (3.000000)) (expression float * (constant float (2.000000)) (swiz x (var_ref t)))))))
+
+ (assign (constant bool (1)) (swiz y (var_ref t))
+ (expression float max
+ (expression float min
+ (expression float / (expression float - (swiz y (var_ref x)) (var_ref edge0)) (expression float - (var_ref edge1) (var_ref edge0)))
+ (constant float (1.0)))
+ (constant float (0.0))))
+ (assign (constant bool (1)) (swiz y (var_ref retval)) (expression float * (swiz y (var_ref t)) (expression float * (swiz y (var_ref t)) (expression float - (constant float (3.000000)) (expression float * (constant float (2.000000)) (swiz y (var_ref t)))))))
+ (return (var_ref retval))
+ ))
+
+ (signature vec3
+ (parameters
+ (declare (in) float edge0)
+ (declare (in) float edge1)
+ (declare (in) vec3 x))
+ ((declare () vec3 t)
+ (declare () vec3 retval)
+
+ (assign (constant bool (1)) (swiz x (var_ref t))
+ (expression float max
+ (expression float min
+ (expression float / (expression float - (swiz x (var_ref x)) (var_ref edge0)) (expression float - (var_ref edge1) (var_ref edge0)))
+ (constant float (1.0)))
+ (constant float (0.0))))
+ (assign (constant bool (1)) (swiz x (var_ref retval)) (expression float * (swiz x (var_ref t)) (expression float * (swiz x (var_ref t)) (expression float - (constant float (3.000000)) (expression float * (constant float (2.000000)) (swiz x (var_ref t)))))))
+
+ (assign (constant bool (1)) (swiz y (var_ref t))
+ (expression float max
+ (expression float min
+ (expression float / (expression float - (swiz y (var_ref x)) (var_ref edge0)) (expression float - (var_ref edge1) (var_ref edge0)))
+ (constant float (1.0)))
+ (constant float (0.0))))
+ (assign (constant bool (1)) (swiz y (var_ref retval)) (expression float * (swiz y (var_ref t)) (expression float * (swiz y (var_ref t)) (expression float - (constant float (3.000000)) (expression float * (constant float (2.000000)) (swiz y (var_ref t)))))))
+
+ (assign (constant bool (1)) (swiz z (var_ref t))
+ (expression float max
+ (expression float min
+ (expression float / (expression float - (swiz z (var_ref x)) (var_ref edge0)) (expression float - (var_ref edge1) (var_ref edge0)))
+ (constant float (1.0)))
+ (constant float (0.0))))
+ (assign (constant bool (1)) (swiz z (var_ref retval)) (expression float * (swiz z (var_ref t)) (expression float * (swiz z (var_ref t)) (expression float - (constant float (3.000000)) (expression float * (constant float (2.000000)) (swiz z (var_ref t)))))))
+ (return (var_ref retval))
+ ))
+
+
+ (signature vec4
+ (parameters
+ (declare (in) float edge0)
+ (declare (in) float edge1)
+ (declare (in) vec4 x))
+ ((declare () vec4 t)
+ (declare () vec4 retval)
+
+ (assign (constant bool (1)) (swiz x (var_ref t))
+ (expression float max
+ (expression float min
+ (expression float / (expression float - (swiz x (var_ref x)) (var_ref edge0)) (expression float - (var_ref edge1) (var_ref edge0)))
+ (constant float (1.0)))
+ (constant float (0.0))))
+ (assign (constant bool (1)) (swiz x (var_ref retval)) (expression float * (swiz x (var_ref t)) (expression float * (swiz x (var_ref t)) (expression float - (constant float (3.000000)) (expression float * (constant float (2.000000)) (swiz x (var_ref t)))))))
+
+ (assign (constant bool (1)) (swiz y (var_ref t))
+ (expression float max
+ (expression float min
+ (expression float / (expression float - (swiz y (var_ref x)) (var_ref edge0)) (expression float - (var_ref edge1) (var_ref edge0)))
+ (constant float (1.0)))
+ (constant float (0.0))))
+ (assign (constant bool (1)) (swiz y (var_ref retval)) (expression float * (swiz y (var_ref t)) (expression float * (swiz y (var_ref t)) (expression float - (constant float (3.000000)) (expression float * (constant float (2.000000)) (swiz y (var_ref t)))))))
+
+ (assign (constant bool (1)) (swiz z (var_ref t))
+ (expression float max
+ (expression float min
+ (expression float / (expression float - (swiz z (var_ref x)) (var_ref edge0)) (expression float - (var_ref edge1) (var_ref edge0)))
+ (constant float (1.0)))
+ (constant float (0.0))))
+ (assign (constant bool (1)) (swiz z (var_ref retval)) (expression float * (swiz z (var_ref t)) (expression float * (swiz z (var_ref t)) (expression float - (constant float (3.000000)) (expression float * (constant float (2.000000)) (swiz z (var_ref t)))))))
+
+ (assign (constant bool (1)) (swiz w (var_ref t))
+ (expression float max
+ (expression float min
+ (expression float / (expression float - (swiz w (var_ref x)) (var_ref edge0)) (expression float - (var_ref edge1) (var_ref edge0)))
+ (constant float (1.0)))
+ (constant float (0.0))))
+ (assign (constant bool (1)) (swiz w (var_ref retval)) (expression float * (swiz w (var_ref t)) (expression float * (swiz w (var_ref t)) (expression float - (constant float (3.000000)) (expression float * (constant float (2.000000)) (swiz w (var_ref t)))))))
+ (return (var_ref retval))
+ ))
+
+ (signature vec2
+ (parameters
+ (declare (in) vec2 edge0)
+ (declare (in) vec2 edge1)
+ (declare (in) vec2 x))
+ ((return (expression vec2 max
+ (expression vec2 min
+ (expression vec2 / (expression vec2 - (var_ref x) (var_ref edge0)) (expression vec2 - (var_ref edge1) (var_ref edge0)))
+ (constant vec2 (1.0 1.0)))
+ (constant vec2 (0.0 0.0))))))
+
+ (signature vec3
+ (parameters
+ (declare (in) vec3 edge0)
+ (declare (in) vec3 edge1)
+ (declare (in) vec3 x))
+ ((return (expression vec3 max
+ (expression vec3 min
+ (expression vec3 / (expression vec3 - (var_ref x) (var_ref edge0)) (expression vec3 - (var_ref edge1) (var_ref edge0)))
+ (constant vec3 (1.0 1.0 1.0)))
+ (constant vec3 (0.0 0.0 0.0))))))
+
+ (signature vec4
+ (parameters
+ (declare (in) vec4 edge0)
+ (declare (in) vec4 edge1)
+ (declare (in) vec4 x))
+ ((return (expression vec4 max
+ (expression vec4 min
+ (expression vec4 / (expression vec4 - (var_ref x) (var_ref edge0)) (expression vec4 - (var_ref edge1) (var_ref edge0)))
+ (constant vec4 (1.0 1.0 1.0 1.0)))
+ (constant vec4 (0.0 0.0 0.0 0.0))))))
+))
+
diff --git a/src/glsl/builtins/ir/sqrt b/src/glsl/builtins/ir/sqrt
new file mode 100644
index 00000000000..0302d164ae5
--- /dev/null
+++ b/src/glsl/builtins/ir/sqrt
@@ -0,0 +1,21 @@
+((function sqrt
+ (signature float
+ (parameters
+ (declare (in) float arg0))
+ ((return (expression float sqrt (var_ref arg0)))))
+
+ (signature vec2
+ (parameters
+ (declare (in) vec2 arg0))
+ ((return (expression vec2 sqrt (var_ref arg0)))))
+
+ (signature vec3
+ (parameters
+ (declare (in) vec3 arg0))
+ ((return (expression vec3 sqrt (var_ref arg0)))))
+
+ (signature vec4
+ (parameters
+ (declare (in) vec4 arg0))
+ ((return (expression vec4 sqrt (var_ref arg0)))))
+))
diff --git a/src/glsl/builtins/ir/step b/src/glsl/builtins/ir/step
new file mode 100644
index 00000000000..ce6f4354228
--- /dev/null
+++ b/src/glsl/builtins/ir/step
@@ -0,0 +1,68 @@
+((function step
+ (signature float
+ (parameters
+ (declare (in) float edge)
+ (declare (in) float x))
+ ((return (expression float b2f (expression bool >= (var_ref x) (var_ref edge))))))
+
+ (signature vec2
+ (parameters
+ (declare (in) float edge)
+ (declare (in) vec2 x))
+ ((declare () vec2 t)
+ (assign (constant bool (1)) (swiz x (var_ref t)) (expression float b2f (expression bool >= (swiz x (var_ref x))(var_ref edge))))
+ (assign (constant bool (1)) (swiz y (var_ref t)) (expression float b2f (expression bool >= (swiz y (var_ref x))(var_ref edge))))
+ (return (var_ref t))))
+
+ (signature vec3
+ (parameters
+ (declare (in) float edge)
+ (declare (in) vec3 x))
+ ((declare () vec3 t)
+ (assign (constant bool (1)) (swiz x (var_ref t)) (expression float b2f (expression bool >= (swiz x (var_ref x))(var_ref edge))))
+ (assign (constant bool (1)) (swiz y (var_ref t)) (expression float b2f (expression bool >= (swiz y (var_ref x))(var_ref edge))))
+ (assign (constant bool (1)) (swiz z (var_ref t)) (expression float b2f (expression bool >= (swiz z (var_ref x))(var_ref edge))))
+ (return (var_ref t))))
+
+ (signature vec4
+ (parameters
+ (declare (in) float edge)
+ (declare (in) vec4 x))
+ ((declare () vec4 t)
+ (assign (constant bool (1)) (swiz x (var_ref t)) (expression float b2f (expression bool >= (swiz x (var_ref x))(var_ref edge))))
+ (assign (constant bool (1)) (swiz y (var_ref t)) (expression float b2f (expression bool >= (swiz y (var_ref x))(var_ref edge))))
+ (assign (constant bool (1)) (swiz z (var_ref t)) (expression float b2f (expression bool >= (swiz z (var_ref x))(var_ref edge))))
+ (assign (constant bool (1)) (swiz w (var_ref t)) (expression float b2f (expression bool >= (swiz w (var_ref x))(var_ref edge))))
+ (return (var_ref t))))
+
+ (signature vec2
+ (parameters
+ (declare (in) vec2 edge)
+ (declare (in) vec2 x))
+ ((declare () vec2 t)
+ (assign (constant bool (1)) (swiz x (var_ref t)) (expression float b2f (expression bool >= (swiz x (var_ref x))(swiz x (var_ref edge)))))
+ (assign (constant bool (1)) (swiz y (var_ref t)) (expression float b2f (expression bool >= (swiz y (var_ref x))(swiz y (var_ref edge)))))
+ (return (var_ref t))))
+
+ (signature vec3
+ (parameters
+ (declare (in) vec3 edge)
+ (declare (in) vec3 x))
+ ((declare () vec3 t)
+ (assign (constant bool (1)) (swiz x (var_ref t)) (expression float b2f (expression bool >= (swiz x (var_ref x))(swiz x (var_ref edge)))))
+ (assign (constant bool (1)) (swiz y (var_ref t)) (expression float b2f (expression bool >= (swiz y (var_ref x))(swiz y (var_ref edge)))))
+ (assign (constant bool (1)) (swiz z (var_ref t)) (expression float b2f (expression bool >= (swiz z (var_ref x))(swiz z (var_ref edge)))))
+ (return (var_ref t))))
+
+ (signature vec4
+ (parameters
+ (declare (in) vec4 edge)
+ (declare (in) vec4 x))
+ ((declare () vec4 t)
+ (assign (constant bool (1)) (swiz x (var_ref t)) (expression float b2f (expression bool >= (swiz x (var_ref x))(swiz x (var_ref edge)))))
+ (assign (constant bool (1)) (swiz y (var_ref t)) (expression float b2f (expression bool >= (swiz y (var_ref x))(swiz y (var_ref edge)))))
+ (assign (constant bool (1)) (swiz z (var_ref t)) (expression float b2f (expression bool >= (swiz y (var_ref x))(swiz z (var_ref edge)))))
+ (assign (constant bool (1)) (swiz w (var_ref t)) (expression float b2f (expression bool >= (swiz w (var_ref x))(swiz w (var_ref edge)))))
+ (return (var_ref t))))
+))
+
diff --git a/src/glsl/builtins/ir/tan b/src/glsl/builtins/ir/tan
new file mode 100644
index 00000000000..99798631859
--- /dev/null
+++ b/src/glsl/builtins/ir/tan
@@ -0,0 +1,21 @@
+((function tan
+ (signature float
+ (parameters
+ (declare (in) float angle))
+ ((return (expression float / (expression float sin (var_ref angle)) (expression float cos (var_ref angle))))))
+
+ (signature vec2
+ (parameters
+ (declare (in) vec2 angle))
+ ((return (expression vec2 / (expression vec2 sin (var_ref angle)) (expression vec2 cos (var_ref angle))))))
+
+ (signature vec3
+ (parameters
+ (declare (in) vec3 angle))
+ ((return (expression vec3 / (expression vec3 sin (var_ref angle)) (expression vec3 cos (var_ref angle))))))
+
+ (signature vec4
+ (parameters
+ (declare (in) vec4 angle))
+ ((return (expression vec4 / (expression vec4 sin (var_ref angle)) (expression vec4 cos (var_ref angle))))))
+))
diff --git a/src/glsl/builtins/ir/tanh b/src/glsl/builtins/ir/tanh
new file mode 100644
index 00000000000..3b7271bf779
--- /dev/null
+++ b/src/glsl/builtins/ir/tanh
@@ -0,0 +1,42 @@
+((function tanh
+ (signature float
+ (parameters
+ (declare (in) float x))
+ ((return (expression float /
+ (expression float -
+ (expression float exp (var_ref x))
+ (expression float exp (expression float neg (var_ref x))))
+ (expression float +
+ (expression float exp (var_ref x))
+ (expression float exp (expression float neg (var_ref x))))))))
+ (signature vec2
+ (parameters
+ (declare (in) vec2 x))
+ ((return (expression vec2 /
+ (expression vec2 -
+ (expression vec2 exp (var_ref x))
+ (expression vec2 exp (expression vec2 neg (var_ref x))))
+ (expression vec2 +
+ (expression vec2 exp (var_ref x))
+ (expression vec2 exp (expression vec2 neg (var_ref x))))))))
+ (signature vec3
+ (parameters
+ (declare (in) vec3 x))
+ ((return (expression vec3 /
+ (expression vec3 -
+ (expression vec3 exp (var_ref x))
+ (expression vec3 exp (expression vec3 neg (var_ref x))))
+ (expression vec3 +
+ (expression vec3 exp (var_ref x))
+ (expression vec3 exp (expression vec3 neg (var_ref x))))))))
+ (signature vec4
+ (parameters
+ (declare (in) vec4 x))
+ ((return (expression vec4 /
+ (expression vec4 -
+ (expression vec4 exp (var_ref x))
+ (expression vec4 exp (expression vec4 neg (var_ref x))))
+ (expression vec4 +
+ (expression vec4 exp (var_ref x))
+ (expression vec4 exp (expression vec4 neg (var_ref x))))))))
+))
diff --git a/src/glsl/builtins/ir/transpose b/src/glsl/builtins/ir/transpose
new file mode 100644
index 00000000000..416a0ee4677
--- /dev/null
+++ b/src/glsl/builtins/ir/transpose
@@ -0,0 +1,139 @@
+((function transpose
+ (signature mat2
+ (parameters
+ (declare (in) mat2 m))
+ ((declare () mat2 t)
+ (assign (constant bool (1)) (swiz x (array_ref (var_ref t) (constant int (0)))) (swiz x (array_ref (var_ref m) (constant int (0)))))
+ (assign (constant bool (1)) (swiz x (array_ref (var_ref t) (constant int (1)))) (swiz y (array_ref (var_ref m) (constant int (0)))))
+ (assign (constant bool (1)) (swiz y (array_ref (var_ref t) (constant int (0)))) (swiz x (array_ref (var_ref m) (constant int (1)))))
+ (assign (constant bool (1)) (swiz y (array_ref (var_ref t) (constant int (1)))) (swiz y (array_ref (var_ref m) (constant int (1)))))
+(return (var_ref t))))
+
+ (signature mat3x2
+ (parameters
+ (declare (in) mat2x3 m))
+ ((declare () mat3x2 t)
+ (assign (constant bool (1)) (swiz x (array_ref (var_ref t) (constant int (0)))) (swiz x (array_ref (var_ref m) (constant int (0)))))
+ (assign (constant bool (1)) (swiz x (array_ref (var_ref t) (constant int (1)))) (swiz y (array_ref (var_ref m) (constant int (0)))))
+ (assign (constant bool (1)) (swiz x (array_ref (var_ref t) (constant int (2)))) (swiz z (array_ref (var_ref m) (constant int (0)))))
+ (assign (constant bool (1)) (swiz y (array_ref (var_ref t) (constant int (0)))) (swiz x (array_ref (var_ref m) (constant int (1)))))
+ (assign (constant bool (1)) (swiz y (array_ref (var_ref t) (constant int (1)))) (swiz y (array_ref (var_ref m) (constant int (1)))))
+ (assign (constant bool (1)) (swiz y (array_ref (var_ref t) (constant int (2)))) (swiz z (array_ref (var_ref m) (constant int (1)))))
+(return (var_ref t))))
+
+ (signature mat4x2
+ (parameters
+ (declare (in) mat2x4 m))
+ ((declare () mat4x2 t)
+ (assign (constant bool (1)) (swiz x (array_ref (var_ref t) (constant int (0)))) (swiz x (array_ref (var_ref m) (constant int (0)))))
+ (assign (constant bool (1)) (swiz x (array_ref (var_ref t) (constant int (1)))) (swiz y (array_ref (var_ref m) (constant int (0)))))
+ (assign (constant bool (1)) (swiz x (array_ref (var_ref t) (constant int (2)))) (swiz z (array_ref (var_ref m) (constant int (0)))))
+ (assign (constant bool (1)) (swiz x (array_ref (var_ref t) (constant int (3)))) (swiz w (array_ref (var_ref m) (constant int (0)))))
+ (assign (constant bool (1)) (swiz y (array_ref (var_ref t) (constant int (0)))) (swiz x (array_ref (var_ref m) (constant int (1)))))
+ (assign (constant bool (1)) (swiz y (array_ref (var_ref t) (constant int (1)))) (swiz y (array_ref (var_ref m) (constant int (1)))))
+ (assign (constant bool (1)) (swiz y (array_ref (var_ref t) (constant int (2)))) (swiz z (array_ref (var_ref m) (constant int (1)))))
+ (assign (constant bool (1)) (swiz y (array_ref (var_ref t) (constant int (3)))) (swiz w (array_ref (var_ref m) (constant int (1)))))
+(return (var_ref t))))
+
+ (signature mat2x3
+ (parameters
+ (declare (in) mat3x2 m))
+ ((declare () mat2x3 t)
+ (assign (constant bool (1)) (swiz x (array_ref (var_ref t) (constant int (0)))) (swiz x (array_ref (var_ref m) (constant int (0)))))
+ (assign (constant bool (1)) (swiz x (array_ref (var_ref t) (constant int (1)))) (swiz y (array_ref (var_ref m) (constant int (0)))))
+ (assign (constant bool (1)) (swiz y (array_ref (var_ref t) (constant int (0)))) (swiz x (array_ref (var_ref m) (constant int (1)))))
+ (assign (constant bool (1)) (swiz y (array_ref (var_ref t) (constant int (1)))) (swiz y (array_ref (var_ref m) (constant int (1)))))
+ (assign (constant bool (1)) (swiz z (array_ref (var_ref t) (constant int (0)))) (swiz x (array_ref (var_ref m) (constant int (2)))))
+ (assign (constant bool (1)) (swiz z (array_ref (var_ref t) (constant int (1)))) (swiz y (array_ref (var_ref m) (constant int (2)))))
+(return (var_ref t))))
+
+ (signature mat3
+ (parameters
+ (declare (in) mat3 m))
+ ((declare () mat3 t)
+ (assign (constant bool (1)) (swiz x (array_ref (var_ref t) (constant int (0)))) (swiz x (array_ref (var_ref m) (constant int (0)))))
+ (assign (constant bool (1)) (swiz x (array_ref (var_ref t) (constant int (1)))) (swiz y (array_ref (var_ref m) (constant int (0)))))
+ (assign (constant bool (1)) (swiz x (array_ref (var_ref t) (constant int (2)))) (swiz z (array_ref (var_ref m) (constant int (0)))))
+ (assign (constant bool (1)) (swiz y (array_ref (var_ref t) (constant int (0)))) (swiz x (array_ref (var_ref m) (constant int (1)))))
+ (assign (constant bool (1)) (swiz y (array_ref (var_ref t) (constant int (1)))) (swiz y (array_ref (var_ref m) (constant int (1)))))
+ (assign (constant bool (1)) (swiz y (array_ref (var_ref t) (constant int (2)))) (swiz z (array_ref (var_ref m) (constant int (1)))))
+ (assign (constant bool (1)) (swiz z (array_ref (var_ref t) (constant int (0)))) (swiz x (array_ref (var_ref m) (constant int (2)))))
+ (assign (constant bool (1)) (swiz z (array_ref (var_ref t) (constant int (1)))) (swiz y (array_ref (var_ref m) (constant int (2)))))
+ (assign (constant bool (1)) (swiz z (array_ref (var_ref t) (constant int (2)))) (swiz z (array_ref (var_ref m) (constant int (2)))))
+(return (var_ref t))))
+
+ (signature mat4x3
+ (parameters
+ (declare (in) mat3x4 m))
+ ((declare () mat4x3 t)
+ (assign (constant bool (1)) (swiz x (array_ref (var_ref t) (constant int (0)))) (swiz x (array_ref (var_ref m) (constant int (0)))))
+ (assign (constant bool (1)) (swiz x (array_ref (var_ref t) (constant int (1)))) (swiz y (array_ref (var_ref m) (constant int (0)))))
+ (assign (constant bool (1)) (swiz x (array_ref (var_ref t) (constant int (2)))) (swiz z (array_ref (var_ref m) (constant int (0)))))
+ (assign (constant bool (1)) (swiz x (array_ref (var_ref t) (constant int (3)))) (swiz w (array_ref (var_ref m) (constant int (0)))))
+ (assign (constant bool (1)) (swiz y (array_ref (var_ref t) (constant int (0)))) (swiz x (array_ref (var_ref m) (constant int (1)))))
+ (assign (constant bool (1)) (swiz y (array_ref (var_ref t) (constant int (1)))) (swiz y (array_ref (var_ref m) (constant int (1)))))
+ (assign (constant bool (1)) (swiz y (array_ref (var_ref t) (constant int (2)))) (swiz z (array_ref (var_ref m) (constant int (1)))))
+ (assign (constant bool (1)) (swiz y (array_ref (var_ref t) (constant int (3)))) (swiz w (array_ref (var_ref m) (constant int (1)))))
+ (assign (constant bool (1)) (swiz z (array_ref (var_ref t) (constant int (0)))) (swiz x (array_ref (var_ref m) (constant int (2)))))
+ (assign (constant bool (1)) (swiz z (array_ref (var_ref t) (constant int (1)))) (swiz y (array_ref (var_ref m) (constant int (2)))))
+ (assign (constant bool (1)) (swiz z (array_ref (var_ref t) (constant int (2)))) (swiz z (array_ref (var_ref m) (constant int (2)))))
+ (assign (constant bool (1)) (swiz z (array_ref (var_ref t) (constant int (3)))) (swiz w (array_ref (var_ref m) (constant int (2)))))
+(return (var_ref t))))
+
+ (signature mat2x4
+ (parameters
+ (declare (in) mat4x2 m))
+ ((declare () mat2x4 t)
+ (assign (constant bool (1)) (swiz x (array_ref (var_ref t) (constant int (0)))) (swiz x (array_ref (var_ref m) (constant int (0)))))
+ (assign (constant bool (1)) (swiz x (array_ref (var_ref t) (constant int (1)))) (swiz y (array_ref (var_ref m) (constant int (0)))))
+ (assign (constant bool (1)) (swiz y (array_ref (var_ref t) (constant int (0)))) (swiz x (array_ref (var_ref m) (constant int (1)))))
+ (assign (constant bool (1)) (swiz y (array_ref (var_ref t) (constant int (1)))) (swiz y (array_ref (var_ref m) (constant int (1)))))
+ (assign (constant bool (1)) (swiz z (array_ref (var_ref t) (constant int (0)))) (swiz x (array_ref (var_ref m) (constant int (2)))))
+ (assign (constant bool (1)) (swiz z (array_ref (var_ref t) (constant int (1)))) (swiz y (array_ref (var_ref m) (constant int (2)))))
+ (assign (constant bool (1)) (swiz w (array_ref (var_ref t) (constant int (0)))) (swiz x (array_ref (var_ref m) (constant int (3)))))
+ (assign (constant bool (1)) (swiz w (array_ref (var_ref t) (constant int (1)))) (swiz y (array_ref (var_ref m) (constant int (3)))))
+(return (var_ref t))))
+
+ (signature mat3x4
+ (parameters
+ (declare (in) mat4x3 m))
+ ((declare () mat3x4 t)
+ (assign (constant bool (1)) (swiz x (array_ref (var_ref t) (constant int (0)))) (swiz x (array_ref (var_ref m) (constant int (0)))))
+ (assign (constant bool (1)) (swiz x (array_ref (var_ref t) (constant int (1)))) (swiz y (array_ref (var_ref m) (constant int (0)))))
+ (assign (constant bool (1)) (swiz x (array_ref (var_ref t) (constant int (2)))) (swiz z (array_ref (var_ref m) (constant int (0)))))
+ (assign (constant bool (1)) (swiz y (array_ref (var_ref t) (constant int (0)))) (swiz x (array_ref (var_ref m) (constant int (1)))))
+ (assign (constant bool (1)) (swiz y (array_ref (var_ref t) (constant int (1)))) (swiz y (array_ref (var_ref m) (constant int (1)))))
+ (assign (constant bool (1)) (swiz y (array_ref (var_ref t) (constant int (2)))) (swiz z (array_ref (var_ref m) (constant int (1)))))
+ (assign (constant bool (1)) (swiz z (array_ref (var_ref t) (constant int (0)))) (swiz x (array_ref (var_ref m) (constant int (2)))))
+ (assign (constant bool (1)) (swiz z (array_ref (var_ref t) (constant int (1)))) (swiz y (array_ref (var_ref m) (constant int (2)))))
+ (assign (constant bool (1)) (swiz z (array_ref (var_ref t) (constant int (2)))) (swiz z (array_ref (var_ref m) (constant int (2)))))
+ (assign (constant bool (1)) (swiz w (array_ref (var_ref t) (constant int (0)))) (swiz x (array_ref (var_ref m) (constant int (3)))))
+ (assign (constant bool (1)) (swiz w (array_ref (var_ref t) (constant int (1)))) (swiz y (array_ref (var_ref m) (constant int (3)))))
+ (assign (constant bool (1)) (swiz w (array_ref (var_ref t) (constant int (2)))) (swiz z (array_ref (var_ref m) (constant int (3)))))
+(return (var_ref t))))
+
+ (signature mat4
+ (parameters
+ (declare (in) mat4 m))
+ ((declare () mat4 t)
+ (assign (constant bool (1)) (swiz x (array_ref (var_ref t) (constant int (0)))) (swiz x (array_ref (var_ref m) (constant int (0)))))
+ (assign (constant bool (1)) (swiz x (array_ref (var_ref t) (constant int (1)))) (swiz y (array_ref (var_ref m) (constant int (0)))))
+ (assign (constant bool (1)) (swiz x (array_ref (var_ref t) (constant int (2)))) (swiz z (array_ref (var_ref m) (constant int (0)))))
+ (assign (constant bool (1)) (swiz x (array_ref (var_ref t) (constant int (3)))) (swiz w (array_ref (var_ref m) (constant int (0)))))
+ (assign (constant bool (1)) (swiz y (array_ref (var_ref t) (constant int (0)))) (swiz x (array_ref (var_ref m) (constant int (1)))))
+ (assign (constant bool (1)) (swiz y (array_ref (var_ref t) (constant int (1)))) (swiz y (array_ref (var_ref m) (constant int (1)))))
+ (assign (constant bool (1)) (swiz y (array_ref (var_ref t) (constant int (2)))) (swiz z (array_ref (var_ref m) (constant int (1)))))
+ (assign (constant bool (1)) (swiz y (array_ref (var_ref t) (constant int (3)))) (swiz w (array_ref (var_ref m) (constant int (1)))))
+ (assign (constant bool (1)) (swiz z (array_ref (var_ref t) (constant int (0)))) (swiz x (array_ref (var_ref m) (constant int (2)))))
+ (assign (constant bool (1)) (swiz z (array_ref (var_ref t) (constant int (1)))) (swiz y (array_ref (var_ref m) (constant int (2)))))
+ (assign (constant bool (1)) (swiz z (array_ref (var_ref t) (constant int (2)))) (swiz z (array_ref (var_ref m) (constant int (2)))))
+ (assign (constant bool (1)) (swiz z (array_ref (var_ref t) (constant int (3)))) (swiz w (array_ref (var_ref m) (constant int (2)))))
+ (assign (constant bool (1)) (swiz w (array_ref (var_ref t) (constant int (0)))) (swiz x (array_ref (var_ref m) (constant int (3)))))
+ (assign (constant bool (1)) (swiz w (array_ref (var_ref t) (constant int (1)))) (swiz y (array_ref (var_ref m) (constant int (3)))))
+ (assign (constant bool (1)) (swiz w (array_ref (var_ref t) (constant int (2)))) (swiz z (array_ref (var_ref m) (constant int (3)))))
+ (assign (constant bool (1)) (swiz w (array_ref (var_ref t) (constant int (3)))) (swiz w (array_ref (var_ref m) (constant int (3)))))
+(return (var_ref t))))
+)
+
+)
+
diff --git a/src/glsl/builtins/profiles/110.frag b/src/glsl/builtins/profiles/110.frag
new file mode 100644
index 00000000000..25bc62c093c
--- /dev/null
+++ b/src/glsl/builtins/profiles/110.frag
@@ -0,0 +1,364 @@
+#version 110
+/*
+ * 8.1 - Angle and Trigonometry Functions
+ */
+float radians(float degrees);
+vec2 radians(vec2 degrees);
+vec3 radians(vec3 degrees);
+vec4 radians(vec4 degrees);
+
+float degrees(float radians);
+vec2 degrees(vec2 radians);
+vec3 degrees(vec3 radians);
+vec4 degrees(vec4 radians);
+
+float sin(float angle);
+vec2 sin(vec2 angle);
+vec3 sin(vec3 angle);
+vec4 sin(vec4 angle);
+
+float cos(float angle);
+vec2 cos(vec2 angle);
+vec3 cos(vec3 angle);
+vec4 cos(vec4 angle);
+
+float tan(float angle);
+vec2 tan(vec2 angle);
+vec3 tan(vec3 angle);
+vec4 tan(vec4 angle);
+
+float asin(float angle);
+vec2 asin(vec2 angle);
+vec3 asin(vec3 angle);
+vec4 asin(vec4 angle);
+
+float acos(float angle);
+vec2 acos(vec2 angle);
+vec3 acos(vec3 angle);
+vec4 acos(vec4 angle);
+
+float atan(float y, float x);
+vec2 atan(vec2 y, vec2 x);
+vec3 atan(vec3 y, vec3 x);
+vec4 atan(vec4 y, vec4 x);
+
+float atan(float y_over_x);
+vec2 atan(vec2 y_over_x);
+vec3 atan(vec3 y_over_x);
+vec4 atan(vec4 y_over_x);
+
+/*
+ * 8.2 - Exponential Functions
+ */
+float pow(float x, float y);
+vec2 pow(vec2 x, vec2 y);
+vec3 pow(vec3 x, vec3 y);
+vec4 pow(vec4 x, vec4 y);
+
+float exp(float x);
+vec2 exp(vec2 x);
+vec3 exp(vec3 x);
+vec4 exp(vec4 x);
+
+float log(float x);
+vec2 log(vec2 x);
+vec3 log(vec3 x);
+vec4 log(vec4 x);
+
+float exp2(float x);
+vec2 exp2(vec2 x);
+vec3 exp2(vec3 x);
+vec4 exp2(vec4 x);
+
+float log2(float x);
+vec2 log2(vec2 x);
+vec3 log2(vec3 x);
+vec4 log2(vec4 x);
+
+float sqrt(float x);
+vec2 sqrt(vec2 x);
+vec3 sqrt(vec3 x);
+vec4 sqrt(vec4 x);
+
+float inversesqrt(float x);
+vec2 inversesqrt(vec2 x);
+vec3 inversesqrt(vec3 x);
+vec4 inversesqrt(vec4 x);
+
+/*
+ * 8.3 - Common Functions
+ */
+float abs(float x);
+vec2 abs(vec2 x);
+vec3 abs(vec3 x);
+vec4 abs(vec4 x);
+
+float sign(float x);
+vec2 sign(vec2 x);
+vec3 sign(vec3 x);
+vec4 sign(vec4 x);
+
+float floor(float x);
+vec2 floor(vec2 x);
+vec3 floor(vec3 x);
+vec4 floor(vec4 x);
+
+float ceil(float x);
+vec2 ceil(vec2 x);
+vec3 ceil(vec3 x);
+vec4 ceil(vec4 x);
+
+float fract(float x);
+vec2 fract(vec2 x);
+vec3 fract(vec3 x);
+vec4 fract(vec4 x);
+
+float mod(float x, float y);
+vec2 mod(vec2 x, float y);
+vec3 mod(vec3 x, float y);
+vec4 mod(vec4 x, float y);
+
+vec2 mod(vec2 x, vec2 y);
+vec3 mod(vec3 x, vec3 y);
+vec4 mod(vec4 x, vec4 y);
+
+float min(float x, float y);
+vec2 min(vec2 x, vec2 y);
+vec3 min(vec3 x, vec3 y);
+vec4 min(vec4 x, vec4 y);
+
+vec2 min(vec2 x, float y);
+vec3 min(vec3 x, float y);
+vec4 min(vec4 x, float y);
+
+float max(float x, float y);
+vec2 max(vec2 x, vec2 y);
+vec3 max(vec3 x, vec3 y);
+vec4 max(vec4 x, vec4 y);
+
+vec2 max(vec2 x, float y);
+vec3 max(vec3 x, float y);
+vec4 max(vec4 x, float y);
+
+float clamp(float x, float minVal, float maxVal);
+vec2 clamp(vec2 x, vec2 minVal, vec2 maxVal);
+vec3 clamp(vec3 x, vec3 minVal, vec3 maxVal);
+vec4 clamp(vec4 x, vec4 minVal, vec4 maxVal);
+
+vec2 clamp(vec2 x, float minVal, float maxVal);
+vec3 clamp(vec3 x, float minVal, float maxVal);
+vec4 clamp(vec4 x, float minVal, float maxVal);
+
+float mix(float x, float y, float a);
+vec2 mix(vec2 x, vec2 y, vec2 a);
+vec3 mix(vec3 x, vec3 y, vec3 a);
+vec4 mix(vec4 x, vec4 y, vec4 a);
+
+vec2 mix(vec2 x, vec2 y, float a);
+vec3 mix(vec3 x, vec3 y, float a);
+vec4 mix(vec4 x, vec4 y, float a);
+
+float step(float edge, float x);
+vec2 step(vec2 edge, vec2 x);
+vec3 step(vec3 edge, vec3 x);
+vec4 step(vec4 edge, vec4 x);
+
+vec2 step(float edge, vec2 x);
+vec3 step(float edge, vec3 x);
+vec4 step(float edge, vec4 x);
+
+float smoothstep(float edge0, float edge1, float x);
+vec2 smoothstep(vec2 edge0, vec2 edge1, vec2 x);
+vec3 smoothstep(vec3 edge0, vec3 edge1, vec3 x);
+vec4 smoothstep(vec4 edge0, vec4 edge1, vec4 x);
+
+vec2 smoothstep(float edge0, float edge1, vec2 x);
+vec3 smoothstep(float edge0, float edge1, vec3 x);
+vec4 smoothstep(float edge0, float edge1, vec4 x);
+
+/*
+ * 8.4 - Geometric Functions
+ */
+float length(float x);
+float length(vec2 x);
+float length(vec3 x);
+float length(vec4 x);
+
+float distance(float p0, float p1);
+float distance(vec2 p0, vec2 p1);
+float distance(vec3 p0, vec3 p1);
+float distance(vec4 p0, vec4 p1);
+
+float dot(float x, float y);
+float dot(vec2 x, vec2 y);
+float dot(vec3 x, vec3 y);
+float dot(vec4 x, vec4 y);
+
+vec3 cross(vec3 x, vec3 y);
+
+float normalize(float x);
+vec2 normalize(vec2 x);
+vec3 normalize(vec3 x);
+vec4 normalize(vec4 x);
+
+float faceforward(float N, float I, float Nref);
+vec2 faceforward(vec2 N, vec2 I, vec2 Nref);
+vec3 faceforward(vec3 N, vec3 I, vec3 Nref);
+vec4 faceforward(vec4 N, vec4 I, vec4 Nref);
+
+float reflect(float I, float N);
+vec2 reflect(vec2 I, vec2 N);
+vec3 reflect(vec3 I, vec3 N);
+vec4 reflect(vec4 I, vec4 N);
+
+float refract(float I, float N, float eta);
+vec2 refract(vec2 I, vec2 N, float eta);
+vec3 refract(vec3 I, vec3 N, float eta);
+vec4 refract(vec4 I, vec4 N, float eta);
+
+
+/*
+ * 8.5 - Matrix Functions
+ */
+mat2 matrixCompMult(mat2 x, mat2 y);
+mat3 matrixCompMult(mat3 x, mat3 y);
+mat4 matrixCompMult(mat4 x, mat4 y);
+
+/*
+ * 8.6 - Vector Relational Functions
+ */
+bvec2 lessThan( vec2 x, vec2 y);
+bvec3 lessThan( vec3 x, vec3 y);
+bvec4 lessThan( vec4 x, vec4 y);
+bvec2 lessThan(ivec2 x, ivec2 y);
+bvec3 lessThan(ivec3 x, ivec3 y);
+bvec4 lessThan(ivec4 x, ivec4 y);
+
+bvec2 lessThanEqual( vec2 x, vec2 y);
+bvec3 lessThanEqual( vec3 x, vec3 y);
+bvec4 lessThanEqual( vec4 x, vec4 y);
+bvec2 lessThanEqual(ivec2 x, ivec2 y);
+bvec3 lessThanEqual(ivec3 x, ivec3 y);
+bvec4 lessThanEqual(ivec4 x, ivec4 y);
+
+bvec2 greaterThan( vec2 x, vec2 y);
+bvec3 greaterThan( vec3 x, vec3 y);
+bvec4 greaterThan( vec4 x, vec4 y);
+bvec2 greaterThan(ivec2 x, ivec2 y);
+bvec3 greaterThan(ivec3 x, ivec3 y);
+bvec4 greaterThan(ivec4 x, ivec4 y);
+
+bvec2 greaterThanEqual( vec2 x, vec2 y);
+bvec3 greaterThanEqual( vec3 x, vec3 y);
+bvec4 greaterThanEqual( vec4 x, vec4 y);
+bvec2 greaterThanEqual(ivec2 x, ivec2 y);
+bvec3 greaterThanEqual(ivec3 x, ivec3 y);
+bvec4 greaterThanEqual(ivec4 x, ivec4 y);
+
+bvec2 equal( vec2 x, vec2 y);
+bvec3 equal( vec3 x, vec3 y);
+bvec4 equal( vec4 x, vec4 y);
+bvec2 equal(ivec2 x, ivec2 y);
+bvec3 equal(ivec3 x, ivec3 y);
+bvec4 equal(ivec4 x, ivec4 y);
+bvec2 equal(bvec2 x, bvec2 y);
+bvec3 equal(bvec3 x, bvec3 y);
+bvec4 equal(bvec4 x, bvec4 y);
+
+bvec2 notEqual( vec2 x, vec2 y);
+bvec3 notEqual( vec3 x, vec3 y);
+bvec4 notEqual( vec4 x, vec4 y);
+bvec2 notEqual(ivec2 x, ivec2 y);
+bvec3 notEqual(ivec3 x, ivec3 y);
+bvec4 notEqual(ivec4 x, ivec4 y);
+bvec2 notEqual(bvec2 x, bvec2 y);
+bvec3 notEqual(bvec3 x, bvec3 y);
+bvec4 notEqual(bvec4 x, bvec4 y);
+
+bool any(bvec2 x);
+bool any(bvec3 x);
+bool any(bvec4 x);
+
+bool all(bvec2 x);
+bool all(bvec3 x);
+bool all(bvec4 x);
+
+bvec2 not(bvec2 x);
+bvec3 not(bvec3 x);
+bvec4 not(bvec4 x);
+
+/*
+ * 8.7 - Texture Lookup Functions
+ */
+vec4 texture1D (sampler1D sampler, float coord);
+vec4 texture1DProj (sampler1D sampler, vec2 coord);
+vec4 texture1DProj (sampler1D sampler, vec4 coord);
+vec4 texture1D (sampler1D sampler, float coord, float bias);
+vec4 texture1DProj (sampler1D sampler, vec2 coord, float bias);
+vec4 texture1DProj (sampler1D sampler, vec4 coord, float bias);
+
+vec4 texture2D (sampler2D sampler, vec2 coord);
+vec4 texture2DProj (sampler2D sampler, vec3 coord);
+vec4 texture2DProj (sampler2D sampler, vec4 coord);
+vec4 texture2D (sampler2D sampler, vec2 coord, float bias);
+vec4 texture2DProj (sampler2D sampler, vec3 coord, float bias);
+vec4 texture2DProj (sampler2D sampler, vec4 coord, float bias);
+
+vec4 texture3D (sampler3D sampler, vec3 coord);
+vec4 texture3DProj (sampler3D sampler, vec4 coord);
+vec4 texture3D (sampler3D sampler, vec3 coord, float bias);
+vec4 texture3DProj (sampler3D sampler, vec4 coord, float bias);
+
+vec4 textureCube (samplerCube sampler, vec3 coord);
+vec4 textureCube (samplerCube sampler, vec3 coord, float bias);
+
+vec4 shadow1D (sampler1DShadow sampler, vec3 coord);
+vec4 shadow2D (sampler2DShadow sampler, vec3 coord);
+vec4 shadow1DProj (sampler1DShadow sampler, vec4 coord);
+vec4 shadow2DProj (sampler2DShadow sampler, vec4 coord);
+vec4 shadow1D (sampler1DShadow sampler, vec3 coord, float bias);
+vec4 shadow2D (sampler2DShadow sampler, vec3 coord, float bias);
+vec4 shadow1DProj (sampler1DShadow sampler, vec4 coord, float bias);
+vec4 shadow2DProj (sampler2DShadow sampler, vec4 coord, float bias);
+
+
+/*
+ * 8.8 - Fragment Processing Functions
+ */
+float dFdx(float p);
+vec2 dFdx(vec2 p);
+vec3 dFdx(vec3 p);
+vec4 dFdx(vec4 p);
+
+float dFdy(float p);
+vec2 dFdy(vec2 p);
+vec3 dFdy(vec3 p);
+vec4 dFdy(vec4 p);
+
+float fwidth(float p);
+vec2 fwidth(vec2 p);
+vec3 fwidth(vec3 p);
+vec4 fwidth(vec4 p);
+
+/*
+ * 8.9 - Noise Functions
+ */
+float noise1(float x);
+float noise1(vec2 x);
+float noise1(vec3 x);
+float noise1(vec4 x);
+
+vec2 noise2(float x);
+vec2 noise2(vec2 x);
+vec2 noise2(vec3 x);
+vec2 noise2(vec4 x);
+
+vec3 noise3(float x);
+vec3 noise3(vec2 x);
+vec3 noise3(vec3 x);
+vec3 noise3(vec4 x);
+
+vec4 noise4(float x);
+vec4 noise4(vec2 x);
+vec4 noise4(vec3 x);
+vec4 noise4(vec4 x);
diff --git a/src/glsl/builtins/profiles/110.vert b/src/glsl/builtins/profiles/110.vert
new file mode 100644
index 00000000000..545e59c5397
--- /dev/null
+++ b/src/glsl/builtins/profiles/110.vert
@@ -0,0 +1,351 @@
+#version 110
+/*
+ * 8.1 - Angle and Trigonometry Functions
+ */
+float radians(float degrees);
+vec2 radians(vec2 degrees);
+vec3 radians(vec3 degrees);
+vec4 radians(vec4 degrees);
+
+float degrees(float radians);
+vec2 degrees(vec2 radians);
+vec3 degrees(vec3 radians);
+vec4 degrees(vec4 radians);
+
+float sin(float angle);
+vec2 sin(vec2 angle);
+vec3 sin(vec3 angle);
+vec4 sin(vec4 angle);
+
+float cos(float angle);
+vec2 cos(vec2 angle);
+vec3 cos(vec3 angle);
+vec4 cos(vec4 angle);
+
+float tan(float angle);
+vec2 tan(vec2 angle);
+vec3 tan(vec3 angle);
+vec4 tan(vec4 angle);
+
+float asin(float angle);
+vec2 asin(vec2 angle);
+vec3 asin(vec3 angle);
+vec4 asin(vec4 angle);
+
+float acos(float angle);
+vec2 acos(vec2 angle);
+vec3 acos(vec3 angle);
+vec4 acos(vec4 angle);
+
+float atan(float y, float x);
+vec2 atan(vec2 y, vec2 x);
+vec3 atan(vec3 y, vec3 x);
+vec4 atan(vec4 y, vec4 x);
+
+float atan(float y_over_x);
+vec2 atan(vec2 y_over_x);
+vec3 atan(vec3 y_over_x);
+vec4 atan(vec4 y_over_x);
+
+/*
+ * 8.2 - Exponential Functions
+ */
+float pow(float x, float y);
+vec2 pow(vec2 x, vec2 y);
+vec3 pow(vec3 x, vec3 y);
+vec4 pow(vec4 x, vec4 y);
+
+float exp(float x);
+vec2 exp(vec2 x);
+vec3 exp(vec3 x);
+vec4 exp(vec4 x);
+
+float log(float x);
+vec2 log(vec2 x);
+vec3 log(vec3 x);
+vec4 log(vec4 x);
+
+float exp2(float x);
+vec2 exp2(vec2 x);
+vec3 exp2(vec3 x);
+vec4 exp2(vec4 x);
+
+float log2(float x);
+vec2 log2(vec2 x);
+vec3 log2(vec3 x);
+vec4 log2(vec4 x);
+
+float sqrt(float x);
+vec2 sqrt(vec2 x);
+vec3 sqrt(vec3 x);
+vec4 sqrt(vec4 x);
+
+float inversesqrt(float x);
+vec2 inversesqrt(vec2 x);
+vec3 inversesqrt(vec3 x);
+vec4 inversesqrt(vec4 x);
+
+/*
+ * 8.3 - Common Functions
+ */
+float abs(float x);
+vec2 abs(vec2 x);
+vec3 abs(vec3 x);
+vec4 abs(vec4 x);
+
+float sign(float x);
+vec2 sign(vec2 x);
+vec3 sign(vec3 x);
+vec4 sign(vec4 x);
+
+float floor(float x);
+vec2 floor(vec2 x);
+vec3 floor(vec3 x);
+vec4 floor(vec4 x);
+
+float ceil(float x);
+vec2 ceil(vec2 x);
+vec3 ceil(vec3 x);
+vec4 ceil(vec4 x);
+
+float fract(float x);
+vec2 fract(vec2 x);
+vec3 fract(vec3 x);
+vec4 fract(vec4 x);
+
+float mod(float x, float y);
+vec2 mod(vec2 x, float y);
+vec3 mod(vec3 x, float y);
+vec4 mod(vec4 x, float y);
+
+vec2 mod(vec2 x, vec2 y);
+vec3 mod(vec3 x, vec3 y);
+vec4 mod(vec4 x, vec4 y);
+
+float min(float x, float y);
+vec2 min(vec2 x, vec2 y);
+vec3 min(vec3 x, vec3 y);
+vec4 min(vec4 x, vec4 y);
+
+vec2 min(vec2 x, float y);
+vec3 min(vec3 x, float y);
+vec4 min(vec4 x, float y);
+
+float max(float x, float y);
+vec2 max(vec2 x, vec2 y);
+vec3 max(vec3 x, vec3 y);
+vec4 max(vec4 x, vec4 y);
+
+vec2 max(vec2 x, float y);
+vec3 max(vec3 x, float y);
+vec4 max(vec4 x, float y);
+
+float clamp(float x, float minVal, float maxVal);
+vec2 clamp(vec2 x, vec2 minVal, vec2 maxVal);
+vec3 clamp(vec3 x, vec3 minVal, vec3 maxVal);
+vec4 clamp(vec4 x, vec4 minVal, vec4 maxVal);
+
+vec2 clamp(vec2 x, float minVal, float maxVal);
+vec3 clamp(vec3 x, float minVal, float maxVal);
+vec4 clamp(vec4 x, float minVal, float maxVal);
+
+float mix(float x, float y, float a);
+vec2 mix(vec2 x, vec2 y, vec2 a);
+vec3 mix(vec3 x, vec3 y, vec3 a);
+vec4 mix(vec4 x, vec4 y, vec4 a);
+
+vec2 mix(vec2 x, vec2 y, float a);
+vec3 mix(vec3 x, vec3 y, float a);
+vec4 mix(vec4 x, vec4 y, float a);
+
+float step(float edge, float x);
+vec2 step(vec2 edge, vec2 x);
+vec3 step(vec3 edge, vec3 x);
+vec4 step(vec4 edge, vec4 x);
+
+vec2 step(float edge, vec2 x);
+vec3 step(float edge, vec3 x);
+vec4 step(float edge, vec4 x);
+
+float smoothstep(float edge0, float edge1, float x);
+vec2 smoothstep(vec2 edge0, vec2 edge1, vec2 x);
+vec3 smoothstep(vec3 edge0, vec3 edge1, vec3 x);
+vec4 smoothstep(vec4 edge0, vec4 edge1, vec4 x);
+
+vec2 smoothstep(float edge0, float edge1, vec2 x);
+vec3 smoothstep(float edge0, float edge1, vec3 x);
+vec4 smoothstep(float edge0, float edge1, vec4 x);
+
+/*
+ * 8.4 - Geometric Functions
+ */
+float length(float x);
+float length(vec2 x);
+float length(vec3 x);
+float length(vec4 x);
+
+float distance(float p0, float p1);
+float distance(vec2 p0, vec2 p1);
+float distance(vec3 p0, vec3 p1);
+float distance(vec4 p0, vec4 p1);
+
+float dot(float x, float y);
+float dot(vec2 x, vec2 y);
+float dot(vec3 x, vec3 y);
+float dot(vec4 x, vec4 y);
+
+vec3 cross(vec3 x, vec3 y);
+
+float normalize(float x);
+vec2 normalize(vec2 x);
+vec3 normalize(vec3 x);
+vec4 normalize(vec4 x);
+
+vec4 ftransform();
+
+float faceforward(float N, float I, float Nref);
+vec2 faceforward(vec2 N, vec2 I, vec2 Nref);
+vec3 faceforward(vec3 N, vec3 I, vec3 Nref);
+vec4 faceforward(vec4 N, vec4 I, vec4 Nref);
+
+float reflect(float I, float N);
+vec2 reflect(vec2 I, vec2 N);
+vec3 reflect(vec3 I, vec3 N);
+vec4 reflect(vec4 I, vec4 N);
+
+float refract(float I, float N, float eta);
+vec2 refract(vec2 I, vec2 N, float eta);
+vec3 refract(vec3 I, vec3 N, float eta);
+vec4 refract(vec4 I, vec4 N, float eta);
+
+
+/*
+ * 8.5 - Matrix Functions
+ */
+mat2 matrixCompMult(mat2 x, mat2 y);
+mat3 matrixCompMult(mat3 x, mat3 y);
+mat4 matrixCompMult(mat4 x, mat4 y);
+
+/*
+ * 8.6 - Vector Relational Functions
+ */
+bvec2 lessThan( vec2 x, vec2 y);
+bvec3 lessThan( vec3 x, vec3 y);
+bvec4 lessThan( vec4 x, vec4 y);
+bvec2 lessThan(ivec2 x, ivec2 y);
+bvec3 lessThan(ivec3 x, ivec3 y);
+bvec4 lessThan(ivec4 x, ivec4 y);
+
+bvec2 lessThanEqual( vec2 x, vec2 y);
+bvec3 lessThanEqual( vec3 x, vec3 y);
+bvec4 lessThanEqual( vec4 x, vec4 y);
+bvec2 lessThanEqual(ivec2 x, ivec2 y);
+bvec3 lessThanEqual(ivec3 x, ivec3 y);
+bvec4 lessThanEqual(ivec4 x, ivec4 y);
+
+bvec2 greaterThan( vec2 x, vec2 y);
+bvec3 greaterThan( vec3 x, vec3 y);
+bvec4 greaterThan( vec4 x, vec4 y);
+bvec2 greaterThan(ivec2 x, ivec2 y);
+bvec3 greaterThan(ivec3 x, ivec3 y);
+bvec4 greaterThan(ivec4 x, ivec4 y);
+
+bvec2 greaterThanEqual( vec2 x, vec2 y);
+bvec3 greaterThanEqual( vec3 x, vec3 y);
+bvec4 greaterThanEqual( vec4 x, vec4 y);
+bvec2 greaterThanEqual(ivec2 x, ivec2 y);
+bvec3 greaterThanEqual(ivec3 x, ivec3 y);
+bvec4 greaterThanEqual(ivec4 x, ivec4 y);
+
+bvec2 equal( vec2 x, vec2 y);
+bvec3 equal( vec3 x, vec3 y);
+bvec4 equal( vec4 x, vec4 y);
+bvec2 equal(ivec2 x, ivec2 y);
+bvec3 equal(ivec3 x, ivec3 y);
+bvec4 equal(ivec4 x, ivec4 y);
+bvec2 equal(bvec2 x, bvec2 y);
+bvec3 equal(bvec3 x, bvec3 y);
+bvec4 equal(bvec4 x, bvec4 y);
+
+bvec2 notEqual( vec2 x, vec2 y);
+bvec3 notEqual( vec3 x, vec3 y);
+bvec4 notEqual( vec4 x, vec4 y);
+bvec2 notEqual(ivec2 x, ivec2 y);
+bvec3 notEqual(ivec3 x, ivec3 y);
+bvec4 notEqual(ivec4 x, ivec4 y);
+bvec2 notEqual(bvec2 x, bvec2 y);
+bvec3 notEqual(bvec3 x, bvec3 y);
+bvec4 notEqual(bvec4 x, bvec4 y);
+
+bool any(bvec2 x);
+bool any(bvec3 x);
+bool any(bvec4 x);
+
+bool all(bvec2 x);
+bool all(bvec3 x);
+bool all(bvec4 x);
+
+bvec2 not(bvec2 x);
+bvec3 not(bvec3 x);
+bvec4 not(bvec4 x);
+
+/*
+ * 8.7 - Texture Lookup Functions
+ */
+vec4 texture1D (sampler1D sampler, float coord);
+vec4 texture1DProj (sampler1D sampler, vec2 coord);
+vec4 texture1DProj (sampler1D sampler, vec4 coord);
+vec4 texture1DLod (sampler1D sampler, float coord, float lod);
+vec4 texture1DProjLod(sampler1D sampler, vec2 coord, float lod);
+vec4 texture1DProjLod(sampler1D sampler, vec4 coord, float lod);
+
+vec4 texture2D (sampler2D sampler, vec2 coord);
+vec4 texture2DProj (sampler2D sampler, vec3 coord);
+vec4 texture2DProj (sampler2D sampler, vec4 coord);
+vec4 texture2DLod (sampler2D sampler, vec2 coord, float lod);
+vec4 texture2DProjLod(sampler2D sampler, vec3 coord, float lod);
+vec4 texture2DProjLod(sampler2D sampler, vec4 coord, float lod);
+
+vec4 texture3D (sampler3D sampler, vec3 coord);
+vec4 texture3DProj (sampler3D sampler, vec4 coord);
+vec4 texture3DLod (sampler3D sampler, vec3 coord, float lod);
+vec4 texture3DProjLod(sampler3D sampler, vec4 coord, float lod);
+
+vec4 textureCube (samplerCube sampler, vec3 coord);
+vec4 textureCubeLod (samplerCube sampler, vec3 coord, float lod);
+
+vec4 shadow1D (sampler1DShadow sampler, vec3 coord);
+vec4 shadow2D (sampler2DShadow sampler, vec3 coord);
+vec4 shadow1DProj (sampler1DShadow sampler, vec4 coord);
+vec4 shadow2DProj (sampler2DShadow sampler, vec4 coord);
+vec4 shadow1DLod (sampler1DShadow sampler, vec3 coord, float lod);
+vec4 shadow2DLod (sampler2DShadow sampler, vec3 coord, float lod);
+vec4 shadow1DProjLod(sampler1DShadow sampler, vec4 coord, float lod);
+vec4 shadow2DProjLod(sampler2DShadow sampler, vec4 coord, float lod);
+
+/*
+ * 8.8 - Fragment Processing Functions (none in vertex shader)
+ */
+
+/*
+ * 8.9 - Noise Functions
+ */
+float noise1(float x);
+float noise1(vec2 x);
+float noise1(vec3 x);
+float noise1(vec4 x);
+
+vec2 noise2(float x);
+vec2 noise2(vec2 x);
+vec2 noise2(vec3 x);
+vec2 noise2(vec4 x);
+
+vec3 noise3(float x);
+vec3 noise3(vec2 x);
+vec3 noise3(vec3 x);
+vec3 noise3(vec4 x);
+
+vec4 noise4(float x);
+vec4 noise4(vec2 x);
+vec4 noise4(vec3 x);
+vec4 noise4(vec4 x);
diff --git a/src/glsl/builtins/profiles/120.frag b/src/glsl/builtins/profiles/120.frag
new file mode 100644
index 00000000000..a207435f337
--- /dev/null
+++ b/src/glsl/builtins/profiles/120.frag
@@ -0,0 +1,396 @@
+#version 120
+/*
+ * 8.1 - Angle and Trigonometry Functions
+ */
+float radians(float degrees);
+vec2 radians(vec2 degrees);
+vec3 radians(vec3 degrees);
+vec4 radians(vec4 degrees);
+
+float degrees(float radians);
+vec2 degrees(vec2 radians);
+vec3 degrees(vec3 radians);
+vec4 degrees(vec4 radians);
+
+float sin(float angle);
+vec2 sin(vec2 angle);
+vec3 sin(vec3 angle);
+vec4 sin(vec4 angle);
+
+float cos(float angle);
+vec2 cos(vec2 angle);
+vec3 cos(vec3 angle);
+vec4 cos(vec4 angle);
+
+float tan(float angle);
+vec2 tan(vec2 angle);
+vec3 tan(vec3 angle);
+vec4 tan(vec4 angle);
+
+float asin(float angle);
+vec2 asin(vec2 angle);
+vec3 asin(vec3 angle);
+vec4 asin(vec4 angle);
+
+float acos(float angle);
+vec2 acos(vec2 angle);
+vec3 acos(vec3 angle);
+vec4 acos(vec4 angle);
+
+float atan(float y, float x);
+vec2 atan(vec2 y, vec2 x);
+vec3 atan(vec3 y, vec3 x);
+vec4 atan(vec4 y, vec4 x);
+
+float atan(float y_over_x);
+vec2 atan(vec2 y_over_x);
+vec3 atan(vec3 y_over_x);
+vec4 atan(vec4 y_over_x);
+
+/*
+ * 8.2 - Exponential Functions
+ */
+float pow(float x, float y);
+vec2 pow(vec2 x, vec2 y);
+vec3 pow(vec3 x, vec3 y);
+vec4 pow(vec4 x, vec4 y);
+
+float exp(float x);
+vec2 exp(vec2 x);
+vec3 exp(vec3 x);
+vec4 exp(vec4 x);
+
+float log(float x);
+vec2 log(vec2 x);
+vec3 log(vec3 x);
+vec4 log(vec4 x);
+
+float exp2(float x);
+vec2 exp2(vec2 x);
+vec3 exp2(vec3 x);
+vec4 exp2(vec4 x);
+
+float log2(float x);
+vec2 log2(vec2 x);
+vec3 log2(vec3 x);
+vec4 log2(vec4 x);
+
+float sqrt(float x);
+vec2 sqrt(vec2 x);
+vec3 sqrt(vec3 x);
+vec4 sqrt(vec4 x);
+
+float inversesqrt(float x);
+vec2 inversesqrt(vec2 x);
+vec3 inversesqrt(vec3 x);
+vec4 inversesqrt(vec4 x);
+
+/*
+ * 8.3 - Common Functions
+ */
+float abs(float x);
+vec2 abs(vec2 x);
+vec3 abs(vec3 x);
+vec4 abs(vec4 x);
+
+float sign(float x);
+vec2 sign(vec2 x);
+vec3 sign(vec3 x);
+vec4 sign(vec4 x);
+
+float floor(float x);
+vec2 floor(vec2 x);
+vec3 floor(vec3 x);
+vec4 floor(vec4 x);
+
+float ceil(float x);
+vec2 ceil(vec2 x);
+vec3 ceil(vec3 x);
+vec4 ceil(vec4 x);
+
+float fract(float x);
+vec2 fract(vec2 x);
+vec3 fract(vec3 x);
+vec4 fract(vec4 x);
+
+float mod(float x, float y);
+vec2 mod(vec2 x, float y);
+vec3 mod(vec3 x, float y);
+vec4 mod(vec4 x, float y);
+
+vec2 mod(vec2 x, vec2 y);
+vec3 mod(vec3 x, vec3 y);
+vec4 mod(vec4 x, vec4 y);
+
+float min(float x, float y);
+vec2 min(vec2 x, vec2 y);
+vec3 min(vec3 x, vec3 y);
+vec4 min(vec4 x, vec4 y);
+
+vec2 min(vec2 x, float y);
+vec3 min(vec3 x, float y);
+vec4 min(vec4 x, float y);
+
+float max(float x, float y);
+vec2 max(vec2 x, vec2 y);
+vec3 max(vec3 x, vec3 y);
+vec4 max(vec4 x, vec4 y);
+
+vec2 max(vec2 x, float y);
+vec3 max(vec3 x, float y);
+vec4 max(vec4 x, float y);
+
+float clamp(float x, float minVal, float maxVal);
+vec2 clamp(vec2 x, vec2 minVal, vec2 maxVal);
+vec3 clamp(vec3 x, vec3 minVal, vec3 maxVal);
+vec4 clamp(vec4 x, vec4 minVal, vec4 maxVal);
+
+vec2 clamp(vec2 x, float minVal, float maxVal);
+vec3 clamp(vec3 x, float minVal, float maxVal);
+vec4 clamp(vec4 x, float minVal, float maxVal);
+
+float mix(float x, float y, float a);
+vec2 mix(vec2 x, vec2 y, vec2 a);
+vec3 mix(vec3 x, vec3 y, vec3 a);
+vec4 mix(vec4 x, vec4 y, vec4 a);
+
+vec2 mix(vec2 x, vec2 y, float a);
+vec3 mix(vec3 x, vec3 y, float a);
+vec4 mix(vec4 x, vec4 y, float a);
+
+float step(float edge, float x);
+vec2 step(vec2 edge, vec2 x);
+vec3 step(vec3 edge, vec3 x);
+vec4 step(vec4 edge, vec4 x);
+
+vec2 step(float edge, vec2 x);
+vec3 step(float edge, vec3 x);
+vec4 step(float edge, vec4 x);
+
+float smoothstep(float edge0, float edge1, float x);
+vec2 smoothstep(vec2 edge0, vec2 edge1, vec2 x);
+vec3 smoothstep(vec3 edge0, vec3 edge1, vec3 x);
+vec4 smoothstep(vec4 edge0, vec4 edge1, vec4 x);
+
+vec2 smoothstep(float edge0, float edge1, vec2 x);
+vec3 smoothstep(float edge0, float edge1, vec3 x);
+vec4 smoothstep(float edge0, float edge1, vec4 x);
+
+/*
+ * 8.4 - Geometric Functions
+ */
+float length(float x);
+float length(vec2 x);
+float length(vec3 x);
+float length(vec4 x);
+
+float distance(float p0, float p1);
+float distance(vec2 p0, vec2 p1);
+float distance(vec3 p0, vec3 p1);
+float distance(vec4 p0, vec4 p1);
+
+float dot(float x, float y);
+float dot(vec2 x, vec2 y);
+float dot(vec3 x, vec3 y);
+float dot(vec4 x, vec4 y);
+
+vec3 cross(vec3 x, vec3 y);
+
+float normalize(float x);
+vec2 normalize(vec2 x);
+vec3 normalize(vec3 x);
+vec4 normalize(vec4 x);
+
+float faceforward(float N, float I, float Nref);
+vec2 faceforward(vec2 N, vec2 I, vec2 Nref);
+vec3 faceforward(vec3 N, vec3 I, vec3 Nref);
+vec4 faceforward(vec4 N, vec4 I, vec4 Nref);
+
+float reflect(float I, float N);
+vec2 reflect(vec2 I, vec2 N);
+vec3 reflect(vec3 I, vec3 N);
+vec4 reflect(vec4 I, vec4 N);
+
+float refract(float I, float N, float eta);
+vec2 refract(vec2 I, vec2 N, float eta);
+vec3 refract(vec3 I, vec3 N, float eta);
+vec4 refract(vec4 I, vec4 N, float eta);
+
+
+/*
+ * 8.5 - Matrix Functions
+ */
+mat2 matrixCompMult(mat2 x, mat2 y);
+mat3 matrixCompMult(mat3 x, mat3 y);
+mat4 matrixCompMult(mat4 x, mat4 y);
+mat2x3 matrixCompMult(mat2x3 x, mat2x3 y);
+mat2x4 matrixCompMult(mat2x4 x, mat2x4 y);
+mat3x2 matrixCompMult(mat3x2 x, mat3x2 y);
+mat3x4 matrixCompMult(mat3x4 x, mat3x4 y);
+mat4x2 matrixCompMult(mat4x2 x, mat4x2 y);
+mat4x3 matrixCompMult(mat4x3 x, mat4x3 y);
+
+mat2 outerProduct(vec2 c, vec2 r);
+mat3 outerProduct(vec3 c, vec3 r);
+mat4 outerProduct(vec4 c, vec4 r);
+
+mat2x3 outerProduct(vec3 c, vec2 r);
+mat3x2 outerProduct(vec2 c, vec3 r);
+
+mat2x4 outerProduct(vec4 c, vec2 r);
+mat4x2 outerProduct(vec2 c, vec4 r);
+
+mat3x4 outerProduct(vec4 c, vec3 r);
+mat4x3 outerProduct(vec3 c, vec4 r);
+
+mat2 transpose(mat2 m);
+mat3 transpose(mat3 m);
+mat4 transpose(mat4 m);
+
+mat2x3 transpose(mat3x2 m);
+mat3x2 transpose(mat2x3 m);
+
+mat2x4 transpose(mat4x2 m);
+mat4x2 transpose(mat2x4 m);
+
+mat3x4 transpose(mat4x3 m);
+mat4x3 transpose(mat3x4 m);
+
+/*
+ * 8.6 - Vector Relational Functions
+ */
+bvec2 lessThan( vec2 x, vec2 y);
+bvec3 lessThan( vec3 x, vec3 y);
+bvec4 lessThan( vec4 x, vec4 y);
+bvec2 lessThan(ivec2 x, ivec2 y);
+bvec3 lessThan(ivec3 x, ivec3 y);
+bvec4 lessThan(ivec4 x, ivec4 y);
+
+bvec2 lessThanEqual( vec2 x, vec2 y);
+bvec3 lessThanEqual( vec3 x, vec3 y);
+bvec4 lessThanEqual( vec4 x, vec4 y);
+bvec2 lessThanEqual(ivec2 x, ivec2 y);
+bvec3 lessThanEqual(ivec3 x, ivec3 y);
+bvec4 lessThanEqual(ivec4 x, ivec4 y);
+
+bvec2 greaterThan( vec2 x, vec2 y);
+bvec3 greaterThan( vec3 x, vec3 y);
+bvec4 greaterThan( vec4 x, vec4 y);
+bvec2 greaterThan(ivec2 x, ivec2 y);
+bvec3 greaterThan(ivec3 x, ivec3 y);
+bvec4 greaterThan(ivec4 x, ivec4 y);
+
+bvec2 greaterThanEqual( vec2 x, vec2 y);
+bvec3 greaterThanEqual( vec3 x, vec3 y);
+bvec4 greaterThanEqual( vec4 x, vec4 y);
+bvec2 greaterThanEqual(ivec2 x, ivec2 y);
+bvec3 greaterThanEqual(ivec3 x, ivec3 y);
+bvec4 greaterThanEqual(ivec4 x, ivec4 y);
+
+bvec2 equal( vec2 x, vec2 y);
+bvec3 equal( vec3 x, vec3 y);
+bvec4 equal( vec4 x, vec4 y);
+bvec2 equal(ivec2 x, ivec2 y);
+bvec3 equal(ivec3 x, ivec3 y);
+bvec4 equal(ivec4 x, ivec4 y);
+bvec2 equal(bvec2 x, bvec2 y);
+bvec3 equal(bvec3 x, bvec3 y);
+bvec4 equal(bvec4 x, bvec4 y);
+
+bvec2 notEqual( vec2 x, vec2 y);
+bvec3 notEqual( vec3 x, vec3 y);
+bvec4 notEqual( vec4 x, vec4 y);
+bvec2 notEqual(ivec2 x, ivec2 y);
+bvec3 notEqual(ivec3 x, ivec3 y);
+bvec4 notEqual(ivec4 x, ivec4 y);
+bvec2 notEqual(bvec2 x, bvec2 y);
+bvec3 notEqual(bvec3 x, bvec3 y);
+bvec4 notEqual(bvec4 x, bvec4 y);
+
+bool any(bvec2 x);
+bool any(bvec3 x);
+bool any(bvec4 x);
+
+bool all(bvec2 x);
+bool all(bvec3 x);
+bool all(bvec4 x);
+
+bvec2 not(bvec2 x);
+bvec3 not(bvec3 x);
+bvec4 not(bvec4 x);
+
+/*
+ * 8.7 - Texture Lookup Functions
+ */
+vec4 texture1D (sampler1D sampler, float coord);
+vec4 texture1DProj (sampler1D sampler, vec2 coord);
+vec4 texture1DProj (sampler1D sampler, vec4 coord);
+vec4 texture1D (sampler1D sampler, float coord, float bias);
+vec4 texture1DProj (sampler1D sampler, vec2 coord, float bias);
+vec4 texture1DProj (sampler1D sampler, vec4 coord, float bias);
+
+vec4 texture2D (sampler2D sampler, vec2 coord);
+vec4 texture2DProj (sampler2D sampler, vec3 coord);
+vec4 texture2DProj (sampler2D sampler, vec4 coord);
+vec4 texture2D (sampler2D sampler, vec2 coord, float bias);
+vec4 texture2DProj (sampler2D sampler, vec3 coord, float bias);
+vec4 texture2DProj (sampler2D sampler, vec4 coord, float bias);
+
+vec4 texture3D (sampler3D sampler, vec3 coord);
+vec4 texture3DProj (sampler3D sampler, vec4 coord);
+vec4 texture3D (sampler3D sampler, vec3 coord, float bias);
+vec4 texture3DProj (sampler3D sampler, vec4 coord, float bias);
+
+vec4 textureCube (samplerCube sampler, vec3 coord);
+vec4 textureCube (samplerCube sampler, vec3 coord, float bias);
+
+vec4 shadow1D (sampler1DShadow sampler, vec3 coord);
+vec4 shadow2D (sampler2DShadow sampler, vec3 coord);
+vec4 shadow1DProj (sampler1DShadow sampler, vec4 coord);
+vec4 shadow2DProj (sampler2DShadow sampler, vec4 coord);
+vec4 shadow1D (sampler1DShadow sampler, vec3 coord, float bias);
+vec4 shadow2D (sampler2DShadow sampler, vec3 coord, float bias);
+vec4 shadow1DProj (sampler1DShadow sampler, vec4 coord, float bias);
+vec4 shadow2DProj (sampler2DShadow sampler, vec4 coord, float bias);
+
+
+/*
+ * 8.8 - Fragment Processing Functions
+ */
+float dFdx(float p);
+vec2 dFdx(vec2 p);
+vec3 dFdx(vec3 p);
+vec4 dFdx(vec4 p);
+
+float dFdy(float p);
+vec2 dFdy(vec2 p);
+vec3 dFdy(vec3 p);
+vec4 dFdy(vec4 p);
+
+float fwidth(float p);
+vec2 fwidth(vec2 p);
+vec3 fwidth(vec3 p);
+vec4 fwidth(vec4 p);
+
+/*
+ * 8.9 - Noise Functions
+ */
+float noise1(float x);
+float noise1(vec2 x);
+float noise1(vec3 x);
+float noise1(vec4 x);
+
+vec2 noise2(float x);
+vec2 noise2(vec2 x);
+vec2 noise2(vec3 x);
+vec2 noise2(vec4 x);
+
+vec3 noise3(float x);
+vec3 noise3(vec2 x);
+vec3 noise3(vec3 x);
+vec3 noise3(vec4 x);
+
+vec4 noise4(float x);
+vec4 noise4(vec2 x);
+vec4 noise4(vec3 x);
+vec4 noise4(vec4 x);
diff --git a/src/glsl/builtins/profiles/120.vert b/src/glsl/builtins/profiles/120.vert
new file mode 100644
index 00000000000..e14c931647f
--- /dev/null
+++ b/src/glsl/builtins/profiles/120.vert
@@ -0,0 +1,383 @@
+#version 120
+/*
+ * 8.1 - Angle and Trigonometry Functions
+ */
+float radians(float degrees);
+vec2 radians(vec2 degrees);
+vec3 radians(vec3 degrees);
+vec4 radians(vec4 degrees);
+
+float degrees(float radians);
+vec2 degrees(vec2 radians);
+vec3 degrees(vec3 radians);
+vec4 degrees(vec4 radians);
+
+float sin(float angle);
+vec2 sin(vec2 angle);
+vec3 sin(vec3 angle);
+vec4 sin(vec4 angle);
+
+float cos(float angle);
+vec2 cos(vec2 angle);
+vec3 cos(vec3 angle);
+vec4 cos(vec4 angle);
+
+float tan(float angle);
+vec2 tan(vec2 angle);
+vec3 tan(vec3 angle);
+vec4 tan(vec4 angle);
+
+float asin(float angle);
+vec2 asin(vec2 angle);
+vec3 asin(vec3 angle);
+vec4 asin(vec4 angle);
+
+float acos(float angle);
+vec2 acos(vec2 angle);
+vec3 acos(vec3 angle);
+vec4 acos(vec4 angle);
+
+float atan(float y, float x);
+vec2 atan(vec2 y, vec2 x);
+vec3 atan(vec3 y, vec3 x);
+vec4 atan(vec4 y, vec4 x);
+
+float atan(float y_over_x);
+vec2 atan(vec2 y_over_x);
+vec3 atan(vec3 y_over_x);
+vec4 atan(vec4 y_over_x);
+
+/*
+ * 8.2 - Exponential Functions
+ */
+float pow(float x, float y);
+vec2 pow(vec2 x, vec2 y);
+vec3 pow(vec3 x, vec3 y);
+vec4 pow(vec4 x, vec4 y);
+
+float exp(float x);
+vec2 exp(vec2 x);
+vec3 exp(vec3 x);
+vec4 exp(vec4 x);
+
+float log(float x);
+vec2 log(vec2 x);
+vec3 log(vec3 x);
+vec4 log(vec4 x);
+
+float exp2(float x);
+vec2 exp2(vec2 x);
+vec3 exp2(vec3 x);
+vec4 exp2(vec4 x);
+
+float log2(float x);
+vec2 log2(vec2 x);
+vec3 log2(vec3 x);
+vec4 log2(vec4 x);
+
+float sqrt(float x);
+vec2 sqrt(vec2 x);
+vec3 sqrt(vec3 x);
+vec4 sqrt(vec4 x);
+
+float inversesqrt(float x);
+vec2 inversesqrt(vec2 x);
+vec3 inversesqrt(vec3 x);
+vec4 inversesqrt(vec4 x);
+
+/*
+ * 8.3 - Common Functions
+ */
+float abs(float x);
+vec2 abs(vec2 x);
+vec3 abs(vec3 x);
+vec4 abs(vec4 x);
+
+float sign(float x);
+vec2 sign(vec2 x);
+vec3 sign(vec3 x);
+vec4 sign(vec4 x);
+
+float floor(float x);
+vec2 floor(vec2 x);
+vec3 floor(vec3 x);
+vec4 floor(vec4 x);
+
+float ceil(float x);
+vec2 ceil(vec2 x);
+vec3 ceil(vec3 x);
+vec4 ceil(vec4 x);
+
+float fract(float x);
+vec2 fract(vec2 x);
+vec3 fract(vec3 x);
+vec4 fract(vec4 x);
+
+float mod(float x, float y);
+vec2 mod(vec2 x, float y);
+vec3 mod(vec3 x, float y);
+vec4 mod(vec4 x, float y);
+
+vec2 mod(vec2 x, vec2 y);
+vec3 mod(vec3 x, vec3 y);
+vec4 mod(vec4 x, vec4 y);
+
+float min(float x, float y);
+vec2 min(vec2 x, vec2 y);
+vec3 min(vec3 x, vec3 y);
+vec4 min(vec4 x, vec4 y);
+
+vec2 min(vec2 x, float y);
+vec3 min(vec3 x, float y);
+vec4 min(vec4 x, float y);
+
+float max(float x, float y);
+vec2 max(vec2 x, vec2 y);
+vec3 max(vec3 x, vec3 y);
+vec4 max(vec4 x, vec4 y);
+
+vec2 max(vec2 x, float y);
+vec3 max(vec3 x, float y);
+vec4 max(vec4 x, float y);
+
+float clamp(float x, float minVal, float maxVal);
+vec2 clamp(vec2 x, vec2 minVal, vec2 maxVal);
+vec3 clamp(vec3 x, vec3 minVal, vec3 maxVal);
+vec4 clamp(vec4 x, vec4 minVal, vec4 maxVal);
+
+vec2 clamp(vec2 x, float minVal, float maxVal);
+vec3 clamp(vec3 x, float minVal, float maxVal);
+vec4 clamp(vec4 x, float minVal, float maxVal);
+
+float mix(float x, float y, float a);
+vec2 mix(vec2 x, vec2 y, vec2 a);
+vec3 mix(vec3 x, vec3 y, vec3 a);
+vec4 mix(vec4 x, vec4 y, vec4 a);
+
+vec2 mix(vec2 x, vec2 y, float a);
+vec3 mix(vec3 x, vec3 y, float a);
+vec4 mix(vec4 x, vec4 y, float a);
+
+float step(float edge, float x);
+vec2 step(vec2 edge, vec2 x);
+vec3 step(vec3 edge, vec3 x);
+vec4 step(vec4 edge, vec4 x);
+
+vec2 step(float edge, vec2 x);
+vec3 step(float edge, vec3 x);
+vec4 step(float edge, vec4 x);
+
+float smoothstep(float edge0, float edge1, float x);
+vec2 smoothstep(vec2 edge0, vec2 edge1, vec2 x);
+vec3 smoothstep(vec3 edge0, vec3 edge1, vec3 x);
+vec4 smoothstep(vec4 edge0, vec4 edge1, vec4 x);
+
+vec2 smoothstep(float edge0, float edge1, vec2 x);
+vec3 smoothstep(float edge0, float edge1, vec3 x);
+vec4 smoothstep(float edge0, float edge1, vec4 x);
+
+/*
+ * 8.4 - Geometric Functions
+ */
+float length(float x);
+float length(vec2 x);
+float length(vec3 x);
+float length(vec4 x);
+
+float distance(float p0, float p1);
+float distance(vec2 p0, vec2 p1);
+float distance(vec3 p0, vec3 p1);
+float distance(vec4 p0, vec4 p1);
+
+float dot(float x, float y);
+float dot(vec2 x, vec2 y);
+float dot(vec3 x, vec3 y);
+float dot(vec4 x, vec4 y);
+
+vec3 cross(vec3 x, vec3 y);
+
+float normalize(float x);
+vec2 normalize(vec2 x);
+vec3 normalize(vec3 x);
+vec4 normalize(vec4 x);
+
+vec4 ftransform();
+
+float faceforward(float N, float I, float Nref);
+vec2 faceforward(vec2 N, vec2 I, vec2 Nref);
+vec3 faceforward(vec3 N, vec3 I, vec3 Nref);
+vec4 faceforward(vec4 N, vec4 I, vec4 Nref);
+
+float reflect(float I, float N);
+vec2 reflect(vec2 I, vec2 N);
+vec3 reflect(vec3 I, vec3 N);
+vec4 reflect(vec4 I, vec4 N);
+
+float refract(float I, float N, float eta);
+vec2 refract(vec2 I, vec2 N, float eta);
+vec3 refract(vec3 I, vec3 N, float eta);
+vec4 refract(vec4 I, vec4 N, float eta);
+
+
+/*
+ * 8.5 - Matrix Functions
+ */
+mat2 matrixCompMult(mat2 x, mat2 y);
+mat3 matrixCompMult(mat3 x, mat3 y);
+mat4 matrixCompMult(mat4 x, mat4 y);
+mat2x3 matrixCompMult(mat2x3 x, mat2x3 y);
+mat2x4 matrixCompMult(mat2x4 x, mat2x4 y);
+mat3x2 matrixCompMult(mat3x2 x, mat3x2 y);
+mat3x4 matrixCompMult(mat3x4 x, mat3x4 y);
+mat4x2 matrixCompMult(mat4x2 x, mat4x2 y);
+mat4x3 matrixCompMult(mat4x3 x, mat4x3 y);
+
+mat2 outerProduct(vec2 c, vec2 r);
+mat3 outerProduct(vec3 c, vec3 r);
+mat4 outerProduct(vec4 c, vec4 r);
+
+mat2x3 outerProduct(vec3 c, vec2 r);
+mat3x2 outerProduct(vec2 c, vec3 r);
+
+mat2x4 outerProduct(vec4 c, vec2 r);
+mat4x2 outerProduct(vec2 c, vec4 r);
+
+mat3x4 outerProduct(vec4 c, vec3 r);
+mat4x3 outerProduct(vec3 c, vec4 r);
+
+mat2 transpose(mat2 m);
+mat3 transpose(mat3 m);
+mat4 transpose(mat4 m);
+
+mat2x3 transpose(mat3x2 m);
+mat3x2 transpose(mat2x3 m);
+
+mat2x4 transpose(mat4x2 m);
+mat4x2 transpose(mat2x4 m);
+
+mat3x4 transpose(mat4x3 m);
+mat4x3 transpose(mat3x4 m);
+
+/*
+ * 8.6 - Vector Relational Functions
+ */
+bvec2 lessThan( vec2 x, vec2 y);
+bvec3 lessThan( vec3 x, vec3 y);
+bvec4 lessThan( vec4 x, vec4 y);
+bvec2 lessThan(ivec2 x, ivec2 y);
+bvec3 lessThan(ivec3 x, ivec3 y);
+bvec4 lessThan(ivec4 x, ivec4 y);
+
+bvec2 lessThanEqual( vec2 x, vec2 y);
+bvec3 lessThanEqual( vec3 x, vec3 y);
+bvec4 lessThanEqual( vec4 x, vec4 y);
+bvec2 lessThanEqual(ivec2 x, ivec2 y);
+bvec3 lessThanEqual(ivec3 x, ivec3 y);
+bvec4 lessThanEqual(ivec4 x, ivec4 y);
+
+bvec2 greaterThan( vec2 x, vec2 y);
+bvec3 greaterThan( vec3 x, vec3 y);
+bvec4 greaterThan( vec4 x, vec4 y);
+bvec2 greaterThan(ivec2 x, ivec2 y);
+bvec3 greaterThan(ivec3 x, ivec3 y);
+bvec4 greaterThan(ivec4 x, ivec4 y);
+
+bvec2 greaterThanEqual( vec2 x, vec2 y);
+bvec3 greaterThanEqual( vec3 x, vec3 y);
+bvec4 greaterThanEqual( vec4 x, vec4 y);
+bvec2 greaterThanEqual(ivec2 x, ivec2 y);
+bvec3 greaterThanEqual(ivec3 x, ivec3 y);
+bvec4 greaterThanEqual(ivec4 x, ivec4 y);
+
+bvec2 equal( vec2 x, vec2 y);
+bvec3 equal( vec3 x, vec3 y);
+bvec4 equal( vec4 x, vec4 y);
+bvec2 equal(ivec2 x, ivec2 y);
+bvec3 equal(ivec3 x, ivec3 y);
+bvec4 equal(ivec4 x, ivec4 y);
+bvec2 equal(bvec2 x, bvec2 y);
+bvec3 equal(bvec3 x, bvec3 y);
+bvec4 equal(bvec4 x, bvec4 y);
+
+bvec2 notEqual( vec2 x, vec2 y);
+bvec3 notEqual( vec3 x, vec3 y);
+bvec4 notEqual( vec4 x, vec4 y);
+bvec2 notEqual(ivec2 x, ivec2 y);
+bvec3 notEqual(ivec3 x, ivec3 y);
+bvec4 notEqual(ivec4 x, ivec4 y);
+bvec2 notEqual(bvec2 x, bvec2 y);
+bvec3 notEqual(bvec3 x, bvec3 y);
+bvec4 notEqual(bvec4 x, bvec4 y);
+
+bool any(bvec2 x);
+bool any(bvec3 x);
+bool any(bvec4 x);
+
+bool all(bvec2 x);
+bool all(bvec3 x);
+bool all(bvec4 x);
+
+bvec2 not(bvec2 x);
+bvec3 not(bvec3 x);
+bvec4 not(bvec4 x);
+
+/*
+ * 8.7 - Texture Lookup Functions
+ */
+vec4 texture1D (sampler1D sampler, float coord);
+vec4 texture1DProj (sampler1D sampler, vec2 coord);
+vec4 texture1DProj (sampler1D sampler, vec4 coord);
+vec4 texture1DLod (sampler1D sampler, float coord, float lod);
+vec4 texture1DProjLod(sampler1D sampler, vec2 coord, float lod);
+vec4 texture1DProjLod(sampler1D sampler, vec4 coord, float lod);
+
+vec4 texture2D (sampler2D sampler, vec2 coord);
+vec4 texture2DProj (sampler2D sampler, vec3 coord);
+vec4 texture2DProj (sampler2D sampler, vec4 coord);
+vec4 texture2DLod (sampler2D sampler, vec2 coord, float lod);
+vec4 texture2DProjLod(sampler2D sampler, vec3 coord, float lod);
+vec4 texture2DProjLod(sampler2D sampler, vec4 coord, float lod);
+
+vec4 texture3D (sampler3D sampler, vec3 coord);
+vec4 texture3DProj (sampler3D sampler, vec4 coord);
+vec4 texture3DLod (sampler3D sampler, vec3 coord, float lod);
+vec4 texture3DProjLod(sampler3D sampler, vec4 coord, float lod);
+
+vec4 textureCube (samplerCube sampler, vec3 coord);
+vec4 textureCubeLod (samplerCube sampler, vec3 coord, float lod);
+
+vec4 shadow1D (sampler1DShadow sampler, vec3 coord);
+vec4 shadow2D (sampler2DShadow sampler, vec3 coord);
+vec4 shadow1DProj (sampler1DShadow sampler, vec4 coord);
+vec4 shadow2DProj (sampler2DShadow sampler, vec4 coord);
+vec4 shadow1DLod (sampler1DShadow sampler, vec3 coord, float lod);
+vec4 shadow2DLod (sampler2DShadow sampler, vec3 coord, float lod);
+vec4 shadow1DProjLod(sampler1DShadow sampler, vec4 coord, float lod);
+vec4 shadow2DProjLod(sampler2DShadow sampler, vec4 coord, float lod);
+
+/*
+ * 8.8 - Fragment Processing Functions (none in vertex shader)
+ */
+
+/*
+ * 8.9 - Noise Functions
+ */
+float noise1(float x);
+float noise1(vec2 x);
+float noise1(vec3 x);
+float noise1(vec4 x);
+
+vec2 noise2(float x);
+vec2 noise2(vec2 x);
+vec2 noise2(vec3 x);
+vec2 noise2(vec4 x);
+
+vec3 noise3(float x);
+vec3 noise3(vec2 x);
+vec3 noise3(vec3 x);
+vec3 noise3(vec4 x);
+
+vec4 noise4(float x);
+vec4 noise4(vec2 x);
+vec4 noise4(vec3 x);
+vec4 noise4(vec4 x);
diff --git a/src/glsl/builtins/profiles/ARB_texture_rectangle.frag b/src/glsl/builtins/profiles/ARB_texture_rectangle.frag
new file mode 100644
index 00000000000..8938aa3e97c
--- /dev/null
+++ b/src/glsl/builtins/profiles/ARB_texture_rectangle.frag
@@ -0,0 +1,7 @@
+#extension GL_ARB_texture_rectangle : enable
+vec4 texture2DRect(sampler2DRect sampler, vec2 coord);
+vec4 texture2DRectProj(sampler2DRect sampler, vec3 coord);
+vec4 texture2DRectProj(sampler2DRect sampler, vec4 coord);
+
+vec4 shadow2DRect(sampler2DRectShadow sampler, vec3 coord);
+vec4 shadow2DRectProj(sampler2DRectShadow sampler, vec4 coord);
diff --git a/src/glsl/builtins/profiles/ARB_texture_rectangle.vert b/src/glsl/builtins/profiles/ARB_texture_rectangle.vert
new file mode 100644
index 00000000000..8938aa3e97c
--- /dev/null
+++ b/src/glsl/builtins/profiles/ARB_texture_rectangle.vert
@@ -0,0 +1,7 @@
+#extension GL_ARB_texture_rectangle : enable
+vec4 texture2DRect(sampler2DRect sampler, vec2 coord);
+vec4 texture2DRectProj(sampler2DRect sampler, vec3 coord);
+vec4 texture2DRectProj(sampler2DRect sampler, vec4 coord);
+
+vec4 shadow2DRect(sampler2DRectShadow sampler, vec3 coord);
+vec4 shadow2DRectProj(sampler2DRectShadow sampler, vec4 coord);
diff --git a/src/glsl/builtins/profiles/EXT_texture_array.frag b/src/glsl/builtins/profiles/EXT_texture_array.frag
new file mode 100644
index 00000000000..d133132191b
--- /dev/null
+++ b/src/glsl/builtins/profiles/EXT_texture_array.frag
@@ -0,0 +1,11 @@
+#extension GL_EXT_texture_array : enable
+vec4 texture1DArray(sampler1DArray sampler, vec2 coord);
+vec4 texture1DArray(sampler1DArray sampler, vec2 coord, float bias);
+
+vec4 texture2DArray(sampler1DArray sampler, vec2 coord);
+vec4 texture2DArray(sampler1DArray sampler, vec2 coord, float bias);
+
+vec4 shadow1DArray(sampler1DArrayShadow sampler, vec3 coord);
+vec4 shadow1DArray(sampler1DArrayShadow sampler, vec3 coord, float bias);
+
+vec4 shadow2DArray(sampler2DArrayShadow sampler, vec4 coord);
diff --git a/src/glsl/builtins/profiles/EXT_texture_array.vert b/src/glsl/builtins/profiles/EXT_texture_array.vert
new file mode 100644
index 00000000000..4f7b2b5f8b1
--- /dev/null
+++ b/src/glsl/builtins/profiles/EXT_texture_array.vert
@@ -0,0 +1,11 @@
+#extension GL_EXT_texture_array : enable
+vec4 texture1DArray(sampler1DArray sampler, vec2 coord);
+vec4 texture1DArrayLod(sampler1DArray sampler, vec2 coord, float lod);
+
+vec4 texture2DArray(sampler1DArray sampler, vec2 coord);
+vec4 texture2DArrayLod(sampler1DArray sampler, vec2 coord, float lod);
+
+vec4 shadow1DArray(sampler1DArrayShadow sampler, vec3 coord);
+vec4 shadow1DArrayLod(sampler1DArrayShadow sampler, vec3 coord, float lod);
+
+vec4 shadow2DArray(sampler2DArrayShadow sampler, vec4 coord);
diff --git a/src/glsl/builtins/tools/builtin_function.cpp b/src/glsl/builtins/tools/builtin_function.cpp
new file mode 100644
index 00000000000..c44804f2ef7
--- /dev/null
+++ b/src/glsl/builtins/tools/builtin_function.cpp
@@ -0,0 +1,39 @@
+/*
+ * Copyright © 2010 Intel Corporation
+ *
+ * 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 (including the next
+ * paragraph) 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
+ * THE AUTHORS OR COPYRIGHT HOLDERS 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.
+ */
+
+#include <stdio.h>
+#include "glsl_parser_extras.h"
+
+/* A dummy file. When compiling prototypes, we don't care about builtins.
+ * We really don't want to half-compile builtin_functions.cpp and fail, though.
+ */
+void
+_mesa_glsl_release_functions(void)
+{
+}
+
+void
+_mesa_glsl_initialize_functions(exec_list *instructions,
+ struct _mesa_glsl_parse_state *state)
+{
+}
diff --git a/src/glsl/builtins/tools/generate_builtins.py b/src/glsl/builtins/tools/generate_builtins.py
new file mode 100755
index 00000000000..2eb67e398a6
--- /dev/null
+++ b/src/glsl/builtins/tools/generate_builtins.py
@@ -0,0 +1,207 @@
+#!/usr/bin/python
+# -*- coding: UTF-8 -*-
+
+import re, glob, sys
+from os import path
+from subprocess import Popen, PIPE
+
+# Local module: generator for texture lookup builtins
+from texture_builtins import generate_texture_functions
+
+builtins_dir = path.join(path.dirname(path.abspath(__file__)), "..")
+
+# Read the files in builtins/ir/*...add them to the supplied dictionary.
+def read_ir_files(fs):
+ for filename in glob.glob(path.join(path.join(builtins_dir, 'ir'), '*')):
+ with open(filename) as f:
+ fs[path.basename(filename)] = f.read()
+
+# Return a dictionary containing all builtin definitions (even generated)
+def get_builtin_definitions():
+ fs = {}
+ generate_texture_functions(fs)
+ read_ir_files(fs)
+ return fs
+
+def stringify(s):
+ t = s.replace('\\', '\\\\').replace('"', '\\"').replace('\n', '\\n"\n "')
+ return ' "' + t + '"\n'
+
+def write_function_definitions():
+ fs = get_builtin_definitions()
+ for k, v in fs.iteritems():
+ print 'static const char *builtin_' + k + ' ='
+ print stringify(v), ';'
+
+def run_compiler(args):
+ compiler_path = path.join(path.join(builtins_dir, '..'), 'glsl_compiler')
+ command = [compiler_path, '--dump-lir'] + args
+ p = Popen(command, 1, stdout=PIPE, shell=False)
+ output = p.communicate()[0]
+ return (output, p.returncode)
+
+def write_profile(filename, profile):
+ (proto_ir, returncode) = run_compiler([filename])
+
+ if returncode != 0:
+ print '#error builtins profile', profile, 'failed to compile'
+ return
+
+ # Kill any global variable declarations. We don't want them.
+ kill_globals = re.compile(r'^\(declare.*\n', re.MULTILINE);
+ proto_ir = kill_globals.sub('', proto_ir)
+
+ print 'static const char *prototypes_for_' + profile + ' ='
+ print stringify(proto_ir), ';'
+
+ # Print a table of all the functions (not signatures) referenced.
+ # This is done so we can avoid bothering with a hash table in the C++ code.
+
+ function_names = set()
+ for func in re.finditer(r'\(function (.+)\n', proto_ir):
+ function_names.add(func.group(1))
+
+ print 'static const char *functions_for_' + profile + ' [] = {'
+ for func in function_names:
+ print ' builtin_' + func + ','
+ print '};'
+
+def write_profiles():
+ profiles = get_profile_list()
+ for (filename, profile) in profiles:
+ write_profile(filename, profile)
+
+def get_profile_list():
+ profiles = []
+ for pfile in glob.glob(path.join(path.join(builtins_dir, 'profiles'), '*')):
+ profiles.append((pfile, path.basename(pfile).replace('.', '_')))
+ return profiles
+
+if __name__ == "__main__":
+ print """/* DO NOT MODIFY - automatically generated by generate_builtins.py */
+/*
+ * Copyright © 2010 Intel Corporation
+ *
+ * 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 (including the next
+ * paragraph) 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
+ * THE AUTHORS OR COPYRIGHT HOLDERS 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.
+ */
+
+#include <stdio.h>
+#include "main/compiler.h"
+#include "glsl_parser_extras.h"
+#include "ir_reader.h"
+#include "program.h"
+#include "ast.h"
+
+extern "C" struct gl_shader *
+_mesa_new_shader(GLcontext *ctx, GLuint name, GLenum type);
+
+gl_shader *
+read_builtins(GLenum target, const char *protos, const char **functions, unsigned count)
+{
+ gl_shader *sh = _mesa_new_shader(NULL, 0, target);
+ struct _mesa_glsl_parse_state *st =
+ new(sh) _mesa_glsl_parse_state(NULL, target, sh);
+
+ st->language_version = 130;
+ st->ARB_texture_rectangle_enable = true;
+ st->EXT_texture_array_enable = true;
+ _mesa_glsl_initialize_types(st);
+
+ sh->ir = new(sh) exec_list;
+ sh->symbols = st->symbols;
+
+ /* Read the IR containing the prototypes */
+ _mesa_glsl_read_ir(st, sh->ir, protos, true);
+
+ /* Read ALL the function bodies, telling the IR reader not to scan for
+ * prototypes (we've already created them). The IR reader will skip any
+ * signature that does not already exist as a prototype.
+ */
+ for (unsigned i = 0; i < count; i++) {
+ _mesa_glsl_read_ir(st, sh->ir, functions[i], false);
+
+ if (st->error) {
+ printf("error reading builtin: %.35s ...\\n", functions[i]);
+ talloc_free(sh);
+ return NULL;
+ }
+ }
+
+ reparent_ir(sh->ir, sh);
+ delete st;
+
+ return sh;
+}
+"""
+
+ write_function_definitions()
+ write_profiles()
+
+ print """
+void *builtin_mem_ctx = NULL;
+
+void
+_mesa_glsl_release_functions(void)
+{
+ talloc_free(builtin_mem_ctx);
+}
+
+void
+_mesa_glsl_initialize_functions(exec_list *instructions,
+ struct _mesa_glsl_parse_state *state)
+{
+ if (builtin_mem_ctx == NULL)
+ builtin_mem_ctx = talloc_init("GLSL built-in functions");
+
+ state->num_builtins_to_link = 0;
+"""
+
+ profiles = get_profile_list()
+ for (filename, profile) in profiles:
+ if profile.endswith('_vert'):
+ check = 'state->target == vertex_shader && '
+ elif profile.endswith('_frag'):
+ check = 'state->target == fragment_shader && '
+
+ version = re.sub(r'_(vert|frag)$', '', profile)
+ if version.isdigit():
+ check += 'state->language_version == ' + version
+ else: # an extension name
+ check += 'state->' + version + '_enable'
+
+ print ' if (' + check + ') {'
+ print ' static gl_shader *sh = NULL;'
+ print ' if (sh == NULL) {'
+ print ' sh = read_builtins(GL_VERTEX_SHADER,'
+ print ' prototypes_for_' + profile + ','
+ print ' functions_for_' + profile + ','
+ print ' Elements(functions_for_' + profile,
+ print '));'
+ print ' talloc_steal(builtin_mem_ctx, sh);'
+ print ' }'
+ print
+ print ' import_prototypes(sh->ir, instructions, state->symbols,'
+ print ' state);'
+ print ' state->builtins_to_link[state->num_builtins_to_link] = sh;'
+ print ' state->num_builtins_to_link++;'
+ print ' }'
+ print
+ print '}'
+
diff --git a/src/glsl/builtins/tools/generate_matrixCompMultGLSL.py b/src/glsl/builtins/tools/generate_matrixCompMultGLSL.py
new file mode 100755
index 00000000000..391ad110d37
--- /dev/null
+++ b/src/glsl/builtins/tools/generate_matrixCompMultGLSL.py
@@ -0,0 +1,28 @@
+#!/usr/bin/python
+
+def gen_matrix(x, y = 0):
+ if y == 0:
+ y = x
+ type = "mat" + str(x)
+ if x != y:
+ type = type + "x" + str(y)
+ print type + " matrixCompMult(" + type + " x, " + type + " y)\n{"
+ print " " + type + " z;"
+
+ for i in range(x):
+ print " z[" + str(i) + "] = x[" + str(i) + "] * y[" + str(i) + "];"
+ print " return z;\n}"
+
+print "#version 120"
+# 1.10
+gen_matrix(2)
+gen_matrix(3)
+gen_matrix(4)
+
+# 1.20
+gen_matrix(2,3) # mat2x3 means 2 columns, 3 rows
+gen_matrix(3,2)
+gen_matrix(2,4)
+gen_matrix(4,2)
+gen_matrix(3,4)
+gen_matrix(4,3)
diff --git a/src/glsl/builtins/tools/generate_outerProductGLSL.py b/src/glsl/builtins/tools/generate_outerProductGLSL.py
new file mode 100755
index 00000000000..c561cc3ba14
--- /dev/null
+++ b/src/glsl/builtins/tools/generate_outerProductGLSL.py
@@ -0,0 +1,23 @@
+#!/usr/bin/python
+
+def gen(x, y):
+ type = "mat" + str(x)
+ if x != y:
+ type = type + "x" + str(y)
+ print type + " outerProduct(vec" + str(y) + " u, vec" + str(x) + " v)\n{"
+ print " " + type + " m;"
+
+ for i in range(x):
+ print " m[" + str(i) + "] = u * v[" + str(i) + "];"
+ print " return m;\n}"
+
+print "#version 120"
+gen(2,2)
+gen(2,3) # mat2x3 means 2 columns, 3 rows
+gen(2,4)
+gen(3,2)
+gen(3,3)
+gen(3,4)
+gen(4,2)
+gen(4,3)
+gen(4,4)
diff --git a/src/glsl/builtins/tools/generate_transposeGLSL.py b/src/glsl/builtins/tools/generate_transposeGLSL.py
new file mode 100755
index 00000000000..8f669ce9839
--- /dev/null
+++ b/src/glsl/builtins/tools/generate_transposeGLSL.py
@@ -0,0 +1,28 @@
+#!/usr/bin/python
+
+def gen(x, y):
+ origtype = "mat" + str(x)
+ trantype = "mat" + str(y)
+ if x != y:
+ origtype = origtype + "x" + str(y)
+ trantype = trantype + "x" + str(x)
+ print trantype + " transpose(" + origtype + " m)\n{"
+ print " " + trantype + " t;"
+
+ # The obvious implementation of transpose
+ for i in range(x):
+ for j in range(y):
+ print " t[" + str(j) + "][" + str(i) + "] =",
+ print "m[" + str(i) + "][" + str(j) + "];"
+ print " return t;\n}"
+
+print "#version 120"
+gen(2,2)
+gen(2,3) # mat2x3 means 2 columns, 3 rows
+gen(2,4)
+gen(3,2)
+gen(3,3)
+gen(3,4)
+gen(4,2)
+gen(4,3)
+gen(4,4)
diff --git a/src/glsl/builtins/tools/texture_builtins.py b/src/glsl/builtins/tools/texture_builtins.py
new file mode 100755
index 00000000000..8bf708b5aac
--- /dev/null
+++ b/src/glsl/builtins/tools/texture_builtins.py
@@ -0,0 +1,349 @@
+#!/usr/bin/python
+
+import sys
+import StringIO
+
+def vec_type(g, size):
+ if size == 1:
+ if g == "i":
+ return "int"
+ elif g == "u":
+ return "uint"
+ return "float"
+ return g + "vec" + str(size)
+
+# Get the base dimension - i.e. sampler3D gives 3
+# Array samplers also get +1 here since the layer is really an extra coordinate
+def get_coord_dim(sampler_type):
+ if sampler_type[0].isdigit():
+ coord_dim = int(sampler_type[0])
+ elif sampler_type.startswith("Cube"):
+ coord_dim = 3
+ else:
+ assert False ("coord_dim: invalid sampler_type: " + sampler_type)
+
+ if sampler_type.find("Array") != -1:
+ coord_dim += 1
+ return coord_dim
+
+# Get the number of extra vector components (i.e. shadow comparitor)
+def get_extra_dim(sampler_type, use_proj, unused_fields):
+ extra_dim = unused_fields
+ if sampler_type.find("Shadow") != -1:
+ extra_dim += 1
+ if use_proj:
+ extra_dim += 1
+ return extra_dim
+
+def generate_sigs(g, tex_inst, sampler_type, use_proj = False, unused_fields = 0):
+ coord_dim = get_coord_dim(sampler_type)
+ extra_dim = get_extra_dim(sampler_type, use_proj, unused_fields)
+
+ # Print parameters
+ print " (signature " + g + "vec4"
+ print " (parameters"
+ print " (declare (in) " + g + "sampler" + sampler_type + " sampler)"
+ print " (declare (in) " + vec_type("i" if tex_inst == "txf" else "", coord_dim + extra_dim) + " P)",
+ if tex_inst == "txb":
+ print "\n (declare (in) float bias)",
+ elif tex_inst == "txl":
+ print "\n (declare (in) float lod)",
+ elif tex_inst == "txf":
+ print "\n (declare (in) int lod)",
+ elif tex_inst == "txd":
+ grad_type = vec_type("", coord_dim)
+ print "\n (declare (in) " + grad_type + " dPdx)",
+ print "\n (declare (in) " + grad_type + " dPdy)",
+
+ print ")\n ((return (" + tex_inst + " (var_ref sampler)",
+
+ # Coordinate
+ if extra_dim > 0:
+ print "(swiz " + "xyzw"[:coord_dim] + " (var_ref P))",
+ else:
+ print "(var_ref P)",
+
+ # Offset
+ print "(0 0 0)",
+
+ if tex_inst != "txf":
+ # Projective divisor
+ if use_proj:
+ print "(swiz " + "xyzw"[coord_dim + extra_dim-1] + " (var_ref P))",
+ else:
+ print "1",
+
+ # Shadow comparitor
+ if sampler_type == "2DArrayShadow": # a special case:
+ print "(swiz w (var_ref P))", # ...array layer is z; shadow is w
+ elif sampler_type.endswith("Shadow"):
+ print "(swiz z (var_ref P))",
+ else:
+ print "()",
+
+ # Bias/explicit LOD/gradient:
+ if tex_inst == "txb":
+ print "(var_ref bias)",
+ elif tex_inst == "txl" or tex_inst == "txf":
+ print "(var_ref lod)",
+ elif tex_inst == "txd":
+ print "((var_ref dPdx) (var_ref dPdy))",
+ print "))))\n"
+
+def generate_fiu_sigs(tex_inst, sampler_type, use_proj = False, unused_fields = 0):
+ generate_sigs("", tex_inst, sampler_type, use_proj, unused_fields)
+ generate_sigs("i", tex_inst, sampler_type, use_proj, unused_fields)
+ generate_sigs("u", tex_inst, sampler_type, use_proj, unused_fields)
+
+def start_function(name):
+ sys.stdout = StringIO.StringIO()
+ print "((function " + name
+
+def end_function(fs, name):
+ print "))"
+ fs[name] = sys.stdout.getvalue();
+ sys.stdout.close()
+
+# Generate all the functions and store them in the supplied dictionary.
+# This is better than writing them to actual files since they should never be
+# edited; it'd also be easy to confuse them with the many hand-generated files.
+#
+# Takes a dictionary as an argument.
+def generate_texture_functions(fs):
+ start_function("texture")
+ generate_fiu_sigs("tex", "1D")
+ generate_fiu_sigs("tex", "2D")
+ generate_fiu_sigs("tex", "3D")
+ generate_fiu_sigs("tex", "Cube")
+ generate_fiu_sigs("tex", "1DArray")
+ generate_fiu_sigs("tex", "2DArray")
+
+ generate_fiu_sigs("txb", "1D")
+ generate_fiu_sigs("txb", "2D")
+ generate_fiu_sigs("txb", "3D")
+ generate_fiu_sigs("txb", "Cube")
+ generate_fiu_sigs("txb", "1DArray")
+ generate_fiu_sigs("txb", "2DArray")
+ end_function(fs, "texture")
+
+ start_function("textureProj")
+ generate_fiu_sigs("tex", "1D", True)
+ generate_fiu_sigs("tex", "1D", True, 2)
+ generate_fiu_sigs("tex", "2D", True)
+ generate_fiu_sigs("tex", "2D", True, 1)
+ generate_fiu_sigs("tex", "3D", True)
+
+ generate_fiu_sigs("txb", "1D", True)
+ generate_fiu_sigs("txb", "1D", True, 2)
+ generate_fiu_sigs("txb", "2D", True)
+ generate_fiu_sigs("txb", "2D", True, 1)
+ generate_fiu_sigs("txb", "3D", True)
+ end_function(fs, "textureProj")
+
+ start_function("textureLod")
+ generate_fiu_sigs("txl", "1D")
+ generate_fiu_sigs("txl", "2D")
+ generate_fiu_sigs("txl", "3D")
+ generate_fiu_sigs("txl", "Cube")
+ generate_fiu_sigs("txl", "1DArray")
+ generate_fiu_sigs("txl", "2DArray")
+ end_function(fs, "textureLod")
+
+ start_function("texelFetch")
+ generate_fiu_sigs("txf", "1D")
+ generate_fiu_sigs("txf", "2D")
+ generate_fiu_sigs("txf", "3D")
+ generate_fiu_sigs("txf", "1DArray")
+ generate_fiu_sigs("txf", "2DArray")
+ end_function(fs, "texelFetch")
+
+ start_function("textureProjLod")
+ generate_fiu_sigs("txl", "1D", True)
+ generate_fiu_sigs("txl", "1D", True, 2)
+ generate_fiu_sigs("txl", "2D", True)
+ generate_fiu_sigs("txl", "2D", True, 1)
+ generate_fiu_sigs("txl", "3D", True)
+ end_function(fs, "textureProjLod")
+
+ start_function("textureGrad")
+ generate_fiu_sigs("txd", "1D")
+ generate_fiu_sigs("txd", "2D")
+ generate_fiu_sigs("txd", "3D")
+ generate_fiu_sigs("txd", "Cube")
+ generate_fiu_sigs("txd", "1DArray")
+ generate_fiu_sigs("txd", "2DArray")
+ end_function(fs, "textureGrad")
+
+ start_function("textureProjGrad")
+ generate_fiu_sigs("txd", "1D", True)
+ generate_fiu_sigs("txd", "1D", True, 2)
+ generate_fiu_sigs("txd", "2D", True)
+ generate_fiu_sigs("txd", "2D", True, 1)
+ generate_fiu_sigs("txd", "3D", True)
+ end_function(fs, "textureProjGrad")
+
+ # ARB_texture_rectangle extension
+ start_function("texture2DRect")
+ generate_sigs("", "tex", "2DRect")
+ end_function(fs, "texture2DRect")
+
+ start_function("texture2DRectProj")
+ generate_sigs("", "tex", "2DRect", True)
+ generate_sigs("", "tex", "2DRect", True, 1)
+ end_function(fs, "texture2DRectProj")
+
+ start_function("shadow2DRect")
+ generate_sigs("", "tex", "2DRectShadow")
+ end_function(fs, "shadow2DRect")
+
+ start_function("shadow2DRectProj")
+ generate_sigs("", "tex", "2DRectShadow", True)
+ end_function(fs, "shadow2DRectProj")
+
+ # EXT_texture_array extension
+ start_function("texture1DArray")
+ generate_sigs("", "tex", "1DArray")
+ generate_sigs("", "txb", "1DArray")
+ end_function(fs, "texture1DArray")
+
+ start_function("texture1DArrayLod")
+ generate_sigs("", "txl", "1DArray")
+ end_function(fs, "texture1DArrayLod")
+
+ start_function("texture2DArray")
+ generate_sigs("", "tex", "2DArray")
+ generate_sigs("", "txb", "2DArray")
+ end_function(fs, "texture2DArray")
+
+ start_function("texture2DArrayLod")
+ generate_sigs("", "txl", "2DArray")
+ end_function(fs, "texture2DArrayLod")
+
+ start_function("shadow1DArray")
+ generate_sigs("", "tex", "1DArrayShadow")
+ generate_sigs("", "txb", "1DArrayShadow")
+ end_function(fs, "shadow1DArray")
+
+ start_function("shadow1DArrayLod")
+ generate_sigs("", "txl", "1DArrayShadow")
+ end_function(fs, "shadow1DArrayLod")
+
+ start_function("shadow2DArray")
+ generate_sigs("", "tex", "2DArrayShadow")
+ end_function(fs, "shadow2DArray")
+
+ # Deprecated (110/120 style) functions with silly names:
+ start_function("texture1D")
+ generate_sigs("", "tex", "1D")
+ generate_sigs("", "txb", "1D")
+ end_function(fs, "texture1D")
+
+ start_function("texture1DLod")
+ generate_sigs("", "txl", "1D")
+ end_function(fs, "texture1DLod")
+
+ start_function("texture1DProj")
+ generate_sigs("", "tex", "1D", True)
+ generate_sigs("", "tex", "1D", True, 2)
+ generate_sigs("", "txb", "1D", True)
+ generate_sigs("", "txb", "1D", True, 2)
+ end_function(fs, "texture1DProj")
+
+ start_function("texture1DProjLod")
+ generate_sigs("", "txl", "1D", True)
+ generate_sigs("", "txl", "1D", True, 2)
+ end_function(fs, "texture1DProjLod")
+
+ start_function("texture2D")
+ generate_sigs("", "tex", "2D")
+ generate_sigs("", "txb", "2D")
+ end_function(fs, "texture2D")
+
+ start_function("texture2DLod")
+ generate_sigs("", "txl", "2D")
+ end_function(fs, "texture2DLod")
+
+ start_function("texture2DProj")
+ generate_sigs("", "tex", "2D", True)
+ generate_sigs("", "tex", "2D", True, 1)
+ generate_sigs("", "txb", "2D", True)
+ generate_sigs("", "txb", "2D", True, 1)
+ end_function(fs, "texture2DProj")
+
+ start_function("texture2DProjLod")
+ generate_sigs("", "txl", "2D", True)
+ generate_sigs("", "txl", "2D", True, 1)
+ end_function(fs, "texture2DProjLod")
+
+ start_function("texture3D")
+ generate_sigs("", "tex", "3D")
+ generate_sigs("", "txb", "3D")
+ end_function(fs, "texture3D")
+
+ start_function("texture3DLod")
+ generate_sigs("", "txl", "3D")
+ end_function(fs, "texture3DLod")
+
+ start_function("texture3DProj")
+ generate_sigs("", "tex", "3D", True)
+ generate_sigs("", "txb", "3D", True)
+ end_function(fs, "texture3DProj")
+
+ start_function("texture3DProjLod")
+ generate_sigs("", "txl", "3D", True)
+ end_function(fs, "texture3DProjLod")
+
+ start_function("textureCube")
+ generate_sigs("", "tex", "Cube")
+ generate_sigs("", "txb", "Cube")
+ end_function(fs, "textureCube")
+
+ start_function("textureCubeLod")
+ generate_sigs("", "txl", "Cube")
+ end_function(fs, "textureCubeLod")
+
+ start_function("shadow1D")
+ generate_sigs("", "tex", "1DShadow", False, 1)
+ generate_sigs("", "txb", "1DShadow", False, 1)
+ end_function(fs, "shadow1D")
+
+ start_function("shadow1DLod")
+ generate_sigs("", "txl", "1DShadow", False, 1)
+ end_function(fs, "shadow1DLod")
+
+ start_function("shadow1DProj")
+ generate_sigs("", "tex", "1DShadow", True, 1)
+ generate_sigs("", "txb", "1DShadow", True, 1)
+ end_function(fs, "shadow1DProj")
+
+ start_function("shadow1DProjLod")
+ generate_sigs("", "txl", "1DShadow", True, 1)
+ end_function(fs, "shadow1DProjLod")
+
+ start_function("shadow2D")
+ generate_sigs("", "tex", "2DShadow")
+ generate_sigs("", "txb", "2DShadow")
+ end_function(fs, "shadow2D")
+
+ start_function("shadow2DLod")
+ generate_sigs("", "txl", "2DShadow")
+ end_function(fs, "shadow2DLod")
+
+ start_function("shadow2DProj")
+ generate_sigs("", "tex", "2DShadow", True)
+ generate_sigs("", "txb", "2DShadow", True)
+ end_function(fs, "shadow2DProj")
+
+ start_function("shadow2DProjLod")
+ generate_sigs("", "txl", "2DShadow", True)
+ end_function(fs, "shadow2DProjLod")
+
+ sys.stdout = sys.__stdout__
+ return fs
+
+# If you actually run this script, it'll print out all the functions.
+if __name__ == "__main__":
+ fs = {}
+ generate_texture_functions(fs);
+ for k, v in fs.iteritems():
+ print v
diff --git a/src/glsl/configure.ac b/src/glsl/configure.ac
new file mode 100644
index 00000000000..73ce67de3d1
--- /dev/null
+++ b/src/glsl/configure.ac
@@ -0,0 +1,69 @@
+# -*- Autoconf -*-
+# Process this file with autoconf to produce a configure script.
+
+AC_PREREQ(2.61)
+AC_INIT(glsl, XXXXX, [email protected], glsl)
+AC_CONFIG_SRCDIR([Makefile.am])
+AM_CONFIG_HEADER([config.h])
+AC_CONFIG_FILES([glcpp/Makefile])
+
+AM_INIT_AUTOMAKE
+LT_INIT
+
+AM_MAINTAINER_MODE
+
+# Checks for programs.
+AC_PROG_CXX
+AC_PROG_CC
+AC_PROG_MAKE_SET
+AC_PROG_YACC
+AC_PROG_LEX
+
+m4_ifdef([AM_SILENT_RULES], [AM_SILENT_RULES([yes])])
+
+# Checks for libraries.
+
+# Checks for header files.
+
+# Checks for typedefs, structures, and compiler characteristics.
+
+# Checks for library functions.
+AC_HEADER_STDC
+
+AH_TOP([#ifndef GLSL_CONFIG_H
+#define GLSL_CONFIG_H])
+AH_BOTTOM([#endif /* GLSL_CONFIG_H */])
+
+PKG_CHECK_MODULES([talloc], [talloc >= 2.0])
+
+AC_ARG_ENABLE([debug],
+ [AS_HELP_STRING([--enable-debug],
+ [use debug compiler flags and macros @<:@default=disabled@:>@])],
+ [enable_debug="$enableval"],
+ [enable_debug=no]
+)
+if test "x$enable_debug" = xyes; then
+ DEFINES="$DEFINES -DDEBUG"
+ if test "x$GCC" = xyes; then
+ # Remove any -g or -O flags from the command line
+ CFLAGS=[`echo $CFLAGS | sed 's/-g[^ \t]*[ \t]*//g;s/-O[^ \t]*[ \t]*//g'`]
+ CFLAGS="$CFLAGS -O0 -ggdb3 -fstack-protector -D_FORTIFY_SOURCE=2"
+ fi
+ if test "x$GXX" = xyes; then
+ # Remove any -g flags from the command line
+ CXXFLAGS=[`echo $CXXFLAGS | sed 's/-g[^ \t]*[ \t]*//g;s/-O[^ \t]*[ \t]*//g'`]
+ CXXFLAGS="$CXXFLAGS -O0 -ggdb3 -fstack-protector -D_FORTIFY_SOURCE=2"
+ fi
+fi
+
+if test "x$GXX" = xyes ; then
+ WARN="-Wall -Wextra -Wunsafe-loop-optimizations -Wstack-protector"
+else
+ WARN=""
+fi
+
+CFLAGS="$CFLAGS $WARN"
+CXXFLAGS="$CXXFLAGS $WARN"
+YFLAGS="-d -v"
+
+AC_OUTPUT([Makefile])
diff --git a/src/glsl/glcpp/.gitignore b/src/glsl/glcpp/.gitignore
new file mode 100644
index 00000000000..dbc37e1926d
--- /dev/null
+++ b/src/glsl/glcpp/.gitignore
@@ -0,0 +1,8 @@
+glcpp
+glcpp-parse.output
+*.o
+*.lo
+*.la
+.libs
+*~
+tests/*.out
diff --git a/src/glsl/glcpp/Makefile.am b/src/glsl/glcpp/Makefile.am
new file mode 100644
index 00000000000..81147e6e12c
--- /dev/null
+++ b/src/glsl/glcpp/Makefile.am
@@ -0,0 +1,44 @@
+# Copyright © 2010 Intel Corporation
+# 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
+# on the rights to use, copy, modify, merge, publish, distribute, sub
+# license, 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 (including the next
+# paragraph) 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 NON-INFRINGEMENT. IN NO EVENT SHALL
+# AUTHORS, COPYRIGHT HOLDERS, AND/OR THEIR SUPPLIERS 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.
+
+noinst_LTLIBRARIES = libglcpp.la
+libglcpp_la_SOURCES = \
+ glcpp-lex.l \
+ glcpp-parse.y \
+ glcpp.h \
+ pp.c
+
+BUILT_SOURCES = glcpp-parse.h glcpp-parse.c glcpp-lex.c
+CLEANFILES = $(BUILT_SOURCES)
+
+glcpp-parse.h: glcpp-parse.c
+
+bin_PROGRAMS = glcpp
+glcpp_LDADD = libglcpp.la
+glcpp_LDFLAGS = @LDFLAGS@ $(talloc_LIBS)
+glcpp_SOURCES = glcpp.c
+
+.l.c:
+ $(LEXCOMPILE) --outfile="$@" $<
+
+test: glcpp
+ @(cd tests; ./glcpp-test)
diff --git a/src/glsl/glcpp/README b/src/glsl/glcpp/README
new file mode 100644
index 00000000000..ab42a3ffe12
--- /dev/null
+++ b/src/glsl/glcpp/README
@@ -0,0 +1,30 @@
+glcpp -- GLSL "C" preprocessor
+
+This is a simple preprocessor designed to provide the preprocessing
+needs of the GLSL language. The requirements for this preprocessor are
+specified in the GLSL 1.30 specification availble from:
+
+http://www.opengl.org/registry/doc/GLSLangSpec.Full.1.30.08.pdf
+
+This specification is not precise on some semantics, (for example,
+#define and #if), defining these merely "as is standard for C++
+preprocessors". To fill in these details, I've been using the C99
+standard (for which I had a convenient copy) as available from:
+
+http://www.open-std.org/jtc1/sc22/wg14/www/docs/n1124.pdf
+
+Known limitations
+-----------------
+Macro invocations cannot include embedded newlines.
+
+The __LINE__, __FILE__, and __VERSION__ macros are not yet supported.
+
+The argument of the 'defined' operator cannot yet include enclosing
+parentheses.
+
+The #error, #pragma, #extension, #version, and #line macros are not
+yet supported.
+
+A file that ends with a function-like macro name as the last
+non-whitespace token will result in a parse error, (where it should be
+passed through as is). \ No newline at end of file
diff --git a/src/glsl/glcpp/glcpp-lex.c b/src/glsl/glcpp/glcpp-lex.c
new file mode 100644
index 00000000000..6b6aa12d8f7
--- /dev/null
+++ b/src/glsl/glcpp/glcpp-lex.c
@@ -0,0 +1,2640 @@
+#line 2 "glcpp/glcpp-lex.c"
+
+#line 4 "glcpp/glcpp-lex.c"
+
+#define YY_INT_ALIGNED short int
+
+/* A lexical scanner generated by flex */
+
+#define FLEX_SCANNER
+#define YY_FLEX_MAJOR_VERSION 2
+#define YY_FLEX_MINOR_VERSION 5
+#define YY_FLEX_SUBMINOR_VERSION 35
+#if YY_FLEX_SUBMINOR_VERSION > 0
+#define FLEX_BETA
+#endif
+
+/* First, we deal with platform-specific or compiler-specific issues. */
+
+/* begin standard C headers. */
+#include <stdio.h>
+#include <string.h>
+#include <errno.h>
+#include <stdlib.h>
+
+/* end standard C headers. */
+
+/* flex integer type definitions */
+
+#ifndef FLEXINT_H
+#define FLEXINT_H
+
+/* C99 systems have <inttypes.h>. Non-C99 systems may or may not. */
+
+#if defined (__STDC_VERSION__) && __STDC_VERSION__ >= 199901L
+
+/* C99 says to define __STDC_LIMIT_MACROS before including stdint.h,
+ * if you want the limit (max/min) macros for int types.
+ */
+#ifndef __STDC_LIMIT_MACROS
+#define __STDC_LIMIT_MACROS 1
+#endif
+
+#include <inttypes.h>
+typedef int8_t flex_int8_t;
+typedef uint8_t flex_uint8_t;
+typedef int16_t flex_int16_t;
+typedef uint16_t flex_uint16_t;
+typedef int32_t flex_int32_t;
+typedef uint32_t flex_uint32_t;
+#else
+typedef signed char flex_int8_t;
+typedef short int flex_int16_t;
+typedef int flex_int32_t;
+typedef unsigned char flex_uint8_t;
+typedef unsigned short int flex_uint16_t;
+typedef unsigned int flex_uint32_t;
+
+/* Limits of integral types. */
+#ifndef INT8_MIN
+#define INT8_MIN (-128)
+#endif
+#ifndef INT16_MIN
+#define INT16_MIN (-32767-1)
+#endif
+#ifndef INT32_MIN
+#define INT32_MIN (-2147483647-1)
+#endif
+#ifndef INT8_MAX
+#define INT8_MAX (127)
+#endif
+#ifndef INT16_MAX
+#define INT16_MAX (32767)
+#endif
+#ifndef INT32_MAX
+#define INT32_MAX (2147483647)
+#endif
+#ifndef UINT8_MAX
+#define UINT8_MAX (255U)
+#endif
+#ifndef UINT16_MAX
+#define UINT16_MAX (65535U)
+#endif
+#ifndef UINT32_MAX
+#define UINT32_MAX (4294967295U)
+#endif
+
+#endif /* ! C99 */
+
+#endif /* ! FLEXINT_H */
+
+#ifdef __cplusplus
+
+/* The "const" storage-class-modifier is valid. */
+#define YY_USE_CONST
+
+#else /* ! __cplusplus */
+
+/* C99 requires __STDC__ to be defined as 1. */
+#if defined (__STDC__)
+
+#define YY_USE_CONST
+
+#endif /* defined (__STDC__) */
+#endif /* ! __cplusplus */
+
+#ifdef YY_USE_CONST
+#define yyconst const
+#else
+#define yyconst
+#endif
+
+/* Returned upon end-of-file. */
+#define YY_NULL 0
+
+/* Promotes a possibly negative, possibly signed char to an unsigned
+ * integer for use as an array index. If the signed char is negative,
+ * we want to instead treat it as an 8-bit unsigned char, hence the
+ * double cast.
+ */
+#define YY_SC_TO_UI(c) ((unsigned int) (unsigned char) c)
+
+/* An opaque pointer. */
+#ifndef YY_TYPEDEF_YY_SCANNER_T
+#define YY_TYPEDEF_YY_SCANNER_T
+typedef void* yyscan_t;
+#endif
+
+/* For convenience, these vars (plus the bison vars far below)
+ are macros in the reentrant scanner. */
+#define yyin yyg->yyin_r
+#define yyout yyg->yyout_r
+#define yyextra yyg->yyextra_r
+#define yyleng yyg->yyleng_r
+#define yytext yyg->yytext_r
+#define yylineno (YY_CURRENT_BUFFER_LVALUE->yy_bs_lineno)
+#define yycolumn (YY_CURRENT_BUFFER_LVALUE->yy_bs_column)
+#define yy_flex_debug yyg->yy_flex_debug_r
+
+/* Enter a start condition. This macro really ought to take a parameter,
+ * but we do it the disgusting crufty way forced on us by the ()-less
+ * definition of BEGIN.
+ */
+#define BEGIN yyg->yy_start = 1 + 2 *
+
+/* Translate the current start state into a value that can be later handed
+ * to BEGIN to return to the state. The YYSTATE alias is for lex
+ * compatibility.
+ */
+#define YY_START ((yyg->yy_start - 1) / 2)
+#define YYSTATE YY_START
+
+/* Action number for EOF rule of a given start state. */
+#define YY_STATE_EOF(state) (YY_END_OF_BUFFER + state + 1)
+
+/* Special action meaning "start processing a new file". */
+#define YY_NEW_FILE glcpp_restart(yyin ,yyscanner )
+
+#define YY_END_OF_BUFFER_CHAR 0
+
+/* Size of default input buffer. */
+#ifndef YY_BUF_SIZE
+#ifdef __ia64__
+/* On IA-64, the buffer size is 16k, not 8k.
+ * Moreover, YY_BUF_SIZE is 2*YY_READ_BUF_SIZE in the general case.
+ * Ditto for the __ia64__ case accordingly.
+ */
+#define YY_BUF_SIZE 32768
+#else
+#define YY_BUF_SIZE 16384
+#endif /* __ia64__ */
+#endif
+
+/* The state buf must be large enough to hold one state per character in the main buffer.
+ */
+#define YY_STATE_BUF_SIZE ((YY_BUF_SIZE + 2) * sizeof(yy_state_type))
+
+#ifndef YY_TYPEDEF_YY_BUFFER_STATE
+#define YY_TYPEDEF_YY_BUFFER_STATE
+typedef struct yy_buffer_state *YY_BUFFER_STATE;
+#endif
+
+#define EOB_ACT_CONTINUE_SCAN 0
+#define EOB_ACT_END_OF_FILE 1
+#define EOB_ACT_LAST_MATCH 2
+
+ #define YY_LESS_LINENO(n)
+
+/* Return all but the first "n" matched characters back to the input stream. */
+#define yyless(n) \
+ do \
+ { \
+ /* Undo effects of setting up yytext. */ \
+ int yyless_macro_arg = (n); \
+ YY_LESS_LINENO(yyless_macro_arg);\
+ *yy_cp = yyg->yy_hold_char; \
+ YY_RESTORE_YY_MORE_OFFSET \
+ yyg->yy_c_buf_p = yy_cp = yy_bp + yyless_macro_arg - YY_MORE_ADJ; \
+ YY_DO_BEFORE_ACTION; /* set up yytext again */ \
+ } \
+ while ( 0 )
+
+#define unput(c) yyunput( c, yyg->yytext_ptr , yyscanner )
+
+#ifndef YY_TYPEDEF_YY_SIZE_T
+#define YY_TYPEDEF_YY_SIZE_T
+typedef size_t yy_size_t;
+#endif
+
+#ifndef YY_STRUCT_YY_BUFFER_STATE
+#define YY_STRUCT_YY_BUFFER_STATE
+struct yy_buffer_state
+ {
+ FILE *yy_input_file;
+
+ char *yy_ch_buf; /* input buffer */
+ char *yy_buf_pos; /* current position in input buffer */
+
+ /* Size of input buffer in bytes, not including room for EOB
+ * characters.
+ */
+ yy_size_t yy_buf_size;
+
+ /* Number of characters read into yy_ch_buf, not including EOB
+ * characters.
+ */
+ int yy_n_chars;
+
+ /* Whether we "own" the buffer - i.e., we know we created it,
+ * and can realloc() it to grow it, and should free() it to
+ * delete it.
+ */
+ int yy_is_our_buffer;
+
+ /* Whether this is an "interactive" input source; if so, and
+ * if we're using stdio for input, then we want to use getc()
+ * instead of fread(), to make sure we stop fetching input after
+ * each newline.
+ */
+ int yy_is_interactive;
+
+ /* Whether we're considered to be at the beginning of a line.
+ * If so, '^' rules will be active on the next match, otherwise
+ * not.
+ */
+ int yy_at_bol;
+
+ int yy_bs_lineno; /**< The line count. */
+ int yy_bs_column; /**< The column count. */
+
+ /* Whether to try to fill the input buffer when we reach the
+ * end of it.
+ */
+ int yy_fill_buffer;
+
+ int yy_buffer_status;
+
+#define YY_BUFFER_NEW 0
+#define YY_BUFFER_NORMAL 1
+ /* When an EOF's been seen but there's still some text to process
+ * then we mark the buffer as YY_EOF_PENDING, to indicate that we
+ * shouldn't try reading from the input source any more. We might
+ * still have a bunch of tokens to match, though, because of
+ * possible backing-up.
+ *
+ * When we actually see the EOF, we change the status to "new"
+ * (via glcpp_restart()), so that the user can continue scanning by
+ * just pointing yyin at a new input file.
+ */
+#define YY_BUFFER_EOF_PENDING 2
+
+ };
+#endif /* !YY_STRUCT_YY_BUFFER_STATE */
+
+/* We provide macros for accessing buffer states in case in the
+ * future we want to put the buffer states in a more general
+ * "scanner state".
+ *
+ * Returns the top of the stack, or NULL.
+ */
+#define YY_CURRENT_BUFFER ( yyg->yy_buffer_stack \
+ ? yyg->yy_buffer_stack[yyg->yy_buffer_stack_top] \
+ : NULL)
+
+/* Same as previous macro, but useful when we know that the buffer stack is not
+ * NULL or when we need an lvalue. For internal use only.
+ */
+#define YY_CURRENT_BUFFER_LVALUE yyg->yy_buffer_stack[yyg->yy_buffer_stack_top]
+
+void glcpp_restart (FILE *input_file ,yyscan_t yyscanner );
+void glcpp__switch_to_buffer (YY_BUFFER_STATE new_buffer ,yyscan_t yyscanner );
+YY_BUFFER_STATE glcpp__create_buffer (FILE *file,int size ,yyscan_t yyscanner );
+void glcpp__delete_buffer (YY_BUFFER_STATE b ,yyscan_t yyscanner );
+void glcpp__flush_buffer (YY_BUFFER_STATE b ,yyscan_t yyscanner );
+void glcpp_push_buffer_state (YY_BUFFER_STATE new_buffer ,yyscan_t yyscanner );
+void glcpp_pop_buffer_state (yyscan_t yyscanner );
+
+static void glcpp_ensure_buffer_stack (yyscan_t yyscanner );
+static void glcpp__load_buffer_state (yyscan_t yyscanner );
+static void glcpp__init_buffer (YY_BUFFER_STATE b,FILE *file ,yyscan_t yyscanner );
+
+#define YY_FLUSH_BUFFER glcpp__flush_buffer(YY_CURRENT_BUFFER ,yyscanner)
+
+YY_BUFFER_STATE glcpp__scan_buffer (char *base,yy_size_t size ,yyscan_t yyscanner );
+YY_BUFFER_STATE glcpp__scan_string (yyconst char *yy_str ,yyscan_t yyscanner );
+YY_BUFFER_STATE glcpp__scan_bytes (yyconst char *bytes,int len ,yyscan_t yyscanner );
+
+void *glcpp_alloc (yy_size_t ,yyscan_t yyscanner );
+void *glcpp_realloc (void *,yy_size_t ,yyscan_t yyscanner );
+void glcpp_free (void * ,yyscan_t yyscanner );
+
+#define yy_new_buffer glcpp__create_buffer
+
+#define yy_set_interactive(is_interactive) \
+ { \
+ if ( ! YY_CURRENT_BUFFER ){ \
+ glcpp_ensure_buffer_stack (yyscanner); \
+ YY_CURRENT_BUFFER_LVALUE = \
+ glcpp__create_buffer(yyin,YY_BUF_SIZE ,yyscanner); \
+ } \
+ YY_CURRENT_BUFFER_LVALUE->yy_is_interactive = is_interactive; \
+ }
+
+#define yy_set_bol(at_bol) \
+ { \
+ if ( ! YY_CURRENT_BUFFER ){\
+ glcpp_ensure_buffer_stack (yyscanner); \
+ YY_CURRENT_BUFFER_LVALUE = \
+ glcpp__create_buffer(yyin,YY_BUF_SIZE ,yyscanner); \
+ } \
+ YY_CURRENT_BUFFER_LVALUE->yy_at_bol = at_bol; \
+ }
+
+#define YY_AT_BOL() (YY_CURRENT_BUFFER_LVALUE->yy_at_bol)
+
+/* Begin user sect3 */
+
+#define glcpp_wrap(n) 1
+#define YY_SKIP_YYWRAP
+
+typedef unsigned char YY_CHAR;
+
+typedef int yy_state_type;
+
+#define yytext_ptr yytext_r
+
+static yy_state_type yy_get_previous_state (yyscan_t yyscanner );
+static yy_state_type yy_try_NUL_trans (yy_state_type current_state ,yyscan_t yyscanner);
+static int yy_get_next_buffer (yyscan_t yyscanner );
+static void yy_fatal_error (yyconst char msg[] ,yyscan_t yyscanner );
+
+/* Done after the current pattern has been matched and before the
+ * corresponding action - sets up yytext.
+ */
+#define YY_DO_BEFORE_ACTION \
+ yyg->yytext_ptr = yy_bp; \
+ yyleng = (size_t) (yy_cp - yy_bp); \
+ yyg->yy_hold_char = *yy_cp; \
+ *yy_cp = '\0'; \
+ yyg->yy_c_buf_p = yy_cp;
+
+#define YY_NUM_RULES 41
+#define YY_END_OF_BUFFER 42
+/* This struct is not used in this scanner,
+ but its presence is necessary. */
+struct yy_trans_info
+ {
+ flex_int32_t yy_verify;
+ flex_int32_t yy_nxt;
+ };
+static yyconst flex_int16_t yy_acclist[133] =
+ { 0,
+ 3, 3, 42, 37, 41, 38, 41, 39, 41, 41,
+ 36, 41, 41, 36, 41, 36, 41, 36, 41, 23,
+ 37, 41, 22, 37, 41, 36, 41, 36, 41, 36,
+ 41, 35, 37, 41, 35, 37, 41, 36, 41, 38,
+ 41, 21, 41, 41, 3, 41, 4, 41, 5, 41,
+ 40, 41, 37, 16, 38, 30, 33, 31, 2, 23,
+ 37, 23, 37, 37, 22, 37, 22, 37, 25, 27,
+ 29, 28, 26, 35, 37, 35, 37, 32, 38, 21,
+ 21, 3, 4, 5, 6, 5, 7, 1, 16, 24,
+ 37, 35, 37,16396, 24, 37, 35, 37, 16, 35,
+
+ 37,16397,16398, 8204, 16, 8204, 35, 37, 8205, 16,
+ 8206, 16,16399, 17,16394, 20, 34, 35, 37, 19,
+ 8207, 16, 17, 8202, 16,16395,16402, 8203, 16, 9,
+ 8, 8210
+ } ;
+
+static yyconst flex_int16_t yy_accept[152] =
+ { 0,
+ 1, 1, 1, 1, 1, 2, 3, 3, 3, 4,
+ 6, 8, 10, 11, 13, 14, 16, 18, 20, 23,
+ 26, 28, 30, 32, 35, 38, 40, 42, 44, 45,
+ 47, 49, 51, 53, 54, 54, 55, 56, 57, 58,
+ 59, 60, 60, 62, 64, 65, 67, 69, 70, 71,
+ 72, 73, 74, 76, 78, 79, 80, 81, 82, 82,
+ 82, 82, 82, 82, 82, 83, 84, 85, 86, 87,
+ 88, 88, 90, 92, 94, 94, 94, 94, 94, 94,
+ 95, 95, 95, 95, 97, 99, 99, 99, 99, 99,
+ 99, 99, 99, 100, 100, 100, 100, 100, 100, 102,
+
+ 102, 103, 104, 104, 104, 104, 104, 106, 106, 107,
+ 107, 107, 107, 107, 107, 109, 109, 109, 111, 111,
+ 113, 114, 115, 115, 116, 116, 116, 117, 117, 120,
+ 121, 121, 123, 124, 124, 124, 126, 127, 127, 127,
+ 128, 128, 128, 130, 131, 132, 132, 132, 133, 133,
+ 133
+ } ;
+
+static yyconst flex_int32_t yy_ec[256] =
+ { 0,
+ 1, 1, 1, 1, 1, 1, 1, 1, 2, 3,
+ 4, 4, 4, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 2, 5, 1, 6, 1, 7, 8, 1, 9,
+ 7, 10, 7, 7, 7, 7, 11, 12, 13, 13,
+ 13, 13, 13, 13, 13, 14, 14, 1, 7, 15,
+ 16, 17, 1, 1, 18, 18, 18, 18, 18, 18,
+ 19, 19, 19, 19, 19, 19, 19, 19, 19, 19,
+ 19, 19, 19, 19, 20, 19, 19, 21, 19, 19,
+ 7, 1, 7, 7, 19, 1, 22, 18, 18, 23,
+
+ 24, 25, 26, 19, 27, 19, 19, 28, 29, 30,
+ 31, 32, 19, 33, 34, 35, 36, 37, 19, 38,
+ 19, 19, 7, 39, 7, 7, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1
+ } ;
+
+static yyconst flex_int32_t yy_meta[40] =
+ { 0,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 2,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1
+ } ;
+
+static yyconst flex_int16_t yy_base[170] =
+ { 0,
+ 0, 38, 0, 0, 38, 39, 427, 426, 428, 48,
+ 43, 549, 424, 44, 63, 423, 59, 65, 87, 125,
+ 58, 67, 68, 164, 203, 40, 75, 241, 549, 422,
+ 549, 140, 549, 140, 421, 549, 144, 420, 419, 418,
+ 417, 415, 156, 179, 267, 0, 209, 414, 413, 412,
+ 411, 410, 388, 124, 408, 153, 404, 403, 154, 198,
+ 159, 155, 160, 192, 405, 549, 186, 549, 214, 549,
+ 404, 549, 162, 159, 227, 229, 230, 234, 199, 303,
+ 232, 235, 236, 262, 56, 243, 237, 247, 245, 252,
+ 291, 359, 358, 292, 238, 296, 293, 254, 336, 256,
+
+ 356, 355, 298, 294, 263, 354, 549, 352, 549, 299,
+ 297, 322, 325, 257, 306, 328, 350, 549, 346, 549,
+ 345, 344, 329, 343, 331, 332, 342, 333, 320, 335,
+ 340, 549, 337, 338, 248, 549, 246, 197, 336, 366,
+ 403, 184, 549, 182, 141, 434, 416, 79, 473, 549,
+ 512, 514, 516, 518, 520, 522, 71, 524, 526, 528,
+ 530, 532, 534, 536, 538, 540, 542, 544, 546
+ } ;
+
+static yyconst flex_int16_t yy_def[170] =
+ { 0,
+ 150, 1, 151, 151, 152, 152, 153, 153, 150, 154,
+ 155, 150, 155, 155, 155, 155, 155, 155, 150, 154,
+ 155, 155, 155, 156, 156, 155, 155, 155, 150, 157,
+ 150, 158, 150, 20, 155, 150, 155, 155, 155, 155,
+ 155, 159, 19, 20, 20, 20, 20, 155, 155, 155,
+ 155, 155, 25, 25, 155, 155, 28, 28, 155, 155,
+ 155, 155, 155, 155, 157, 150, 158, 150, 158, 150,
+ 159, 150, 45, 25, 155, 155, 155, 155, 155, 155,
+ 155, 155, 155, 20, 25, 155, 155, 155, 155, 155,
+ 155, 160, 161, 155, 155, 155, 155, 155, 25, 155,
+
+ 162, 163, 155, 155, 155, 160, 150, 161, 150, 155,
+ 155, 155, 155, 155, 25, 155, 162, 150, 163, 150,
+ 164, 165, 155, 166, 155, 155, 155, 155, 25, 155,
+ 164, 150, 165, 155, 166, 150, 167, 168, 155, 150,
+ 155, 167, 150, 168, 155, 169, 155, 155, 169, 0,
+ 150, 150, 150, 150, 150, 150, 150, 150, 150, 150,
+ 150, 150, 150, 150, 150, 150, 150, 150, 150
+ } ;
+
+static yyconst flex_int16_t yy_nxt[589] =
+ { 0,
+ 10, 11, 12, 13, 14, 15, 16, 17, 16, 16,
+ 18, 19, 20, 20, 21, 22, 23, 24, 24, 24,
+ 24, 24, 25, 24, 24, 24, 24, 24, 24, 24,
+ 24, 24, 24, 24, 24, 24, 24, 24, 26, 27,
+ 31, 31, 36, 28, 37, 36, 36, 32, 32, 35,
+ 36, 35, 35, 35, 35, 35, 35, 35, 35, 38,
+ 36, 36, 35, 35, 35, 36, 40, 36, 39, 36,
+ 36, 65, 48, 49, 41, 42, 56, 36, 55, 53,
+ 57, 36, 50, 51, 52, 99, 35, 34, 35, 36,
+ 35, 35, 35, 35, 35, 35, 35, 35, 43, 43,
+
+ 34, 35, 35, 35, 34, 34, 44, 45, 34, 34,
+ 34, 34, 34, 34, 34, 34, 34, 34, 34, 34,
+ 34, 34, 44, 34, 45, 35, 35, 36, 35, 35,
+ 35, 35, 35, 35, 35, 35, 46, 46, 46, 35,
+ 35, 35, 68, 36, 47, 37, 36, 53, 74, 69,
+ 70, 34, 34, 34, 56, 36, 36, 36, 57, 34,
+ 47, 36, 36, 35, 34, 35, 36, 35, 35, 35,
+ 35, 35, 35, 35, 35, 34, 34, 75, 35, 35,
+ 35, 84, 53, 80, 36, 85, 143, 81, 68, 82,
+ 34, 34, 34, 34, 36, 150, 150, 84, 34, 36,
+
+ 36, 36, 35, 34, 35, 36, 35, 35, 35, 35,
+ 35, 35, 35, 35, 34, 83, 68, 35, 35, 35,
+ 34, 34, 34, 69, 70, 76, 54, 77, 34, 36,
+ 78, 36, 36, 91, 36, 79, 36, 36, 36, 36,
+ 36, 35, 58, 36, 34, 36, 39, 36, 143, 36,
+ 136, 86, 89, 96, 36, 87, 36, 97, 36, 36,
+ 111, 101, 88, 59, 60, 36, 90, 61, 98, 100,
+ 102, 103, 62, 34, 34, 34, 63, 64, 73, 73,
+ 73, 34, 104, 128, 73, 116, 34, 114, 73, 73,
+ 73, 73, 123, 36, 36, 36, 36, 34, 36, 36,
+
+ 36, 36, 34, 92, 92, 93, 92, 92, 92, 92,
+ 92, 92, 92, 92, 105, 110, 113, 92, 92, 92,
+ 125, 112, 121, 124, 36, 94, 122, 36, 129, 53,
+ 36, 36, 95, 36, 36, 36, 140, 36, 36, 36,
+ 36, 92, 132, 53, 36, 136, 36, 132, 120, 127,
+ 126, 130, 118, 138, 109, 137, 107, 120, 118, 115,
+ 109, 107, 134, 139, 141, 145, 35, 140, 36, 35,
+ 35, 35, 35, 35, 35, 35, 35, 35, 35, 35,
+ 35, 35, 35, 146, 146, 146, 146, 146, 146, 146,
+ 146, 146, 146, 146, 146, 146, 146, 146, 146, 146,
+
+ 146, 146, 146, 146, 35, 36, 72, 66, 35, 35,
+ 36, 53, 36, 36, 36, 36, 36, 72, 36, 36,
+ 36, 36, 36, 36, 66, 36, 36, 150, 29, 29,
+ 150, 150, 150, 147, 35, 35, 36, 35, 35, 35,
+ 35, 35, 148, 35, 35, 138, 150, 150, 35, 35,
+ 35, 150, 150, 150, 150, 150, 150, 150, 150, 150,
+ 150, 150, 150, 150, 150, 150, 150, 150, 150, 150,
+ 150, 150, 35, 35, 35, 36, 35, 35, 35, 35,
+ 35, 148, 35, 35, 150, 150, 150, 35, 35, 35,
+ 150, 150, 150, 150, 150, 150, 150, 150, 150, 150,
+
+ 150, 150, 150, 150, 150, 150, 150, 150, 150, 150,
+ 150, 35, 29, 29, 30, 30, 33, 33, 34, 34,
+ 35, 35, 53, 53, 67, 67, 71, 71, 106, 106,
+ 108, 108, 117, 117, 119, 119, 131, 131, 133, 133,
+ 135, 135, 142, 142, 144, 144, 149, 149, 9, 150,
+ 150, 150, 150, 150, 150, 150, 150, 150, 150, 150,
+ 150, 150, 150, 150, 150, 150, 150, 150, 150, 150,
+ 150, 150, 150, 150, 150, 150, 150, 150, 150, 150,
+ 150, 150, 150, 150, 150, 150, 150, 150
+ } ;
+
+static yyconst flex_int16_t yy_chk[589] =
+ { 0,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 2,
+ 5, 6, 26, 2, 11, 11, 14, 5, 6, 10,
+ 10, 10, 10, 10, 10, 10, 10, 10, 10, 14,
+ 21, 17, 10, 10, 10, 15, 17, 18, 15, 22,
+ 23, 157, 21, 21, 18, 18, 27, 27, 26, 85,
+ 27, 148, 22, 23, 23, 85, 10, 19, 19, 19,
+ 19, 19, 19, 19, 19, 19, 19, 19, 19, 19,
+
+ 19, 19, 19, 19, 19, 19, 19, 19, 19, 19,
+ 19, 19, 19, 19, 19, 19, 19, 19, 19, 19,
+ 19, 19, 19, 19, 19, 19, 20, 20, 20, 20,
+ 20, 20, 20, 20, 20, 20, 20, 20, 20, 20,
+ 20, 20, 32, 145, 20, 37, 37, 54, 54, 32,
+ 32, 34, 34, 34, 56, 56, 59, 62, 56, 34,
+ 20, 61, 63, 20, 24, 24, 24, 24, 24, 24,
+ 24, 24, 24, 24, 24, 34, 43, 59, 24, 24,
+ 24, 73, 74, 61, 144, 74, 142, 62, 67, 63,
+ 44, 44, 44, 43, 64, 67, 67, 73, 44, 138,
+
+ 60, 79, 24, 25, 25, 25, 25, 25, 25, 25,
+ 25, 25, 25, 25, 44, 64, 69, 25, 25, 25,
+ 47, 47, 47, 69, 69, 60, 25, 60, 47, 75,
+ 60, 76, 77, 79, 81, 60, 78, 82, 83, 87,
+ 95, 25, 28, 28, 47, 86, 28, 89, 137, 88,
+ 135, 75, 77, 81, 90, 76, 98, 82, 100, 114,
+ 95, 87, 76, 28, 28, 105, 78, 28, 83, 86,
+ 88, 89, 28, 84, 84, 84, 28, 28, 45, 45,
+ 45, 84, 90, 114, 45, 100, 45, 98, 45, 45,
+ 45, 45, 105, 91, 94, 97, 104, 84, 96, 111,
+
+ 103, 110, 45, 80, 80, 80, 80, 80, 80, 80,
+ 80, 80, 80, 80, 91, 94, 97, 80, 80, 80,
+ 111, 96, 103, 110, 112, 80, 104, 113, 115, 115,
+ 116, 123, 80, 125, 126, 128, 130, 130, 139, 133,
+ 134, 80, 131, 129, 127, 124, 122, 121, 119, 113,
+ 112, 116, 117, 126, 108, 125, 106, 102, 101, 99,
+ 93, 92, 123, 128, 134, 139, 140, 140, 140, 140,
+ 140, 140, 140, 140, 140, 140, 140, 140, 140, 140,
+ 140, 140, 140, 140, 140, 140, 140, 140, 140, 140,
+ 140, 140, 140, 140, 140, 140, 140, 140, 140, 140,
+
+ 140, 140, 140, 140, 140, 141, 71, 65, 58, 57,
+ 55, 53, 52, 51, 50, 49, 48, 42, 147, 41,
+ 40, 39, 38, 35, 30, 16, 13, 9, 8, 7,
+ 0, 0, 0, 141, 146, 146, 146, 146, 146, 146,
+ 146, 146, 146, 146, 146, 147, 0, 0, 146, 146,
+ 146, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 146, 149, 149, 149, 149, 149, 149, 149,
+ 149, 149, 149, 149, 0, 0, 0, 149, 149, 149,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 149, 151, 151, 152, 152, 153, 153, 154, 154,
+ 155, 155, 156, 156, 158, 158, 159, 159, 160, 160,
+ 161, 161, 162, 162, 163, 163, 164, 164, 165, 165,
+ 166, 166, 167, 167, 168, 168, 169, 169, 150, 150,
+ 150, 150, 150, 150, 150, 150, 150, 150, 150, 150,
+ 150, 150, 150, 150, 150, 150, 150, 150, 150, 150,
+ 150, 150, 150, 150, 150, 150, 150, 150, 150, 150,
+ 150, 150, 150, 150, 150, 150, 150, 150
+ } ;
+
+#define YY_TRAILING_MASK 0x2000
+#define YY_TRAILING_HEAD_MASK 0x4000
+#define REJECT \
+{ \
+*yy_cp = yyg->yy_hold_char; /* undo effects of setting up yytext */ \
+yy_cp = yyg->yy_full_match; /* restore poss. backed-over text */ \
+yyg->yy_lp = yyg->yy_full_lp; /* restore orig. accepting pos. */ \
+yyg->yy_state_ptr = yyg->yy_full_state; /* restore orig. state */ \
+yy_current_state = *yyg->yy_state_ptr; /* restore curr. state */ \
+++yyg->yy_lp; \
+goto find_rule; \
+}
+
+#define yymore() yymore_used_but_not_detected
+#define YY_MORE_ADJ 0
+#define YY_RESTORE_YY_MORE_OFFSET
+#line 1 "glcpp/glcpp-lex.l"
+#line 2 "glcpp/glcpp-lex.l"
+/*
+ * Copyright © 2010 Intel Corporation
+ *
+ * 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 (including the next
+ * paragraph) 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
+ * THE AUTHORS OR COPYRIGHT HOLDERS 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.
+ */
+
+#include <stdio.h>
+#include <string.h>
+#include <ctype.h>
+
+#include "glcpp.h"
+#include "glcpp-parse.h"
+
+/* Flex annoyingly generates some functions without making them
+ * static. Let's declare them here. */
+int glcpp_get_column (yyscan_t yyscanner);
+void glcpp_set_column (int column_no , yyscan_t yyscanner);
+
+#define YY_NO_INPUT
+
+#define YY_USER_ACTION \
+ do { \
+ yylloc->source = 0; \
+ yylloc->first_column = yycolumn + 1; \
+ yylloc->first_line = yylineno; \
+ yycolumn += yyleng; \
+ } while(0);
+#define YY_USER_INIT yylineno = 1; yycolumn = 1;
+
+#line 695 "glcpp/glcpp-lex.c"
+
+#define INITIAL 0
+#define DONE 1
+#define COMMENT 2
+#define UNREACHABLE 3
+
+#define YY_EXTRA_TYPE glcpp_parser_t *
+
+/* Holds the entire state of the reentrant scanner. */
+struct yyguts_t
+ {
+
+ /* User-defined. Not touched by flex. */
+ YY_EXTRA_TYPE yyextra_r;
+
+ /* The rest are the same as the globals declared in the non-reentrant scanner. */
+ FILE *yyin_r, *yyout_r;
+ size_t yy_buffer_stack_top; /**< index of top of stack. */
+ size_t yy_buffer_stack_max; /**< capacity of stack. */
+ YY_BUFFER_STATE * yy_buffer_stack; /**< Stack as an array. */
+ char yy_hold_char;
+ int yy_n_chars;
+ int yyleng_r;
+ char *yy_c_buf_p;
+ int yy_init;
+ int yy_start;
+ int yy_did_buffer_switch_on_eof;
+ int yy_start_stack_ptr;
+ int yy_start_stack_depth;
+ int *yy_start_stack;
+ yy_state_type yy_last_accepting_state;
+ char* yy_last_accepting_cpos;
+
+ int yylineno_r;
+ int yy_flex_debug_r;
+
+ yy_state_type *yy_state_buf;
+ yy_state_type *yy_state_ptr;
+ char *yy_full_match;
+ int yy_lp;
+
+ /* These are only needed for trailing context rules,
+ * but there's no conditional variable for that yet. */
+ int yy_looking_for_trail_begin;
+ int yy_full_lp;
+ int *yy_full_state;
+
+ char *yytext_r;
+ int yy_more_flag;
+ int yy_more_len;
+
+ YYSTYPE * yylval_r;
+
+ YYLTYPE * yylloc_r;
+
+ }; /* end struct yyguts_t */
+
+static int yy_init_globals (yyscan_t yyscanner );
+
+ /* This must go here because YYSTYPE and YYLTYPE are included
+ * from bison output in section 1.*/
+ # define yylval yyg->yylval_r
+
+ # define yylloc yyg->yylloc_r
+
+int glcpp_lex_init (yyscan_t* scanner);
+
+int glcpp_lex_init_extra (YY_EXTRA_TYPE user_defined,yyscan_t* scanner);
+
+/* Accessor methods to globals.
+ These are made visible to non-reentrant scanners for convenience. */
+
+int glcpp_lex_destroy (yyscan_t yyscanner );
+
+int glcpp_get_debug (yyscan_t yyscanner );
+
+void glcpp_set_debug (int debug_flag ,yyscan_t yyscanner );
+
+YY_EXTRA_TYPE glcpp_get_extra (yyscan_t yyscanner );
+
+void glcpp_set_extra (YY_EXTRA_TYPE user_defined ,yyscan_t yyscanner );
+
+FILE *glcpp_get_in (yyscan_t yyscanner );
+
+void glcpp_set_in (FILE * in_str ,yyscan_t yyscanner );
+
+FILE *glcpp_get_out (yyscan_t yyscanner );
+
+void glcpp_set_out (FILE * out_str ,yyscan_t yyscanner );
+
+int glcpp_get_leng (yyscan_t yyscanner );
+
+char *glcpp_get_text (yyscan_t yyscanner );
+
+int glcpp_get_lineno (yyscan_t yyscanner );
+
+void glcpp_set_lineno (int line_number ,yyscan_t yyscanner );
+
+YYSTYPE * glcpp_get_lval (yyscan_t yyscanner );
+
+void glcpp_set_lval (YYSTYPE * yylval_param ,yyscan_t yyscanner );
+
+ YYLTYPE *glcpp_get_lloc (yyscan_t yyscanner );
+
+ void glcpp_set_lloc (YYLTYPE * yylloc_param ,yyscan_t yyscanner );
+
+/* Macros after this point can all be overridden by user definitions in
+ * section 1.
+ */
+
+#ifndef YY_SKIP_YYWRAP
+#ifdef __cplusplus
+extern "C" int glcpp_wrap (yyscan_t yyscanner );
+#else
+extern int glcpp_wrap (yyscan_t yyscanner );
+#endif
+#endif
+
+ static void yyunput (int c,char *buf_ptr ,yyscan_t yyscanner);
+
+#ifndef yytext_ptr
+static void yy_flex_strncpy (char *,yyconst char *,int ,yyscan_t yyscanner);
+#endif
+
+#ifdef YY_NEED_STRLEN
+static int yy_flex_strlen (yyconst char * ,yyscan_t yyscanner);
+#endif
+
+#ifndef YY_NO_INPUT
+
+#ifdef __cplusplus
+static int yyinput (yyscan_t yyscanner );
+#else
+static int input (yyscan_t yyscanner );
+#endif
+
+#endif
+
+ static void yy_push_state (int new_state ,yyscan_t yyscanner);
+
+ static void yy_pop_state (yyscan_t yyscanner );
+
+ static int yy_top_state (yyscan_t yyscanner );
+
+/* Amount of stuff to slurp up with each read. */
+#ifndef YY_READ_BUF_SIZE
+#ifdef __ia64__
+/* On IA-64, the buffer size is 16k, not 8k */
+#define YY_READ_BUF_SIZE 16384
+#else
+#define YY_READ_BUF_SIZE 8192
+#endif /* __ia64__ */
+#endif
+
+/* Copy whatever the last rule matched to the standard output. */
+#ifndef ECHO
+/* This used to be an fputs(), but since the string might contain NUL's,
+ * we now use fwrite().
+ */
+#define ECHO do { if (fwrite( yytext, yyleng, 1, yyout )) {} } while (0)
+#endif
+
+/* Gets input and stuffs it into "buf". number of characters read, or YY_NULL,
+ * is returned in "result".
+ */
+#ifndef YY_INPUT
+#define YY_INPUT(buf,result,max_size) \
+ if ( YY_CURRENT_BUFFER_LVALUE->yy_is_interactive ) \
+ { \
+ int c = '*'; \
+ size_t n; \
+ for ( n = 0; n < max_size && \
+ (c = getc( yyin )) != EOF && c != '\n'; ++n ) \
+ buf[n] = (char) c; \
+ if ( c == '\n' ) \
+ buf[n++] = (char) c; \
+ if ( c == EOF && ferror( yyin ) ) \
+ YY_FATAL_ERROR( "input in flex scanner failed" ); \
+ result = n; \
+ } \
+ else \
+ { \
+ errno=0; \
+ while ( (result = fread(buf, 1, max_size, yyin))==0 && ferror(yyin)) \
+ { \
+ if( errno != EINTR) \
+ { \
+ YY_FATAL_ERROR( "input in flex scanner failed" ); \
+ break; \
+ } \
+ errno=0; \
+ clearerr(yyin); \
+ } \
+ }\
+\
+
+#endif
+
+/* No semi-colon after return; correct usage is to write "yyterminate();" -
+ * we don't want an extra ';' after the "return" because that will cause
+ * some compilers to complain about unreachable statements.
+ */
+#ifndef yyterminate
+#define yyterminate() return YY_NULL
+#endif
+
+/* Number of entries by which start-condition stack grows. */
+#ifndef YY_START_STACK_INCR
+#define YY_START_STACK_INCR 25
+#endif
+
+/* Report a fatal error. */
+#ifndef YY_FATAL_ERROR
+#define YY_FATAL_ERROR(msg) yy_fatal_error( msg , yyscanner)
+#endif
+
+/* end tables serialization structures and prototypes */
+
+/* Default declaration of generated scanner - a define so the user can
+ * easily add parameters.
+ */
+#ifndef YY_DECL
+#define YY_DECL_IS_OURS 1
+
+extern int glcpp_lex \
+ (YYSTYPE * yylval_param,YYLTYPE * yylloc_param ,yyscan_t yyscanner);
+
+#define YY_DECL int glcpp_lex \
+ (YYSTYPE * yylval_param, YYLTYPE * yylloc_param , yyscan_t yyscanner)
+#endif /* !YY_DECL */
+
+/* Code executed at the beginning of each rule, after yytext and yyleng
+ * have been set up.
+ */
+#ifndef YY_USER_ACTION
+#define YY_USER_ACTION
+#endif
+
+/* Code executed at the end of each rule. */
+#ifndef YY_BREAK
+#define YY_BREAK break;
+#endif
+
+#define YY_RULE_SETUP \
+ if ( yyleng > 0 ) \
+ YY_CURRENT_BUFFER_LVALUE->yy_at_bol = \
+ (yytext[yyleng - 1] == '\n'); \
+ YY_USER_ACTION
+
+/** The main scanner function which does all the work.
+ */
+YY_DECL
+{
+ register yy_state_type yy_current_state;
+ register char *yy_cp, *yy_bp;
+ register int yy_act;
+ struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
+
+#line 70 "glcpp/glcpp-lex.l"
+
+
+ /* Single-line comments */
+#line 958 "glcpp/glcpp-lex.c"
+
+ yylval = yylval_param;
+
+ yylloc = yylloc_param;
+
+ if ( !yyg->yy_init )
+ {
+ yyg->yy_init = 1;
+
+#ifdef YY_USER_INIT
+ YY_USER_INIT;
+#endif
+
+ /* Create the reject buffer large enough to save one state per allowed character. */
+ if ( ! yyg->yy_state_buf )
+ yyg->yy_state_buf = (yy_state_type *)glcpp_alloc(YY_STATE_BUF_SIZE ,yyscanner);
+ if ( ! yyg->yy_state_buf )
+ YY_FATAL_ERROR( "out of dynamic memory in glcpp_lex()" );
+
+ if ( ! yyg->yy_start )
+ yyg->yy_start = 1; /* first start state */
+
+ if ( ! yyin )
+ yyin = stdin;
+
+ if ( ! yyout )
+ yyout = stdout;
+
+ if ( ! YY_CURRENT_BUFFER ) {
+ glcpp_ensure_buffer_stack (yyscanner);
+ YY_CURRENT_BUFFER_LVALUE =
+ glcpp__create_buffer(yyin,YY_BUF_SIZE ,yyscanner);
+ }
+
+ glcpp__load_buffer_state(yyscanner );
+ }
+
+ while ( 1 ) /* loops until end-of-file is reached */
+ {
+ yy_cp = yyg->yy_c_buf_p;
+
+ /* Support of yytext. */
+ *yy_cp = yyg->yy_hold_char;
+
+ /* yy_bp points to the position in yy_ch_buf of the start of
+ * the current run.
+ */
+ yy_bp = yy_cp;
+
+ yy_current_state = yyg->yy_start;
+ yy_current_state += YY_AT_BOL();
+
+ yyg->yy_state_ptr = yyg->yy_state_buf;
+ *yyg->yy_state_ptr++ = yy_current_state;
+
+yy_match:
+ do
+ {
+ register YY_CHAR yy_c = yy_ec[YY_SC_TO_UI(*yy_cp)];
+ while ( yy_chk[yy_base[yy_current_state] + yy_c] != yy_current_state )
+ {
+ yy_current_state = (int) yy_def[yy_current_state];
+ if ( yy_current_state >= 151 )
+ yy_c = yy_meta[(unsigned int) yy_c];
+ }
+ yy_current_state = yy_nxt[yy_base[yy_current_state] + (unsigned int) yy_c];
+ *yyg->yy_state_ptr++ = yy_current_state;
+ ++yy_cp;
+ }
+ while ( yy_current_state != 150 );
+
+yy_find_action:
+ yy_current_state = *--yyg->yy_state_ptr;
+ yyg->yy_lp = yy_accept[yy_current_state];
+find_rule: /* we branch to this label when backing up */
+ for ( ; ; ) /* until we find what rule we matched */
+ {
+ if ( yyg->yy_lp && yyg->yy_lp < yy_accept[yy_current_state + 1] )
+ {
+ yy_act = yy_acclist[yyg->yy_lp];
+ if ( yy_act & YY_TRAILING_HEAD_MASK ||
+ yyg->yy_looking_for_trail_begin )
+ {
+ if ( yy_act == yyg->yy_looking_for_trail_begin )
+ {
+ yyg->yy_looking_for_trail_begin = 0;
+ yy_act &= ~YY_TRAILING_HEAD_MASK;
+ break;
+ }
+ }
+ else if ( yy_act & YY_TRAILING_MASK )
+ {
+ yyg->yy_looking_for_trail_begin = yy_act & ~YY_TRAILING_MASK;
+ yyg->yy_looking_for_trail_begin |= YY_TRAILING_HEAD_MASK;
+ yyg->yy_full_match = yy_cp;
+ yyg->yy_full_state = yyg->yy_state_ptr;
+ yyg->yy_full_lp = yyg->yy_lp;
+ }
+ else
+ {
+ yyg->yy_full_match = yy_cp;
+ yyg->yy_full_state = yyg->yy_state_ptr;
+ yyg->yy_full_lp = yyg->yy_lp;
+ break;
+ }
+ ++yyg->yy_lp;
+ goto find_rule;
+ }
+ --yy_cp;
+ yy_current_state = *--yyg->yy_state_ptr;
+ yyg->yy_lp = yy_accept[yy_current_state];
+ }
+
+ YY_DO_BEFORE_ACTION;
+
+do_action: /* This label is used only to access EOF actions. */
+
+ switch ( yy_act )
+ { /* beginning of action switch */
+case 1:
+/* rule 1 can match eol */
+YY_RULE_SETUP
+#line 73 "glcpp/glcpp-lex.l"
+{
+ yylineno++;
+ yycolumn = 0;
+ return NEWLINE;
+}
+ YY_BREAK
+/* Multi-line comments */
+case 2:
+YY_RULE_SETUP
+#line 80 "glcpp/glcpp-lex.l"
+{ yy_push_state(COMMENT, yyscanner); }
+ YY_BREAK
+case 3:
+YY_RULE_SETUP
+#line 81 "glcpp/glcpp-lex.l"
+
+ YY_BREAK
+case 4:
+/* rule 4 can match eol */
+YY_RULE_SETUP
+#line 82 "glcpp/glcpp-lex.l"
+{ yylineno++; yycolumn = 0; }
+ YY_BREAK
+case 5:
+YY_RULE_SETUP
+#line 83 "glcpp/glcpp-lex.l"
+
+ YY_BREAK
+case 6:
+/* rule 6 can match eol */
+YY_RULE_SETUP
+#line 84 "glcpp/glcpp-lex.l"
+{ yylineno++; yycolumn = 0; }
+ YY_BREAK
+case 7:
+YY_RULE_SETUP
+#line 85 "glcpp/glcpp-lex.l"
+{
+ yy_pop_state(yyscanner);
+ if (yyextra->space_tokens)
+ return SPACE;
+}
+ YY_BREAK
+case 8:
+YY_RULE_SETUP
+#line 91 "glcpp/glcpp-lex.l"
+{
+ yylval->str = talloc_strdup (yyextra, yytext);
+ yylineno++;
+ yycolumn = 0;
+ yyextra->space_tokens = 0;
+ return HASH_VERSION;
+}
+ YY_BREAK
+/* glcpp doesn't handle #extension, #version, or #pragma directives.
+ * Simply pass them through to the main compiler's lexer/parser. */
+case 9:
+YY_RULE_SETUP
+#line 101 "glcpp/glcpp-lex.l"
+{
+ yylval->str = talloc_strdup (yyextra, yytext);
+ yylineno++;
+ yycolumn = 0;
+ return OTHER;
+}
+ YY_BREAK
+case 10:
+/* rule 10 can match eol */
+YY_RULE_SETUP
+#line 108 "glcpp/glcpp-lex.l"
+{
+ yyextra->lexing_if = 1;
+ yyextra->space_tokens = 0;
+ return HASH_IFDEF;
+}
+ YY_BREAK
+case 11:
+/* rule 11 can match eol */
+YY_RULE_SETUP
+#line 114 "glcpp/glcpp-lex.l"
+{
+ yyextra->lexing_if = 1;
+ yyextra->space_tokens = 0;
+ return HASH_IFNDEF;
+}
+ YY_BREAK
+case 12:
+/* rule 12 can match eol */
+YY_RULE_SETUP
+#line 120 "glcpp/glcpp-lex.l"
+{
+ yyextra->lexing_if = 1;
+ yyextra->space_tokens = 0;
+ return HASH_IF;
+}
+ YY_BREAK
+case 13:
+/* rule 13 can match eol */
+YY_RULE_SETUP
+#line 126 "glcpp/glcpp-lex.l"
+{
+ yyextra->lexing_if = 1;
+ yyextra->space_tokens = 0;
+ return HASH_ELIF;
+}
+ YY_BREAK
+case 14:
+/* rule 14 can match eol */
+YY_RULE_SETUP
+#line 132 "glcpp/glcpp-lex.l"
+{
+ yyextra->space_tokens = 0;
+ return HASH_ELSE;
+}
+ YY_BREAK
+case 15:
+/* rule 15 can match eol */
+YY_RULE_SETUP
+#line 137 "glcpp/glcpp-lex.l"
+{
+ yyextra->space_tokens = 0;
+ return HASH_ENDIF;
+}
+ YY_BREAK
+/* When skipping (due to an #if 0 or similar) consume anything
+ * up to a newline. We do this with less priority than any
+ * #if-related directive (#if, #elif, #else, #endif), but with
+ * more priority than any other directive or token to avoid
+ * any side-effects from skipped content.
+ *
+ * We use the lexing_if flag to avoid skipping any part of an
+ * if conditional expression. */
+case 16:
+/* rule 16 can match eol */
+*yy_cp = yyg->yy_hold_char; /* undo effects of setting up yytext */
+yyg->yy_c_buf_p = yy_cp -= 1;
+YY_DO_BEFORE_ACTION; /* set up yytext again */
+YY_RULE_SETUP
+#line 150 "glcpp/glcpp-lex.l"
+{
+ /* Since this rule always matches, YY_USER_ACTION gets called for it,
+ * wrongly incrementing yycolumn. We undo that effect here. */
+ yycolumn -= yyleng;
+ if (yyextra->lexing_if ||
+ yyextra->skip_stack == NULL ||
+ yyextra->skip_stack->type == SKIP_NO_SKIP)
+ {
+ REJECT;
+ }
+}
+ YY_BREAK
+case 17:
+YY_RULE_SETUP
+#line 162 "glcpp/glcpp-lex.l"
+{
+ char *p;
+ for (p = yytext; !isalpha(p[0]); p++); /* skip " # " */
+ p += 5; /* skip "error" */
+ glcpp_error(yylloc, yyextra, "#error%s", p);
+}
+ YY_BREAK
+case 18:
+YY_RULE_SETUP
+#line 169 "glcpp/glcpp-lex.l"
+{
+ yyextra->space_tokens = 0;
+ return HASH_DEFINE_FUNC;
+}
+ YY_BREAK
+case 19:
+YY_RULE_SETUP
+#line 174 "glcpp/glcpp-lex.l"
+{
+ yyextra->space_tokens = 0;
+ return HASH_DEFINE_OBJ;
+}
+ YY_BREAK
+case 20:
+YY_RULE_SETUP
+#line 179 "glcpp/glcpp-lex.l"
+{
+ yyextra->space_tokens = 0;
+ return HASH_UNDEF;
+}
+ YY_BREAK
+case 21:
+YY_RULE_SETUP
+#line 184 "glcpp/glcpp-lex.l"
+{
+ yyextra->space_tokens = 0;
+ return HASH;
+}
+ YY_BREAK
+case 22:
+YY_RULE_SETUP
+#line 189 "glcpp/glcpp-lex.l"
+{
+ yylval->str = talloc_strdup (yyextra, yytext);
+ return INTEGER_STRING;
+}
+ YY_BREAK
+case 23:
+YY_RULE_SETUP
+#line 194 "glcpp/glcpp-lex.l"
+{
+ yylval->str = talloc_strdup (yyextra, yytext);
+ return INTEGER_STRING;
+}
+ YY_BREAK
+case 24:
+YY_RULE_SETUP
+#line 199 "glcpp/glcpp-lex.l"
+{
+ yylval->str = talloc_strdup (yyextra, yytext);
+ return INTEGER_STRING;
+}
+ YY_BREAK
+case 25:
+YY_RULE_SETUP
+#line 204 "glcpp/glcpp-lex.l"
+{
+ return LEFT_SHIFT;
+}
+ YY_BREAK
+case 26:
+YY_RULE_SETUP
+#line 208 "glcpp/glcpp-lex.l"
+{
+ return RIGHT_SHIFT;
+}
+ YY_BREAK
+case 27:
+YY_RULE_SETUP
+#line 212 "glcpp/glcpp-lex.l"
+{
+ return LESS_OR_EQUAL;
+}
+ YY_BREAK
+case 28:
+YY_RULE_SETUP
+#line 216 "glcpp/glcpp-lex.l"
+{
+ return GREATER_OR_EQUAL;
+}
+ YY_BREAK
+case 29:
+YY_RULE_SETUP
+#line 220 "glcpp/glcpp-lex.l"
+{
+ return EQUAL;
+}
+ YY_BREAK
+case 30:
+YY_RULE_SETUP
+#line 224 "glcpp/glcpp-lex.l"
+{
+ return NOT_EQUAL;
+}
+ YY_BREAK
+case 31:
+YY_RULE_SETUP
+#line 228 "glcpp/glcpp-lex.l"
+{
+ return AND;
+}
+ YY_BREAK
+case 32:
+YY_RULE_SETUP
+#line 232 "glcpp/glcpp-lex.l"
+{
+ return OR;
+}
+ YY_BREAK
+case 33:
+YY_RULE_SETUP
+#line 236 "glcpp/glcpp-lex.l"
+{
+ return PASTE;
+}
+ YY_BREAK
+case 34:
+YY_RULE_SETUP
+#line 240 "glcpp/glcpp-lex.l"
+{
+ return DEFINED;
+}
+ YY_BREAK
+case 35:
+YY_RULE_SETUP
+#line 244 "glcpp/glcpp-lex.l"
+{
+ yylval->str = talloc_strdup (yyextra, yytext);
+ return IDENTIFIER;
+}
+ YY_BREAK
+case 36:
+YY_RULE_SETUP
+#line 249 "glcpp/glcpp-lex.l"
+{
+ return yytext[0];
+}
+ YY_BREAK
+case 37:
+YY_RULE_SETUP
+#line 253 "glcpp/glcpp-lex.l"
+{
+ yylval->str = talloc_strdup (yyextra, yytext);
+ return OTHER;
+}
+ YY_BREAK
+case 38:
+YY_RULE_SETUP
+#line 258 "glcpp/glcpp-lex.l"
+{
+ if (yyextra->space_tokens) {
+ return SPACE;
+ }
+}
+ YY_BREAK
+case 39:
+/* rule 39 can match eol */
+YY_RULE_SETUP
+#line 264 "glcpp/glcpp-lex.l"
+{
+ yyextra->lexing_if = 0;
+ yylineno++;
+ yycolumn = 0;
+ return NEWLINE;
+}
+ YY_BREAK
+/* Handle missing newline at EOF. */
+case YY_STATE_EOF(INITIAL):
+#line 272 "glcpp/glcpp-lex.l"
+{
+ BEGIN DONE; /* Don't keep matching this rule forever. */
+ yyextra->lexing_if = 0;
+ return NEWLINE;
+}
+ YY_BREAK
+/* We don't actually use the UNREACHABLE start condition. We
+ only have this action here so that we can pretend to call some
+ generated functions, (to avoid "defined but not used"
+ warnings. */
+case 40:
+YY_RULE_SETUP
+#line 282 "glcpp/glcpp-lex.l"
+{
+ unput('.');
+ yy_top_state(yyextra);
+}
+ YY_BREAK
+case 41:
+YY_RULE_SETUP
+#line 287 "glcpp/glcpp-lex.l"
+ECHO;
+ YY_BREAK
+#line 1438 "glcpp/glcpp-lex.c"
+ case YY_STATE_EOF(DONE):
+ case YY_STATE_EOF(COMMENT):
+ case YY_STATE_EOF(UNREACHABLE):
+ yyterminate();
+
+ case YY_END_OF_BUFFER:
+ {
+ /* Amount of text matched not including the EOB char. */
+ int yy_amount_of_matched_text = (int) (yy_cp - yyg->yytext_ptr) - 1;
+
+ /* Undo the effects of YY_DO_BEFORE_ACTION. */
+ *yy_cp = yyg->yy_hold_char;
+ YY_RESTORE_YY_MORE_OFFSET
+
+ if ( YY_CURRENT_BUFFER_LVALUE->yy_buffer_status == YY_BUFFER_NEW )
+ {
+ /* We're scanning a new file or input source. It's
+ * possible that this happened because the user
+ * just pointed yyin at a new source and called
+ * glcpp_lex(). If so, then we have to assure
+ * consistency between YY_CURRENT_BUFFER and our
+ * globals. Here is the right place to do so, because
+ * this is the first action (other than possibly a
+ * back-up) that will match for the new input source.
+ */
+ yyg->yy_n_chars = YY_CURRENT_BUFFER_LVALUE->yy_n_chars;
+ YY_CURRENT_BUFFER_LVALUE->yy_input_file = yyin;
+ YY_CURRENT_BUFFER_LVALUE->yy_buffer_status = YY_BUFFER_NORMAL;
+ }
+
+ /* Note that here we test for yy_c_buf_p "<=" to the position
+ * of the first EOB in the buffer, since yy_c_buf_p will
+ * already have been incremented past the NUL character
+ * (since all states make transitions on EOB to the
+ * end-of-buffer state). Contrast this with the test
+ * in input().
+ */
+ if ( yyg->yy_c_buf_p <= &YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[yyg->yy_n_chars] )
+ { /* This was really a NUL. */
+ yy_state_type yy_next_state;
+
+ yyg->yy_c_buf_p = yyg->yytext_ptr + yy_amount_of_matched_text;
+
+ yy_current_state = yy_get_previous_state( yyscanner );
+
+ /* Okay, we're now positioned to make the NUL
+ * transition. We couldn't have
+ * yy_get_previous_state() go ahead and do it
+ * for us because it doesn't know how to deal
+ * with the possibility of jamming (and we don't
+ * want to build jamming into it because then it
+ * will run more slowly).
+ */
+
+ yy_next_state = yy_try_NUL_trans( yy_current_state , yyscanner);
+
+ yy_bp = yyg->yytext_ptr + YY_MORE_ADJ;
+
+ if ( yy_next_state )
+ {
+ /* Consume the NUL. */
+ yy_cp = ++yyg->yy_c_buf_p;
+ yy_current_state = yy_next_state;
+ goto yy_match;
+ }
+
+ else
+ {
+ yy_cp = yyg->yy_c_buf_p;
+ goto yy_find_action;
+ }
+ }
+
+ else switch ( yy_get_next_buffer( yyscanner ) )
+ {
+ case EOB_ACT_END_OF_FILE:
+ {
+ yyg->yy_did_buffer_switch_on_eof = 0;
+
+ if ( glcpp_wrap(yyscanner ) )
+ {
+ /* Note: because we've taken care in
+ * yy_get_next_buffer() to have set up
+ * yytext, we can now set up
+ * yy_c_buf_p so that if some total
+ * hoser (like flex itself) wants to
+ * call the scanner after we return the
+ * YY_NULL, it'll still work - another
+ * YY_NULL will get returned.
+ */
+ yyg->yy_c_buf_p = yyg->yytext_ptr + YY_MORE_ADJ;
+
+ yy_act = YY_STATE_EOF(YY_START);
+ goto do_action;
+ }
+
+ else
+ {
+ if ( ! yyg->yy_did_buffer_switch_on_eof )
+ YY_NEW_FILE;
+ }
+ break;
+ }
+
+ case EOB_ACT_CONTINUE_SCAN:
+ yyg->yy_c_buf_p =
+ yyg->yytext_ptr + yy_amount_of_matched_text;
+
+ yy_current_state = yy_get_previous_state( yyscanner );
+
+ yy_cp = yyg->yy_c_buf_p;
+ yy_bp = yyg->yytext_ptr + YY_MORE_ADJ;
+ goto yy_match;
+
+ case EOB_ACT_LAST_MATCH:
+ yyg->yy_c_buf_p =
+ &YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[yyg->yy_n_chars];
+
+ yy_current_state = yy_get_previous_state( yyscanner );
+
+ yy_cp = yyg->yy_c_buf_p;
+ yy_bp = yyg->yytext_ptr + YY_MORE_ADJ;
+ goto yy_find_action;
+ }
+ break;
+ }
+
+ default:
+ YY_FATAL_ERROR(
+ "fatal flex scanner internal error--no action found" );
+ } /* end of action switch */
+ } /* end of scanning one token */
+} /* end of glcpp_lex */
+
+/* yy_get_next_buffer - try to read in a new buffer
+ *
+ * Returns a code representing an action:
+ * EOB_ACT_LAST_MATCH -
+ * EOB_ACT_CONTINUE_SCAN - continue scanning from current position
+ * EOB_ACT_END_OF_FILE - end of file
+ */
+static int yy_get_next_buffer (yyscan_t yyscanner)
+{
+ struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
+ register char *dest = YY_CURRENT_BUFFER_LVALUE->yy_ch_buf;
+ register char *source = yyg->yytext_ptr;
+ register int number_to_move, i;
+ int ret_val;
+
+ if ( yyg->yy_c_buf_p > &YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[yyg->yy_n_chars + 1] )
+ YY_FATAL_ERROR(
+ "fatal flex scanner internal error--end of buffer missed" );
+
+ if ( YY_CURRENT_BUFFER_LVALUE->yy_fill_buffer == 0 )
+ { /* Don't try to fill the buffer, so this is an EOF. */
+ if ( yyg->yy_c_buf_p - yyg->yytext_ptr - YY_MORE_ADJ == 1 )
+ {
+ /* We matched a single character, the EOB, so
+ * treat this as a final EOF.
+ */
+ return EOB_ACT_END_OF_FILE;
+ }
+
+ else
+ {
+ /* We matched some text prior to the EOB, first
+ * process it.
+ */
+ return EOB_ACT_LAST_MATCH;
+ }
+ }
+
+ /* Try to read more data. */
+
+ /* First move last chars to start of buffer. */
+ number_to_move = (int) (yyg->yy_c_buf_p - yyg->yytext_ptr) - 1;
+
+ for ( i = 0; i < number_to_move; ++i )
+ *(dest++) = *(source++);
+
+ if ( YY_CURRENT_BUFFER_LVALUE->yy_buffer_status == YY_BUFFER_EOF_PENDING )
+ /* don't do the read, it's not guaranteed to return an EOF,
+ * just force an EOF
+ */
+ YY_CURRENT_BUFFER_LVALUE->yy_n_chars = yyg->yy_n_chars = 0;
+
+ else
+ {
+ int num_to_read =
+ YY_CURRENT_BUFFER_LVALUE->yy_buf_size - number_to_move - 1;
+
+ while ( num_to_read <= 0 )
+ { /* Not enough room in the buffer - grow it. */
+
+ YY_FATAL_ERROR(
+"input buffer overflow, can't enlarge buffer because scanner uses REJECT" );
+
+ }
+
+ if ( num_to_read > YY_READ_BUF_SIZE )
+ num_to_read = YY_READ_BUF_SIZE;
+
+ /* Read in more data. */
+ YY_INPUT( (&YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[number_to_move]),
+ yyg->yy_n_chars, (size_t) num_to_read );
+
+ YY_CURRENT_BUFFER_LVALUE->yy_n_chars = yyg->yy_n_chars;
+ }
+
+ if ( yyg->yy_n_chars == 0 )
+ {
+ if ( number_to_move == YY_MORE_ADJ )
+ {
+ ret_val = EOB_ACT_END_OF_FILE;
+ glcpp_restart(yyin ,yyscanner);
+ }
+
+ else
+ {
+ ret_val = EOB_ACT_LAST_MATCH;
+ YY_CURRENT_BUFFER_LVALUE->yy_buffer_status =
+ YY_BUFFER_EOF_PENDING;
+ }
+ }
+
+ else
+ ret_val = EOB_ACT_CONTINUE_SCAN;
+
+ if ((yy_size_t) (yyg->yy_n_chars + number_to_move) > YY_CURRENT_BUFFER_LVALUE->yy_buf_size) {
+ /* Extend the array by 50%, plus the number we really need. */
+ yy_size_t new_size = yyg->yy_n_chars + number_to_move + (yyg->yy_n_chars >> 1);
+ YY_CURRENT_BUFFER_LVALUE->yy_ch_buf = (char *) glcpp_realloc((void *) YY_CURRENT_BUFFER_LVALUE->yy_ch_buf,new_size ,yyscanner );
+ if ( ! YY_CURRENT_BUFFER_LVALUE->yy_ch_buf )
+ YY_FATAL_ERROR( "out of dynamic memory in yy_get_next_buffer()" );
+ }
+
+ yyg->yy_n_chars += number_to_move;
+ YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[yyg->yy_n_chars] = YY_END_OF_BUFFER_CHAR;
+ YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[yyg->yy_n_chars + 1] = YY_END_OF_BUFFER_CHAR;
+
+ yyg->yytext_ptr = &YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[0];
+
+ return ret_val;
+}
+
+/* yy_get_previous_state - get the state just before the EOB char was reached */
+
+ static yy_state_type yy_get_previous_state (yyscan_t yyscanner)
+{
+ register yy_state_type yy_current_state;
+ register char *yy_cp;
+ struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
+
+ yy_current_state = yyg->yy_start;
+ yy_current_state += YY_AT_BOL();
+
+ yyg->yy_state_ptr = yyg->yy_state_buf;
+ *yyg->yy_state_ptr++ = yy_current_state;
+
+ for ( yy_cp = yyg->yytext_ptr + YY_MORE_ADJ; yy_cp < yyg->yy_c_buf_p; ++yy_cp )
+ {
+ register YY_CHAR yy_c = (*yy_cp ? yy_ec[YY_SC_TO_UI(*yy_cp)] : 1);
+ while ( yy_chk[yy_base[yy_current_state] + yy_c] != yy_current_state )
+ {
+ yy_current_state = (int) yy_def[yy_current_state];
+ if ( yy_current_state >= 151 )
+ yy_c = yy_meta[(unsigned int) yy_c];
+ }
+ yy_current_state = yy_nxt[yy_base[yy_current_state] + (unsigned int) yy_c];
+ *yyg->yy_state_ptr++ = yy_current_state;
+ }
+
+ return yy_current_state;
+}
+
+/* yy_try_NUL_trans - try to make a transition on the NUL character
+ *
+ * synopsis
+ * next_state = yy_try_NUL_trans( current_state );
+ */
+ static yy_state_type yy_try_NUL_trans (yy_state_type yy_current_state , yyscan_t yyscanner)
+{
+ register int yy_is_jam;
+ struct yyguts_t * yyg = (struct yyguts_t*)yyscanner; /* This var may be unused depending upon options. */
+
+ register YY_CHAR yy_c = 1;
+ while ( yy_chk[yy_base[yy_current_state] + yy_c] != yy_current_state )
+ {
+ yy_current_state = (int) yy_def[yy_current_state];
+ if ( yy_current_state >= 151 )
+ yy_c = yy_meta[(unsigned int) yy_c];
+ }
+ yy_current_state = yy_nxt[yy_base[yy_current_state] + (unsigned int) yy_c];
+ yy_is_jam = (yy_current_state == 150);
+ if ( ! yy_is_jam )
+ *yyg->yy_state_ptr++ = yy_current_state;
+
+ return yy_is_jam ? 0 : yy_current_state;
+}
+
+ static void yyunput (int c, register char * yy_bp , yyscan_t yyscanner)
+{
+ register char *yy_cp;
+ struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
+
+ yy_cp = yyg->yy_c_buf_p;
+
+ /* undo effects of setting up yytext */
+ *yy_cp = yyg->yy_hold_char;
+
+ if ( yy_cp < YY_CURRENT_BUFFER_LVALUE->yy_ch_buf + 2 )
+ { /* need to shift things up to make room */
+ /* +2 for EOB chars. */
+ register int number_to_move = yyg->yy_n_chars + 2;
+ register char *dest = &YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[
+ YY_CURRENT_BUFFER_LVALUE->yy_buf_size + 2];
+ register char *source =
+ &YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[number_to_move];
+
+ while ( source > YY_CURRENT_BUFFER_LVALUE->yy_ch_buf )
+ *--dest = *--source;
+
+ yy_cp += (int) (dest - source);
+ yy_bp += (int) (dest - source);
+ YY_CURRENT_BUFFER_LVALUE->yy_n_chars =
+ yyg->yy_n_chars = YY_CURRENT_BUFFER_LVALUE->yy_buf_size;
+
+ if ( yy_cp < YY_CURRENT_BUFFER_LVALUE->yy_ch_buf + 2 )
+ YY_FATAL_ERROR( "flex scanner push-back overflow" );
+ }
+
+ *--yy_cp = (char) c;
+
+ yyg->yytext_ptr = yy_bp;
+ yyg->yy_hold_char = *yy_cp;
+ yyg->yy_c_buf_p = yy_cp;
+}
+
+#ifndef YY_NO_INPUT
+#ifdef __cplusplus
+ static int yyinput (yyscan_t yyscanner)
+#else
+ static int input (yyscan_t yyscanner)
+#endif
+
+{
+ int c;
+ struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
+
+ *yyg->yy_c_buf_p = yyg->yy_hold_char;
+
+ if ( *yyg->yy_c_buf_p == YY_END_OF_BUFFER_CHAR )
+ {
+ /* yy_c_buf_p now points to the character we want to return.
+ * If this occurs *before* the EOB characters, then it's a
+ * valid NUL; if not, then we've hit the end of the buffer.
+ */
+ if ( yyg->yy_c_buf_p < &YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[yyg->yy_n_chars] )
+ /* This was really a NUL. */
+ *yyg->yy_c_buf_p = '\0';
+
+ else
+ { /* need more input */
+ int offset = yyg->yy_c_buf_p - yyg->yytext_ptr;
+ ++yyg->yy_c_buf_p;
+
+ switch ( yy_get_next_buffer( yyscanner ) )
+ {
+ case EOB_ACT_LAST_MATCH:
+ /* This happens because yy_g_n_b()
+ * sees that we've accumulated a
+ * token and flags that we need to
+ * try matching the token before
+ * proceeding. But for input(),
+ * there's no matching to consider.
+ * So convert the EOB_ACT_LAST_MATCH
+ * to EOB_ACT_END_OF_FILE.
+ */
+
+ /* Reset buffer status. */
+ glcpp_restart(yyin ,yyscanner);
+
+ /*FALLTHROUGH*/
+
+ case EOB_ACT_END_OF_FILE:
+ {
+ if ( glcpp_wrap(yyscanner ) )
+ return EOF;
+
+ if ( ! yyg->yy_did_buffer_switch_on_eof )
+ YY_NEW_FILE;
+#ifdef __cplusplus
+ return yyinput(yyscanner);
+#else
+ return input(yyscanner);
+#endif
+ }
+
+ case EOB_ACT_CONTINUE_SCAN:
+ yyg->yy_c_buf_p = yyg->yytext_ptr + offset;
+ break;
+ }
+ }
+ }
+
+ c = *(unsigned char *) yyg->yy_c_buf_p; /* cast for 8-bit char's */
+ *yyg->yy_c_buf_p = '\0'; /* preserve yytext */
+ yyg->yy_hold_char = *++yyg->yy_c_buf_p;
+
+ YY_CURRENT_BUFFER_LVALUE->yy_at_bol = (c == '\n');
+
+ return c;
+}
+#endif /* ifndef YY_NO_INPUT */
+
+/** Immediately switch to a different input stream.
+ * @param input_file A readable stream.
+ * @param yyscanner The scanner object.
+ * @note This function does not reset the start condition to @c INITIAL .
+ */
+ void glcpp_restart (FILE * input_file , yyscan_t yyscanner)
+{
+ struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
+
+ if ( ! YY_CURRENT_BUFFER ){
+ glcpp_ensure_buffer_stack (yyscanner);
+ YY_CURRENT_BUFFER_LVALUE =
+ glcpp__create_buffer(yyin,YY_BUF_SIZE ,yyscanner);
+ }
+
+ glcpp__init_buffer(YY_CURRENT_BUFFER,input_file ,yyscanner);
+ glcpp__load_buffer_state(yyscanner );
+}
+
+/** Switch to a different input buffer.
+ * @param new_buffer The new input buffer.
+ * @param yyscanner The scanner object.
+ */
+ void glcpp__switch_to_buffer (YY_BUFFER_STATE new_buffer , yyscan_t yyscanner)
+{
+ struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
+
+ /* TODO. We should be able to replace this entire function body
+ * with
+ * glcpp_pop_buffer_state();
+ * glcpp_push_buffer_state(new_buffer);
+ */
+ glcpp_ensure_buffer_stack (yyscanner);
+ if ( YY_CURRENT_BUFFER == new_buffer )
+ return;
+
+ if ( YY_CURRENT_BUFFER )
+ {
+ /* Flush out information for old buffer. */
+ *yyg->yy_c_buf_p = yyg->yy_hold_char;
+ YY_CURRENT_BUFFER_LVALUE->yy_buf_pos = yyg->yy_c_buf_p;
+ YY_CURRENT_BUFFER_LVALUE->yy_n_chars = yyg->yy_n_chars;
+ }
+
+ YY_CURRENT_BUFFER_LVALUE = new_buffer;
+ glcpp__load_buffer_state(yyscanner );
+
+ /* We don't actually know whether we did this switch during
+ * EOF (glcpp_wrap()) processing, but the only time this flag
+ * is looked at is after glcpp_wrap() is called, so it's safe
+ * to go ahead and always set it.
+ */
+ yyg->yy_did_buffer_switch_on_eof = 1;
+}
+
+static void glcpp__load_buffer_state (yyscan_t yyscanner)
+{
+ struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
+ yyg->yy_n_chars = YY_CURRENT_BUFFER_LVALUE->yy_n_chars;
+ yyg->yytext_ptr = yyg->yy_c_buf_p = YY_CURRENT_BUFFER_LVALUE->yy_buf_pos;
+ yyin = YY_CURRENT_BUFFER_LVALUE->yy_input_file;
+ yyg->yy_hold_char = *yyg->yy_c_buf_p;
+}
+
+/** Allocate and initialize an input buffer state.
+ * @param file A readable stream.
+ * @param size The character buffer size in bytes. When in doubt, use @c YY_BUF_SIZE.
+ * @param yyscanner The scanner object.
+ * @return the allocated buffer state.
+ */
+ YY_BUFFER_STATE glcpp__create_buffer (FILE * file, int size , yyscan_t yyscanner)
+{
+ YY_BUFFER_STATE b;
+
+ b = (YY_BUFFER_STATE) glcpp_alloc(sizeof( struct yy_buffer_state ) ,yyscanner );
+ if ( ! b )
+ YY_FATAL_ERROR( "out of dynamic memory in glcpp__create_buffer()" );
+
+ b->yy_buf_size = size;
+
+ /* yy_ch_buf has to be 2 characters longer than the size given because
+ * we need to put in 2 end-of-buffer characters.
+ */
+ b->yy_ch_buf = (char *) glcpp_alloc(b->yy_buf_size + 2 ,yyscanner );
+ if ( ! b->yy_ch_buf )
+ YY_FATAL_ERROR( "out of dynamic memory in glcpp__create_buffer()" );
+
+ b->yy_is_our_buffer = 1;
+
+ glcpp__init_buffer(b,file ,yyscanner);
+
+ return b;
+}
+
+/** Destroy the buffer.
+ * @param b a buffer created with glcpp__create_buffer()
+ * @param yyscanner The scanner object.
+ */
+ void glcpp__delete_buffer (YY_BUFFER_STATE b , yyscan_t yyscanner)
+{
+ struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
+
+ if ( ! b )
+ return;
+
+ if ( b == YY_CURRENT_BUFFER ) /* Not sure if we should pop here. */
+ YY_CURRENT_BUFFER_LVALUE = (YY_BUFFER_STATE) 0;
+
+ if ( b->yy_is_our_buffer )
+ glcpp_free((void *) b->yy_ch_buf ,yyscanner );
+
+ glcpp_free((void *) b ,yyscanner );
+}
+
+/* Initializes or reinitializes a buffer.
+ * This function is sometimes called more than once on the same buffer,
+ * such as during a glcpp_restart() or at EOF.
+ */
+ static void glcpp__init_buffer (YY_BUFFER_STATE b, FILE * file , yyscan_t yyscanner)
+
+{
+ int oerrno = errno;
+ struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
+
+ glcpp__flush_buffer(b ,yyscanner);
+
+ b->yy_input_file = file;
+ b->yy_fill_buffer = 1;
+
+ /* If b is the current buffer, then glcpp__init_buffer was _probably_
+ * called from glcpp_restart() or through yy_get_next_buffer.
+ * In that case, we don't want to reset the lineno or column.
+ */
+ if (b != YY_CURRENT_BUFFER){
+ b->yy_bs_lineno = 1;
+ b->yy_bs_column = 0;
+ }
+
+ b->yy_is_interactive = 0;
+
+ errno = oerrno;
+}
+
+/** Discard all buffered characters. On the next scan, YY_INPUT will be called.
+ * @param b the buffer state to be flushed, usually @c YY_CURRENT_BUFFER.
+ * @param yyscanner The scanner object.
+ */
+ void glcpp__flush_buffer (YY_BUFFER_STATE b , yyscan_t yyscanner)
+{
+ struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
+ if ( ! b )
+ return;
+
+ b->yy_n_chars = 0;
+
+ /* We always need two end-of-buffer characters. The first causes
+ * a transition to the end-of-buffer state. The second causes
+ * a jam in that state.
+ */
+ b->yy_ch_buf[0] = YY_END_OF_BUFFER_CHAR;
+ b->yy_ch_buf[1] = YY_END_OF_BUFFER_CHAR;
+
+ b->yy_buf_pos = &b->yy_ch_buf[0];
+
+ b->yy_at_bol = 1;
+ b->yy_buffer_status = YY_BUFFER_NEW;
+
+ if ( b == YY_CURRENT_BUFFER )
+ glcpp__load_buffer_state(yyscanner );
+}
+
+/** Pushes the new state onto the stack. The new state becomes
+ * the current state. This function will allocate the stack
+ * if necessary.
+ * @param new_buffer The new state.
+ * @param yyscanner The scanner object.
+ */
+void glcpp_push_buffer_state (YY_BUFFER_STATE new_buffer , yyscan_t yyscanner)
+{
+ struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
+ if (new_buffer == NULL)
+ return;
+
+ glcpp_ensure_buffer_stack(yyscanner);
+
+ /* This block is copied from glcpp__switch_to_buffer. */
+ if ( YY_CURRENT_BUFFER )
+ {
+ /* Flush out information for old buffer. */
+ *yyg->yy_c_buf_p = yyg->yy_hold_char;
+ YY_CURRENT_BUFFER_LVALUE->yy_buf_pos = yyg->yy_c_buf_p;
+ YY_CURRENT_BUFFER_LVALUE->yy_n_chars = yyg->yy_n_chars;
+ }
+
+ /* Only push if top exists. Otherwise, replace top. */
+ if (YY_CURRENT_BUFFER)
+ yyg->yy_buffer_stack_top++;
+ YY_CURRENT_BUFFER_LVALUE = new_buffer;
+
+ /* copied from glcpp__switch_to_buffer. */
+ glcpp__load_buffer_state(yyscanner );
+ yyg->yy_did_buffer_switch_on_eof = 1;
+}
+
+/** Removes and deletes the top of the stack, if present.
+ * The next element becomes the new top.
+ * @param yyscanner The scanner object.
+ */
+void glcpp_pop_buffer_state (yyscan_t yyscanner)
+{
+ struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
+ if (!YY_CURRENT_BUFFER)
+ return;
+
+ glcpp__delete_buffer(YY_CURRENT_BUFFER ,yyscanner);
+ YY_CURRENT_BUFFER_LVALUE = NULL;
+ if (yyg->yy_buffer_stack_top > 0)
+ --yyg->yy_buffer_stack_top;
+
+ if (YY_CURRENT_BUFFER) {
+ glcpp__load_buffer_state(yyscanner );
+ yyg->yy_did_buffer_switch_on_eof = 1;
+ }
+}
+
+/* Allocates the stack if it does not exist.
+ * Guarantees space for at least one push.
+ */
+static void glcpp_ensure_buffer_stack (yyscan_t yyscanner)
+{
+ int num_to_alloc;
+ struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
+
+ if (!yyg->yy_buffer_stack) {
+
+ /* First allocation is just for 2 elements, since we don't know if this
+ * scanner will even need a stack. We use 2 instead of 1 to avoid an
+ * immediate realloc on the next call.
+ */
+ num_to_alloc = 1;
+ yyg->yy_buffer_stack = (struct yy_buffer_state**)glcpp_alloc
+ (num_to_alloc * sizeof(struct yy_buffer_state*)
+ , yyscanner);
+ if ( ! yyg->yy_buffer_stack )
+ YY_FATAL_ERROR( "out of dynamic memory in glcpp_ensure_buffer_stack()" );
+
+ memset(yyg->yy_buffer_stack, 0, num_to_alloc * sizeof(struct yy_buffer_state*));
+
+ yyg->yy_buffer_stack_max = num_to_alloc;
+ yyg->yy_buffer_stack_top = 0;
+ return;
+ }
+
+ if (yyg->yy_buffer_stack_top >= (yyg->yy_buffer_stack_max) - 1){
+
+ /* Increase the buffer to prepare for a possible push. */
+ int grow_size = 8 /* arbitrary grow size */;
+
+ num_to_alloc = yyg->yy_buffer_stack_max + grow_size;
+ yyg->yy_buffer_stack = (struct yy_buffer_state**)glcpp_realloc
+ (yyg->yy_buffer_stack,
+ num_to_alloc * sizeof(struct yy_buffer_state*)
+ , yyscanner);
+ if ( ! yyg->yy_buffer_stack )
+ YY_FATAL_ERROR( "out of dynamic memory in glcpp_ensure_buffer_stack()" );
+
+ /* zero only the new slots.*/
+ memset(yyg->yy_buffer_stack + yyg->yy_buffer_stack_max, 0, grow_size * sizeof(struct yy_buffer_state*));
+ yyg->yy_buffer_stack_max = num_to_alloc;
+ }
+}
+
+/** Setup the input buffer state to scan directly from a user-specified character buffer.
+ * @param base the character buffer
+ * @param size the size in bytes of the character buffer
+ * @param yyscanner The scanner object.
+ * @return the newly allocated buffer state object.
+ */
+YY_BUFFER_STATE glcpp__scan_buffer (char * base, yy_size_t size , yyscan_t yyscanner)
+{
+ YY_BUFFER_STATE b;
+
+ if ( size < 2 ||
+ base[size-2] != YY_END_OF_BUFFER_CHAR ||
+ base[size-1] != YY_END_OF_BUFFER_CHAR )
+ /* They forgot to leave room for the EOB's. */
+ return 0;
+
+ b = (YY_BUFFER_STATE) glcpp_alloc(sizeof( struct yy_buffer_state ) ,yyscanner );
+ if ( ! b )
+ YY_FATAL_ERROR( "out of dynamic memory in glcpp__scan_buffer()" );
+
+ b->yy_buf_size = size - 2; /* "- 2" to take care of EOB's */
+ b->yy_buf_pos = b->yy_ch_buf = base;
+ b->yy_is_our_buffer = 0;
+ b->yy_input_file = 0;
+ b->yy_n_chars = b->yy_buf_size;
+ b->yy_is_interactive = 0;
+ b->yy_at_bol = 1;
+ b->yy_fill_buffer = 0;
+ b->yy_buffer_status = YY_BUFFER_NEW;
+
+ glcpp__switch_to_buffer(b ,yyscanner );
+
+ return b;
+}
+
+/** Setup the input buffer state to scan a string. The next call to glcpp_lex() will
+ * scan from a @e copy of @a str.
+ * @param yystr a NUL-terminated string to scan
+ * @param yyscanner The scanner object.
+ * @return the newly allocated buffer state object.
+ * @note If you want to scan bytes that may contain NUL values, then use
+ * glcpp__scan_bytes() instead.
+ */
+YY_BUFFER_STATE glcpp__scan_string (yyconst char * yystr , yyscan_t yyscanner)
+{
+
+ return glcpp__scan_bytes(yystr,strlen(yystr) ,yyscanner);
+}
+
+/** Setup the input buffer state to scan the given bytes. The next call to glcpp_lex() will
+ * scan from a @e copy of @a bytes.
+ * @param yybytes the byte buffer to scan
+ * @param _yybytes_len the number of bytes in the buffer pointed to by @a bytes.
+ * @param yyscanner The scanner object.
+ * @return the newly allocated buffer state object.
+ */
+YY_BUFFER_STATE glcpp__scan_bytes (yyconst char * yybytes, int _yybytes_len , yyscan_t yyscanner)
+{
+ YY_BUFFER_STATE b;
+ char *buf;
+ yy_size_t n;
+ int i;
+
+ /* Get memory for full buffer, including space for trailing EOB's. */
+ n = _yybytes_len + 2;
+ buf = (char *) glcpp_alloc(n ,yyscanner );
+ if ( ! buf )
+ YY_FATAL_ERROR( "out of dynamic memory in glcpp__scan_bytes()" );
+
+ for ( i = 0; i < _yybytes_len; ++i )
+ buf[i] = yybytes[i];
+
+ buf[_yybytes_len] = buf[_yybytes_len+1] = YY_END_OF_BUFFER_CHAR;
+
+ b = glcpp__scan_buffer(buf,n ,yyscanner);
+ if ( ! b )
+ YY_FATAL_ERROR( "bad buffer in glcpp__scan_bytes()" );
+
+ /* It's okay to grow etc. this buffer, and we should throw it
+ * away when we're done.
+ */
+ b->yy_is_our_buffer = 1;
+
+ return b;
+}
+
+ static void yy_push_state (int new_state , yyscan_t yyscanner)
+{
+ struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
+ if ( yyg->yy_start_stack_ptr >= yyg->yy_start_stack_depth )
+ {
+ yy_size_t new_size;
+
+ yyg->yy_start_stack_depth += YY_START_STACK_INCR;
+ new_size = yyg->yy_start_stack_depth * sizeof( int );
+
+ if ( ! yyg->yy_start_stack )
+ yyg->yy_start_stack = (int *) glcpp_alloc(new_size ,yyscanner );
+
+ else
+ yyg->yy_start_stack = (int *) glcpp_realloc((void *) yyg->yy_start_stack,new_size ,yyscanner );
+
+ if ( ! yyg->yy_start_stack )
+ YY_FATAL_ERROR( "out of memory expanding start-condition stack" );
+ }
+
+ yyg->yy_start_stack[yyg->yy_start_stack_ptr++] = YY_START;
+
+ BEGIN(new_state);
+}
+
+ static void yy_pop_state (yyscan_t yyscanner)
+{
+ struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
+ if ( --yyg->yy_start_stack_ptr < 0 )
+ YY_FATAL_ERROR( "start-condition stack underflow" );
+
+ BEGIN(yyg->yy_start_stack[yyg->yy_start_stack_ptr]);
+}
+
+ static int yy_top_state (yyscan_t yyscanner)
+{
+ struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
+ return yyg->yy_start_stack[yyg->yy_start_stack_ptr - 1];
+}
+
+#ifndef YY_EXIT_FAILURE
+#define YY_EXIT_FAILURE 2
+#endif
+
+static void yy_fatal_error (yyconst char* msg , yyscan_t yyscanner)
+{
+ (void) fprintf( stderr, "%s\n", msg );
+ exit( YY_EXIT_FAILURE );
+}
+
+/* Redefine yyless() so it works in section 3 code. */
+
+#undef yyless
+#define yyless(n) \
+ do \
+ { \
+ /* Undo effects of setting up yytext. */ \
+ int yyless_macro_arg = (n); \
+ YY_LESS_LINENO(yyless_macro_arg);\
+ yytext[yyleng] = yyg->yy_hold_char; \
+ yyg->yy_c_buf_p = yytext + yyless_macro_arg; \
+ yyg->yy_hold_char = *yyg->yy_c_buf_p; \
+ *yyg->yy_c_buf_p = '\0'; \
+ yyleng = yyless_macro_arg; \
+ } \
+ while ( 0 )
+
+/* Accessor methods (get/set functions) to struct members. */
+
+/** Get the user-defined data for this scanner.
+ * @param yyscanner The scanner object.
+ */
+YY_EXTRA_TYPE glcpp_get_extra (yyscan_t yyscanner)
+{
+ struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
+ return yyextra;
+}
+
+/** Get the current line number.
+ * @param yyscanner The scanner object.
+ */
+int glcpp_get_lineno (yyscan_t yyscanner)
+{
+ struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
+
+ if (! YY_CURRENT_BUFFER)
+ return 0;
+
+ return yylineno;
+}
+
+/** Get the current column number.
+ * @param yyscanner The scanner object.
+ */
+int glcpp_get_column (yyscan_t yyscanner)
+{
+ struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
+
+ if (! YY_CURRENT_BUFFER)
+ return 0;
+
+ return yycolumn;
+}
+
+/** Get the input stream.
+ * @param yyscanner The scanner object.
+ */
+FILE *glcpp_get_in (yyscan_t yyscanner)
+{
+ struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
+ return yyin;
+}
+
+/** Get the output stream.
+ * @param yyscanner The scanner object.
+ */
+FILE *glcpp_get_out (yyscan_t yyscanner)
+{
+ struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
+ return yyout;
+}
+
+/** Get the length of the current token.
+ * @param yyscanner The scanner object.
+ */
+int glcpp_get_leng (yyscan_t yyscanner)
+{
+ struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
+ return yyleng;
+}
+
+/** Get the current token.
+ * @param yyscanner The scanner object.
+ */
+
+char *glcpp_get_text (yyscan_t yyscanner)
+{
+ struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
+ return yytext;
+}
+
+/** Set the user-defined data. This data is never touched by the scanner.
+ * @param user_defined The data to be associated with this scanner.
+ * @param yyscanner The scanner object.
+ */
+void glcpp_set_extra (YY_EXTRA_TYPE user_defined , yyscan_t yyscanner)
+{
+ struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
+ yyextra = user_defined ;
+}
+
+/** Set the current line number.
+ * @param line_number
+ * @param yyscanner The scanner object.
+ */
+void glcpp_set_lineno (int line_number , yyscan_t yyscanner)
+{
+ struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
+
+ /* lineno is only valid if an input buffer exists. */
+ if (! YY_CURRENT_BUFFER )
+ yy_fatal_error( "glcpp_set_lineno called with no buffer" , yyscanner);
+
+ yylineno = line_number;
+}
+
+/** Set the current column.
+ * @param line_number
+ * @param yyscanner The scanner object.
+ */
+void glcpp_set_column (int column_no , yyscan_t yyscanner)
+{
+ struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
+
+ /* column is only valid if an input buffer exists. */
+ if (! YY_CURRENT_BUFFER )
+ yy_fatal_error( "glcpp_set_column called with no buffer" , yyscanner);
+
+ yycolumn = column_no;
+}
+
+/** Set the input stream. This does not discard the current
+ * input buffer.
+ * @param in_str A readable stream.
+ * @param yyscanner The scanner object.
+ * @see glcpp__switch_to_buffer
+ */
+void glcpp_set_in (FILE * in_str , yyscan_t yyscanner)
+{
+ struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
+ yyin = in_str ;
+}
+
+void glcpp_set_out (FILE * out_str , yyscan_t yyscanner)
+{
+ struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
+ yyout = out_str ;
+}
+
+int glcpp_get_debug (yyscan_t yyscanner)
+{
+ struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
+ return yy_flex_debug;
+}
+
+void glcpp_set_debug (int bdebug , yyscan_t yyscanner)
+{
+ struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
+ yy_flex_debug = bdebug ;
+}
+
+/* Accessor methods for yylval and yylloc */
+
+YYSTYPE * glcpp_get_lval (yyscan_t yyscanner)
+{
+ struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
+ return yylval;
+}
+
+void glcpp_set_lval (YYSTYPE * yylval_param , yyscan_t yyscanner)
+{
+ struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
+ yylval = yylval_param;
+}
+
+YYLTYPE *glcpp_get_lloc (yyscan_t yyscanner)
+{
+ struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
+ return yylloc;
+}
+
+void glcpp_set_lloc (YYLTYPE * yylloc_param , yyscan_t yyscanner)
+{
+ struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
+ yylloc = yylloc_param;
+}
+
+/* User-visible API */
+
+/* glcpp_lex_init is special because it creates the scanner itself, so it is
+ * the ONLY reentrant function that doesn't take the scanner as the last argument.
+ * That's why we explicitly handle the declaration, instead of using our macros.
+ */
+
+int glcpp_lex_init(yyscan_t* ptr_yy_globals)
+
+{
+ if (ptr_yy_globals == NULL){
+ errno = EINVAL;
+ return 1;
+ }
+
+ *ptr_yy_globals = (yyscan_t) glcpp_alloc ( sizeof( struct yyguts_t ), NULL );
+
+ if (*ptr_yy_globals == NULL){
+ errno = ENOMEM;
+ return 1;
+ }
+
+ /* By setting to 0xAA, we expose bugs in yy_init_globals. Leave at 0x00 for releases. */
+ memset(*ptr_yy_globals,0x00,sizeof(struct yyguts_t));
+
+ return yy_init_globals ( *ptr_yy_globals );
+}
+
+/* glcpp_lex_init_extra has the same functionality as glcpp_lex_init, but follows the
+ * convention of taking the scanner as the last argument. Note however, that
+ * this is a *pointer* to a scanner, as it will be allocated by this call (and
+ * is the reason, too, why this function also must handle its own declaration).
+ * The user defined value in the first argument will be available to glcpp_alloc in
+ * the yyextra field.
+ */
+
+int glcpp_lex_init_extra(YY_EXTRA_TYPE yy_user_defined,yyscan_t* ptr_yy_globals )
+
+{
+ struct yyguts_t dummy_yyguts;
+
+ glcpp_set_extra (yy_user_defined, &dummy_yyguts);
+
+ if (ptr_yy_globals == NULL){
+ errno = EINVAL;
+ return 1;
+ }
+
+ *ptr_yy_globals = (yyscan_t) glcpp_alloc ( sizeof( struct yyguts_t ), &dummy_yyguts );
+
+ if (*ptr_yy_globals == NULL){
+ errno = ENOMEM;
+ return 1;
+ }
+
+ /* By setting to 0xAA, we expose bugs in
+ yy_init_globals. Leave at 0x00 for releases. */
+ memset(*ptr_yy_globals,0x00,sizeof(struct yyguts_t));
+
+ glcpp_set_extra (yy_user_defined, *ptr_yy_globals);
+
+ return yy_init_globals ( *ptr_yy_globals );
+}
+
+static int yy_init_globals (yyscan_t yyscanner)
+{
+ struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
+ /* Initialization is the same as for the non-reentrant scanner.
+ * This function is called from glcpp_lex_destroy(), so don't allocate here.
+ */
+
+ yyg->yy_buffer_stack = 0;
+ yyg->yy_buffer_stack_top = 0;
+ yyg->yy_buffer_stack_max = 0;
+ yyg->yy_c_buf_p = (char *) 0;
+ yyg->yy_init = 0;
+ yyg->yy_start = 0;
+
+ yyg->yy_start_stack_ptr = 0;
+ yyg->yy_start_stack_depth = 0;
+ yyg->yy_start_stack = NULL;
+
+ yyg->yy_state_buf = 0;
+ yyg->yy_state_ptr = 0;
+ yyg->yy_full_match = 0;
+ yyg->yy_lp = 0;
+
+/* Defined in main.c */
+#ifdef YY_STDINIT
+ yyin = stdin;
+ yyout = stdout;
+#else
+ yyin = (FILE *) 0;
+ yyout = (FILE *) 0;
+#endif
+
+ /* For future reference: Set errno on error, since we are called by
+ * glcpp_lex_init()
+ */
+ return 0;
+}
+
+/* glcpp_lex_destroy is for both reentrant and non-reentrant scanners. */
+int glcpp_lex_destroy (yyscan_t yyscanner)
+{
+ struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
+
+ /* Pop the buffer stack, destroying each element. */
+ while(YY_CURRENT_BUFFER){
+ glcpp__delete_buffer(YY_CURRENT_BUFFER ,yyscanner );
+ YY_CURRENT_BUFFER_LVALUE = NULL;
+ glcpp_pop_buffer_state(yyscanner);
+ }
+
+ /* Destroy the stack itself. */
+ glcpp_free(yyg->yy_buffer_stack ,yyscanner);
+ yyg->yy_buffer_stack = NULL;
+
+ /* Destroy the start condition stack. */
+ glcpp_free(yyg->yy_start_stack ,yyscanner );
+ yyg->yy_start_stack = NULL;
+
+ glcpp_free ( yyg->yy_state_buf , yyscanner);
+ yyg->yy_state_buf = NULL;
+
+ /* Reset the globals. This is important in a non-reentrant scanner so the next time
+ * glcpp_lex() is called, initialization will occur. */
+ yy_init_globals( yyscanner);
+
+ /* Destroy the main struct (reentrant only). */
+ glcpp_free ( yyscanner , yyscanner );
+ yyscanner = NULL;
+ return 0;
+}
+
+/*
+ * Internal utility routines.
+ */
+
+#ifndef yytext_ptr
+static void yy_flex_strncpy (char* s1, yyconst char * s2, int n , yyscan_t yyscanner)
+{
+ register int i;
+ for ( i = 0; i < n; ++i )
+ s1[i] = s2[i];
+}
+#endif
+
+#ifdef YY_NEED_STRLEN
+static int yy_flex_strlen (yyconst char * s , yyscan_t yyscanner)
+{
+ register int n;
+ for ( n = 0; s[n]; ++n )
+ ;
+
+ return n;
+}
+#endif
+
+void *glcpp_alloc (yy_size_t size , yyscan_t yyscanner)
+{
+ return (void *) malloc( size );
+}
+
+void *glcpp_realloc (void * ptr, yy_size_t size , yyscan_t yyscanner)
+{
+ /* The cast to (char *) in the following accommodates both
+ * implementations that use char* generic pointers, and those
+ * that use void* generic pointers. It works with the latter
+ * because both ANSI C and C++ allow castless assignment from
+ * any pointer type to void*, and deal with argument conversions
+ * as though doing an assignment.
+ */
+ return (void *) realloc( (char *) ptr, size );
+}
+
+void glcpp_free (void * ptr , yyscan_t yyscanner)
+{
+ free( (char *) ptr ); /* see glcpp_realloc() for (char *) cast */
+}
+
+#define YYTABLES_NAME "yytables"
+
+#line 287 "glcpp/glcpp-lex.l"
+
+
+
+void
+glcpp_lex_set_source_string(glcpp_parser_t *parser, const char *shader)
+{
+ glcpp__scan_string(shader,parser->scanner);
+}
+
diff --git a/src/glsl/glcpp/glcpp-lex.l b/src/glsl/glcpp/glcpp-lex.l
new file mode 100644
index 00000000000..1cd95b238d2
--- /dev/null
+++ b/src/glsl/glcpp/glcpp-lex.l
@@ -0,0 +1,293 @@
+%{
+/*
+ * Copyright © 2010 Intel Corporation
+ *
+ * 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 (including the next
+ * paragraph) 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
+ * THE AUTHORS OR COPYRIGHT HOLDERS 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.
+ */
+
+#include <stdio.h>
+#include <string.h>
+#include <ctype.h>
+
+#include "glcpp.h"
+#include "glcpp-parse.h"
+
+/* Flex annoyingly generates some functions without making them
+ * static. Let's declare them here. */
+int glcpp_get_column (yyscan_t yyscanner);
+void glcpp_set_column (int column_no , yyscan_t yyscanner);
+
+#define YY_NO_INPUT
+
+#define YY_USER_ACTION \
+ do { \
+ yylloc->source = 0; \
+ yylloc->first_column = yycolumn + 1; \
+ yylloc->first_line = yylineno; \
+ yycolumn += yyleng; \
+ } while(0);
+#define YY_USER_INIT yylineno = 1; yycolumn = 1;
+%}
+
+%option bison-bridge bison-locations reentrant noyywrap
+%option extra-type="glcpp_parser_t *"
+%option prefix="glcpp_"
+%option stack
+%option never-interactive
+
+%x DONE COMMENT UNREACHABLE
+
+SPACE [[:space:]]
+NONSPACE [^[:space:]]
+NEWLINE [\n]
+HSPACE [ \t]
+HASH ^{HSPACE}*#{HSPACE}*
+IDENTIFIER [_a-zA-Z][_a-zA-Z0-9]*
+PUNCTUATION [][(){}.&*~!/%<>^|;,=+-]
+OTHER [^][(){}.&*~!/%<>^|;,=#[:space:]+-]+
+
+DECIMAL_INTEGER [1-9][0-9]*[uU]?
+OCTAL_INTEGER 0[0-7]*[uU]?
+HEXADECIMAL_INTEGER 0[xX][0-9a-fA-F]+[uU]?
+
+%%
+
+ /* Single-line comments */
+"//"[^\n]*\n {
+ yylineno++;
+ yycolumn = 0;
+ return NEWLINE;
+}
+
+ /* Multi-line comments */
+"/*" { yy_push_state(COMMENT, yyscanner); }
+<COMMENT>[^*\n]*
+<COMMENT>[^*\n]*\n { yylineno++; yycolumn = 0; }
+<COMMENT>"*"+[^*/\n]*
+<COMMENT>"*"+[^*/\n]*\n { yylineno++; yycolumn = 0; }
+<COMMENT>"*"+"/" {
+ yy_pop_state(yyscanner);
+ if (yyextra->space_tokens)
+ return SPACE;
+}
+
+{HASH}(version) {
+ yylval->str = talloc_strdup (yyextra, yytext);
+ yylineno++;
+ yycolumn = 0;
+ yyextra->space_tokens = 0;
+ return HASH_VERSION;
+}
+
+ /* glcpp doesn't handle #extension, #version, or #pragma directives.
+ * Simply pass them through to the main compiler's lexer/parser. */
+{HASH}(extension|pragma)[^\n]+ {
+ yylval->str = talloc_strdup (yyextra, yytext);
+ yylineno++;
+ yycolumn = 0;
+ return OTHER;
+}
+
+{HASH}ifdef/.*\n {
+ yyextra->lexing_if = 1;
+ yyextra->space_tokens = 0;
+ return HASH_IFDEF;
+}
+
+{HASH}ifndef/.*\n {
+ yyextra->lexing_if = 1;
+ yyextra->space_tokens = 0;
+ return HASH_IFNDEF;
+}
+
+{HASH}if/[^_a-zA-Z0-9].*\n {
+ yyextra->lexing_if = 1;
+ yyextra->space_tokens = 0;
+ return HASH_IF;
+}
+
+{HASH}elif/.*\n {
+ yyextra->lexing_if = 1;
+ yyextra->space_tokens = 0;
+ return HASH_ELIF;
+}
+
+{HASH}else/.*\n {
+ yyextra->space_tokens = 0;
+ return HASH_ELSE;
+}
+
+{HASH}endif/.*\n {
+ yyextra->space_tokens = 0;
+ return HASH_ENDIF;
+}
+
+ /* When skipping (due to an #if 0 or similar) consume anything
+ * up to a newline. We do this with less priority than any
+ * #if-related directive (#if, #elif, #else, #endif), but with
+ * more priority than any other directive or token to avoid
+ * any side-effects from skipped content.
+ *
+ * We use the lexing_if flag to avoid skipping any part of an
+ * if conditional expression. */
+[^\n]+/\n {
+ /* Since this rule always matches, YY_USER_ACTION gets called for it,
+ * wrongly incrementing yycolumn. We undo that effect here. */
+ yycolumn -= yyleng;
+ if (yyextra->lexing_if ||
+ yyextra->skip_stack == NULL ||
+ yyextra->skip_stack->type == SKIP_NO_SKIP)
+ {
+ REJECT;
+ }
+}
+
+{HASH}error.* {
+ char *p;
+ for (p = yytext; !isalpha(p[0]); p++); /* skip " # " */
+ p += 5; /* skip "error" */
+ glcpp_error(yylloc, yyextra, "#error%s", p);
+}
+
+{HASH}define{HSPACE}+/{IDENTIFIER}"(" {
+ yyextra->space_tokens = 0;
+ return HASH_DEFINE_FUNC;
+}
+
+{HASH}define {
+ yyextra->space_tokens = 0;
+ return HASH_DEFINE_OBJ;
+}
+
+{HASH}undef {
+ yyextra->space_tokens = 0;
+ return HASH_UNDEF;
+}
+
+{HASH} {
+ yyextra->space_tokens = 0;
+ return HASH;
+}
+
+{DECIMAL_INTEGER} {
+ yylval->str = talloc_strdup (yyextra, yytext);
+ return INTEGER_STRING;
+}
+
+{OCTAL_INTEGER} {
+ yylval->str = talloc_strdup (yyextra, yytext);
+ return INTEGER_STRING;
+}
+
+{HEXADECIMAL_INTEGER} {
+ yylval->str = talloc_strdup (yyextra, yytext);
+ return INTEGER_STRING;
+}
+
+"<<" {
+ return LEFT_SHIFT;
+}
+
+">>" {
+ return RIGHT_SHIFT;
+}
+
+"<=" {
+ return LESS_OR_EQUAL;
+}
+
+">=" {
+ return GREATER_OR_EQUAL;
+}
+
+"==" {
+ return EQUAL;
+}
+
+"!=" {
+ return NOT_EQUAL;
+}
+
+"&&" {
+ return AND;
+}
+
+"||" {
+ return OR;
+}
+
+"##" {
+ return PASTE;
+}
+
+"defined" {
+ return DEFINED;
+}
+
+{IDENTIFIER} {
+ yylval->str = talloc_strdup (yyextra, yytext);
+ return IDENTIFIER;
+}
+
+{PUNCTUATION} {
+ return yytext[0];
+}
+
+{OTHER}+ {
+ yylval->str = talloc_strdup (yyextra, yytext);
+ return OTHER;
+}
+
+{HSPACE}+ {
+ if (yyextra->space_tokens) {
+ return SPACE;
+ }
+}
+
+\n {
+ yyextra->lexing_if = 0;
+ yylineno++;
+ yycolumn = 0;
+ return NEWLINE;
+}
+
+ /* Handle missing newline at EOF. */
+<INITIAL><<EOF>> {
+ BEGIN DONE; /* Don't keep matching this rule forever. */
+ yyextra->lexing_if = 0;
+ return NEWLINE;
+}
+
+ /* We don't actually use the UNREACHABLE start condition. We
+ only have this action here so that we can pretend to call some
+ generated functions, (to avoid "defined but not used"
+ warnings. */
+<UNREACHABLE>. {
+ unput('.');
+ yy_top_state(yyextra);
+}
+
+%%
+
+void
+glcpp_lex_set_source_string(glcpp_parser_t *parser, const char *shader)
+{
+ yy_scan_string(shader, parser->scanner);
+}
diff --git a/src/glsl/glcpp/glcpp-parse.c b/src/glsl/glcpp/glcpp-parse.c
new file mode 100644
index 00000000000..579fe7c7ad8
--- /dev/null
+++ b/src/glsl/glcpp/glcpp-parse.c
@@ -0,0 +1,4055 @@
+/* A Bison parser, made by GNU Bison 2.4.3. */
+
+/* Skeleton implementation for Bison's Yacc-like parsers in C
+
+ Copyright (C) 1984, 1989, 1990, 2000, 2001, 2002, 2003, 2004, 2005, 2006,
+ 2009, 2010 Free Software Foundation, Inc.
+
+ This program is free software: you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program. If not, see <http://www.gnu.org/licenses/>. */
+
+/* As a special exception, you may create a larger work that contains
+ part or all of the Bison parser skeleton and distribute that work
+ under terms of your choice, so long as that work isn't itself a
+ parser generator using the skeleton or a modified version thereof
+ as a parser skeleton. Alternatively, if you modify or redistribute
+ the parser skeleton itself, you may (at your option) remove this
+ special exception, which will cause the skeleton and the resulting
+ Bison output files to be licensed under the GNU General Public
+ License without this special exception.
+
+ This special exception was added by the Free Software Foundation in
+ version 2.2 of Bison. */
+
+/* C LALR(1) parser skeleton written by Richard Stallman, by
+ simplifying the original so-called "semantic" parser. */
+
+/* All symbols defined below should begin with yy or YY, to avoid
+ infringing on user name space. This should be done even for local
+ variables, as they might otherwise be expanded by user macros.
+ There are some unavoidable exceptions within include files to
+ define necessary library symbols; they are noted "INFRINGES ON
+ USER NAME SPACE" below. */
+
+/* Identify Bison output. */
+#define YYBISON 1
+
+/* Bison version. */
+#define YYBISON_VERSION "2.4.3"
+
+/* Skeleton name. */
+#define YYSKELETON_NAME "yacc.c"
+
+/* Pure parsers. */
+#define YYPURE 1
+
+/* Push parsers. */
+#define YYPUSH 0
+
+/* Pull parsers. */
+#define YYPULL 1
+
+/* Using locations. */
+#define YYLSP_NEEDED 1
+
+
+
+/* Copy the first part of user declarations. */
+
+/* Line 189 of yacc.c */
+#line 1 "glcpp/glcpp-parse.y"
+
+/*
+ * Copyright © 2010 Intel Corporation
+ *
+ * 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 (including the next
+ * paragraph) 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
+ * THE AUTHORS OR COPYRIGHT HOLDERS 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.
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <assert.h>
+#include <stdint.h>
+
+#include "glcpp.h"
+#include "main/mtypes.h"
+
+#define glcpp_print(stream, str) stream = talloc_strdup_append(stream, str)
+#define glcpp_printf(stream, fmt, args, ...) \
+ stream = talloc_asprintf_append(stream, fmt, args)
+
+static void
+yyerror (YYLTYPE *locp, glcpp_parser_t *parser, const char *error);
+
+static void
+_define_object_macro (glcpp_parser_t *parser,
+ YYLTYPE *loc,
+ const char *macro,
+ token_list_t *replacements);
+
+static void
+_define_function_macro (glcpp_parser_t *parser,
+ YYLTYPE *loc,
+ const char *macro,
+ string_list_t *parameters,
+ token_list_t *replacements);
+
+static string_list_t *
+_string_list_create (void *ctx);
+
+static void
+_string_list_append_item (string_list_t *list, const char *str);
+
+static int
+_string_list_contains (string_list_t *list, const char *member, int *index);
+
+static int
+_string_list_length (string_list_t *list);
+
+static argument_list_t *
+_argument_list_create (void *ctx);
+
+static void
+_argument_list_append (argument_list_t *list, token_list_t *argument);
+
+static int
+_argument_list_length (argument_list_t *list);
+
+static token_list_t *
+_argument_list_member_at (argument_list_t *list, int index);
+
+/* Note: This function talloc_steal()s the str pointer. */
+static token_t *
+_token_create_str (void *ctx, int type, char *str);
+
+static token_t *
+_token_create_ival (void *ctx, int type, int ival);
+
+static token_list_t *
+_token_list_create (void *ctx);
+
+/* Note: This function adds a talloc_reference() to token.
+ *
+ * You may want to talloc_unlink any current reference if you no
+ * longer need it. */
+static void
+_token_list_append (token_list_t *list, token_t *token);
+
+static void
+_token_list_append_list (token_list_t *list, token_list_t *tail);
+
+static active_list_t *
+_active_list_push (active_list_t *list,
+ const char *identifier,
+ token_node_t *marker);
+
+static active_list_t *
+_active_list_pop (active_list_t *list);
+
+int
+_active_list_contains (active_list_t *list, const char *identifier);
+
+static void
+_glcpp_parser_expand_if (glcpp_parser_t *parser, int type, token_list_t *list);
+
+static void
+_glcpp_parser_expand_token_list (glcpp_parser_t *parser,
+ token_list_t *list);
+
+static void
+_glcpp_parser_print_expanded_token_list (glcpp_parser_t *parser,
+ token_list_t *list);
+
+static void
+_glcpp_parser_skip_stack_push_if (glcpp_parser_t *parser, YYLTYPE *loc,
+ int condition);
+
+static void
+_glcpp_parser_skip_stack_change_if (glcpp_parser_t *parser, YYLTYPE *loc,
+ const char *type, int condition);
+
+static void
+_glcpp_parser_skip_stack_pop (glcpp_parser_t *parser, YYLTYPE *loc);
+
+#define yylex glcpp_parser_lex
+
+static int
+glcpp_parser_lex (YYSTYPE *yylval, YYLTYPE *yylloc, glcpp_parser_t *parser);
+
+static void
+glcpp_parser_lex_from (glcpp_parser_t *parser, token_list_t *list);
+
+static void
+add_builtin_define(glcpp_parser_t *parser, const char *name, int value);
+
+
+
+/* Line 189 of yacc.c */
+#line 216 "glcpp/glcpp-parse.c"
+
+/* Enabling traces. */
+#ifndef YYDEBUG
+# define YYDEBUG 0
+#endif
+
+/* Enabling verbose error messages. */
+#ifdef YYERROR_VERBOSE
+# undef YYERROR_VERBOSE
+# define YYERROR_VERBOSE 1
+#else
+# define YYERROR_VERBOSE 1
+#endif
+
+/* Enabling the token table. */
+#ifndef YYTOKEN_TABLE
+# define YYTOKEN_TABLE 0
+#endif
+
+
+/* Tokens. */
+#ifndef YYTOKENTYPE
+# define YYTOKENTYPE
+ /* Put the tokens into the symbol table, so that GDB and other debuggers
+ know about them. */
+ enum yytokentype {
+ COMMA_FINAL = 258,
+ DEFINED = 259,
+ ELIF_EXPANDED = 260,
+ HASH = 261,
+ HASH_DEFINE_FUNC = 262,
+ HASH_DEFINE_OBJ = 263,
+ HASH_ELIF = 264,
+ HASH_ELSE = 265,
+ HASH_ENDIF = 266,
+ HASH_IF = 267,
+ HASH_IFDEF = 268,
+ HASH_IFNDEF = 269,
+ HASH_UNDEF = 270,
+ HASH_VERSION = 271,
+ IDENTIFIER = 272,
+ IF_EXPANDED = 273,
+ INTEGER = 274,
+ INTEGER_STRING = 275,
+ NEWLINE = 276,
+ OTHER = 277,
+ PLACEHOLDER = 278,
+ SPACE = 279,
+ PASTE = 280,
+ OR = 281,
+ AND = 282,
+ NOT_EQUAL = 283,
+ EQUAL = 284,
+ GREATER_OR_EQUAL = 285,
+ LESS_OR_EQUAL = 286,
+ RIGHT_SHIFT = 287,
+ LEFT_SHIFT = 288,
+ UNARY = 289
+ };
+#endif
+
+
+
+#if ! defined YYSTYPE && ! defined YYSTYPE_IS_DECLARED
+
+# define yystype YYSTYPE /* obsolescent; will be withdrawn */
+# define YYSTYPE_IS_DECLARED 1
+#endif
+
+#if ! defined YYLTYPE && ! defined YYLTYPE_IS_DECLARED
+typedef struct YYLTYPE
+{
+ int first_line;
+ int first_column;
+ int last_line;
+ int last_column;
+} YYLTYPE;
+# define yyltype YYLTYPE /* obsolescent; will be withdrawn */
+# define YYLTYPE_IS_DECLARED 1
+# define YYLTYPE_IS_TRIVIAL 1
+#endif
+
+
+/* Copy the second part of user declarations. */
+
+
+/* Line 264 of yacc.c */
+#line 304 "glcpp/glcpp-parse.c"
+
+#ifdef short
+# undef short
+#endif
+
+#ifdef YYTYPE_UINT8
+typedef YYTYPE_UINT8 yytype_uint8;
+#else
+typedef unsigned char yytype_uint8;
+#endif
+
+#ifdef YYTYPE_INT8
+typedef YYTYPE_INT8 yytype_int8;
+#elif (defined __STDC__ || defined __C99__FUNC__ \
+ || defined __cplusplus || defined _MSC_VER)
+typedef signed char yytype_int8;
+#else
+typedef short int yytype_int8;
+#endif
+
+#ifdef YYTYPE_UINT16
+typedef YYTYPE_UINT16 yytype_uint16;
+#else
+typedef unsigned short int yytype_uint16;
+#endif
+
+#ifdef YYTYPE_INT16
+typedef YYTYPE_INT16 yytype_int16;
+#else
+typedef short int yytype_int16;
+#endif
+
+#ifndef YYSIZE_T
+# ifdef __SIZE_TYPE__
+# define YYSIZE_T __SIZE_TYPE__
+# elif defined size_t
+# define YYSIZE_T size_t
+# elif ! defined YYSIZE_T && (defined __STDC__ || defined __C99__FUNC__ \
+ || defined __cplusplus || defined _MSC_VER)
+# include <stddef.h> /* INFRINGES ON USER NAME SPACE */
+# define YYSIZE_T size_t
+# else
+# define YYSIZE_T unsigned int
+# endif
+#endif
+
+#define YYSIZE_MAXIMUM ((YYSIZE_T) -1)
+
+#ifndef YY_
+# if defined YYENABLE_NLS && YYENABLE_NLS
+# if ENABLE_NLS
+# include <libintl.h> /* INFRINGES ON USER NAME SPACE */
+# define YY_(msgid) dgettext ("bison-runtime", msgid)
+# endif
+# endif
+# ifndef YY_
+# define YY_(msgid) msgid
+# endif
+#endif
+
+/* Suppress unused-variable warnings by "using" E. */
+#if ! defined lint || defined __GNUC__
+# define YYUSE(e) ((void) (e))
+#else
+# define YYUSE(e) /* empty */
+#endif
+
+/* Identity function, used to suppress warnings about constant conditions. */
+#ifndef lint
+# define YYID(n) (n)
+#else
+#if (defined __STDC__ || defined __C99__FUNC__ \
+ || defined __cplusplus || defined _MSC_VER)
+static int
+YYID (int yyi)
+#else
+static int
+YYID (yyi)
+ int yyi;
+#endif
+{
+ return yyi;
+}
+#endif
+
+#if ! defined yyoverflow || YYERROR_VERBOSE
+
+/* The parser invokes alloca or malloc; define the necessary symbols. */
+
+# ifdef YYSTACK_USE_ALLOCA
+# if YYSTACK_USE_ALLOCA
+# ifdef __GNUC__
+# define YYSTACK_ALLOC __builtin_alloca
+# elif defined __BUILTIN_VA_ARG_INCR
+# include <alloca.h> /* INFRINGES ON USER NAME SPACE */
+# elif defined _AIX
+# define YYSTACK_ALLOC __alloca
+# elif defined _MSC_VER
+# include <malloc.h> /* INFRINGES ON USER NAME SPACE */
+# define alloca _alloca
+# else
+# define YYSTACK_ALLOC alloca
+# if ! defined _ALLOCA_H && ! defined _STDLIB_H && (defined __STDC__ || defined __C99__FUNC__ \
+ || defined __cplusplus || defined _MSC_VER)
+# include <stdlib.h> /* INFRINGES ON USER NAME SPACE */
+# ifndef _STDLIB_H
+# define _STDLIB_H 1
+# endif
+# endif
+# endif
+# endif
+# endif
+
+# ifdef YYSTACK_ALLOC
+ /* Pacify GCC's `empty if-body' warning. */
+# define YYSTACK_FREE(Ptr) do { /* empty */; } while (YYID (0))
+# ifndef YYSTACK_ALLOC_MAXIMUM
+ /* The OS might guarantee only one guard page at the bottom of the stack,
+ and a page size can be as small as 4096 bytes. So we cannot safely
+ invoke alloca (N) if N exceeds 4096. Use a slightly smaller number
+ to allow for a few compiler-allocated temporary stack slots. */
+# define YYSTACK_ALLOC_MAXIMUM 4032 /* reasonable circa 2006 */
+# endif
+# else
+# define YYSTACK_ALLOC YYMALLOC
+# define YYSTACK_FREE YYFREE
+# ifndef YYSTACK_ALLOC_MAXIMUM
+# define YYSTACK_ALLOC_MAXIMUM YYSIZE_MAXIMUM
+# endif
+# if (defined __cplusplus && ! defined _STDLIB_H \
+ && ! ((defined YYMALLOC || defined malloc) \
+ && (defined YYFREE || defined free)))
+# include <stdlib.h> /* INFRINGES ON USER NAME SPACE */
+# ifndef _STDLIB_H
+# define _STDLIB_H 1
+# endif
+# endif
+# ifndef YYMALLOC
+# define YYMALLOC malloc
+# if ! defined malloc && ! defined _STDLIB_H && (defined __STDC__ || defined __C99__FUNC__ \
+ || defined __cplusplus || defined _MSC_VER)
+void *malloc (YYSIZE_T); /* INFRINGES ON USER NAME SPACE */
+# endif
+# endif
+# ifndef YYFREE
+# define YYFREE free
+# if ! defined free && ! defined _STDLIB_H && (defined __STDC__ || defined __C99__FUNC__ \
+ || defined __cplusplus || defined _MSC_VER)
+void free (void *); /* INFRINGES ON USER NAME SPACE */
+# endif
+# endif
+# endif
+#endif /* ! defined yyoverflow || YYERROR_VERBOSE */
+
+
+#if (! defined yyoverflow \
+ && (! defined __cplusplus \
+ || (defined YYLTYPE_IS_TRIVIAL && YYLTYPE_IS_TRIVIAL \
+ && defined YYSTYPE_IS_TRIVIAL && YYSTYPE_IS_TRIVIAL)))
+
+/* A type that is properly aligned for any stack member. */
+union yyalloc
+{
+ yytype_int16 yyss_alloc;
+ YYSTYPE yyvs_alloc;
+ YYLTYPE yyls_alloc;
+};
+
+/* The size of the maximum gap between one aligned stack and the next. */
+# define YYSTACK_GAP_MAXIMUM (sizeof (union yyalloc) - 1)
+
+/* The size of an array large to enough to hold all stacks, each with
+ N elements. */
+# define YYSTACK_BYTES(N) \
+ ((N) * (sizeof (yytype_int16) + sizeof (YYSTYPE) + sizeof (YYLTYPE)) \
+ + 2 * YYSTACK_GAP_MAXIMUM)
+
+/* Copy COUNT objects from FROM to TO. The source and destination do
+ not overlap. */
+# ifndef YYCOPY
+# if defined __GNUC__ && 1 < __GNUC__
+# define YYCOPY(To, From, Count) \
+ __builtin_memcpy (To, From, (Count) * sizeof (*(From)))
+# else
+# define YYCOPY(To, From, Count) \
+ do \
+ { \
+ YYSIZE_T yyi; \
+ for (yyi = 0; yyi < (Count); yyi++) \
+ (To)[yyi] = (From)[yyi]; \
+ } \
+ while (YYID (0))
+# endif
+# endif
+
+/* Relocate STACK from its old location to the new one. The
+ local variables YYSIZE and YYSTACKSIZE give the old and new number of
+ elements in the stack, and YYPTR gives the new location of the
+ stack. Advance YYPTR to a properly aligned location for the next
+ stack. */
+# define YYSTACK_RELOCATE(Stack_alloc, Stack) \
+ do \
+ { \
+ YYSIZE_T yynewbytes; \
+ YYCOPY (&yyptr->Stack_alloc, Stack, yysize); \
+ Stack = &yyptr->Stack_alloc; \
+ yynewbytes = yystacksize * sizeof (*Stack) + YYSTACK_GAP_MAXIMUM; \
+ yyptr += yynewbytes / sizeof (*yyptr); \
+ } \
+ while (YYID (0))
+
+#endif
+
+/* YYFINAL -- State number of the termination state. */
+#define YYFINAL 2
+/* YYLAST -- Last index in YYTABLE. */
+#define YYLAST 606
+
+/* YYNTOKENS -- Number of terminals. */
+#define YYNTOKENS 57
+/* YYNNTS -- Number of nonterminals. */
+#define YYNNTS 17
+/* YYNRULES -- Number of rules. */
+#define YYNRULES 101
+/* YYNRULES -- Number of states. */
+#define YYNSTATES 162
+
+/* YYTRANSLATE(YYLEX) -- Bison symbol number corresponding to YYLEX. */
+#define YYUNDEFTOK 2
+#define YYMAXUTOK 289
+
+#define YYTRANSLATE(YYX) \
+ ((unsigned int) (YYX) <= YYMAXUTOK ? yytranslate[YYX] : YYUNDEFTOK)
+
+/* YYTRANSLATE[YYLEX] -- Bison symbol number corresponding to YYLEX. */
+static const yytype_uint8 yytranslate[] =
+{
+ 0, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 47, 2, 2, 2, 43, 30, 2,
+ 45, 46, 41, 39, 49, 40, 54, 42, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 55,
+ 33, 56, 34, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 50, 2, 51, 29, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 52, 28, 53, 48, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 1, 2, 3, 4,
+ 5, 6, 7, 8, 9, 10, 11, 12, 13, 14,
+ 15, 16, 17, 18, 19, 20, 21, 22, 23, 24,
+ 25, 26, 27, 31, 32, 35, 36, 37, 38, 44
+};
+
+#if YYDEBUG
+/* YYPRHS[YYN] -- Index of the first RHS symbol of rule number YYN in
+ YYRHS. */
+static const yytype_uint16 yyprhs[] =
+{
+ 0, 0, 3, 4, 7, 9, 11, 13, 16, 20,
+ 24, 29, 36, 44, 48, 52, 55, 60, 65, 69,
+ 72, 75, 78, 82, 85, 87, 89, 91, 95, 99,
+ 103, 107, 111, 115, 119, 123, 127, 131, 135, 139,
+ 143, 147, 151, 155, 159, 163, 166, 169, 172, 175,
+ 179, 181, 185, 187, 190, 193, 194, 196, 197, 199,
+ 202, 207, 209, 211, 214, 216, 219, 221, 223, 225,
+ 227, 229, 231, 233, 235, 237, 239, 241, 243, 245,
+ 247, 249, 251, 253, 255, 257, 259, 261, 263, 265,
+ 267, 269, 271, 273, 275, 277, 279, 281, 283, 285,
+ 287, 289
+};
+
+/* YYRHS -- A `-1'-separated list of the rules' RHS. */
+static const yytype_int8 yyrhs[] =
+{
+ 58, 0, -1, -1, 58, 59, -1, 61, -1, 65,
+ -1, 60, -1, 6, 66, -1, 18, 63, 21, -1,
+ 5, 63, 21, -1, 8, 17, 67, 21, -1, 7,
+ 17, 45, 46, 67, 21, -1, 7, 17, 45, 64,
+ 46, 67, 21, -1, 15, 17, 21, -1, 12, 70,
+ 21, -1, 12, 21, -1, 13, 17, 68, 21, -1,
+ 14, 17, 68, 21, -1, 9, 70, 21, -1, 9,
+ 21, -1, 10, 21, -1, 11, 21, -1, 16, 62,
+ 21, -1, 6, 21, -1, 20, -1, 19, -1, 62,
+ -1, 63, 26, 63, -1, 63, 27, 63, -1, 63,
+ 28, 63, -1, 63, 29, 63, -1, 63, 30, 63,
+ -1, 63, 31, 63, -1, 63, 32, 63, -1, 63,
+ 35, 63, -1, 63, 36, 63, -1, 63, 34, 63,
+ -1, 63, 33, 63, -1, 63, 37, 63, -1, 63,
+ 38, 63, -1, 63, 40, 63, -1, 63, 39, 63,
+ -1, 63, 43, 63, -1, 63, 42, 63, -1, 63,
+ 41, 63, -1, 47, 63, -1, 48, 63, -1, 40,
+ 63, -1, 39, 63, -1, 45, 63, 46, -1, 17,
+ -1, 64, 49, 17, -1, 21, -1, 71, 21, -1,
+ 71, 21, -1, -1, 71, -1, -1, 71, -1, 4,
+ 17, -1, 4, 45, 17, 46, -1, 72, -1, 69,
+ -1, 70, 69, -1, 72, -1, 71, 72, -1, 17,
+ -1, 20, -1, 73, -1, 22, -1, 24, -1, 50,
+ -1, 51, -1, 45, -1, 46, -1, 52, -1, 53,
+ -1, 54, -1, 30, -1, 41, -1, 39, -1, 40,
+ -1, 48, -1, 47, -1, 42, -1, 43, -1, 38,
+ -1, 37, -1, 33, -1, 34, -1, 36, -1, 35,
+ -1, 32, -1, 31, -1, 29, -1, 28, -1, 27,
+ -1, 26, -1, 55, -1, 49, -1, 56, -1, 25,
+ -1
+};
+
+/* YYRLINE[YYN] -- source line where rule number YYN was defined. */
+static const yytype_uint16 yyrline[] =
+{
+ 0, 181, 181, 183, 187, 190, 195, 196, 200, 203,
+ 209, 212, 215, 218, 226, 245, 255, 260, 265, 284,
+ 299, 302, 305, 314, 318, 327, 332, 333, 336, 339,
+ 342, 345, 348, 351, 354, 357, 360, 363, 366, 369,
+ 372, 375, 378, 381, 384, 387, 390, 393, 396, 399,
+ 405, 410, 418, 419, 423, 429, 430, 433, 435, 442,
+ 446, 450, 455, 461, 469, 475, 483, 487, 491, 495,
+ 499, 506, 507, 508, 509, 510, 511, 512, 513, 514,
+ 515, 516, 517, 518, 519, 520, 521, 522, 523, 524,
+ 525, 526, 527, 528, 529, 530, 531, 532, 533, 534,
+ 535, 536
+};
+#endif
+
+#if YYDEBUG || YYERROR_VERBOSE || YYTOKEN_TABLE
+/* YYTNAME[SYMBOL-NUM] -- String name of the symbol SYMBOL-NUM.
+ First, the terminals, then, starting at YYNTOKENS, nonterminals. */
+static const char *const yytname[] =
+{
+ "$end", "error", "$undefined", "COMMA_FINAL", "DEFINED",
+ "ELIF_EXPANDED", "HASH", "HASH_DEFINE_FUNC", "HASH_DEFINE_OBJ",
+ "HASH_ELIF", "HASH_ELSE", "HASH_ENDIF", "HASH_IF", "HASH_IFDEF",
+ "HASH_IFNDEF", "HASH_UNDEF", "HASH_VERSION", "IDENTIFIER", "IF_EXPANDED",
+ "INTEGER", "INTEGER_STRING", "NEWLINE", "OTHER", "PLACEHOLDER", "SPACE",
+ "PASTE", "OR", "AND", "'|'", "'^'", "'&'", "NOT_EQUAL", "EQUAL", "'<'",
+ "'>'", "GREATER_OR_EQUAL", "LESS_OR_EQUAL", "RIGHT_SHIFT", "LEFT_SHIFT",
+ "'+'", "'-'", "'*'", "'/'", "'%'", "UNARY", "'('", "')'", "'!'", "'~'",
+ "','", "'['", "']'", "'{'", "'}'", "'.'", "';'", "'='", "$accept",
+ "input", "line", "expanded_line", "control_line", "integer_constant",
+ "expression", "identifier_list", "text_line", "non_directive",
+ "replacement_list", "junk", "conditional_token", "conditional_tokens",
+ "pp_tokens", "preprocessing_token", "operator", 0
+};
+#endif
+
+# ifdef YYPRINT
+/* YYTOKNUM[YYLEX-NUM] -- Internal token number corresponding to
+ token YYLEX-NUM. */
+static const yytype_uint16 yytoknum[] =
+{
+ 0, 256, 257, 258, 259, 260, 261, 262, 263, 264,
+ 265, 266, 267, 268, 269, 270, 271, 272, 273, 274,
+ 275, 276, 277, 278, 279, 280, 281, 282, 124, 94,
+ 38, 283, 284, 60, 62, 285, 286, 287, 288, 43,
+ 45, 42, 47, 37, 289, 40, 41, 33, 126, 44,
+ 91, 93, 123, 125, 46, 59, 61
+};
+# endif
+
+/* YYR1[YYN] -- Symbol number of symbol that rule YYN derives. */
+static const yytype_uint8 yyr1[] =
+{
+ 0, 57, 58, 58, 59, 59, 59, 59, 60, 60,
+ 61, 61, 61, 61, 61, 61, 61, 61, 61, 61,
+ 61, 61, 61, 61, 62, 62, 63, 63, 63, 63,
+ 63, 63, 63, 63, 63, 63, 63, 63, 63, 63,
+ 63, 63, 63, 63, 63, 63, 63, 63, 63, 63,
+ 64, 64, 65, 65, 66, 67, 67, 68, 68, 69,
+ 69, 69, 70, 70, 71, 71, 72, 72, 72, 72,
+ 72, 73, 73, 73, 73, 73, 73, 73, 73, 73,
+ 73, 73, 73, 73, 73, 73, 73, 73, 73, 73,
+ 73, 73, 73, 73, 73, 73, 73, 73, 73, 73,
+ 73, 73
+};
+
+/* YYR2[YYN] -- Number of symbols composing right hand side of rule YYN. */
+static const yytype_uint8 yyr2[] =
+{
+ 0, 2, 0, 2, 1, 1, 1, 2, 3, 3,
+ 4, 6, 7, 3, 3, 2, 4, 4, 3, 2,
+ 2, 2, 3, 2, 1, 1, 1, 3, 3, 3,
+ 3, 3, 3, 3, 3, 3, 3, 3, 3, 3,
+ 3, 3, 3, 3, 3, 2, 2, 2, 2, 3,
+ 1, 3, 1, 2, 2, 0, 1, 0, 1, 2,
+ 4, 1, 1, 2, 1, 2, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1
+};
+
+/* YYDEFACT[STATE-NAME] -- Default rule to reduce with in state
+ STATE-NUM when YYTABLE doesn't specify something else to do. Zero
+ means the default is an error. */
+static const yytype_uint8 yydefact[] =
+{
+ 2, 0, 1, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 66, 0, 67, 52, 69,
+ 70, 101, 97, 96, 95, 94, 78, 93, 92, 88,
+ 89, 91, 90, 87, 86, 80, 81, 79, 84, 85,
+ 73, 74, 83, 82, 99, 71, 72, 75, 76, 77,
+ 98, 100, 3, 6, 4, 5, 0, 64, 68, 25,
+ 24, 0, 0, 0, 0, 0, 26, 0, 23, 7,
+ 0, 0, 55, 0, 19, 62, 0, 61, 20, 21,
+ 15, 0, 57, 57, 0, 0, 0, 53, 65, 48,
+ 47, 0, 45, 46, 9, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 54, 0, 0, 56, 59, 0, 18,
+ 63, 14, 0, 58, 0, 13, 22, 8, 49, 27,
+ 28, 29, 30, 31, 32, 33, 37, 36, 34, 35,
+ 38, 39, 41, 40, 44, 43, 42, 50, 55, 0,
+ 10, 0, 16, 17, 0, 55, 0, 60, 11, 0,
+ 51, 12
+};
+
+/* YYDEFGOTO[NTERM-NUM]. */
+static const yytype_int16 yydefgoto[] =
+{
+ -1, 1, 52, 53, 54, 66, 67, 149, 55, 69,
+ 115, 122, 75, 76, 116, 57, 58
+};
+
+/* YYPACT[STATE-NUM] -- Index in YYTABLE of the portion describing
+ STATE-NUM. */
+#define YYPACT_NINF -147
+static const yytype_int16 yypact[] =
+{
+ -147, 112, -147, 28, -10, 55, 62, 152, -15, 59,
+ 192, 85, 86, 87, 51, -147, 28, -147, -147, -147,
+ -147, -147, -147, -147, -147, -147, -147, -147, -147, -147,
+ -147, -147, -147, -147, -147, -147, -147, -147, -147, -147,
+ -147, -147, -147, -147, -147, -147, -147, -147, -147, -147,
+ -147, -147, -147, -147, -147, -147, 312, -147, -147, -147,
+ -147, 28, 28, 28, 28, 28, -147, 428, -147, -147,
+ 352, 63, 392, 17, -147, -147, 232, -147, -147, -147,
+ -147, 272, 392, 392, 84, 89, 451, -147, -147, -147,
+ -147, 469, -147, -147, -147, 28, 28, 28, 28, 28,
+ 28, 28, 28, 28, 28, 28, 28, 28, 28, 28,
+ 28, 28, 28, -147, 60, 90, 392, -147, 96, -147,
+ -147, -147, 93, 392, 94, -147, -147, -147, -147, 489,
+ 505, 520, 534, 547, 558, 558, 18, 18, 18, 18,
+ 563, 563, 23, 23, -147, -147, -147, -147, 392, 32,
+ -147, 61, -147, -147, 110, 392, 118, -147, -147, 149,
+ -147, -147
+};
+
+/* YYPGOTO[NTERM-NUM]. */
+static const yytype_int16 yypgoto[] =
+{
+ -147, -147, -147, -147, -147, 157, -11, -147, -147, -147,
+ -146, 92, -68, 200, 0, -7, -147
+};
+
+/* YYTABLE[YYPACT[STATE-NUM]]. What to do in state STATE-NUM. If
+ positive, shift that token. If negative, reduce the rule which
+ number is the opposite. If zero, do what YYDEFACT says.
+ If YYTABLE_NINF, syntax error. */
+#define YYTABLE_NINF -1
+static const yytype_uint8 yytable[] =
+{
+ 77, 56, 154, 77, 70, 86, 78, 15, 120, 159,
+ 17, 68, 19, 120, 20, 21, 22, 23, 24, 25,
+ 26, 27, 28, 29, 30, 31, 32, 33, 34, 35,
+ 36, 37, 38, 39, 117, 40, 41, 42, 43, 44,
+ 45, 46, 47, 48, 49, 50, 51, 59, 60, 88,
+ 89, 90, 91, 92, 93, 106, 107, 108, 109, 110,
+ 111, 112, 118, 88, 110, 111, 112, 61, 62, 77,
+ 59, 60, 71, 63, 77, 64, 65, 147, 155, 72,
+ 79, 156, 123, 123, 129, 130, 131, 132, 133, 134,
+ 135, 136, 137, 138, 139, 140, 141, 142, 143, 144,
+ 145, 146, 82, 83, 84, 125, 148, 157, 114, 88,
+ 126, 150, 2, 151, 152, 153, 88, 3, 4, 5,
+ 6, 7, 8, 9, 10, 11, 12, 13, 14, 15,
+ 16, 158, 17, 18, 19, 160, 20, 21, 22, 23,
+ 24, 25, 26, 27, 28, 29, 30, 31, 32, 33,
+ 34, 35, 36, 37, 38, 39, 73, 40, 41, 42,
+ 43, 44, 45, 46, 47, 48, 49, 50, 51, 15,
+ 161, 85, 17, 74, 19, 124, 20, 21, 22, 23,
+ 24, 25, 26, 27, 28, 29, 30, 31, 32, 33,
+ 34, 35, 36, 37, 38, 39, 73, 40, 41, 42,
+ 43, 44, 45, 46, 47, 48, 49, 50, 51, 15,
+ 81, 0, 17, 80, 19, 0, 20, 21, 22, 23,
+ 24, 25, 26, 27, 28, 29, 30, 31, 32, 33,
+ 34, 35, 36, 37, 38, 39, 73, 40, 41, 42,
+ 43, 44, 45, 46, 47, 48, 49, 50, 51, 15,
+ 0, 0, 17, 119, 19, 0, 20, 21, 22, 23,
+ 24, 25, 26, 27, 28, 29, 30, 31, 32, 33,
+ 34, 35, 36, 37, 38, 39, 73, 40, 41, 42,
+ 43, 44, 45, 46, 47, 48, 49, 50, 51, 15,
+ 0, 0, 17, 121, 19, 0, 20, 21, 22, 23,
+ 24, 25, 26, 27, 28, 29, 30, 31, 32, 33,
+ 34, 35, 36, 37, 38, 39, 0, 40, 41, 42,
+ 43, 44, 45, 46, 47, 48, 49, 50, 51, 15,
+ 0, 0, 17, 87, 19, 0, 20, 21, 22, 23,
+ 24, 25, 26, 27, 28, 29, 30, 31, 32, 33,
+ 34, 35, 36, 37, 38, 39, 0, 40, 41, 42,
+ 43, 44, 45, 46, 47, 48, 49, 50, 51, 15,
+ 0, 0, 17, 113, 19, 0, 20, 21, 22, 23,
+ 24, 25, 26, 27, 28, 29, 30, 31, 32, 33,
+ 34, 35, 36, 37, 38, 39, 0, 40, 41, 42,
+ 43, 44, 45, 46, 47, 48, 49, 50, 51, 15,
+ 0, 0, 17, 0, 19, 0, 20, 21, 22, 23,
+ 24, 25, 26, 27, 28, 29, 30, 31, 32, 33,
+ 34, 35, 36, 37, 38, 39, 0, 40, 41, 42,
+ 43, 44, 45, 46, 47, 48, 49, 50, 51, 94,
+ 0, 0, 0, 0, 95, 96, 97, 98, 99, 100,
+ 101, 102, 103, 104, 105, 106, 107, 108, 109, 110,
+ 111, 112, 127, 0, 0, 0, 0, 95, 96, 97,
+ 98, 99, 100, 101, 102, 103, 104, 105, 106, 107,
+ 108, 109, 110, 111, 112, 95, 96, 97, 98, 99,
+ 100, 101, 102, 103, 104, 105, 106, 107, 108, 109,
+ 110, 111, 112, 0, 0, 128, 96, 97, 98, 99,
+ 100, 101, 102, 103, 104, 105, 106, 107, 108, 109,
+ 110, 111, 112, 97, 98, 99, 100, 101, 102, 103,
+ 104, 105, 106, 107, 108, 109, 110, 111, 112, 98,
+ 99, 100, 101, 102, 103, 104, 105, 106, 107, 108,
+ 109, 110, 111, 112, 99, 100, 101, 102, 103, 104,
+ 105, 106, 107, 108, 109, 110, 111, 112, 100, 101,
+ 102, 103, 104, 105, 106, 107, 108, 109, 110, 111,
+ 112, 102, 103, 104, 105, 106, 107, 108, 109, 110,
+ 111, 112, 108, 109, 110, 111, 112
+};
+
+static const yytype_int16 yycheck[] =
+{
+ 7, 1, 148, 10, 4, 16, 21, 17, 76, 155,
+ 20, 21, 22, 81, 24, 25, 26, 27, 28, 29,
+ 30, 31, 32, 33, 34, 35, 36, 37, 38, 39,
+ 40, 41, 42, 43, 17, 45, 46, 47, 48, 49,
+ 50, 51, 52, 53, 54, 55, 56, 19, 20, 56,
+ 61, 62, 63, 64, 65, 37, 38, 39, 40, 41,
+ 42, 43, 45, 70, 41, 42, 43, 39, 40, 76,
+ 19, 20, 17, 45, 81, 47, 48, 17, 46, 17,
+ 21, 49, 82, 83, 95, 96, 97, 98, 99, 100,
+ 101, 102, 103, 104, 105, 106, 107, 108, 109, 110,
+ 111, 112, 17, 17, 17, 21, 46, 46, 45, 116,
+ 21, 21, 0, 17, 21, 21, 123, 5, 6, 7,
+ 8, 9, 10, 11, 12, 13, 14, 15, 16, 17,
+ 18, 21, 20, 21, 22, 17, 24, 25, 26, 27,
+ 28, 29, 30, 31, 32, 33, 34, 35, 36, 37,
+ 38, 39, 40, 41, 42, 43, 4, 45, 46, 47,
+ 48, 49, 50, 51, 52, 53, 54, 55, 56, 17,
+ 21, 14, 20, 21, 22, 83, 24, 25, 26, 27,
+ 28, 29, 30, 31, 32, 33, 34, 35, 36, 37,
+ 38, 39, 40, 41, 42, 43, 4, 45, 46, 47,
+ 48, 49, 50, 51, 52, 53, 54, 55, 56, 17,
+ 10, -1, 20, 21, 22, -1, 24, 25, 26, 27,
+ 28, 29, 30, 31, 32, 33, 34, 35, 36, 37,
+ 38, 39, 40, 41, 42, 43, 4, 45, 46, 47,
+ 48, 49, 50, 51, 52, 53, 54, 55, 56, 17,
+ -1, -1, 20, 21, 22, -1, 24, 25, 26, 27,
+ 28, 29, 30, 31, 32, 33, 34, 35, 36, 37,
+ 38, 39, 40, 41, 42, 43, 4, 45, 46, 47,
+ 48, 49, 50, 51, 52, 53, 54, 55, 56, 17,
+ -1, -1, 20, 21, 22, -1, 24, 25, 26, 27,
+ 28, 29, 30, 31, 32, 33, 34, 35, 36, 37,
+ 38, 39, 40, 41, 42, 43, -1, 45, 46, 47,
+ 48, 49, 50, 51, 52, 53, 54, 55, 56, 17,
+ -1, -1, 20, 21, 22, -1, 24, 25, 26, 27,
+ 28, 29, 30, 31, 32, 33, 34, 35, 36, 37,
+ 38, 39, 40, 41, 42, 43, -1, 45, 46, 47,
+ 48, 49, 50, 51, 52, 53, 54, 55, 56, 17,
+ -1, -1, 20, 21, 22, -1, 24, 25, 26, 27,
+ 28, 29, 30, 31, 32, 33, 34, 35, 36, 37,
+ 38, 39, 40, 41, 42, 43, -1, 45, 46, 47,
+ 48, 49, 50, 51, 52, 53, 54, 55, 56, 17,
+ -1, -1, 20, -1, 22, -1, 24, 25, 26, 27,
+ 28, 29, 30, 31, 32, 33, 34, 35, 36, 37,
+ 38, 39, 40, 41, 42, 43, -1, 45, 46, 47,
+ 48, 49, 50, 51, 52, 53, 54, 55, 56, 21,
+ -1, -1, -1, -1, 26, 27, 28, 29, 30, 31,
+ 32, 33, 34, 35, 36, 37, 38, 39, 40, 41,
+ 42, 43, 21, -1, -1, -1, -1, 26, 27, 28,
+ 29, 30, 31, 32, 33, 34, 35, 36, 37, 38,
+ 39, 40, 41, 42, 43, 26, 27, 28, 29, 30,
+ 31, 32, 33, 34, 35, 36, 37, 38, 39, 40,
+ 41, 42, 43, -1, -1, 46, 27, 28, 29, 30,
+ 31, 32, 33, 34, 35, 36, 37, 38, 39, 40,
+ 41, 42, 43, 28, 29, 30, 31, 32, 33, 34,
+ 35, 36, 37, 38, 39, 40, 41, 42, 43, 29,
+ 30, 31, 32, 33, 34, 35, 36, 37, 38, 39,
+ 40, 41, 42, 43, 30, 31, 32, 33, 34, 35,
+ 36, 37, 38, 39, 40, 41, 42, 43, 31, 32,
+ 33, 34, 35, 36, 37, 38, 39, 40, 41, 42,
+ 43, 33, 34, 35, 36, 37, 38, 39, 40, 41,
+ 42, 43, 39, 40, 41, 42, 43
+};
+
+/* YYSTOS[STATE-NUM] -- The (internal number of the) accessing
+ symbol of state STATE-NUM. */
+static const yytype_uint8 yystos[] =
+{
+ 0, 58, 0, 5, 6, 7, 8, 9, 10, 11,
+ 12, 13, 14, 15, 16, 17, 18, 20, 21, 22,
+ 24, 25, 26, 27, 28, 29, 30, 31, 32, 33,
+ 34, 35, 36, 37, 38, 39, 40, 41, 42, 43,
+ 45, 46, 47, 48, 49, 50, 51, 52, 53, 54,
+ 55, 56, 59, 60, 61, 65, 71, 72, 73, 19,
+ 20, 39, 40, 45, 47, 48, 62, 63, 21, 66,
+ 71, 17, 17, 4, 21, 69, 70, 72, 21, 21,
+ 21, 70, 17, 17, 17, 62, 63, 21, 72, 63,
+ 63, 63, 63, 63, 21, 26, 27, 28, 29, 30,
+ 31, 32, 33, 34, 35, 36, 37, 38, 39, 40,
+ 41, 42, 43, 21, 45, 67, 71, 17, 45, 21,
+ 69, 21, 68, 71, 68, 21, 21, 21, 46, 63,
+ 63, 63, 63, 63, 63, 63, 63, 63, 63, 63,
+ 63, 63, 63, 63, 63, 63, 63, 17, 46, 64,
+ 21, 17, 21, 21, 67, 46, 49, 46, 21, 67,
+ 17, 21
+};
+
+#define yyerrok (yyerrstatus = 0)
+#define yyclearin (yychar = YYEMPTY)
+#define YYEMPTY (-2)
+#define YYEOF 0
+
+#define YYACCEPT goto yyacceptlab
+#define YYABORT goto yyabortlab
+#define YYERROR goto yyerrorlab
+
+
+/* Like YYERROR except do call yyerror. This remains here temporarily
+ to ease the transition to the new meaning of YYERROR, for GCC.
+ Once GCC version 2 has supplanted version 1, this can go. However,
+ YYFAIL appears to be in use. Nevertheless, it is formally deprecated
+ in Bison 2.4.2's NEWS entry, where a plan to phase it out is
+ discussed. */
+
+#define YYFAIL goto yyerrlab
+#if defined YYFAIL
+ /* This is here to suppress warnings from the GCC cpp's
+ -Wunused-macros. Normally we don't worry about that warning, but
+ some users do, and we want to make it easy for users to remove
+ YYFAIL uses, which will produce warnings from Bison 2.5. */
+#endif
+
+#define YYRECOVERING() (!!yyerrstatus)
+
+#define YYBACKUP(Token, Value) \
+do \
+ if (yychar == YYEMPTY && yylen == 1) \
+ { \
+ yychar = (Token); \
+ yylval = (Value); \
+ yytoken = YYTRANSLATE (yychar); \
+ YYPOPSTACK (1); \
+ goto yybackup; \
+ } \
+ else \
+ { \
+ yyerror (&yylloc, parser, YY_("syntax error: cannot back up")); \
+ YYERROR; \
+ } \
+while (YYID (0))
+
+
+#define YYTERROR 1
+#define YYERRCODE 256
+
+
+/* YYLLOC_DEFAULT -- Set CURRENT to span from RHS[1] to RHS[N].
+ If N is 0, then set CURRENT to the empty location which ends
+ the previous symbol: RHS[0] (always defined). */
+
+#define YYRHSLOC(Rhs, K) ((Rhs)[K])
+#ifndef YYLLOC_DEFAULT
+# define YYLLOC_DEFAULT(Current, Rhs, N) \
+ do \
+ if (YYID (N)) \
+ { \
+ (Current).first_line = YYRHSLOC (Rhs, 1).first_line; \
+ (Current).first_column = YYRHSLOC (Rhs, 1).first_column; \
+ (Current).last_line = YYRHSLOC (Rhs, N).last_line; \
+ (Current).last_column = YYRHSLOC (Rhs, N).last_column; \
+ } \
+ else \
+ { \
+ (Current).first_line = (Current).last_line = \
+ YYRHSLOC (Rhs, 0).last_line; \
+ (Current).first_column = (Current).last_column = \
+ YYRHSLOC (Rhs, 0).last_column; \
+ } \
+ while (YYID (0))
+#endif
+
+
+/* YY_LOCATION_PRINT -- Print the location on the stream.
+ This macro was not mandated originally: define only if we know
+ we won't break user code: when these are the locations we know. */
+
+#ifndef YY_LOCATION_PRINT
+# if defined YYLTYPE_IS_TRIVIAL && YYLTYPE_IS_TRIVIAL
+# define YY_LOCATION_PRINT(File, Loc) \
+ fprintf (File, "%d.%d-%d.%d", \
+ (Loc).first_line, (Loc).first_column, \
+ (Loc).last_line, (Loc).last_column)
+# else
+# define YY_LOCATION_PRINT(File, Loc) ((void) 0)
+# endif
+#endif
+
+
+/* YYLEX -- calling `yylex' with the right arguments. */
+
+#ifdef YYLEX_PARAM
+# define YYLEX yylex (&yylval, &yylloc, YYLEX_PARAM)
+#else
+# define YYLEX yylex (&yylval, &yylloc, parser)
+#endif
+
+/* Enable debugging if requested. */
+#if YYDEBUG
+
+# ifndef YYFPRINTF
+# include <stdio.h> /* INFRINGES ON USER NAME SPACE */
+# define YYFPRINTF fprintf
+# endif
+
+# define YYDPRINTF(Args) \
+do { \
+ if (yydebug) \
+ YYFPRINTF Args; \
+} while (YYID (0))
+
+# define YY_SYMBOL_PRINT(Title, Type, Value, Location) \
+do { \
+ if (yydebug) \
+ { \
+ YYFPRINTF (stderr, "%s ", Title); \
+ yy_symbol_print (stderr, \
+ Type, Value, Location, parser); \
+ YYFPRINTF (stderr, "\n"); \
+ } \
+} while (YYID (0))
+
+
+/*--------------------------------.
+| Print this symbol on YYOUTPUT. |
+`--------------------------------*/
+
+/*ARGSUSED*/
+#if (defined __STDC__ || defined __C99__FUNC__ \
+ || defined __cplusplus || defined _MSC_VER)
+static void
+yy_symbol_value_print (FILE *yyoutput, int yytype, YYSTYPE const * const yyvaluep, YYLTYPE const * const yylocationp, glcpp_parser_t *parser)
+#else
+static void
+yy_symbol_value_print (yyoutput, yytype, yyvaluep, yylocationp, parser)
+ FILE *yyoutput;
+ int yytype;
+ YYSTYPE const * const yyvaluep;
+ YYLTYPE const * const yylocationp;
+ glcpp_parser_t *parser;
+#endif
+{
+ if (!yyvaluep)
+ return;
+ YYUSE (yylocationp);
+ YYUSE (parser);
+# ifdef YYPRINT
+ if (yytype < YYNTOKENS)
+ YYPRINT (yyoutput, yytoknum[yytype], *yyvaluep);
+# else
+ YYUSE (yyoutput);
+# endif
+ switch (yytype)
+ {
+ default:
+ break;
+ }
+}
+
+
+/*--------------------------------.
+| Print this symbol on YYOUTPUT. |
+`--------------------------------*/
+
+#if (defined __STDC__ || defined __C99__FUNC__ \
+ || defined __cplusplus || defined _MSC_VER)
+static void
+yy_symbol_print (FILE *yyoutput, int yytype, YYSTYPE const * const yyvaluep, YYLTYPE const * const yylocationp, glcpp_parser_t *parser)
+#else
+static void
+yy_symbol_print (yyoutput, yytype, yyvaluep, yylocationp, parser)
+ FILE *yyoutput;
+ int yytype;
+ YYSTYPE const * const yyvaluep;
+ YYLTYPE const * const yylocationp;
+ glcpp_parser_t *parser;
+#endif
+{
+ if (yytype < YYNTOKENS)
+ YYFPRINTF (yyoutput, "token %s (", yytname[yytype]);
+ else
+ YYFPRINTF (yyoutput, "nterm %s (", yytname[yytype]);
+
+ YY_LOCATION_PRINT (yyoutput, *yylocationp);
+ YYFPRINTF (yyoutput, ": ");
+ yy_symbol_value_print (yyoutput, yytype, yyvaluep, yylocationp, parser);
+ YYFPRINTF (yyoutput, ")");
+}
+
+/*------------------------------------------------------------------.
+| yy_stack_print -- Print the state stack from its BOTTOM up to its |
+| TOP (included). |
+`------------------------------------------------------------------*/
+
+#if (defined __STDC__ || defined __C99__FUNC__ \
+ || defined __cplusplus || defined _MSC_VER)
+static void
+yy_stack_print (yytype_int16 *yybottom, yytype_int16 *yytop)
+#else
+static void
+yy_stack_print (yybottom, yytop)
+ yytype_int16 *yybottom;
+ yytype_int16 *yytop;
+#endif
+{
+ YYFPRINTF (stderr, "Stack now");
+ for (; yybottom <= yytop; yybottom++)
+ {
+ int yybot = *yybottom;
+ YYFPRINTF (stderr, " %d", yybot);
+ }
+ YYFPRINTF (stderr, "\n");
+}
+
+# define YY_STACK_PRINT(Bottom, Top) \
+do { \
+ if (yydebug) \
+ yy_stack_print ((Bottom), (Top)); \
+} while (YYID (0))
+
+
+/*------------------------------------------------.
+| Report that the YYRULE is going to be reduced. |
+`------------------------------------------------*/
+
+#if (defined __STDC__ || defined __C99__FUNC__ \
+ || defined __cplusplus || defined _MSC_VER)
+static void
+yy_reduce_print (YYSTYPE *yyvsp, YYLTYPE *yylsp, int yyrule, glcpp_parser_t *parser)
+#else
+static void
+yy_reduce_print (yyvsp, yylsp, yyrule, parser)
+ YYSTYPE *yyvsp;
+ YYLTYPE *yylsp;
+ int yyrule;
+ glcpp_parser_t *parser;
+#endif
+{
+ int yynrhs = yyr2[yyrule];
+ int yyi;
+ unsigned long int yylno = yyrline[yyrule];
+ YYFPRINTF (stderr, "Reducing stack by rule %d (line %lu):\n",
+ yyrule - 1, yylno);
+ /* The symbols being reduced. */
+ for (yyi = 0; yyi < yynrhs; yyi++)
+ {
+ YYFPRINTF (stderr, " $%d = ", yyi + 1);
+ yy_symbol_print (stderr, yyrhs[yyprhs[yyrule] + yyi],
+ &(yyvsp[(yyi + 1) - (yynrhs)])
+ , &(yylsp[(yyi + 1) - (yynrhs)]) , parser);
+ YYFPRINTF (stderr, "\n");
+ }
+}
+
+# define YY_REDUCE_PRINT(Rule) \
+do { \
+ if (yydebug) \
+ yy_reduce_print (yyvsp, yylsp, Rule, parser); \
+} while (YYID (0))
+
+/* Nonzero means print parse trace. It is left uninitialized so that
+ multiple parsers can coexist. */
+int yydebug;
+#else /* !YYDEBUG */
+# define YYDPRINTF(Args)
+# define YY_SYMBOL_PRINT(Title, Type, Value, Location)
+# define YY_STACK_PRINT(Bottom, Top)
+# define YY_REDUCE_PRINT(Rule)
+#endif /* !YYDEBUG */
+
+
+/* YYINITDEPTH -- initial size of the parser's stacks. */
+#ifndef YYINITDEPTH
+# define YYINITDEPTH 200
+#endif
+
+/* YYMAXDEPTH -- maximum size the stacks can grow to (effective only
+ if the built-in stack extension method is used).
+
+ Do not make this value too large; the results are undefined if
+ YYSTACK_ALLOC_MAXIMUM < YYSTACK_BYTES (YYMAXDEPTH)
+ evaluated with infinite-precision integer arithmetic. */
+
+#ifndef YYMAXDEPTH
+# define YYMAXDEPTH 10000
+#endif
+
+
+
+#if YYERROR_VERBOSE
+
+# ifndef yystrlen
+# if defined __GLIBC__ && defined _STRING_H
+# define yystrlen strlen
+# else
+/* Return the length of YYSTR. */
+#if (defined __STDC__ || defined __C99__FUNC__ \
+ || defined __cplusplus || defined _MSC_VER)
+static YYSIZE_T
+yystrlen (const char *yystr)
+#else
+static YYSIZE_T
+yystrlen (yystr)
+ const char *yystr;
+#endif
+{
+ YYSIZE_T yylen;
+ for (yylen = 0; yystr[yylen]; yylen++)
+ continue;
+ return yylen;
+}
+# endif
+# endif
+
+# ifndef yystpcpy
+# if defined __GLIBC__ && defined _STRING_H && defined _GNU_SOURCE
+# define yystpcpy stpcpy
+# else
+/* Copy YYSRC to YYDEST, returning the address of the terminating '\0' in
+ YYDEST. */
+#if (defined __STDC__ || defined __C99__FUNC__ \
+ || defined __cplusplus || defined _MSC_VER)
+static char *
+yystpcpy (char *yydest, const char *yysrc)
+#else
+static char *
+yystpcpy (yydest, yysrc)
+ char *yydest;
+ const char *yysrc;
+#endif
+{
+ char *yyd = yydest;
+ const char *yys = yysrc;
+
+ while ((*yyd++ = *yys++) != '\0')
+ continue;
+
+ return yyd - 1;
+}
+# endif
+# endif
+
+# ifndef yytnamerr
+/* Copy to YYRES the contents of YYSTR after stripping away unnecessary
+ quotes and backslashes, so that it's suitable for yyerror. The
+ heuristic is that double-quoting is unnecessary unless the string
+ contains an apostrophe, a comma, or backslash (other than
+ backslash-backslash). YYSTR is taken from yytname. If YYRES is
+ null, do not copy; instead, return the length of what the result
+ would have been. */
+static YYSIZE_T
+yytnamerr (char *yyres, const char *yystr)
+{
+ if (*yystr == '"')
+ {
+ YYSIZE_T yyn = 0;
+ char const *yyp = yystr;
+
+ for (;;)
+ switch (*++yyp)
+ {
+ case '\'':
+ case ',':
+ goto do_not_strip_quotes;
+
+ case '\\':
+ if (*++yyp != '\\')
+ goto do_not_strip_quotes;
+ /* Fall through. */
+ default:
+ if (yyres)
+ yyres[yyn] = *yyp;
+ yyn++;
+ break;
+
+ case '"':
+ if (yyres)
+ yyres[yyn] = '\0';
+ return yyn;
+ }
+ do_not_strip_quotes: ;
+ }
+
+ if (! yyres)
+ return yystrlen (yystr);
+
+ return yystpcpy (yyres, yystr) - yyres;
+}
+# endif
+
+/* Copy into YYRESULT an error message about the unexpected token
+ YYCHAR while in state YYSTATE. Return the number of bytes copied,
+ including the terminating null byte. If YYRESULT is null, do not
+ copy anything; just return the number of bytes that would be
+ copied. As a special case, return 0 if an ordinary "syntax error"
+ message will do. Return YYSIZE_MAXIMUM if overflow occurs during
+ size calculation. */
+static YYSIZE_T
+yysyntax_error (char *yyresult, int yystate, int yychar)
+{
+ int yyn = yypact[yystate];
+
+ if (! (YYPACT_NINF < yyn && yyn <= YYLAST))
+ return 0;
+ else
+ {
+ int yytype = YYTRANSLATE (yychar);
+ YYSIZE_T yysize0 = yytnamerr (0, yytname[yytype]);
+ YYSIZE_T yysize = yysize0;
+ YYSIZE_T yysize1;
+ int yysize_overflow = 0;
+ enum { YYERROR_VERBOSE_ARGS_MAXIMUM = 5 };
+ char const *yyarg[YYERROR_VERBOSE_ARGS_MAXIMUM];
+ int yyx;
+
+# if 0
+ /* This is so xgettext sees the translatable formats that are
+ constructed on the fly. */
+ YY_("syntax error, unexpected %s");
+ YY_("syntax error, unexpected %s, expecting %s");
+ YY_("syntax error, unexpected %s, expecting %s or %s");
+ YY_("syntax error, unexpected %s, expecting %s or %s or %s");
+ YY_("syntax error, unexpected %s, expecting %s or %s or %s or %s");
+# endif
+ char *yyfmt;
+ char const *yyf;
+ static char const yyunexpected[] = "syntax error, unexpected %s";
+ static char const yyexpecting[] = ", expecting %s";
+ static char const yyor[] = " or %s";
+ char yyformat[sizeof yyunexpected
+ + sizeof yyexpecting - 1
+ + ((YYERROR_VERBOSE_ARGS_MAXIMUM - 2)
+ * (sizeof yyor - 1))];
+ char const *yyprefix = yyexpecting;
+
+ /* Start YYX at -YYN if negative to avoid negative indexes in
+ YYCHECK. */
+ int yyxbegin = yyn < 0 ? -yyn : 0;
+
+ /* Stay within bounds of both yycheck and yytname. */
+ int yychecklim = YYLAST - yyn + 1;
+ int yyxend = yychecklim < YYNTOKENS ? yychecklim : YYNTOKENS;
+ int yycount = 1;
+
+ yyarg[0] = yytname[yytype];
+ yyfmt = yystpcpy (yyformat, yyunexpected);
+
+ for (yyx = yyxbegin; yyx < yyxend; ++yyx)
+ if (yycheck[yyx + yyn] == yyx && yyx != YYTERROR)
+ {
+ if (yycount == YYERROR_VERBOSE_ARGS_MAXIMUM)
+ {
+ yycount = 1;
+ yysize = yysize0;
+ yyformat[sizeof yyunexpected - 1] = '\0';
+ break;
+ }
+ yyarg[yycount++] = yytname[yyx];
+ yysize1 = yysize + yytnamerr (0, yytname[yyx]);
+ yysize_overflow |= (yysize1 < yysize);
+ yysize = yysize1;
+ yyfmt = yystpcpy (yyfmt, yyprefix);
+ yyprefix = yyor;
+ }
+
+ yyf = YY_(yyformat);
+ yysize1 = yysize + yystrlen (yyf);
+ yysize_overflow |= (yysize1 < yysize);
+ yysize = yysize1;
+
+ if (yysize_overflow)
+ return YYSIZE_MAXIMUM;
+
+ if (yyresult)
+ {
+ /* Avoid sprintf, as that infringes on the user's name space.
+ Don't have undefined behavior even if the translation
+ produced a string with the wrong number of "%s"s. */
+ char *yyp = yyresult;
+ int yyi = 0;
+ while ((*yyp = *yyf) != '\0')
+ {
+ if (*yyp == '%' && yyf[1] == 's' && yyi < yycount)
+ {
+ yyp += yytnamerr (yyp, yyarg[yyi++]);
+ yyf += 2;
+ }
+ else
+ {
+ yyp++;
+ yyf++;
+ }
+ }
+ }
+ return yysize;
+ }
+}
+#endif /* YYERROR_VERBOSE */
+
+
+/*-----------------------------------------------.
+| Release the memory associated to this symbol. |
+`-----------------------------------------------*/
+
+/*ARGSUSED*/
+#if (defined __STDC__ || defined __C99__FUNC__ \
+ || defined __cplusplus || defined _MSC_VER)
+static void
+yydestruct (const char *yymsg, int yytype, YYSTYPE *yyvaluep, YYLTYPE *yylocationp, glcpp_parser_t *parser)
+#else
+static void
+yydestruct (yymsg, yytype, yyvaluep, yylocationp, parser)
+ const char *yymsg;
+ int yytype;
+ YYSTYPE *yyvaluep;
+ YYLTYPE *yylocationp;
+ glcpp_parser_t *parser;
+#endif
+{
+ YYUSE (yyvaluep);
+ YYUSE (yylocationp);
+ YYUSE (parser);
+
+ if (!yymsg)
+ yymsg = "Deleting";
+ YY_SYMBOL_PRINT (yymsg, yytype, yyvaluep, yylocationp);
+
+ switch (yytype)
+ {
+
+ default:
+ break;
+ }
+}
+
+/* Prevent warnings from -Wmissing-prototypes. */
+#ifdef YYPARSE_PARAM
+#if defined __STDC__ || defined __cplusplus
+int yyparse (void *YYPARSE_PARAM);
+#else
+int yyparse ();
+#endif
+#else /* ! YYPARSE_PARAM */
+#if defined __STDC__ || defined __cplusplus
+int yyparse (glcpp_parser_t *parser);
+#else
+int yyparse ();
+#endif
+#endif /* ! YYPARSE_PARAM */
+
+
+
+
+
+/*-------------------------.
+| yyparse or yypush_parse. |
+`-------------------------*/
+
+#ifdef YYPARSE_PARAM
+#if (defined __STDC__ || defined __C99__FUNC__ \
+ || defined __cplusplus || defined _MSC_VER)
+int
+yyparse (void *YYPARSE_PARAM)
+#else
+int
+yyparse (YYPARSE_PARAM)
+ void *YYPARSE_PARAM;
+#endif
+#else /* ! YYPARSE_PARAM */
+#if (defined __STDC__ || defined __C99__FUNC__ \
+ || defined __cplusplus || defined _MSC_VER)
+int
+yyparse (glcpp_parser_t *parser)
+#else
+int
+yyparse (parser)
+ glcpp_parser_t *parser;
+#endif
+#endif
+{
+/* The lookahead symbol. */
+int yychar;
+
+/* The semantic value of the lookahead symbol. */
+YYSTYPE yylval;
+
+/* Location data for the lookahead symbol. */
+YYLTYPE yylloc;
+
+ /* Number of syntax errors so far. */
+ int yynerrs;
+
+ int yystate;
+ /* Number of tokens to shift before error messages enabled. */
+ int yyerrstatus;
+
+ /* The stacks and their tools:
+ `yyss': related to states.
+ `yyvs': related to semantic values.
+ `yyls': related to locations.
+
+ Refer to the stacks thru separate pointers, to allow yyoverflow
+ to reallocate them elsewhere. */
+
+ /* The state stack. */
+ yytype_int16 yyssa[YYINITDEPTH];
+ yytype_int16 *yyss;
+ yytype_int16 *yyssp;
+
+ /* The semantic value stack. */
+ YYSTYPE yyvsa[YYINITDEPTH];
+ YYSTYPE *yyvs;
+ YYSTYPE *yyvsp;
+
+ /* The location stack. */
+ YYLTYPE yylsa[YYINITDEPTH];
+ YYLTYPE *yyls;
+ YYLTYPE *yylsp;
+
+ /* The locations where the error started and ended. */
+ YYLTYPE yyerror_range[3];
+
+ YYSIZE_T yystacksize;
+
+ int yyn;
+ int yyresult;
+ /* Lookahead token as an internal (translated) token number. */
+ int yytoken;
+ /* The variables used to return semantic value and location from the
+ action routines. */
+ YYSTYPE yyval;
+ YYLTYPE yyloc;
+
+#if YYERROR_VERBOSE
+ /* Buffer for error messages, and its allocated size. */
+ char yymsgbuf[128];
+ char *yymsg = yymsgbuf;
+ YYSIZE_T yymsg_alloc = sizeof yymsgbuf;
+#endif
+
+#define YYPOPSTACK(N) (yyvsp -= (N), yyssp -= (N), yylsp -= (N))
+
+ /* The number of symbols on the RHS of the reduced rule.
+ Keep to zero when no symbol should be popped. */
+ int yylen = 0;
+
+ yytoken = 0;
+ yyss = yyssa;
+ yyvs = yyvsa;
+ yyls = yylsa;
+ yystacksize = YYINITDEPTH;
+
+ YYDPRINTF ((stderr, "Starting parse\n"));
+
+ yystate = 0;
+ yyerrstatus = 0;
+ yynerrs = 0;
+ yychar = YYEMPTY; /* Cause a token to be read. */
+
+ /* Initialize stack pointers.
+ Waste one element of value and location stack
+ so that they stay on the same level as the state stack.
+ The wasted elements are never initialized. */
+ yyssp = yyss;
+ yyvsp = yyvs;
+ yylsp = yyls;
+
+#if defined YYLTYPE_IS_TRIVIAL && YYLTYPE_IS_TRIVIAL
+ /* Initialize the default location before parsing starts. */
+ yylloc.first_line = yylloc.last_line = 1;
+ yylloc.first_column = yylloc.last_column = 1;
+#endif
+
+/* User initialization code. */
+
+/* Line 1251 of yacc.c */
+#line 148 "glcpp/glcpp-parse.y"
+{
+ yylloc.first_line = 1;
+ yylloc.first_column = 1;
+ yylloc.last_line = 1;
+ yylloc.last_column = 1;
+ yylloc.source = 0;
+}
+
+/* Line 1251 of yacc.c */
+#line 1618 "glcpp/glcpp-parse.c"
+ yylsp[0] = yylloc;
+
+ goto yysetstate;
+
+/*------------------------------------------------------------.
+| yynewstate -- Push a new state, which is found in yystate. |
+`------------------------------------------------------------*/
+ yynewstate:
+ /* In all cases, when you get here, the value and location stacks
+ have just been pushed. So pushing a state here evens the stacks. */
+ yyssp++;
+
+ yysetstate:
+ *yyssp = yystate;
+
+ if (yyss + yystacksize - 1 <= yyssp)
+ {
+ /* Get the current used size of the three stacks, in elements. */
+ YYSIZE_T yysize = yyssp - yyss + 1;
+
+#ifdef yyoverflow
+ {
+ /* Give user a chance to reallocate the stack. Use copies of
+ these so that the &'s don't force the real ones into
+ memory. */
+ YYSTYPE *yyvs1 = yyvs;
+ yytype_int16 *yyss1 = yyss;
+ YYLTYPE *yyls1 = yyls;
+
+ /* Each stack pointer address is followed by the size of the
+ data in use in that stack, in bytes. This used to be a
+ conditional around just the two extra args, but that might
+ be undefined if yyoverflow is a macro. */
+ yyoverflow (YY_("memory exhausted"),
+ &yyss1, yysize * sizeof (*yyssp),
+ &yyvs1, yysize * sizeof (*yyvsp),
+ &yyls1, yysize * sizeof (*yylsp),
+ &yystacksize);
+
+ yyls = yyls1;
+ yyss = yyss1;
+ yyvs = yyvs1;
+ }
+#else /* no yyoverflow */
+# ifndef YYSTACK_RELOCATE
+ goto yyexhaustedlab;
+# else
+ /* Extend the stack our own way. */
+ if (YYMAXDEPTH <= yystacksize)
+ goto yyexhaustedlab;
+ yystacksize *= 2;
+ if (YYMAXDEPTH < yystacksize)
+ yystacksize = YYMAXDEPTH;
+
+ {
+ yytype_int16 *yyss1 = yyss;
+ union yyalloc *yyptr =
+ (union yyalloc *) YYSTACK_ALLOC (YYSTACK_BYTES (yystacksize));
+ if (! yyptr)
+ goto yyexhaustedlab;
+ YYSTACK_RELOCATE (yyss_alloc, yyss);
+ YYSTACK_RELOCATE (yyvs_alloc, yyvs);
+ YYSTACK_RELOCATE (yyls_alloc, yyls);
+# undef YYSTACK_RELOCATE
+ if (yyss1 != yyssa)
+ YYSTACK_FREE (yyss1);
+ }
+# endif
+#endif /* no yyoverflow */
+
+ yyssp = yyss + yysize - 1;
+ yyvsp = yyvs + yysize - 1;
+ yylsp = yyls + yysize - 1;
+
+ YYDPRINTF ((stderr, "Stack size increased to %lu\n",
+ (unsigned long int) yystacksize));
+
+ if (yyss + yystacksize - 1 <= yyssp)
+ YYABORT;
+ }
+
+ YYDPRINTF ((stderr, "Entering state %d\n", yystate));
+
+ if (yystate == YYFINAL)
+ YYACCEPT;
+
+ goto yybackup;
+
+/*-----------.
+| yybackup. |
+`-----------*/
+yybackup:
+
+ /* Do appropriate processing given the current state. Read a
+ lookahead token if we need one and don't already have one. */
+
+ /* First try to decide what to do without reference to lookahead token. */
+ yyn = yypact[yystate];
+ if (yyn == YYPACT_NINF)
+ goto yydefault;
+
+ /* Not known => get a lookahead token if don't already have one. */
+
+ /* YYCHAR is either YYEMPTY or YYEOF or a valid lookahead symbol. */
+ if (yychar == YYEMPTY)
+ {
+ YYDPRINTF ((stderr, "Reading a token: "));
+ yychar = YYLEX;
+ }
+
+ if (yychar <= YYEOF)
+ {
+ yychar = yytoken = YYEOF;
+ YYDPRINTF ((stderr, "Now at end of input.\n"));
+ }
+ else
+ {
+ yytoken = YYTRANSLATE (yychar);
+ YY_SYMBOL_PRINT ("Next token is", yytoken, &yylval, &yylloc);
+ }
+
+ /* If the proper action on seeing token YYTOKEN is to reduce or to
+ detect an error, take that action. */
+ yyn += yytoken;
+ if (yyn < 0 || YYLAST < yyn || yycheck[yyn] != yytoken)
+ goto yydefault;
+ yyn = yytable[yyn];
+ if (yyn <= 0)
+ {
+ if (yyn == 0 || yyn == YYTABLE_NINF)
+ goto yyerrlab;
+ yyn = -yyn;
+ goto yyreduce;
+ }
+
+ /* Count tokens shifted since error; after three, turn off error
+ status. */
+ if (yyerrstatus)
+ yyerrstatus--;
+
+ /* Shift the lookahead token. */
+ YY_SYMBOL_PRINT ("Shifting", yytoken, &yylval, &yylloc);
+
+ /* Discard the shifted token. */
+ yychar = YYEMPTY;
+
+ yystate = yyn;
+ *++yyvsp = yylval;
+ *++yylsp = yylloc;
+ goto yynewstate;
+
+
+/*-----------------------------------------------------------.
+| yydefault -- do the default action for the current state. |
+`-----------------------------------------------------------*/
+yydefault:
+ yyn = yydefact[yystate];
+ if (yyn == 0)
+ goto yyerrlab;
+ goto yyreduce;
+
+
+/*-----------------------------.
+| yyreduce -- Do a reduction. |
+`-----------------------------*/
+yyreduce:
+ /* yyn is the number of a rule to reduce with. */
+ yylen = yyr2[yyn];
+
+ /* If YYLEN is nonzero, implement the default value of the action:
+ `$$ = $1'.
+
+ Otherwise, the following line sets YYVAL to garbage.
+ This behavior is undocumented and Bison
+ users should not rely upon it. Assigning to YYVAL
+ unconditionally makes the parser a bit smaller, and it avoids a
+ GCC warning that YYVAL may be used uninitialized. */
+ yyval = yyvsp[1-yylen];
+
+ /* Default location. */
+ YYLLOC_DEFAULT (yyloc, (yylsp - yylen), yylen);
+ YY_REDUCE_PRINT (yyn);
+ switch (yyn)
+ {
+ case 4:
+
+/* Line 1464 of yacc.c */
+#line 187 "glcpp/glcpp-parse.y"
+ {
+ glcpp_print(parser->output, "\n");
+ ;}
+ break;
+
+ case 5:
+
+/* Line 1464 of yacc.c */
+#line 190 "glcpp/glcpp-parse.y"
+ {
+ _glcpp_parser_print_expanded_token_list (parser, (yyvsp[(1) - (1)].token_list));
+ glcpp_print(parser->output, "\n");
+ talloc_free ((yyvsp[(1) - (1)].token_list));
+ ;}
+ break;
+
+ case 8:
+
+/* Line 1464 of yacc.c */
+#line 200 "glcpp/glcpp-parse.y"
+ {
+ _glcpp_parser_skip_stack_push_if (parser, & (yylsp[(1) - (3)]), (yyvsp[(2) - (3)].ival));
+ ;}
+ break;
+
+ case 9:
+
+/* Line 1464 of yacc.c */
+#line 203 "glcpp/glcpp-parse.y"
+ {
+ _glcpp_parser_skip_stack_change_if (parser, & (yylsp[(1) - (3)]), "elif", (yyvsp[(2) - (3)].ival));
+ ;}
+ break;
+
+ case 10:
+
+/* Line 1464 of yacc.c */
+#line 209 "glcpp/glcpp-parse.y"
+ {
+ _define_object_macro (parser, & (yylsp[(2) - (4)]), (yyvsp[(2) - (4)].str), (yyvsp[(3) - (4)].token_list));
+ ;}
+ break;
+
+ case 11:
+
+/* Line 1464 of yacc.c */
+#line 212 "glcpp/glcpp-parse.y"
+ {
+ _define_function_macro (parser, & (yylsp[(2) - (6)]), (yyvsp[(2) - (6)].str), NULL, (yyvsp[(5) - (6)].token_list));
+ ;}
+ break;
+
+ case 12:
+
+/* Line 1464 of yacc.c */
+#line 215 "glcpp/glcpp-parse.y"
+ {
+ _define_function_macro (parser, & (yylsp[(2) - (7)]), (yyvsp[(2) - (7)].str), (yyvsp[(4) - (7)].string_list), (yyvsp[(6) - (7)].token_list));
+ ;}
+ break;
+
+ case 13:
+
+/* Line 1464 of yacc.c */
+#line 218 "glcpp/glcpp-parse.y"
+ {
+ macro_t *macro = hash_table_find (parser->defines, (yyvsp[(2) - (3)].str));
+ if (macro) {
+ hash_table_remove (parser->defines, (yyvsp[(2) - (3)].str));
+ talloc_free (macro);
+ }
+ talloc_free ((yyvsp[(2) - (3)].str));
+ ;}
+ break;
+
+ case 14:
+
+/* Line 1464 of yacc.c */
+#line 226 "glcpp/glcpp-parse.y"
+ {
+ /* Be careful to only evaluate the 'if' expression if
+ * we are not skipping. When we are skipping, we
+ * simply push a new 0-valued 'if' onto the skip
+ * stack.
+ *
+ * This avoids generating diagnostics for invalid
+ * expressions that are being skipped. */
+ if (parser->skip_stack == NULL ||
+ parser->skip_stack->type == SKIP_NO_SKIP)
+ {
+ _glcpp_parser_expand_if (parser, IF_EXPANDED, (yyvsp[(2) - (3)].token_list));
+ }
+ else
+ {
+ _glcpp_parser_skip_stack_push_if (parser, & (yylsp[(1) - (3)]), 0);
+ parser->skip_stack->type = SKIP_TO_ENDIF;
+ }
+ ;}
+ break;
+
+ case 15:
+
+/* Line 1464 of yacc.c */
+#line 245 "glcpp/glcpp-parse.y"
+ {
+ /* #if without an expression is only an error if we
+ * are not skipping */
+ if (parser->skip_stack == NULL ||
+ parser->skip_stack->type == SKIP_NO_SKIP)
+ {
+ glcpp_error(& (yylsp[(1) - (2)]), parser, "#if with no expression");
+ }
+ _glcpp_parser_skip_stack_push_if (parser, & (yylsp[(1) - (2)]), 0);
+ ;}
+ break;
+
+ case 16:
+
+/* Line 1464 of yacc.c */
+#line 255 "glcpp/glcpp-parse.y"
+ {
+ macro_t *macro = hash_table_find (parser->defines, (yyvsp[(2) - (4)].str));
+ talloc_free ((yyvsp[(2) - (4)].str));
+ _glcpp_parser_skip_stack_push_if (parser, & (yylsp[(1) - (4)]), macro != NULL);
+ ;}
+ break;
+
+ case 17:
+
+/* Line 1464 of yacc.c */
+#line 260 "glcpp/glcpp-parse.y"
+ {
+ macro_t *macro = hash_table_find (parser->defines, (yyvsp[(2) - (4)].str));
+ talloc_free ((yyvsp[(2) - (4)].str));
+ _glcpp_parser_skip_stack_push_if (parser, & (yylsp[(1) - (4)]), macro == NULL);
+ ;}
+ break;
+
+ case 18:
+
+/* Line 1464 of yacc.c */
+#line 265 "glcpp/glcpp-parse.y"
+ {
+ /* Be careful to only evaluate the 'elif' expression
+ * if we are not skipping. When we are skipping, we
+ * simply change to a 0-valued 'elif' on the skip
+ * stack.
+ *
+ * This avoids generating diagnostics for invalid
+ * expressions that are being skipped. */
+ if (parser->skip_stack &&
+ parser->skip_stack->type == SKIP_TO_ELSE)
+ {
+ _glcpp_parser_expand_if (parser, ELIF_EXPANDED, (yyvsp[(2) - (3)].token_list));
+ }
+ else
+ {
+ _glcpp_parser_skip_stack_change_if (parser, & (yylsp[(1) - (3)]),
+ "elif", 0);
+ }
+ ;}
+ break;
+
+ case 19:
+
+/* Line 1464 of yacc.c */
+#line 284 "glcpp/glcpp-parse.y"
+ {
+ /* #elif without an expression is an error unless we
+ * are skipping. */
+ if (parser->skip_stack &&
+ parser->skip_stack->type == SKIP_TO_ELSE)
+ {
+ glcpp_error(& (yylsp[(1) - (2)]), parser, "#elif with no expression");
+ }
+ else
+ {
+ _glcpp_parser_skip_stack_change_if (parser, & (yylsp[(1) - (2)]),
+ "elif", 0);
+ glcpp_warning(& (yylsp[(1) - (2)]), parser, "ignoring illegal #elif without expression");
+ }
+ ;}
+ break;
+
+ case 20:
+
+/* Line 1464 of yacc.c */
+#line 299 "glcpp/glcpp-parse.y"
+ {
+ _glcpp_parser_skip_stack_change_if (parser, & (yylsp[(1) - (2)]), "else", 1);
+ ;}
+ break;
+
+ case 21:
+
+/* Line 1464 of yacc.c */
+#line 302 "glcpp/glcpp-parse.y"
+ {
+ _glcpp_parser_skip_stack_pop (parser, & (yylsp[(1) - (2)]));
+ ;}
+ break;
+
+ case 22:
+
+/* Line 1464 of yacc.c */
+#line 305 "glcpp/glcpp-parse.y"
+ {
+ macro_t *macro = hash_table_find (parser->defines, "__VERSION__");
+ if (macro) {
+ hash_table_remove (parser->defines, "__VERSION__");
+ talloc_free (macro);
+ }
+ add_builtin_define (parser, "__VERSION__", (yyvsp[(2) - (3)].ival));
+ glcpp_printf(parser->output, "#version %" PRIiMAX "\n", (yyvsp[(2) - (3)].ival));
+ ;}
+ break;
+
+ case 24:
+
+/* Line 1464 of yacc.c */
+#line 318 "glcpp/glcpp-parse.y"
+ {
+ if (strlen ((yyvsp[(1) - (1)].str)) >= 3 && strncmp ((yyvsp[(1) - (1)].str), "0x", 2) == 0) {
+ (yyval.ival) = strtoll ((yyvsp[(1) - (1)].str) + 2, NULL, 16);
+ } else if ((yyvsp[(1) - (1)].str)[0] == '0') {
+ (yyval.ival) = strtoll ((yyvsp[(1) - (1)].str), NULL, 8);
+ } else {
+ (yyval.ival) = strtoll ((yyvsp[(1) - (1)].str), NULL, 10);
+ }
+ ;}
+ break;
+
+ case 25:
+
+/* Line 1464 of yacc.c */
+#line 327 "glcpp/glcpp-parse.y"
+ {
+ (yyval.ival) = (yyvsp[(1) - (1)].ival);
+ ;}
+ break;
+
+ case 27:
+
+/* Line 1464 of yacc.c */
+#line 333 "glcpp/glcpp-parse.y"
+ {
+ (yyval.ival) = (yyvsp[(1) - (3)].ival) || (yyvsp[(3) - (3)].ival);
+ ;}
+ break;
+
+ case 28:
+
+/* Line 1464 of yacc.c */
+#line 336 "glcpp/glcpp-parse.y"
+ {
+ (yyval.ival) = (yyvsp[(1) - (3)].ival) && (yyvsp[(3) - (3)].ival);
+ ;}
+ break;
+
+ case 29:
+
+/* Line 1464 of yacc.c */
+#line 339 "glcpp/glcpp-parse.y"
+ {
+ (yyval.ival) = (yyvsp[(1) - (3)].ival) | (yyvsp[(3) - (3)].ival);
+ ;}
+ break;
+
+ case 30:
+
+/* Line 1464 of yacc.c */
+#line 342 "glcpp/glcpp-parse.y"
+ {
+ (yyval.ival) = (yyvsp[(1) - (3)].ival) ^ (yyvsp[(3) - (3)].ival);
+ ;}
+ break;
+
+ case 31:
+
+/* Line 1464 of yacc.c */
+#line 345 "glcpp/glcpp-parse.y"
+ {
+ (yyval.ival) = (yyvsp[(1) - (3)].ival) & (yyvsp[(3) - (3)].ival);
+ ;}
+ break;
+
+ case 32:
+
+/* Line 1464 of yacc.c */
+#line 348 "glcpp/glcpp-parse.y"
+ {
+ (yyval.ival) = (yyvsp[(1) - (3)].ival) != (yyvsp[(3) - (3)].ival);
+ ;}
+ break;
+
+ case 33:
+
+/* Line 1464 of yacc.c */
+#line 351 "glcpp/glcpp-parse.y"
+ {
+ (yyval.ival) = (yyvsp[(1) - (3)].ival) == (yyvsp[(3) - (3)].ival);
+ ;}
+ break;
+
+ case 34:
+
+/* Line 1464 of yacc.c */
+#line 354 "glcpp/glcpp-parse.y"
+ {
+ (yyval.ival) = (yyvsp[(1) - (3)].ival) >= (yyvsp[(3) - (3)].ival);
+ ;}
+ break;
+
+ case 35:
+
+/* Line 1464 of yacc.c */
+#line 357 "glcpp/glcpp-parse.y"
+ {
+ (yyval.ival) = (yyvsp[(1) - (3)].ival) <= (yyvsp[(3) - (3)].ival);
+ ;}
+ break;
+
+ case 36:
+
+/* Line 1464 of yacc.c */
+#line 360 "glcpp/glcpp-parse.y"
+ {
+ (yyval.ival) = (yyvsp[(1) - (3)].ival) > (yyvsp[(3) - (3)].ival);
+ ;}
+ break;
+
+ case 37:
+
+/* Line 1464 of yacc.c */
+#line 363 "glcpp/glcpp-parse.y"
+ {
+ (yyval.ival) = (yyvsp[(1) - (3)].ival) < (yyvsp[(3) - (3)].ival);
+ ;}
+ break;
+
+ case 38:
+
+/* Line 1464 of yacc.c */
+#line 366 "glcpp/glcpp-parse.y"
+ {
+ (yyval.ival) = (yyvsp[(1) - (3)].ival) >> (yyvsp[(3) - (3)].ival);
+ ;}
+ break;
+
+ case 39:
+
+/* Line 1464 of yacc.c */
+#line 369 "glcpp/glcpp-parse.y"
+ {
+ (yyval.ival) = (yyvsp[(1) - (3)].ival) << (yyvsp[(3) - (3)].ival);
+ ;}
+ break;
+
+ case 40:
+
+/* Line 1464 of yacc.c */
+#line 372 "glcpp/glcpp-parse.y"
+ {
+ (yyval.ival) = (yyvsp[(1) - (3)].ival) - (yyvsp[(3) - (3)].ival);
+ ;}
+ break;
+
+ case 41:
+
+/* Line 1464 of yacc.c */
+#line 375 "glcpp/glcpp-parse.y"
+ {
+ (yyval.ival) = (yyvsp[(1) - (3)].ival) + (yyvsp[(3) - (3)].ival);
+ ;}
+ break;
+
+ case 42:
+
+/* Line 1464 of yacc.c */
+#line 378 "glcpp/glcpp-parse.y"
+ {
+ (yyval.ival) = (yyvsp[(1) - (3)].ival) % (yyvsp[(3) - (3)].ival);
+ ;}
+ break;
+
+ case 43:
+
+/* Line 1464 of yacc.c */
+#line 381 "glcpp/glcpp-parse.y"
+ {
+ (yyval.ival) = (yyvsp[(1) - (3)].ival) / (yyvsp[(3) - (3)].ival);
+ ;}
+ break;
+
+ case 44:
+
+/* Line 1464 of yacc.c */
+#line 384 "glcpp/glcpp-parse.y"
+ {
+ (yyval.ival) = (yyvsp[(1) - (3)].ival) * (yyvsp[(3) - (3)].ival);
+ ;}
+ break;
+
+ case 45:
+
+/* Line 1464 of yacc.c */
+#line 387 "glcpp/glcpp-parse.y"
+ {
+ (yyval.ival) = ! (yyvsp[(2) - (2)].ival);
+ ;}
+ break;
+
+ case 46:
+
+/* Line 1464 of yacc.c */
+#line 390 "glcpp/glcpp-parse.y"
+ {
+ (yyval.ival) = ~ (yyvsp[(2) - (2)].ival);
+ ;}
+ break;
+
+ case 47:
+
+/* Line 1464 of yacc.c */
+#line 393 "glcpp/glcpp-parse.y"
+ {
+ (yyval.ival) = - (yyvsp[(2) - (2)].ival);
+ ;}
+ break;
+
+ case 48:
+
+/* Line 1464 of yacc.c */
+#line 396 "glcpp/glcpp-parse.y"
+ {
+ (yyval.ival) = + (yyvsp[(2) - (2)].ival);
+ ;}
+ break;
+
+ case 49:
+
+/* Line 1464 of yacc.c */
+#line 399 "glcpp/glcpp-parse.y"
+ {
+ (yyval.ival) = (yyvsp[(2) - (3)].ival);
+ ;}
+ break;
+
+ case 50:
+
+/* Line 1464 of yacc.c */
+#line 405 "glcpp/glcpp-parse.y"
+ {
+ (yyval.string_list) = _string_list_create (parser);
+ _string_list_append_item ((yyval.string_list), (yyvsp[(1) - (1)].str));
+ talloc_steal ((yyval.string_list), (yyvsp[(1) - (1)].str));
+ ;}
+ break;
+
+ case 51:
+
+/* Line 1464 of yacc.c */
+#line 410 "glcpp/glcpp-parse.y"
+ {
+ (yyval.string_list) = (yyvsp[(1) - (3)].string_list);
+ _string_list_append_item ((yyval.string_list), (yyvsp[(3) - (3)].str));
+ talloc_steal ((yyval.string_list), (yyvsp[(3) - (3)].str));
+ ;}
+ break;
+
+ case 52:
+
+/* Line 1464 of yacc.c */
+#line 418 "glcpp/glcpp-parse.y"
+ { (yyval.token_list) = NULL; ;}
+ break;
+
+ case 54:
+
+/* Line 1464 of yacc.c */
+#line 423 "glcpp/glcpp-parse.y"
+ {
+ yyerror (& (yylsp[(1) - (2)]), parser, "Invalid tokens after #");
+ ;}
+ break;
+
+ case 55:
+
+/* Line 1464 of yacc.c */
+#line 429 "glcpp/glcpp-parse.y"
+ { (yyval.token_list) = NULL; ;}
+ break;
+
+ case 58:
+
+/* Line 1464 of yacc.c */
+#line 435 "glcpp/glcpp-parse.y"
+ {
+ glcpp_warning(&(yylsp[(1) - (1)]), parser, "extra tokens at end of directive");
+ ;}
+ break;
+
+ case 59:
+
+/* Line 1464 of yacc.c */
+#line 442 "glcpp/glcpp-parse.y"
+ {
+ int v = hash_table_find (parser->defines, (yyvsp[(2) - (2)].str)) ? 1 : 0;
+ (yyval.token) = _token_create_ival (parser, INTEGER, v);
+ ;}
+ break;
+
+ case 60:
+
+/* Line 1464 of yacc.c */
+#line 446 "glcpp/glcpp-parse.y"
+ {
+ int v = hash_table_find (parser->defines, (yyvsp[(3) - (4)].str)) ? 1 : 0;
+ (yyval.token) = _token_create_ival (parser, INTEGER, v);
+ ;}
+ break;
+
+ case 62:
+
+/* Line 1464 of yacc.c */
+#line 455 "glcpp/glcpp-parse.y"
+ {
+ parser->space_tokens = 1;
+ (yyval.token_list) = _token_list_create (parser);
+ _token_list_append ((yyval.token_list), (yyvsp[(1) - (1)].token));
+ talloc_unlink (parser, (yyvsp[(1) - (1)].token));
+ ;}
+ break;
+
+ case 63:
+
+/* Line 1464 of yacc.c */
+#line 461 "glcpp/glcpp-parse.y"
+ {
+ (yyval.token_list) = (yyvsp[(1) - (2)].token_list);
+ _token_list_append ((yyval.token_list), (yyvsp[(2) - (2)].token));
+ talloc_unlink (parser, (yyvsp[(2) - (2)].token));
+ ;}
+ break;
+
+ case 64:
+
+/* Line 1464 of yacc.c */
+#line 469 "glcpp/glcpp-parse.y"
+ {
+ parser->space_tokens = 1;
+ (yyval.token_list) = _token_list_create (parser);
+ _token_list_append ((yyval.token_list), (yyvsp[(1) - (1)].token));
+ talloc_unlink (parser, (yyvsp[(1) - (1)].token));
+ ;}
+ break;
+
+ case 65:
+
+/* Line 1464 of yacc.c */
+#line 475 "glcpp/glcpp-parse.y"
+ {
+ (yyval.token_list) = (yyvsp[(1) - (2)].token_list);
+ _token_list_append ((yyval.token_list), (yyvsp[(2) - (2)].token));
+ talloc_unlink (parser, (yyvsp[(2) - (2)].token));
+ ;}
+ break;
+
+ case 66:
+
+/* Line 1464 of yacc.c */
+#line 483 "glcpp/glcpp-parse.y"
+ {
+ (yyval.token) = _token_create_str (parser, IDENTIFIER, (yyvsp[(1) - (1)].str));
+ (yyval.token)->location = yylloc;
+ ;}
+ break;
+
+ case 67:
+
+/* Line 1464 of yacc.c */
+#line 487 "glcpp/glcpp-parse.y"
+ {
+ (yyval.token) = _token_create_str (parser, INTEGER_STRING, (yyvsp[(1) - (1)].str));
+ (yyval.token)->location = yylloc;
+ ;}
+ break;
+
+ case 68:
+
+/* Line 1464 of yacc.c */
+#line 491 "glcpp/glcpp-parse.y"
+ {
+ (yyval.token) = _token_create_ival (parser, (yyvsp[(1) - (1)].ival), (yyvsp[(1) - (1)].ival));
+ (yyval.token)->location = yylloc;
+ ;}
+ break;
+
+ case 69:
+
+/* Line 1464 of yacc.c */
+#line 495 "glcpp/glcpp-parse.y"
+ {
+ (yyval.token) = _token_create_str (parser, OTHER, (yyvsp[(1) - (1)].str));
+ (yyval.token)->location = yylloc;
+ ;}
+ break;
+
+ case 70:
+
+/* Line 1464 of yacc.c */
+#line 499 "glcpp/glcpp-parse.y"
+ {
+ (yyval.token) = _token_create_ival (parser, SPACE, SPACE);
+ (yyval.token)->location = yylloc;
+ ;}
+ break;
+
+ case 71:
+
+/* Line 1464 of yacc.c */
+#line 506 "glcpp/glcpp-parse.y"
+ { (yyval.ival) = '['; ;}
+ break;
+
+ case 72:
+
+/* Line 1464 of yacc.c */
+#line 507 "glcpp/glcpp-parse.y"
+ { (yyval.ival) = ']'; ;}
+ break;
+
+ case 73:
+
+/* Line 1464 of yacc.c */
+#line 508 "glcpp/glcpp-parse.y"
+ { (yyval.ival) = '('; ;}
+ break;
+
+ case 74:
+
+/* Line 1464 of yacc.c */
+#line 509 "glcpp/glcpp-parse.y"
+ { (yyval.ival) = ')'; ;}
+ break;
+
+ case 75:
+
+/* Line 1464 of yacc.c */
+#line 510 "glcpp/glcpp-parse.y"
+ { (yyval.ival) = '{'; ;}
+ break;
+
+ case 76:
+
+/* Line 1464 of yacc.c */
+#line 511 "glcpp/glcpp-parse.y"
+ { (yyval.ival) = '}'; ;}
+ break;
+
+ case 77:
+
+/* Line 1464 of yacc.c */
+#line 512 "glcpp/glcpp-parse.y"
+ { (yyval.ival) = '.'; ;}
+ break;
+
+ case 78:
+
+/* Line 1464 of yacc.c */
+#line 513 "glcpp/glcpp-parse.y"
+ { (yyval.ival) = '&'; ;}
+ break;
+
+ case 79:
+
+/* Line 1464 of yacc.c */
+#line 514 "glcpp/glcpp-parse.y"
+ { (yyval.ival) = '*'; ;}
+ break;
+
+ case 80:
+
+/* Line 1464 of yacc.c */
+#line 515 "glcpp/glcpp-parse.y"
+ { (yyval.ival) = '+'; ;}
+ break;
+
+ case 81:
+
+/* Line 1464 of yacc.c */
+#line 516 "glcpp/glcpp-parse.y"
+ { (yyval.ival) = '-'; ;}
+ break;
+
+ case 82:
+
+/* Line 1464 of yacc.c */
+#line 517 "glcpp/glcpp-parse.y"
+ { (yyval.ival) = '~'; ;}
+ break;
+
+ case 83:
+
+/* Line 1464 of yacc.c */
+#line 518 "glcpp/glcpp-parse.y"
+ { (yyval.ival) = '!'; ;}
+ break;
+
+ case 84:
+
+/* Line 1464 of yacc.c */
+#line 519 "glcpp/glcpp-parse.y"
+ { (yyval.ival) = '/'; ;}
+ break;
+
+ case 85:
+
+/* Line 1464 of yacc.c */
+#line 520 "glcpp/glcpp-parse.y"
+ { (yyval.ival) = '%'; ;}
+ break;
+
+ case 86:
+
+/* Line 1464 of yacc.c */
+#line 521 "glcpp/glcpp-parse.y"
+ { (yyval.ival) = LEFT_SHIFT; ;}
+ break;
+
+ case 87:
+
+/* Line 1464 of yacc.c */
+#line 522 "glcpp/glcpp-parse.y"
+ { (yyval.ival) = RIGHT_SHIFT; ;}
+ break;
+
+ case 88:
+
+/* Line 1464 of yacc.c */
+#line 523 "glcpp/glcpp-parse.y"
+ { (yyval.ival) = '<'; ;}
+ break;
+
+ case 89:
+
+/* Line 1464 of yacc.c */
+#line 524 "glcpp/glcpp-parse.y"
+ { (yyval.ival) = '>'; ;}
+ break;
+
+ case 90:
+
+/* Line 1464 of yacc.c */
+#line 525 "glcpp/glcpp-parse.y"
+ { (yyval.ival) = LESS_OR_EQUAL; ;}
+ break;
+
+ case 91:
+
+/* Line 1464 of yacc.c */
+#line 526 "glcpp/glcpp-parse.y"
+ { (yyval.ival) = GREATER_OR_EQUAL; ;}
+ break;
+
+ case 92:
+
+/* Line 1464 of yacc.c */
+#line 527 "glcpp/glcpp-parse.y"
+ { (yyval.ival) = EQUAL; ;}
+ break;
+
+ case 93:
+
+/* Line 1464 of yacc.c */
+#line 528 "glcpp/glcpp-parse.y"
+ { (yyval.ival) = NOT_EQUAL; ;}
+ break;
+
+ case 94:
+
+/* Line 1464 of yacc.c */
+#line 529 "glcpp/glcpp-parse.y"
+ { (yyval.ival) = '^'; ;}
+ break;
+
+ case 95:
+
+/* Line 1464 of yacc.c */
+#line 530 "glcpp/glcpp-parse.y"
+ { (yyval.ival) = '|'; ;}
+ break;
+
+ case 96:
+
+/* Line 1464 of yacc.c */
+#line 531 "glcpp/glcpp-parse.y"
+ { (yyval.ival) = AND; ;}
+ break;
+
+ case 97:
+
+/* Line 1464 of yacc.c */
+#line 532 "glcpp/glcpp-parse.y"
+ { (yyval.ival) = OR; ;}
+ break;
+
+ case 98:
+
+/* Line 1464 of yacc.c */
+#line 533 "glcpp/glcpp-parse.y"
+ { (yyval.ival) = ';'; ;}
+ break;
+
+ case 99:
+
+/* Line 1464 of yacc.c */
+#line 534 "glcpp/glcpp-parse.y"
+ { (yyval.ival) = ','; ;}
+ break;
+
+ case 100:
+
+/* Line 1464 of yacc.c */
+#line 535 "glcpp/glcpp-parse.y"
+ { (yyval.ival) = '='; ;}
+ break;
+
+ case 101:
+
+/* Line 1464 of yacc.c */
+#line 536 "glcpp/glcpp-parse.y"
+ { (yyval.ival) = PASTE; ;}
+ break;
+
+
+
+/* Line 1464 of yacc.c */
+#line 2645 "glcpp/glcpp-parse.c"
+ default: break;
+ }
+ YY_SYMBOL_PRINT ("-> $$ =", yyr1[yyn], &yyval, &yyloc);
+
+ YYPOPSTACK (yylen);
+ yylen = 0;
+ YY_STACK_PRINT (yyss, yyssp);
+
+ *++yyvsp = yyval;
+ *++yylsp = yyloc;
+
+ /* Now `shift' the result of the reduction. Determine what state
+ that goes to, based on the state we popped back to and the rule
+ number reduced by. */
+
+ yyn = yyr1[yyn];
+
+ yystate = yypgoto[yyn - YYNTOKENS] + *yyssp;
+ if (0 <= yystate && yystate <= YYLAST && yycheck[yystate] == *yyssp)
+ yystate = yytable[yystate];
+ else
+ yystate = yydefgoto[yyn - YYNTOKENS];
+
+ goto yynewstate;
+
+
+/*------------------------------------.
+| yyerrlab -- here on detecting error |
+`------------------------------------*/
+yyerrlab:
+ /* If not already recovering from an error, report this error. */
+ if (!yyerrstatus)
+ {
+ ++yynerrs;
+#if ! YYERROR_VERBOSE
+ yyerror (&yylloc, parser, YY_("syntax error"));
+#else
+ {
+ YYSIZE_T yysize = yysyntax_error (0, yystate, yychar);
+ if (yymsg_alloc < yysize && yymsg_alloc < YYSTACK_ALLOC_MAXIMUM)
+ {
+ YYSIZE_T yyalloc = 2 * yysize;
+ if (! (yysize <= yyalloc && yyalloc <= YYSTACK_ALLOC_MAXIMUM))
+ yyalloc = YYSTACK_ALLOC_MAXIMUM;
+ if (yymsg != yymsgbuf)
+ YYSTACK_FREE (yymsg);
+ yymsg = (char *) YYSTACK_ALLOC (yyalloc);
+ if (yymsg)
+ yymsg_alloc = yyalloc;
+ else
+ {
+ yymsg = yymsgbuf;
+ yymsg_alloc = sizeof yymsgbuf;
+ }
+ }
+
+ if (0 < yysize && yysize <= yymsg_alloc)
+ {
+ (void) yysyntax_error (yymsg, yystate, yychar);
+ yyerror (&yylloc, parser, yymsg);
+ }
+ else
+ {
+ yyerror (&yylloc, parser, YY_("syntax error"));
+ if (yysize != 0)
+ goto yyexhaustedlab;
+ }
+ }
+#endif
+ }
+
+ yyerror_range[1] = yylloc;
+
+ if (yyerrstatus == 3)
+ {
+ /* If just tried and failed to reuse lookahead token after an
+ error, discard it. */
+
+ if (yychar <= YYEOF)
+ {
+ /* Return failure if at end of input. */
+ if (yychar == YYEOF)
+ YYABORT;
+ }
+ else
+ {
+ yydestruct ("Error: discarding",
+ yytoken, &yylval, &yylloc, parser);
+ yychar = YYEMPTY;
+ }
+ }
+
+ /* Else will try to reuse lookahead token after shifting the error
+ token. */
+ goto yyerrlab1;
+
+
+/*---------------------------------------------------.
+| yyerrorlab -- error raised explicitly by YYERROR. |
+`---------------------------------------------------*/
+yyerrorlab:
+
+ /* Pacify compilers like GCC when the user code never invokes
+ YYERROR and the label yyerrorlab therefore never appears in user
+ code. */
+ if (/*CONSTCOND*/ 0)
+ goto yyerrorlab;
+
+ yyerror_range[1] = yylsp[1-yylen];
+ /* Do not reclaim the symbols of the rule which action triggered
+ this YYERROR. */
+ YYPOPSTACK (yylen);
+ yylen = 0;
+ YY_STACK_PRINT (yyss, yyssp);
+ yystate = *yyssp;
+ goto yyerrlab1;
+
+
+/*-------------------------------------------------------------.
+| yyerrlab1 -- common code for both syntax error and YYERROR. |
+`-------------------------------------------------------------*/
+yyerrlab1:
+ yyerrstatus = 3; /* Each real token shifted decrements this. */
+
+ for (;;)
+ {
+ yyn = yypact[yystate];
+ if (yyn != YYPACT_NINF)
+ {
+ yyn += YYTERROR;
+ if (0 <= yyn && yyn <= YYLAST && yycheck[yyn] == YYTERROR)
+ {
+ yyn = yytable[yyn];
+ if (0 < yyn)
+ break;
+ }
+ }
+
+ /* Pop the current state because it cannot handle the error token. */
+ if (yyssp == yyss)
+ YYABORT;
+
+ yyerror_range[1] = *yylsp;
+ yydestruct ("Error: popping",
+ yystos[yystate], yyvsp, yylsp, parser);
+ YYPOPSTACK (1);
+ yystate = *yyssp;
+ YY_STACK_PRINT (yyss, yyssp);
+ }
+
+ *++yyvsp = yylval;
+
+ yyerror_range[2] = yylloc;
+ /* Using YYLLOC is tempting, but would change the location of
+ the lookahead. YYLOC is available though. */
+ YYLLOC_DEFAULT (yyloc, yyerror_range, 2);
+ *++yylsp = yyloc;
+
+ /* Shift the error token. */
+ YY_SYMBOL_PRINT ("Shifting", yystos[yyn], yyvsp, yylsp);
+
+ yystate = yyn;
+ goto yynewstate;
+
+
+/*-------------------------------------.
+| yyacceptlab -- YYACCEPT comes here. |
+`-------------------------------------*/
+yyacceptlab:
+ yyresult = 0;
+ goto yyreturn;
+
+/*-----------------------------------.
+| yyabortlab -- YYABORT comes here. |
+`-----------------------------------*/
+yyabortlab:
+ yyresult = 1;
+ goto yyreturn;
+
+#if !defined(yyoverflow) || YYERROR_VERBOSE
+/*-------------------------------------------------.
+| yyexhaustedlab -- memory exhaustion comes here. |
+`-------------------------------------------------*/
+yyexhaustedlab:
+ yyerror (&yylloc, parser, YY_("memory exhausted"));
+ yyresult = 2;
+ /* Fall through. */
+#endif
+
+yyreturn:
+ if (yychar != YYEMPTY)
+ yydestruct ("Cleanup: discarding lookahead",
+ yytoken, &yylval, &yylloc, parser);
+ /* Do not reclaim the symbols of the rule which action triggered
+ this YYABORT or YYACCEPT. */
+ YYPOPSTACK (yylen);
+ YY_STACK_PRINT (yyss, yyssp);
+ while (yyssp != yyss)
+ {
+ yydestruct ("Cleanup: popping",
+ yystos[*yyssp], yyvsp, yylsp, parser);
+ YYPOPSTACK (1);
+ }
+#ifndef yyoverflow
+ if (yyss != yyssa)
+ YYSTACK_FREE (yyss);
+#endif
+#if YYERROR_VERBOSE
+ if (yymsg != yymsgbuf)
+ YYSTACK_FREE (yymsg);
+#endif
+ /* Make sure YYID is used. */
+ return YYID (yyresult);
+}
+
+
+
+/* Line 1684 of yacc.c */
+#line 539 "glcpp/glcpp-parse.y"
+
+
+string_list_t *
+_string_list_create (void *ctx)
+{
+ string_list_t *list;
+
+ list = talloc (ctx, string_list_t);
+ list->head = NULL;
+ list->tail = NULL;
+
+ return list;
+}
+
+void
+_string_list_append_item (string_list_t *list, const char *str)
+{
+ string_node_t *node;
+
+ node = talloc (list, string_node_t);
+ node->str = talloc_strdup (node, str);
+
+ node->next = NULL;
+
+ if (list->head == NULL) {
+ list->head = node;
+ } else {
+ list->tail->next = node;
+ }
+
+ list->tail = node;
+}
+
+int
+_string_list_contains (string_list_t *list, const char *member, int *index)
+{
+ string_node_t *node;
+ int i;
+
+ if (list == NULL)
+ return 0;
+
+ for (i = 0, node = list->head; node; i++, node = node->next) {
+ if (strcmp (node->str, member) == 0) {
+ if (index)
+ *index = i;
+ return 1;
+ }
+ }
+
+ return 0;
+}
+
+int
+_string_list_length (string_list_t *list)
+{
+ int length = 0;
+ string_node_t *node;
+
+ if (list == NULL)
+ return 0;
+
+ for (node = list->head; node; node = node->next)
+ length++;
+
+ return length;
+}
+
+argument_list_t *
+_argument_list_create (void *ctx)
+{
+ argument_list_t *list;
+
+ list = talloc (ctx, argument_list_t);
+ list->head = NULL;
+ list->tail = NULL;
+
+ return list;
+}
+
+void
+_argument_list_append (argument_list_t *list, token_list_t *argument)
+{
+ argument_node_t *node;
+
+ node = talloc (list, argument_node_t);
+ node->argument = argument;
+
+ node->next = NULL;
+
+ if (list->head == NULL) {
+ list->head = node;
+ } else {
+ list->tail->next = node;
+ }
+
+ list->tail = node;
+}
+
+int
+_argument_list_length (argument_list_t *list)
+{
+ int length = 0;
+ argument_node_t *node;
+
+ if (list == NULL)
+ return 0;
+
+ for (node = list->head; node; node = node->next)
+ length++;
+
+ return length;
+}
+
+token_list_t *
+_argument_list_member_at (argument_list_t *list, int index)
+{
+ argument_node_t *node;
+ int i;
+
+ if (list == NULL)
+ return NULL;
+
+ node = list->head;
+ for (i = 0; i < index; i++) {
+ node = node->next;
+ if (node == NULL)
+ break;
+ }
+
+ if (node)
+ return node->argument;
+
+ return NULL;
+}
+
+/* Note: This function talloc_steal()s the str pointer. */
+token_t *
+_token_create_str (void *ctx, int type, char *str)
+{
+ token_t *token;
+
+ token = talloc (ctx, token_t);
+ token->type = type;
+ token->value.str = talloc_steal (token, str);
+
+ return token;
+}
+
+token_t *
+_token_create_ival (void *ctx, int type, int ival)
+{
+ token_t *token;
+
+ token = talloc (ctx, token_t);
+ token->type = type;
+ token->value.ival = ival;
+
+ return token;
+}
+
+token_list_t *
+_token_list_create (void *ctx)
+{
+ token_list_t *list;
+
+ list = talloc (ctx, token_list_t);
+ list->head = NULL;
+ list->tail = NULL;
+ list->non_space_tail = NULL;
+
+ return list;
+}
+
+void
+_token_list_append (token_list_t *list, token_t *token)
+{
+ token_node_t *node;
+
+ node = talloc (list, token_node_t);
+ node->token = talloc_reference (list, token);
+
+ node->next = NULL;
+
+ if (list->head == NULL) {
+ list->head = node;
+ } else {
+ list->tail->next = node;
+ }
+
+ list->tail = node;
+ if (token->type != SPACE)
+ list->non_space_tail = node;
+}
+
+void
+_token_list_append_list (token_list_t *list, token_list_t *tail)
+{
+ if (tail == NULL || tail->head == NULL)
+ return;
+
+ if (list->head == NULL) {
+ list->head = tail->head;
+ } else {
+ list->tail->next = tail->head;
+ }
+
+ list->tail = tail->tail;
+ list->non_space_tail = tail->non_space_tail;
+}
+
+static token_list_t *
+_token_list_copy (void *ctx, token_list_t *other)
+{
+ token_list_t *copy;
+ token_node_t *node;
+
+ if (other == NULL)
+ return NULL;
+
+ copy = _token_list_create (ctx);
+ for (node = other->head; node; node = node->next)
+ _token_list_append (copy, node->token);
+
+ return copy;
+}
+
+static void
+_token_list_trim_trailing_space (token_list_t *list)
+{
+ token_node_t *tail, *next;
+
+ if (list->non_space_tail) {
+ tail = list->non_space_tail->next;
+ list->non_space_tail->next = NULL;
+ list->tail = list->non_space_tail;
+
+ while (tail) {
+ next = tail->next;
+ talloc_free (tail);
+ tail = next;
+ }
+ }
+}
+
+static void
+_token_print (char **out, token_t *token)
+{
+ if (token->type < 256) {
+ glcpp_printf (*out, "%c", token->type);
+ return;
+ }
+
+ switch (token->type) {
+ case INTEGER:
+ glcpp_printf (*out, "%" PRIiMAX, token->value.ival);
+ break;
+ case IDENTIFIER:
+ case INTEGER_STRING:
+ case OTHER:
+ glcpp_print (*out, token->value.str);
+ break;
+ case SPACE:
+ glcpp_print (*out, " ");
+ break;
+ case LEFT_SHIFT:
+ glcpp_print (*out, "<<");
+ break;
+ case RIGHT_SHIFT:
+ glcpp_print (*out, ">>");
+ break;
+ case LESS_OR_EQUAL:
+ glcpp_print (*out, "<=");
+ break;
+ case GREATER_OR_EQUAL:
+ glcpp_print (*out, ">=");
+ break;
+ case EQUAL:
+ glcpp_print (*out, "==");
+ break;
+ case NOT_EQUAL:
+ glcpp_print (*out, "!=");
+ break;
+ case AND:
+ glcpp_print (*out, "&&");
+ break;
+ case OR:
+ glcpp_print (*out, "||");
+ break;
+ case PASTE:
+ glcpp_print (*out, "##");
+ break;
+ case COMMA_FINAL:
+ glcpp_print (*out, ",");
+ break;
+ case PLACEHOLDER:
+ /* Nothing to print. */
+ break;
+ default:
+ assert(!"Error: Don't know how to print token.");
+ break;
+ }
+}
+
+/* Return a new token (talloc()ed off of 'token') formed by pasting
+ * 'token' and 'other'. Note that this function may return 'token' or
+ * 'other' directly rather than allocating anything new.
+ *
+ * Caution: Only very cursory error-checking is performed to see if
+ * the final result is a valid single token. */
+static token_t *
+_token_paste (glcpp_parser_t *parser, token_t *token, token_t *other)
+{
+ token_t *combined = NULL;
+
+ /* Pasting a placeholder onto anything makes no change. */
+ if (other->type == PLACEHOLDER)
+ return token;
+
+ /* When 'token' is a placeholder, just return 'other'. */
+ if (token->type == PLACEHOLDER)
+ return other;
+
+ /* A very few single-character punctuators can be combined
+ * with another to form a multi-character punctuator. */
+ switch (token->type) {
+ case '<':
+ if (other->type == '<')
+ combined = _token_create_ival (token, LEFT_SHIFT, LEFT_SHIFT);
+ else if (other->type == '=')
+ combined = _token_create_ival (token, LESS_OR_EQUAL, LESS_OR_EQUAL);
+ break;
+ case '>':
+ if (other->type == '>')
+ combined = _token_create_ival (token, RIGHT_SHIFT, RIGHT_SHIFT);
+ else if (other->type == '=')
+ combined = _token_create_ival (token, GREATER_OR_EQUAL, GREATER_OR_EQUAL);
+ break;
+ case '=':
+ if (other->type == '=')
+ combined = _token_create_ival (token, EQUAL, EQUAL);
+ break;
+ case '!':
+ if (other->type == '=')
+ combined = _token_create_ival (token, NOT_EQUAL, NOT_EQUAL);
+ break;
+ case '&':
+ if (other->type == '&')
+ combined = _token_create_ival (token, AND, AND);
+ break;
+ case '|':
+ if (other->type == '|')
+ combined = _token_create_ival (token, OR, OR);
+ break;
+ }
+
+ if (combined != NULL) {
+ /* Inherit the location from the first token */
+ combined->location = token->location;
+ return combined;
+ }
+
+ /* Two string-valued tokens can usually just be mashed
+ * together.
+ *
+ * XXX: This isn't actually legitimate. Several things here
+ * should result in a diagnostic since the result cannot be a
+ * valid, single pre-processing token. For example, pasting
+ * "123" and "abc" is not legal, but we don't catch that
+ * here. */
+ if ((token->type == IDENTIFIER || token->type == OTHER || token->type == INTEGER_STRING) &&
+ (other->type == IDENTIFIER || other->type == OTHER || other->type == INTEGER_STRING))
+ {
+ char *str;
+
+ str = talloc_asprintf (token, "%s%s", token->value.str,
+ other->value.str);
+ combined = _token_create_str (token, token->type, str);
+ combined->location = token->location;
+ return combined;
+ }
+
+ glcpp_error (&token->location, parser, "");
+ glcpp_print (parser->info_log, "Pasting \"");
+ _token_print (&parser->info_log, token);
+ glcpp_print (parser->info_log, "\" and \"");
+ _token_print (&parser->info_log, other);
+ glcpp_print (parser->info_log, "\" does not give a valid preprocessing token.\n");
+
+ return token;
+}
+
+static void
+_token_list_print (glcpp_parser_t *parser, token_list_t *list)
+{
+ token_node_t *node;
+
+ if (list == NULL)
+ return;
+
+ for (node = list->head; node; node = node->next)
+ _token_print (&parser->output, node->token);
+}
+
+void
+yyerror (YYLTYPE *locp, glcpp_parser_t *parser, const char *error)
+{
+ glcpp_error(locp, parser, "%s", error);
+}
+
+static void add_builtin_define(glcpp_parser_t *parser,
+ const char *name, int value)
+{
+ token_t *tok;
+ token_list_t *list;
+
+ tok = _token_create_ival (parser, INTEGER, value);
+
+ list = _token_list_create(parser);
+ _token_list_append(list, tok);
+ _define_object_macro(parser, NULL, name, list);
+
+ talloc_unlink(parser, tok);
+}
+
+glcpp_parser_t *
+glcpp_parser_create (const struct gl_extensions *extensions)
+{
+ glcpp_parser_t *parser;
+ int language_version;
+
+ parser = talloc (NULL, glcpp_parser_t);
+
+ glcpp_lex_init_extra (parser, &parser->scanner);
+ parser->defines = hash_table_ctor (32, hash_table_string_hash,
+ hash_table_string_compare);
+ parser->active = NULL;
+ parser->lexing_if = 0;
+ parser->space_tokens = 1;
+ parser->newline_as_space = 0;
+ parser->in_control_line = 0;
+ parser->paren_count = 0;
+
+ parser->skip_stack = NULL;
+
+ parser->lex_from_list = NULL;
+ parser->lex_from_node = NULL;
+
+ parser->output = talloc_strdup(parser, "");
+ parser->info_log = talloc_strdup(parser, "");
+ parser->error = 0;
+
+ /* Add pre-defined macros. */
+ add_builtin_define(parser, "GL_ARB_draw_buffers", 1);
+ add_builtin_define(parser, "GL_ARB_texture_rectangle", 1);
+
+ if (extensions != NULL) {
+ if (extensions->EXT_texture_array) {
+ add_builtin_define(parser, "GL_EXT_texture_array", 1);
+ }
+
+ if (extensions->ARB_fragment_coord_conventions)
+ add_builtin_define(parser, "GL_ARB_fragment_coord_conventions",
+ 1);
+ }
+
+ language_version = 110;
+ add_builtin_define(parser, "__VERSION__", language_version);
+
+ return parser;
+}
+
+int
+glcpp_parser_parse (glcpp_parser_t *parser)
+{
+ return yyparse (parser);
+}
+
+void
+glcpp_parser_destroy (glcpp_parser_t *parser)
+{
+ glcpp_lex_destroy (parser->scanner);
+ hash_table_dtor (parser->defines);
+ talloc_free (parser);
+}
+
+typedef enum function_status
+{
+ FUNCTION_STATUS_SUCCESS,
+ FUNCTION_NOT_A_FUNCTION,
+ FUNCTION_UNBALANCED_PARENTHESES
+} function_status_t;
+
+/* Find a set of function-like macro arguments by looking for a
+ * balanced set of parentheses.
+ *
+ * When called, 'node' should be the opening-parenthesis token, (or
+ * perhaps preceeding SPACE tokens). Upon successful return *last will
+ * be the last consumed node, (corresponding to the closing right
+ * parenthesis).
+ *
+ * Return values:
+ *
+ * FUNCTION_STATUS_SUCCESS:
+ *
+ * Successfully parsed a set of function arguments.
+ *
+ * FUNCTION_NOT_A_FUNCTION:
+ *
+ * Macro name not followed by a '('. This is not an error, but
+ * simply that the macro name should be treated as a non-macro.
+ *
+ * FUNCTION_UNBALANCED_PARENTHESES
+ *
+ * Macro name is not followed by a balanced set of parentheses.
+ */
+static function_status_t
+_arguments_parse (argument_list_t *arguments,
+ token_node_t *node,
+ token_node_t **last)
+{
+ token_list_t *argument;
+ int paren_count;
+
+ node = node->next;
+
+ /* Ignore whitespace before first parenthesis. */
+ while (node && node->token->type == SPACE)
+ node = node->next;
+
+ if (node == NULL || node->token->type != '(')
+ return FUNCTION_NOT_A_FUNCTION;
+
+ node = node->next;
+
+ argument = _token_list_create (arguments);
+ _argument_list_append (arguments, argument);
+
+ for (paren_count = 1; node; node = node->next) {
+ if (node->token->type == '(')
+ {
+ paren_count++;
+ }
+ else if (node->token->type == ')')
+ {
+ paren_count--;
+ if (paren_count == 0)
+ break;
+ }
+
+ if (node->token->type == ',' &&
+ paren_count == 1)
+ {
+ _token_list_trim_trailing_space (argument);
+ argument = _token_list_create (arguments);
+ _argument_list_append (arguments, argument);
+ }
+ else {
+ if (argument->head == NULL) {
+ /* Don't treat initial whitespace as
+ * part of the arguement. */
+ if (node->token->type == SPACE)
+ continue;
+ }
+ _token_list_append (argument, node->token);
+ }
+ }
+
+ if (paren_count)
+ return FUNCTION_UNBALANCED_PARENTHESES;
+
+ *last = node;
+
+ return FUNCTION_STATUS_SUCCESS;
+}
+
+static token_list_t *
+_token_list_create_with_one_space (void *ctx)
+{
+ token_list_t *list;
+ token_t *space;
+
+ list = _token_list_create (ctx);
+ space = _token_create_ival (list, SPACE, SPACE);
+ _token_list_append (list, space);
+
+ return list;
+}
+
+static void
+_glcpp_parser_expand_if (glcpp_parser_t *parser, int type, token_list_t *list)
+{
+ token_list_t *expanded;
+ token_t *token;
+
+ expanded = _token_list_create (parser);
+ token = _token_create_ival (parser, type, type);
+ _token_list_append (expanded, token);
+ _glcpp_parser_expand_token_list (parser, list);
+ _token_list_append_list (expanded, list);
+ glcpp_parser_lex_from (parser, expanded);
+}
+
+/* This is a helper function that's essentially part of the
+ * implementation of _glcpp_parser_expand_node. It shouldn't be called
+ * except for by that function.
+ *
+ * Returns NULL if node is a simple token with no expansion, (that is,
+ * although 'node' corresponds to an identifier defined as a
+ * function-like macro, it is not followed with a parenthesized
+ * argument list).
+ *
+ * Compute the complete expansion of node (which is a function-like
+ * macro) and subsequent nodes which are arguments.
+ *
+ * Returns the token list that results from the expansion and sets
+ * *last to the last node in the list that was consumed by the
+ * expansion. Specifically, *last will be set as follows: as the
+ * token of the closing right parenthesis.
+ */
+static token_list_t *
+_glcpp_parser_expand_function (glcpp_parser_t *parser,
+ token_node_t *node,
+ token_node_t **last)
+
+{
+ macro_t *macro;
+ const char *identifier;
+ argument_list_t *arguments;
+ function_status_t status;
+ token_list_t *substituted;
+ int parameter_index;
+
+ identifier = node->token->value.str;
+
+ macro = hash_table_find (parser->defines, identifier);
+
+ assert (macro->is_function);
+
+ arguments = _argument_list_create (parser);
+ status = _arguments_parse (arguments, node, last);
+
+ switch (status) {
+ case FUNCTION_STATUS_SUCCESS:
+ break;
+ case FUNCTION_NOT_A_FUNCTION:
+ return NULL;
+ case FUNCTION_UNBALANCED_PARENTHESES:
+ glcpp_error (&node->token->location, parser, "Macro %s call has unbalanced parentheses\n", identifier);
+ return NULL;
+ }
+
+ /* Replace a macro defined as empty with a SPACE token. */
+ if (macro->replacements == NULL) {
+ talloc_free (arguments);
+ return _token_list_create_with_one_space (parser);
+ }
+
+ if (! ((_argument_list_length (arguments) ==
+ _string_list_length (macro->parameters)) ||
+ (_string_list_length (macro->parameters) == 0 &&
+ _argument_list_length (arguments) == 1 &&
+ arguments->head->argument->head == NULL)))
+ {
+ glcpp_error (&node->token->location, parser,
+ "Error: macro %s invoked with %d arguments (expected %d)\n",
+ identifier,
+ _argument_list_length (arguments),
+ _string_list_length (macro->parameters));
+ return NULL;
+ }
+
+ /* Perform argument substitution on the replacement list. */
+ substituted = _token_list_create (arguments);
+
+ for (node = macro->replacements->head; node; node = node->next)
+ {
+ if (node->token->type == IDENTIFIER &&
+ _string_list_contains (macro->parameters,
+ node->token->value.str,
+ &parameter_index))
+ {
+ token_list_t *argument;
+ argument = _argument_list_member_at (arguments,
+ parameter_index);
+ /* Before substituting, we expand the argument
+ * tokens, or append a placeholder token for
+ * an empty argument. */
+ if (argument->head) {
+ token_list_t *expanded_argument;
+ expanded_argument = _token_list_copy (parser,
+ argument);
+ _glcpp_parser_expand_token_list (parser,
+ expanded_argument);
+ _token_list_append_list (substituted,
+ expanded_argument);
+ } else {
+ token_t *new_token;
+
+ new_token = _token_create_ival (substituted,
+ PLACEHOLDER,
+ PLACEHOLDER);
+ _token_list_append (substituted, new_token);
+ }
+ } else {
+ _token_list_append (substituted, node->token);
+ }
+ }
+
+ /* After argument substitution, and before further expansion
+ * below, implement token pasting. */
+
+ _token_list_trim_trailing_space (substituted);
+
+ node = substituted->head;
+ while (node)
+ {
+ token_node_t *next_non_space;
+
+ /* Look ahead for a PASTE token, skipping space. */
+ next_non_space = node->next;
+ while (next_non_space && next_non_space->token->type == SPACE)
+ next_non_space = next_non_space->next;
+
+ if (next_non_space == NULL)
+ break;
+
+ if (next_non_space->token->type != PASTE) {
+ node = next_non_space;
+ continue;
+ }
+
+ /* Now find the next non-space token after the PASTE. */
+ next_non_space = next_non_space->next;
+ while (next_non_space && next_non_space->token->type == SPACE)
+ next_non_space = next_non_space->next;
+
+ if (next_non_space == NULL) {
+ yyerror (&node->token->location, parser, "'##' cannot appear at either end of a macro expansion\n");
+ return NULL;
+ }
+
+ node->token = _token_paste (parser, node->token, next_non_space->token);
+ node->next = next_non_space->next;
+ if (next_non_space == substituted->tail)
+ substituted->tail = node;
+
+ node = node->next;
+ }
+
+ substituted->non_space_tail = substituted->tail;
+
+ return substituted;
+}
+
+/* Compute the complete expansion of node, (and subsequent nodes after
+ * 'node' in the case that 'node' is a function-like macro and
+ * subsequent nodes are arguments).
+ *
+ * Returns NULL if node is a simple token with no expansion.
+ *
+ * Otherwise, returns the token list that results from the expansion
+ * and sets *last to the last node in the list that was consumed by
+ * the expansion. Specifically, *last will be set as follows:
+ *
+ * As 'node' in the case of object-like macro expansion.
+ *
+ * As the token of the closing right parenthesis in the case of
+ * function-like macro expansion.
+ */
+static token_list_t *
+_glcpp_parser_expand_node (glcpp_parser_t *parser,
+ token_node_t *node,
+ token_node_t **last)
+{
+ token_t *token = node->token;
+ const char *identifier;
+ macro_t *macro;
+
+ /* We only expand identifiers */
+ if (token->type != IDENTIFIER) {
+ /* We change any COMMA into a COMMA_FINAL to prevent
+ * it being mistaken for an argument separator
+ * later. */
+ if (token->type == ',') {
+ token->type = COMMA_FINAL;
+ token->value.ival = COMMA_FINAL;
+ }
+
+ return NULL;
+ }
+
+ /* Look up this identifier in the hash table. */
+ identifier = token->value.str;
+ macro = hash_table_find (parser->defines, identifier);
+
+ /* Not a macro, so no expansion needed. */
+ if (macro == NULL)
+ return NULL;
+
+ /* Finally, don't expand this macro if we're already actively
+ * expanding it, (to avoid infinite recursion). */
+ if (_active_list_contains (parser->active, identifier)) {
+ /* We change the token type here from IDENTIFIER to
+ * OTHER to prevent any future expansion of this
+ * unexpanded token. */
+ char *str;
+ token_list_t *expansion;
+ token_t *final;
+
+ str = talloc_strdup (parser, token->value.str);
+ final = _token_create_str (parser, OTHER, str);
+ expansion = _token_list_create (parser);
+ _token_list_append (expansion, final);
+ *last = node;
+ return expansion;
+ }
+
+ if (! macro->is_function)
+ {
+ *last = node;
+
+ /* Replace a macro defined as empty with a SPACE token. */
+ if (macro->replacements == NULL)
+ return _token_list_create_with_one_space (parser);
+
+ return _token_list_copy (parser, macro->replacements);
+ }
+
+ return _glcpp_parser_expand_function (parser, node, last);
+}
+
+/* Push a new identifier onto the active list, returning the new list.
+ *
+ * Here, 'marker' is the token node that appears in the list after the
+ * expansion of 'identifier'. That is, when the list iterator begins
+ * examinging 'marker', then it is time to pop this node from the
+ * active stack.
+ */
+active_list_t *
+_active_list_push (active_list_t *list,
+ const char *identifier,
+ token_node_t *marker)
+{
+ active_list_t *node;
+
+ node = talloc (list, active_list_t);
+ node->identifier = talloc_strdup (node, identifier);
+ node->marker = marker;
+ node->next = list;
+
+ return node;
+}
+
+active_list_t *
+_active_list_pop (active_list_t *list)
+{
+ active_list_t *node = list;
+
+ if (node == NULL)
+ return NULL;
+
+ node = list->next;
+ talloc_free (list);
+
+ return node;
+}
+
+int
+_active_list_contains (active_list_t *list, const char *identifier)
+{
+ active_list_t *node;
+
+ if (list == NULL)
+ return 0;
+
+ for (node = list; node; node = node->next)
+ if (strcmp (node->identifier, identifier) == 0)
+ return 1;
+
+ return 0;
+}
+
+/* Walk over the token list replacing nodes with their expansion.
+ * Whenever nodes are expanded the walking will walk over the new
+ * nodes, continuing to expand as necessary. The results are placed in
+ * 'list' itself;
+ */
+static void
+_glcpp_parser_expand_token_list (glcpp_parser_t *parser,
+ token_list_t *list)
+{
+ token_node_t *node_prev;
+ token_node_t *node, *last = NULL;
+ token_list_t *expansion;
+
+ if (list == NULL)
+ return;
+
+ _token_list_trim_trailing_space (list);
+
+ node_prev = NULL;
+ node = list->head;
+
+ while (node) {
+
+ while (parser->active && parser->active->marker == node)
+ parser->active = _active_list_pop (parser->active);
+
+ /* Find the expansion for node, which will replace all
+ * nodes from node to last, inclusive. */
+ expansion = _glcpp_parser_expand_node (parser, node, &last);
+ if (expansion) {
+ token_node_t *n;
+
+ for (n = node; n != last->next; n = n->next)
+ while (parser->active &&
+ parser->active->marker == n)
+ {
+ parser->active = _active_list_pop (parser->active);
+ }
+
+ parser->active = _active_list_push (parser->active,
+ node->token->value.str,
+ last->next);
+
+ /* Splice expansion into list, supporting a
+ * simple deletion if the expansion is
+ * empty. */
+ if (expansion->head) {
+ if (node_prev)
+ node_prev->next = expansion->head;
+ else
+ list->head = expansion->head;
+ expansion->tail->next = last->next;
+ if (last == list->tail)
+ list->tail = expansion->tail;
+ } else {
+ if (node_prev)
+ node_prev->next = last->next;
+ else
+ list->head = last->next;
+ if (last == list->tail)
+ list->tail = NULL;
+ }
+ } else {
+ node_prev = node;
+ }
+ node = node_prev ? node_prev->next : list->head;
+ }
+
+ while (parser->active)
+ parser->active = _active_list_pop (parser->active);
+
+ list->non_space_tail = list->tail;
+}
+
+void
+_glcpp_parser_print_expanded_token_list (glcpp_parser_t *parser,
+ token_list_t *list)
+{
+ if (list == NULL)
+ return;
+
+ _glcpp_parser_expand_token_list (parser, list);
+
+ _token_list_trim_trailing_space (list);
+
+ _token_list_print (parser, list);
+}
+
+static void
+_check_for_reserved_macro_name (glcpp_parser_t *parser, YYLTYPE *loc,
+ const char *identifier)
+{
+ /* According to the GLSL specification, macro names starting with "__"
+ * or "GL_" are reserved for future use. So, don't allow them.
+ */
+ if (strncmp(identifier, "__", 2) == 0) {
+ glcpp_error (loc, parser, "Macro names starting with \"__\" are reserved.\n");
+ }
+ if (strncmp(identifier, "GL_", 3) == 0) {
+ glcpp_error (loc, parser, "Macro names starting with \"GL_\" are reserved.\n");
+ }
+}
+
+void
+_define_object_macro (glcpp_parser_t *parser,
+ YYLTYPE *loc,
+ const char *identifier,
+ token_list_t *replacements)
+{
+ macro_t *macro;
+
+ if (loc != NULL)
+ _check_for_reserved_macro_name(parser, loc, identifier);
+
+ macro = talloc (parser, macro_t);
+
+ macro->is_function = 0;
+ macro->parameters = NULL;
+ macro->identifier = talloc_strdup (macro, identifier);
+ macro->replacements = talloc_steal (macro, replacements);
+
+ hash_table_insert (parser->defines, macro, identifier);
+}
+
+void
+_define_function_macro (glcpp_parser_t *parser,
+ YYLTYPE *loc,
+ const char *identifier,
+ string_list_t *parameters,
+ token_list_t *replacements)
+{
+ macro_t *macro;
+
+ _check_for_reserved_macro_name(parser, loc, identifier);
+
+ macro = talloc (parser, macro_t);
+
+ macro->is_function = 1;
+ macro->parameters = talloc_steal (macro, parameters);
+ macro->identifier = talloc_strdup (macro, identifier);
+ macro->replacements = talloc_steal (macro, replacements);
+
+ hash_table_insert (parser->defines, macro, identifier);
+}
+
+static int
+glcpp_parser_lex (YYSTYPE *yylval, YYLTYPE *yylloc, glcpp_parser_t *parser)
+{
+ token_node_t *node;
+ int ret;
+
+ if (parser->lex_from_list == NULL) {
+ ret = glcpp_lex (yylval, yylloc, parser->scanner);
+
+ /* XXX: This ugly block of code exists for the sole
+ * purpose of converting a NEWLINE token into a SPACE
+ * token, but only in the case where we have seen a
+ * function-like macro name, but have not yet seen its
+ * closing parenthesis.
+ *
+ * There's perhaps a more compact way to do this with
+ * mid-rule actions in the grammar.
+ *
+ * I'm definitely not pleased with the complexity of
+ * this code here.
+ */
+ if (parser->newline_as_space)
+ {
+ if (ret == '(') {
+ parser->paren_count++;
+ } else if (ret == ')') {
+ parser->paren_count--;
+ if (parser->paren_count == 0)
+ parser->newline_as_space = 0;
+ } else if (ret == NEWLINE) {
+ ret = SPACE;
+ } else if (ret != SPACE) {
+ if (parser->paren_count == 0)
+ parser->newline_as_space = 0;
+ }
+ }
+ else if (parser->in_control_line)
+ {
+ if (ret == NEWLINE)
+ parser->in_control_line = 0;
+ }
+ else if (ret == HASH_DEFINE_OBJ || ret == HASH_DEFINE_FUNC ||
+ ret == HASH_UNDEF || ret == HASH_IF ||
+ ret == HASH_IFDEF || ret == HASH_IFNDEF ||
+ ret == HASH_ELIF || ret == HASH_ELSE ||
+ ret == HASH_ENDIF || ret == HASH)
+ {
+ parser->in_control_line = 1;
+ }
+ else if (ret == IDENTIFIER)
+ {
+ macro_t *macro;
+ macro = hash_table_find (parser->defines,
+ yylval->str);
+ if (macro && macro->is_function) {
+ parser->newline_as_space = 1;
+ parser->paren_count = 0;
+ }
+ }
+
+ return ret;
+ }
+
+ node = parser->lex_from_node;
+
+ if (node == NULL) {
+ talloc_free (parser->lex_from_list);
+ parser->lex_from_list = NULL;
+ return NEWLINE;
+ }
+
+ *yylval = node->token->value;
+ ret = node->token->type;
+
+ parser->lex_from_node = node->next;
+
+ return ret;
+}
+
+static void
+glcpp_parser_lex_from (glcpp_parser_t *parser, token_list_t *list)
+{
+ token_node_t *node;
+
+ assert (parser->lex_from_list == NULL);
+
+ /* Copy list, eliminating any space tokens. */
+ parser->lex_from_list = _token_list_create (parser);
+
+ for (node = list->head; node; node = node->next) {
+ if (node->token->type == SPACE)
+ continue;
+ _token_list_append (parser->lex_from_list, node->token);
+ }
+
+ talloc_free (list);
+
+ parser->lex_from_node = parser->lex_from_list->head;
+
+ /* It's possible the list consisted of nothing but whitespace. */
+ if (parser->lex_from_node == NULL) {
+ talloc_free (parser->lex_from_list);
+ parser->lex_from_list = NULL;
+ }
+}
+
+static void
+_glcpp_parser_skip_stack_push_if (glcpp_parser_t *parser, YYLTYPE *loc,
+ int condition)
+{
+ skip_type_t current = SKIP_NO_SKIP;
+ skip_node_t *node;
+
+ if (parser->skip_stack)
+ current = parser->skip_stack->type;
+
+ node = talloc (parser, skip_node_t);
+ node->loc = *loc;
+
+ if (current == SKIP_NO_SKIP) {
+ if (condition)
+ node->type = SKIP_NO_SKIP;
+ else
+ node->type = SKIP_TO_ELSE;
+ } else {
+ node->type = SKIP_TO_ENDIF;
+ }
+
+ node->next = parser->skip_stack;
+ parser->skip_stack = node;
+}
+
+static void
+_glcpp_parser_skip_stack_change_if (glcpp_parser_t *parser, YYLTYPE *loc,
+ const char *type, int condition)
+{
+ if (parser->skip_stack == NULL) {
+ glcpp_error (loc, parser, "%s without #if\n", type);
+ return;
+ }
+
+ if (parser->skip_stack->type == SKIP_TO_ELSE) {
+ if (condition)
+ parser->skip_stack->type = SKIP_NO_SKIP;
+ } else {
+ parser->skip_stack->type = SKIP_TO_ENDIF;
+ }
+}
+
+static void
+_glcpp_parser_skip_stack_pop (glcpp_parser_t *parser, YYLTYPE *loc)
+{
+ skip_node_t *node;
+
+ if (parser->skip_stack == NULL) {
+ glcpp_error (loc, parser, "#endif without #if\n");
+ return;
+ }
+
+ node = parser->skip_stack;
+ parser->skip_stack = node->next;
+ talloc_free (node);
+}
+
diff --git a/src/glsl/glcpp/glcpp-parse.h b/src/glsl/glcpp/glcpp-parse.h
new file mode 100644
index 00000000000..40556854f38
--- /dev/null
+++ b/src/glsl/glcpp/glcpp-parse.h
@@ -0,0 +1,100 @@
+/* A Bison parser, made by GNU Bison 2.4.3. */
+
+/* Skeleton interface for Bison's Yacc-like parsers in C
+
+ Copyright (C) 1984, 1989, 1990, 2000, 2001, 2002, 2003, 2004, 2005, 2006,
+ 2009, 2010 Free Software Foundation, Inc.
+
+ This program is free software: you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program. If not, see <http://www.gnu.org/licenses/>. */
+
+/* As a special exception, you may create a larger work that contains
+ part or all of the Bison parser skeleton and distribute that work
+ under terms of your choice, so long as that work isn't itself a
+ parser generator using the skeleton or a modified version thereof
+ as a parser skeleton. Alternatively, if you modify or redistribute
+ the parser skeleton itself, you may (at your option) remove this
+ special exception, which will cause the skeleton and the resulting
+ Bison output files to be licensed under the GNU General Public
+ License without this special exception.
+
+ This special exception was added by the Free Software Foundation in
+ version 2.2 of Bison. */
+
+
+/* Tokens. */
+#ifndef YYTOKENTYPE
+# define YYTOKENTYPE
+ /* Put the tokens into the symbol table, so that GDB and other debuggers
+ know about them. */
+ enum yytokentype {
+ COMMA_FINAL = 258,
+ DEFINED = 259,
+ ELIF_EXPANDED = 260,
+ HASH = 261,
+ HASH_DEFINE_FUNC = 262,
+ HASH_DEFINE_OBJ = 263,
+ HASH_ELIF = 264,
+ HASH_ELSE = 265,
+ HASH_ENDIF = 266,
+ HASH_IF = 267,
+ HASH_IFDEF = 268,
+ HASH_IFNDEF = 269,
+ HASH_UNDEF = 270,
+ HASH_VERSION = 271,
+ IDENTIFIER = 272,
+ IF_EXPANDED = 273,
+ INTEGER = 274,
+ INTEGER_STRING = 275,
+ NEWLINE = 276,
+ OTHER = 277,
+ PLACEHOLDER = 278,
+ SPACE = 279,
+ PASTE = 280,
+ OR = 281,
+ AND = 282,
+ NOT_EQUAL = 283,
+ EQUAL = 284,
+ GREATER_OR_EQUAL = 285,
+ LESS_OR_EQUAL = 286,
+ RIGHT_SHIFT = 287,
+ LEFT_SHIFT = 288,
+ UNARY = 289
+ };
+#endif
+
+
+
+#if ! defined YYSTYPE && ! defined YYSTYPE_IS_DECLARED
+
+# define yystype YYSTYPE /* obsolescent; will be withdrawn */
+# define YYSTYPE_IS_DECLARED 1
+#endif
+
+
+
+#if ! defined YYLTYPE && ! defined YYLTYPE_IS_DECLARED
+typedef struct YYLTYPE
+{
+ int first_line;
+ int first_column;
+ int last_line;
+ int last_column;
+} YYLTYPE;
+# define yyltype YYLTYPE /* obsolescent; will be withdrawn */
+# define YYLTYPE_IS_DECLARED 1
+# define YYLTYPE_IS_TRIVIAL 1
+#endif
+
+
+
diff --git a/src/glsl/glcpp/glcpp-parse.y b/src/glsl/glcpp/glcpp-parse.y
new file mode 100644
index 00000000000..ce4197e240c
--- /dev/null
+++ b/src/glsl/glcpp/glcpp-parse.y
@@ -0,0 +1,1729 @@
+%{
+/*
+ * Copyright © 2010 Intel Corporation
+ *
+ * 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 (including the next
+ * paragraph) 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
+ * THE AUTHORS OR COPYRIGHT HOLDERS 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.
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <assert.h>
+#include <stdint.h>
+
+#include "glcpp.h"
+#include "main/mtypes.h"
+
+#define glcpp_print(stream, str) stream = talloc_strdup_append(stream, str)
+#define glcpp_printf(stream, fmt, args, ...) \
+ stream = talloc_asprintf_append(stream, fmt, args)
+
+static void
+yyerror (YYLTYPE *locp, glcpp_parser_t *parser, const char *error);
+
+static void
+_define_object_macro (glcpp_parser_t *parser,
+ YYLTYPE *loc,
+ const char *macro,
+ token_list_t *replacements);
+
+static void
+_define_function_macro (glcpp_parser_t *parser,
+ YYLTYPE *loc,
+ const char *macro,
+ string_list_t *parameters,
+ token_list_t *replacements);
+
+static string_list_t *
+_string_list_create (void *ctx);
+
+static void
+_string_list_append_item (string_list_t *list, const char *str);
+
+static int
+_string_list_contains (string_list_t *list, const char *member, int *index);
+
+static int
+_string_list_length (string_list_t *list);
+
+static argument_list_t *
+_argument_list_create (void *ctx);
+
+static void
+_argument_list_append (argument_list_t *list, token_list_t *argument);
+
+static int
+_argument_list_length (argument_list_t *list);
+
+static token_list_t *
+_argument_list_member_at (argument_list_t *list, int index);
+
+/* Note: This function talloc_steal()s the str pointer. */
+static token_t *
+_token_create_str (void *ctx, int type, char *str);
+
+static token_t *
+_token_create_ival (void *ctx, int type, int ival);
+
+static token_list_t *
+_token_list_create (void *ctx);
+
+/* Note: This function adds a talloc_reference() to token.
+ *
+ * You may want to talloc_unlink any current reference if you no
+ * longer need it. */
+static void
+_token_list_append (token_list_t *list, token_t *token);
+
+static void
+_token_list_append_list (token_list_t *list, token_list_t *tail);
+
+static active_list_t *
+_active_list_push (active_list_t *list,
+ const char *identifier,
+ token_node_t *marker);
+
+static active_list_t *
+_active_list_pop (active_list_t *list);
+
+int
+_active_list_contains (active_list_t *list, const char *identifier);
+
+static void
+_glcpp_parser_expand_if (glcpp_parser_t *parser, int type, token_list_t *list);
+
+static void
+_glcpp_parser_expand_token_list (glcpp_parser_t *parser,
+ token_list_t *list);
+
+static void
+_glcpp_parser_print_expanded_token_list (glcpp_parser_t *parser,
+ token_list_t *list);
+
+static void
+_glcpp_parser_skip_stack_push_if (glcpp_parser_t *parser, YYLTYPE *loc,
+ int condition);
+
+static void
+_glcpp_parser_skip_stack_change_if (glcpp_parser_t *parser, YYLTYPE *loc,
+ const char *type, int condition);
+
+static void
+_glcpp_parser_skip_stack_pop (glcpp_parser_t *parser, YYLTYPE *loc);
+
+#define yylex glcpp_parser_lex
+
+static int
+glcpp_parser_lex (YYSTYPE *yylval, YYLTYPE *yylloc, glcpp_parser_t *parser);
+
+static void
+glcpp_parser_lex_from (glcpp_parser_t *parser, token_list_t *list);
+
+static void
+add_builtin_define(glcpp_parser_t *parser, const char *name, int value);
+
+%}
+
+%pure-parser
+%error-verbose
+
+%locations
+%initial-action {
+ @$.first_line = 1;
+ @$.first_column = 1;
+ @$.last_line = 1;
+ @$.last_column = 1;
+ @$.source = 0;
+}
+
+%parse-param {glcpp_parser_t *parser}
+%lex-param {glcpp_parser_t *parser}
+
+%expect 0
+%token COMMA_FINAL DEFINED ELIF_EXPANDED HASH HASH_DEFINE_FUNC HASH_DEFINE_OBJ HASH_ELIF HASH_ELSE HASH_ENDIF HASH_IF HASH_IFDEF HASH_IFNDEF HASH_UNDEF HASH_VERSION IDENTIFIER IF_EXPANDED INTEGER INTEGER_STRING NEWLINE OTHER PLACEHOLDER SPACE
+%token PASTE
+%type <ival> expression INTEGER operator SPACE integer_constant
+%type <str> IDENTIFIER INTEGER_STRING OTHER
+%type <string_list> identifier_list
+%type <token> preprocessing_token conditional_token
+%type <token_list> pp_tokens replacement_list text_line conditional_tokens
+%left OR
+%left AND
+%left '|'
+%left '^'
+%left '&'
+%left EQUAL NOT_EQUAL
+%left '<' '>' LESS_OR_EQUAL GREATER_OR_EQUAL
+%left LEFT_SHIFT RIGHT_SHIFT
+%left '+' '-'
+%left '*' '/' '%'
+%right UNARY
+
+%%
+
+input:
+ /* empty */
+| input line
+;
+
+line:
+ control_line {
+ glcpp_print(parser->output, "\n");
+ }
+| text_line {
+ _glcpp_parser_print_expanded_token_list (parser, $1);
+ glcpp_print(parser->output, "\n");
+ talloc_free ($1);
+ }
+| expanded_line
+| HASH non_directive
+;
+
+expanded_line:
+ IF_EXPANDED expression NEWLINE {
+ _glcpp_parser_skip_stack_push_if (parser, & @1, $2);
+ }
+| ELIF_EXPANDED expression NEWLINE {
+ _glcpp_parser_skip_stack_change_if (parser, & @1, "elif", $2);
+ }
+;
+
+control_line:
+ HASH_DEFINE_OBJ IDENTIFIER replacement_list NEWLINE {
+ _define_object_macro (parser, & @2, $2, $3);
+ }
+| HASH_DEFINE_FUNC IDENTIFIER '(' ')' replacement_list NEWLINE {
+ _define_function_macro (parser, & @2, $2, NULL, $5);
+ }
+| HASH_DEFINE_FUNC IDENTIFIER '(' identifier_list ')' replacement_list NEWLINE {
+ _define_function_macro (parser, & @2, $2, $4, $6);
+ }
+| HASH_UNDEF IDENTIFIER NEWLINE {
+ macro_t *macro = hash_table_find (parser->defines, $2);
+ if (macro) {
+ hash_table_remove (parser->defines, $2);
+ talloc_free (macro);
+ }
+ talloc_free ($2);
+ }
+| HASH_IF conditional_tokens NEWLINE {
+ /* Be careful to only evaluate the 'if' expression if
+ * we are not skipping. When we are skipping, we
+ * simply push a new 0-valued 'if' onto the skip
+ * stack.
+ *
+ * This avoids generating diagnostics for invalid
+ * expressions that are being skipped. */
+ if (parser->skip_stack == NULL ||
+ parser->skip_stack->type == SKIP_NO_SKIP)
+ {
+ _glcpp_parser_expand_if (parser, IF_EXPANDED, $2);
+ }
+ else
+ {
+ _glcpp_parser_skip_stack_push_if (parser, & @1, 0);
+ parser->skip_stack->type = SKIP_TO_ENDIF;
+ }
+ }
+| HASH_IF NEWLINE {
+ /* #if without an expression is only an error if we
+ * are not skipping */
+ if (parser->skip_stack == NULL ||
+ parser->skip_stack->type == SKIP_NO_SKIP)
+ {
+ glcpp_error(& @1, parser, "#if with no expression");
+ }
+ _glcpp_parser_skip_stack_push_if (parser, & @1, 0);
+ }
+| HASH_IFDEF IDENTIFIER junk NEWLINE {
+ macro_t *macro = hash_table_find (parser->defines, $2);
+ talloc_free ($2);
+ _glcpp_parser_skip_stack_push_if (parser, & @1, macro != NULL);
+ }
+| HASH_IFNDEF IDENTIFIER junk NEWLINE {
+ macro_t *macro = hash_table_find (parser->defines, $2);
+ talloc_free ($2);
+ _glcpp_parser_skip_stack_push_if (parser, & @1, macro == NULL);
+ }
+| HASH_ELIF conditional_tokens NEWLINE {
+ /* Be careful to only evaluate the 'elif' expression
+ * if we are not skipping. When we are skipping, we
+ * simply change to a 0-valued 'elif' on the skip
+ * stack.
+ *
+ * This avoids generating diagnostics for invalid
+ * expressions that are being skipped. */
+ if (parser->skip_stack &&
+ parser->skip_stack->type == SKIP_TO_ELSE)
+ {
+ _glcpp_parser_expand_if (parser, ELIF_EXPANDED, $2);
+ }
+ else
+ {
+ _glcpp_parser_skip_stack_change_if (parser, & @1,
+ "elif", 0);
+ }
+ }
+| HASH_ELIF NEWLINE {
+ /* #elif without an expression is an error unless we
+ * are skipping. */
+ if (parser->skip_stack &&
+ parser->skip_stack->type == SKIP_TO_ELSE)
+ {
+ glcpp_error(& @1, parser, "#elif with no expression");
+ }
+ else
+ {
+ _glcpp_parser_skip_stack_change_if (parser, & @1,
+ "elif", 0);
+ glcpp_warning(& @1, parser, "ignoring illegal #elif without expression");
+ }
+ }
+| HASH_ELSE NEWLINE {
+ _glcpp_parser_skip_stack_change_if (parser, & @1, "else", 1);
+ }
+| HASH_ENDIF NEWLINE {
+ _glcpp_parser_skip_stack_pop (parser, & @1);
+ }
+| HASH_VERSION integer_constant NEWLINE {
+ macro_t *macro = hash_table_find (parser->defines, "__VERSION__");
+ if (macro) {
+ hash_table_remove (parser->defines, "__VERSION__");
+ talloc_free (macro);
+ }
+ add_builtin_define (parser, "__VERSION__", $2);
+ glcpp_printf(parser->output, "#version %" PRIiMAX "\n", $2);
+ }
+| HASH NEWLINE
+;
+
+integer_constant:
+ INTEGER_STRING {
+ if (strlen ($1) >= 3 && strncmp ($1, "0x", 2) == 0) {
+ $$ = strtoll ($1 + 2, NULL, 16);
+ } else if ($1[0] == '0') {
+ $$ = strtoll ($1, NULL, 8);
+ } else {
+ $$ = strtoll ($1, NULL, 10);
+ }
+ }
+| INTEGER {
+ $$ = $1;
+ }
+
+expression:
+ integer_constant
+| expression OR expression {
+ $$ = $1 || $3;
+ }
+| expression AND expression {
+ $$ = $1 && $3;
+ }
+| expression '|' expression {
+ $$ = $1 | $3;
+ }
+| expression '^' expression {
+ $$ = $1 ^ $3;
+ }
+| expression '&' expression {
+ $$ = $1 & $3;
+ }
+| expression NOT_EQUAL expression {
+ $$ = $1 != $3;
+ }
+| expression EQUAL expression {
+ $$ = $1 == $3;
+ }
+| expression GREATER_OR_EQUAL expression {
+ $$ = $1 >= $3;
+ }
+| expression LESS_OR_EQUAL expression {
+ $$ = $1 <= $3;
+ }
+| expression '>' expression {
+ $$ = $1 > $3;
+ }
+| expression '<' expression {
+ $$ = $1 < $3;
+ }
+| expression RIGHT_SHIFT expression {
+ $$ = $1 >> $3;
+ }
+| expression LEFT_SHIFT expression {
+ $$ = $1 << $3;
+ }
+| expression '-' expression {
+ $$ = $1 - $3;
+ }
+| expression '+' expression {
+ $$ = $1 + $3;
+ }
+| expression '%' expression {
+ $$ = $1 % $3;
+ }
+| expression '/' expression {
+ $$ = $1 / $3;
+ }
+| expression '*' expression {
+ $$ = $1 * $3;
+ }
+| '!' expression %prec UNARY {
+ $$ = ! $2;
+ }
+| '~' expression %prec UNARY {
+ $$ = ~ $2;
+ }
+| '-' expression %prec UNARY {
+ $$ = - $2;
+ }
+| '+' expression %prec UNARY {
+ $$ = + $2;
+ }
+| '(' expression ')' {
+ $$ = $2;
+ }
+;
+
+identifier_list:
+ IDENTIFIER {
+ $$ = _string_list_create (parser);
+ _string_list_append_item ($$, $1);
+ talloc_steal ($$, $1);
+ }
+| identifier_list ',' IDENTIFIER {
+ $$ = $1;
+ _string_list_append_item ($$, $3);
+ talloc_steal ($$, $3);
+ }
+;
+
+text_line:
+ NEWLINE { $$ = NULL; }
+| pp_tokens NEWLINE
+;
+
+non_directive:
+ pp_tokens NEWLINE {
+ yyerror (& @1, parser, "Invalid tokens after #");
+ }
+;
+
+replacement_list:
+ /* empty */ { $$ = NULL; }
+| pp_tokens
+;
+
+junk:
+ /* empty */
+| pp_tokens {
+ glcpp_warning(&@1, parser, "extra tokens at end of directive");
+ }
+;
+
+conditional_token:
+ /* Handle "defined" operator */
+ DEFINED IDENTIFIER {
+ int v = hash_table_find (parser->defines, $2) ? 1 : 0;
+ $$ = _token_create_ival (parser, INTEGER, v);
+ }
+| DEFINED '(' IDENTIFIER ')' {
+ int v = hash_table_find (parser->defines, $3) ? 1 : 0;
+ $$ = _token_create_ival (parser, INTEGER, v);
+ }
+| preprocessing_token
+;
+
+conditional_tokens:
+ /* Exactly the same as pp_tokens, but using conditional_token */
+ conditional_token {
+ parser->space_tokens = 1;
+ $$ = _token_list_create (parser);
+ _token_list_append ($$, $1);
+ talloc_unlink (parser, $1);
+ }
+| conditional_tokens conditional_token {
+ $$ = $1;
+ _token_list_append ($$, $2);
+ talloc_unlink (parser, $2);
+ }
+;
+
+pp_tokens:
+ preprocessing_token {
+ parser->space_tokens = 1;
+ $$ = _token_list_create (parser);
+ _token_list_append ($$, $1);
+ talloc_unlink (parser, $1);
+ }
+| pp_tokens preprocessing_token {
+ $$ = $1;
+ _token_list_append ($$, $2);
+ talloc_unlink (parser, $2);
+ }
+;
+
+preprocessing_token:
+ IDENTIFIER {
+ $$ = _token_create_str (parser, IDENTIFIER, $1);
+ $$->location = yylloc;
+ }
+| INTEGER_STRING {
+ $$ = _token_create_str (parser, INTEGER_STRING, $1);
+ $$->location = yylloc;
+ }
+| operator {
+ $$ = _token_create_ival (parser, $1, $1);
+ $$->location = yylloc;
+ }
+| OTHER {
+ $$ = _token_create_str (parser, OTHER, $1);
+ $$->location = yylloc;
+ }
+| SPACE {
+ $$ = _token_create_ival (parser, SPACE, SPACE);
+ $$->location = yylloc;
+ }
+;
+
+operator:
+ '[' { $$ = '['; }
+| ']' { $$ = ']'; }
+| '(' { $$ = '('; }
+| ')' { $$ = ')'; }
+| '{' { $$ = '{'; }
+| '}' { $$ = '}'; }
+| '.' { $$ = '.'; }
+| '&' { $$ = '&'; }
+| '*' { $$ = '*'; }
+| '+' { $$ = '+'; }
+| '-' { $$ = '-'; }
+| '~' { $$ = '~'; }
+| '!' { $$ = '!'; }
+| '/' { $$ = '/'; }
+| '%' { $$ = '%'; }
+| LEFT_SHIFT { $$ = LEFT_SHIFT; }
+| RIGHT_SHIFT { $$ = RIGHT_SHIFT; }
+| '<' { $$ = '<'; }
+| '>' { $$ = '>'; }
+| LESS_OR_EQUAL { $$ = LESS_OR_EQUAL; }
+| GREATER_OR_EQUAL { $$ = GREATER_OR_EQUAL; }
+| EQUAL { $$ = EQUAL; }
+| NOT_EQUAL { $$ = NOT_EQUAL; }
+| '^' { $$ = '^'; }
+| '|' { $$ = '|'; }
+| AND { $$ = AND; }
+| OR { $$ = OR; }
+| ';' { $$ = ';'; }
+| ',' { $$ = ','; }
+| '=' { $$ = '='; }
+| PASTE { $$ = PASTE; }
+;
+
+%%
+
+string_list_t *
+_string_list_create (void *ctx)
+{
+ string_list_t *list;
+
+ list = talloc (ctx, string_list_t);
+ list->head = NULL;
+ list->tail = NULL;
+
+ return list;
+}
+
+void
+_string_list_append_item (string_list_t *list, const char *str)
+{
+ string_node_t *node;
+
+ node = talloc (list, string_node_t);
+ node->str = talloc_strdup (node, str);
+
+ node->next = NULL;
+
+ if (list->head == NULL) {
+ list->head = node;
+ } else {
+ list->tail->next = node;
+ }
+
+ list->tail = node;
+}
+
+int
+_string_list_contains (string_list_t *list, const char *member, int *index)
+{
+ string_node_t *node;
+ int i;
+
+ if (list == NULL)
+ return 0;
+
+ for (i = 0, node = list->head; node; i++, node = node->next) {
+ if (strcmp (node->str, member) == 0) {
+ if (index)
+ *index = i;
+ return 1;
+ }
+ }
+
+ return 0;
+}
+
+int
+_string_list_length (string_list_t *list)
+{
+ int length = 0;
+ string_node_t *node;
+
+ if (list == NULL)
+ return 0;
+
+ for (node = list->head; node; node = node->next)
+ length++;
+
+ return length;
+}
+
+argument_list_t *
+_argument_list_create (void *ctx)
+{
+ argument_list_t *list;
+
+ list = talloc (ctx, argument_list_t);
+ list->head = NULL;
+ list->tail = NULL;
+
+ return list;
+}
+
+void
+_argument_list_append (argument_list_t *list, token_list_t *argument)
+{
+ argument_node_t *node;
+
+ node = talloc (list, argument_node_t);
+ node->argument = argument;
+
+ node->next = NULL;
+
+ if (list->head == NULL) {
+ list->head = node;
+ } else {
+ list->tail->next = node;
+ }
+
+ list->tail = node;
+}
+
+int
+_argument_list_length (argument_list_t *list)
+{
+ int length = 0;
+ argument_node_t *node;
+
+ if (list == NULL)
+ return 0;
+
+ for (node = list->head; node; node = node->next)
+ length++;
+
+ return length;
+}
+
+token_list_t *
+_argument_list_member_at (argument_list_t *list, int index)
+{
+ argument_node_t *node;
+ int i;
+
+ if (list == NULL)
+ return NULL;
+
+ node = list->head;
+ for (i = 0; i < index; i++) {
+ node = node->next;
+ if (node == NULL)
+ break;
+ }
+
+ if (node)
+ return node->argument;
+
+ return NULL;
+}
+
+/* Note: This function talloc_steal()s the str pointer. */
+token_t *
+_token_create_str (void *ctx, int type, char *str)
+{
+ token_t *token;
+
+ token = talloc (ctx, token_t);
+ token->type = type;
+ token->value.str = talloc_steal (token, str);
+
+ return token;
+}
+
+token_t *
+_token_create_ival (void *ctx, int type, int ival)
+{
+ token_t *token;
+
+ token = talloc (ctx, token_t);
+ token->type = type;
+ token->value.ival = ival;
+
+ return token;
+}
+
+token_list_t *
+_token_list_create (void *ctx)
+{
+ token_list_t *list;
+
+ list = talloc (ctx, token_list_t);
+ list->head = NULL;
+ list->tail = NULL;
+ list->non_space_tail = NULL;
+
+ return list;
+}
+
+void
+_token_list_append (token_list_t *list, token_t *token)
+{
+ token_node_t *node;
+
+ node = talloc (list, token_node_t);
+ node->token = talloc_reference (list, token);
+
+ node->next = NULL;
+
+ if (list->head == NULL) {
+ list->head = node;
+ } else {
+ list->tail->next = node;
+ }
+
+ list->tail = node;
+ if (token->type != SPACE)
+ list->non_space_tail = node;
+}
+
+void
+_token_list_append_list (token_list_t *list, token_list_t *tail)
+{
+ if (tail == NULL || tail->head == NULL)
+ return;
+
+ if (list->head == NULL) {
+ list->head = tail->head;
+ } else {
+ list->tail->next = tail->head;
+ }
+
+ list->tail = tail->tail;
+ list->non_space_tail = tail->non_space_tail;
+}
+
+static token_list_t *
+_token_list_copy (void *ctx, token_list_t *other)
+{
+ token_list_t *copy;
+ token_node_t *node;
+
+ if (other == NULL)
+ return NULL;
+
+ copy = _token_list_create (ctx);
+ for (node = other->head; node; node = node->next)
+ _token_list_append (copy, node->token);
+
+ return copy;
+}
+
+static void
+_token_list_trim_trailing_space (token_list_t *list)
+{
+ token_node_t *tail, *next;
+
+ if (list->non_space_tail) {
+ tail = list->non_space_tail->next;
+ list->non_space_tail->next = NULL;
+ list->tail = list->non_space_tail;
+
+ while (tail) {
+ next = tail->next;
+ talloc_free (tail);
+ tail = next;
+ }
+ }
+}
+
+static void
+_token_print (char **out, token_t *token)
+{
+ if (token->type < 256) {
+ glcpp_printf (*out, "%c", token->type);
+ return;
+ }
+
+ switch (token->type) {
+ case INTEGER:
+ glcpp_printf (*out, "%" PRIiMAX, token->value.ival);
+ break;
+ case IDENTIFIER:
+ case INTEGER_STRING:
+ case OTHER:
+ glcpp_print (*out, token->value.str);
+ break;
+ case SPACE:
+ glcpp_print (*out, " ");
+ break;
+ case LEFT_SHIFT:
+ glcpp_print (*out, "<<");
+ break;
+ case RIGHT_SHIFT:
+ glcpp_print (*out, ">>");
+ break;
+ case LESS_OR_EQUAL:
+ glcpp_print (*out, "<=");
+ break;
+ case GREATER_OR_EQUAL:
+ glcpp_print (*out, ">=");
+ break;
+ case EQUAL:
+ glcpp_print (*out, "==");
+ break;
+ case NOT_EQUAL:
+ glcpp_print (*out, "!=");
+ break;
+ case AND:
+ glcpp_print (*out, "&&");
+ break;
+ case OR:
+ glcpp_print (*out, "||");
+ break;
+ case PASTE:
+ glcpp_print (*out, "##");
+ break;
+ case COMMA_FINAL:
+ glcpp_print (*out, ",");
+ break;
+ case PLACEHOLDER:
+ /* Nothing to print. */
+ break;
+ default:
+ assert(!"Error: Don't know how to print token.");
+ break;
+ }
+}
+
+/* Return a new token (talloc()ed off of 'token') formed by pasting
+ * 'token' and 'other'. Note that this function may return 'token' or
+ * 'other' directly rather than allocating anything new.
+ *
+ * Caution: Only very cursory error-checking is performed to see if
+ * the final result is a valid single token. */
+static token_t *
+_token_paste (glcpp_parser_t *parser, token_t *token, token_t *other)
+{
+ token_t *combined = NULL;
+
+ /* Pasting a placeholder onto anything makes no change. */
+ if (other->type == PLACEHOLDER)
+ return token;
+
+ /* When 'token' is a placeholder, just return 'other'. */
+ if (token->type == PLACEHOLDER)
+ return other;
+
+ /* A very few single-character punctuators can be combined
+ * with another to form a multi-character punctuator. */
+ switch (token->type) {
+ case '<':
+ if (other->type == '<')
+ combined = _token_create_ival (token, LEFT_SHIFT, LEFT_SHIFT);
+ else if (other->type == '=')
+ combined = _token_create_ival (token, LESS_OR_EQUAL, LESS_OR_EQUAL);
+ break;
+ case '>':
+ if (other->type == '>')
+ combined = _token_create_ival (token, RIGHT_SHIFT, RIGHT_SHIFT);
+ else if (other->type == '=')
+ combined = _token_create_ival (token, GREATER_OR_EQUAL, GREATER_OR_EQUAL);
+ break;
+ case '=':
+ if (other->type == '=')
+ combined = _token_create_ival (token, EQUAL, EQUAL);
+ break;
+ case '!':
+ if (other->type == '=')
+ combined = _token_create_ival (token, NOT_EQUAL, NOT_EQUAL);
+ break;
+ case '&':
+ if (other->type == '&')
+ combined = _token_create_ival (token, AND, AND);
+ break;
+ case '|':
+ if (other->type == '|')
+ combined = _token_create_ival (token, OR, OR);
+ break;
+ }
+
+ if (combined != NULL) {
+ /* Inherit the location from the first token */
+ combined->location = token->location;
+ return combined;
+ }
+
+ /* Two string-valued tokens can usually just be mashed
+ * together.
+ *
+ * XXX: This isn't actually legitimate. Several things here
+ * should result in a diagnostic since the result cannot be a
+ * valid, single pre-processing token. For example, pasting
+ * "123" and "abc" is not legal, but we don't catch that
+ * here. */
+ if ((token->type == IDENTIFIER || token->type == OTHER || token->type == INTEGER_STRING) &&
+ (other->type == IDENTIFIER || other->type == OTHER || other->type == INTEGER_STRING))
+ {
+ char *str;
+
+ str = talloc_asprintf (token, "%s%s", token->value.str,
+ other->value.str);
+ combined = _token_create_str (token, token->type, str);
+ combined->location = token->location;
+ return combined;
+ }
+
+ glcpp_error (&token->location, parser, "");
+ glcpp_print (parser->info_log, "Pasting \"");
+ _token_print (&parser->info_log, token);
+ glcpp_print (parser->info_log, "\" and \"");
+ _token_print (&parser->info_log, other);
+ glcpp_print (parser->info_log, "\" does not give a valid preprocessing token.\n");
+
+ return token;
+}
+
+static void
+_token_list_print (glcpp_parser_t *parser, token_list_t *list)
+{
+ token_node_t *node;
+
+ if (list == NULL)
+ return;
+
+ for (node = list->head; node; node = node->next)
+ _token_print (&parser->output, node->token);
+}
+
+void
+yyerror (YYLTYPE *locp, glcpp_parser_t *parser, const char *error)
+{
+ glcpp_error(locp, parser, "%s", error);
+}
+
+static void add_builtin_define(glcpp_parser_t *parser,
+ const char *name, int value)
+{
+ token_t *tok;
+ token_list_t *list;
+
+ tok = _token_create_ival (parser, INTEGER, value);
+
+ list = _token_list_create(parser);
+ _token_list_append(list, tok);
+ _define_object_macro(parser, NULL, name, list);
+
+ talloc_unlink(parser, tok);
+}
+
+glcpp_parser_t *
+glcpp_parser_create (const struct gl_extensions *extensions)
+{
+ glcpp_parser_t *parser;
+ int language_version;
+
+ parser = talloc (NULL, glcpp_parser_t);
+
+ glcpp_lex_init_extra (parser, &parser->scanner);
+ parser->defines = hash_table_ctor (32, hash_table_string_hash,
+ hash_table_string_compare);
+ parser->active = NULL;
+ parser->lexing_if = 0;
+ parser->space_tokens = 1;
+ parser->newline_as_space = 0;
+ parser->in_control_line = 0;
+ parser->paren_count = 0;
+
+ parser->skip_stack = NULL;
+
+ parser->lex_from_list = NULL;
+ parser->lex_from_node = NULL;
+
+ parser->output = talloc_strdup(parser, "");
+ parser->info_log = talloc_strdup(parser, "");
+ parser->error = 0;
+
+ /* Add pre-defined macros. */
+ add_builtin_define(parser, "GL_ARB_draw_buffers", 1);
+ add_builtin_define(parser, "GL_ARB_texture_rectangle", 1);
+
+ if (extensions != NULL) {
+ if (extensions->EXT_texture_array) {
+ add_builtin_define(parser, "GL_EXT_texture_array", 1);
+ }
+
+ if (extensions->ARB_fragment_coord_conventions)
+ add_builtin_define(parser, "GL_ARB_fragment_coord_conventions",
+ 1);
+ }
+
+ language_version = 110;
+ add_builtin_define(parser, "__VERSION__", language_version);
+
+ return parser;
+}
+
+int
+glcpp_parser_parse (glcpp_parser_t *parser)
+{
+ return yyparse (parser);
+}
+
+void
+glcpp_parser_destroy (glcpp_parser_t *parser)
+{
+ glcpp_lex_destroy (parser->scanner);
+ hash_table_dtor (parser->defines);
+ talloc_free (parser);
+}
+
+typedef enum function_status
+{
+ FUNCTION_STATUS_SUCCESS,
+ FUNCTION_NOT_A_FUNCTION,
+ FUNCTION_UNBALANCED_PARENTHESES
+} function_status_t;
+
+/* Find a set of function-like macro arguments by looking for a
+ * balanced set of parentheses.
+ *
+ * When called, 'node' should be the opening-parenthesis token, (or
+ * perhaps preceeding SPACE tokens). Upon successful return *last will
+ * be the last consumed node, (corresponding to the closing right
+ * parenthesis).
+ *
+ * Return values:
+ *
+ * FUNCTION_STATUS_SUCCESS:
+ *
+ * Successfully parsed a set of function arguments.
+ *
+ * FUNCTION_NOT_A_FUNCTION:
+ *
+ * Macro name not followed by a '('. This is not an error, but
+ * simply that the macro name should be treated as a non-macro.
+ *
+ * FUNCTION_UNBALANCED_PARENTHESES
+ *
+ * Macro name is not followed by a balanced set of parentheses.
+ */
+static function_status_t
+_arguments_parse (argument_list_t *arguments,
+ token_node_t *node,
+ token_node_t **last)
+{
+ token_list_t *argument;
+ int paren_count;
+
+ node = node->next;
+
+ /* Ignore whitespace before first parenthesis. */
+ while (node && node->token->type == SPACE)
+ node = node->next;
+
+ if (node == NULL || node->token->type != '(')
+ return FUNCTION_NOT_A_FUNCTION;
+
+ node = node->next;
+
+ argument = _token_list_create (arguments);
+ _argument_list_append (arguments, argument);
+
+ for (paren_count = 1; node; node = node->next) {
+ if (node->token->type == '(')
+ {
+ paren_count++;
+ }
+ else if (node->token->type == ')')
+ {
+ paren_count--;
+ if (paren_count == 0)
+ break;
+ }
+
+ if (node->token->type == ',' &&
+ paren_count == 1)
+ {
+ _token_list_trim_trailing_space (argument);
+ argument = _token_list_create (arguments);
+ _argument_list_append (arguments, argument);
+ }
+ else {
+ if (argument->head == NULL) {
+ /* Don't treat initial whitespace as
+ * part of the arguement. */
+ if (node->token->type == SPACE)
+ continue;
+ }
+ _token_list_append (argument, node->token);
+ }
+ }
+
+ if (paren_count)
+ return FUNCTION_UNBALANCED_PARENTHESES;
+
+ *last = node;
+
+ return FUNCTION_STATUS_SUCCESS;
+}
+
+static token_list_t *
+_token_list_create_with_one_space (void *ctx)
+{
+ token_list_t *list;
+ token_t *space;
+
+ list = _token_list_create (ctx);
+ space = _token_create_ival (list, SPACE, SPACE);
+ _token_list_append (list, space);
+
+ return list;
+}
+
+static void
+_glcpp_parser_expand_if (glcpp_parser_t *parser, int type, token_list_t *list)
+{
+ token_list_t *expanded;
+ token_t *token;
+
+ expanded = _token_list_create (parser);
+ token = _token_create_ival (parser, type, type);
+ _token_list_append (expanded, token);
+ _glcpp_parser_expand_token_list (parser, list);
+ _token_list_append_list (expanded, list);
+ glcpp_parser_lex_from (parser, expanded);
+}
+
+/* This is a helper function that's essentially part of the
+ * implementation of _glcpp_parser_expand_node. It shouldn't be called
+ * except for by that function.
+ *
+ * Returns NULL if node is a simple token with no expansion, (that is,
+ * although 'node' corresponds to an identifier defined as a
+ * function-like macro, it is not followed with a parenthesized
+ * argument list).
+ *
+ * Compute the complete expansion of node (which is a function-like
+ * macro) and subsequent nodes which are arguments.
+ *
+ * Returns the token list that results from the expansion and sets
+ * *last to the last node in the list that was consumed by the
+ * expansion. Specifically, *last will be set as follows: as the
+ * token of the closing right parenthesis.
+ */
+static token_list_t *
+_glcpp_parser_expand_function (glcpp_parser_t *parser,
+ token_node_t *node,
+ token_node_t **last)
+
+{
+ macro_t *macro;
+ const char *identifier;
+ argument_list_t *arguments;
+ function_status_t status;
+ token_list_t *substituted;
+ int parameter_index;
+
+ identifier = node->token->value.str;
+
+ macro = hash_table_find (parser->defines, identifier);
+
+ assert (macro->is_function);
+
+ arguments = _argument_list_create (parser);
+ status = _arguments_parse (arguments, node, last);
+
+ switch (status) {
+ case FUNCTION_STATUS_SUCCESS:
+ break;
+ case FUNCTION_NOT_A_FUNCTION:
+ return NULL;
+ case FUNCTION_UNBALANCED_PARENTHESES:
+ glcpp_error (&node->token->location, parser, "Macro %s call has unbalanced parentheses\n", identifier);
+ return NULL;
+ }
+
+ /* Replace a macro defined as empty with a SPACE token. */
+ if (macro->replacements == NULL) {
+ talloc_free (arguments);
+ return _token_list_create_with_one_space (parser);
+ }
+
+ if (! ((_argument_list_length (arguments) ==
+ _string_list_length (macro->parameters)) ||
+ (_string_list_length (macro->parameters) == 0 &&
+ _argument_list_length (arguments) == 1 &&
+ arguments->head->argument->head == NULL)))
+ {
+ glcpp_error (&node->token->location, parser,
+ "Error: macro %s invoked with %d arguments (expected %d)\n",
+ identifier,
+ _argument_list_length (arguments),
+ _string_list_length (macro->parameters));
+ return NULL;
+ }
+
+ /* Perform argument substitution on the replacement list. */
+ substituted = _token_list_create (arguments);
+
+ for (node = macro->replacements->head; node; node = node->next)
+ {
+ if (node->token->type == IDENTIFIER &&
+ _string_list_contains (macro->parameters,
+ node->token->value.str,
+ &parameter_index))
+ {
+ token_list_t *argument;
+ argument = _argument_list_member_at (arguments,
+ parameter_index);
+ /* Before substituting, we expand the argument
+ * tokens, or append a placeholder token for
+ * an empty argument. */
+ if (argument->head) {
+ token_list_t *expanded_argument;
+ expanded_argument = _token_list_copy (parser,
+ argument);
+ _glcpp_parser_expand_token_list (parser,
+ expanded_argument);
+ _token_list_append_list (substituted,
+ expanded_argument);
+ } else {
+ token_t *new_token;
+
+ new_token = _token_create_ival (substituted,
+ PLACEHOLDER,
+ PLACEHOLDER);
+ _token_list_append (substituted, new_token);
+ }
+ } else {
+ _token_list_append (substituted, node->token);
+ }
+ }
+
+ /* After argument substitution, and before further expansion
+ * below, implement token pasting. */
+
+ _token_list_trim_trailing_space (substituted);
+
+ node = substituted->head;
+ while (node)
+ {
+ token_node_t *next_non_space;
+
+ /* Look ahead for a PASTE token, skipping space. */
+ next_non_space = node->next;
+ while (next_non_space && next_non_space->token->type == SPACE)
+ next_non_space = next_non_space->next;
+
+ if (next_non_space == NULL)
+ break;
+
+ if (next_non_space->token->type != PASTE) {
+ node = next_non_space;
+ continue;
+ }
+
+ /* Now find the next non-space token after the PASTE. */
+ next_non_space = next_non_space->next;
+ while (next_non_space && next_non_space->token->type == SPACE)
+ next_non_space = next_non_space->next;
+
+ if (next_non_space == NULL) {
+ yyerror (&node->token->location, parser, "'##' cannot appear at either end of a macro expansion\n");
+ return NULL;
+ }
+
+ node->token = _token_paste (parser, node->token, next_non_space->token);
+ node->next = next_non_space->next;
+ if (next_non_space == substituted->tail)
+ substituted->tail = node;
+
+ node = node->next;
+ }
+
+ substituted->non_space_tail = substituted->tail;
+
+ return substituted;
+}
+
+/* Compute the complete expansion of node, (and subsequent nodes after
+ * 'node' in the case that 'node' is a function-like macro and
+ * subsequent nodes are arguments).
+ *
+ * Returns NULL if node is a simple token with no expansion.
+ *
+ * Otherwise, returns the token list that results from the expansion
+ * and sets *last to the last node in the list that was consumed by
+ * the expansion. Specifically, *last will be set as follows:
+ *
+ * As 'node' in the case of object-like macro expansion.
+ *
+ * As the token of the closing right parenthesis in the case of
+ * function-like macro expansion.
+ */
+static token_list_t *
+_glcpp_parser_expand_node (glcpp_parser_t *parser,
+ token_node_t *node,
+ token_node_t **last)
+{
+ token_t *token = node->token;
+ const char *identifier;
+ macro_t *macro;
+
+ /* We only expand identifiers */
+ if (token->type != IDENTIFIER) {
+ /* We change any COMMA into a COMMA_FINAL to prevent
+ * it being mistaken for an argument separator
+ * later. */
+ if (token->type == ',') {
+ token->type = COMMA_FINAL;
+ token->value.ival = COMMA_FINAL;
+ }
+
+ return NULL;
+ }
+
+ /* Look up this identifier in the hash table. */
+ identifier = token->value.str;
+ macro = hash_table_find (parser->defines, identifier);
+
+ /* Not a macro, so no expansion needed. */
+ if (macro == NULL)
+ return NULL;
+
+ /* Finally, don't expand this macro if we're already actively
+ * expanding it, (to avoid infinite recursion). */
+ if (_active_list_contains (parser->active, identifier)) {
+ /* We change the token type here from IDENTIFIER to
+ * OTHER to prevent any future expansion of this
+ * unexpanded token. */
+ char *str;
+ token_list_t *expansion;
+ token_t *final;
+
+ str = talloc_strdup (parser, token->value.str);
+ final = _token_create_str (parser, OTHER, str);
+ expansion = _token_list_create (parser);
+ _token_list_append (expansion, final);
+ *last = node;
+ return expansion;
+ }
+
+ if (! macro->is_function)
+ {
+ *last = node;
+
+ /* Replace a macro defined as empty with a SPACE token. */
+ if (macro->replacements == NULL)
+ return _token_list_create_with_one_space (parser);
+
+ return _token_list_copy (parser, macro->replacements);
+ }
+
+ return _glcpp_parser_expand_function (parser, node, last);
+}
+
+/* Push a new identifier onto the active list, returning the new list.
+ *
+ * Here, 'marker' is the token node that appears in the list after the
+ * expansion of 'identifier'. That is, when the list iterator begins
+ * examinging 'marker', then it is time to pop this node from the
+ * active stack.
+ */
+active_list_t *
+_active_list_push (active_list_t *list,
+ const char *identifier,
+ token_node_t *marker)
+{
+ active_list_t *node;
+
+ node = talloc (list, active_list_t);
+ node->identifier = talloc_strdup (node, identifier);
+ node->marker = marker;
+ node->next = list;
+
+ return node;
+}
+
+active_list_t *
+_active_list_pop (active_list_t *list)
+{
+ active_list_t *node = list;
+
+ if (node == NULL)
+ return NULL;
+
+ node = list->next;
+ talloc_free (list);
+
+ return node;
+}
+
+int
+_active_list_contains (active_list_t *list, const char *identifier)
+{
+ active_list_t *node;
+
+ if (list == NULL)
+ return 0;
+
+ for (node = list; node; node = node->next)
+ if (strcmp (node->identifier, identifier) == 0)
+ return 1;
+
+ return 0;
+}
+
+/* Walk over the token list replacing nodes with their expansion.
+ * Whenever nodes are expanded the walking will walk over the new
+ * nodes, continuing to expand as necessary. The results are placed in
+ * 'list' itself;
+ */
+static void
+_glcpp_parser_expand_token_list (glcpp_parser_t *parser,
+ token_list_t *list)
+{
+ token_node_t *node_prev;
+ token_node_t *node, *last = NULL;
+ token_list_t *expansion;
+
+ if (list == NULL)
+ return;
+
+ _token_list_trim_trailing_space (list);
+
+ node_prev = NULL;
+ node = list->head;
+
+ while (node) {
+
+ while (parser->active && parser->active->marker == node)
+ parser->active = _active_list_pop (parser->active);
+
+ /* Find the expansion for node, which will replace all
+ * nodes from node to last, inclusive. */
+ expansion = _glcpp_parser_expand_node (parser, node, &last);
+ if (expansion) {
+ token_node_t *n;
+
+ for (n = node; n != last->next; n = n->next)
+ while (parser->active &&
+ parser->active->marker == n)
+ {
+ parser->active = _active_list_pop (parser->active);
+ }
+
+ parser->active = _active_list_push (parser->active,
+ node->token->value.str,
+ last->next);
+
+ /* Splice expansion into list, supporting a
+ * simple deletion if the expansion is
+ * empty. */
+ if (expansion->head) {
+ if (node_prev)
+ node_prev->next = expansion->head;
+ else
+ list->head = expansion->head;
+ expansion->tail->next = last->next;
+ if (last == list->tail)
+ list->tail = expansion->tail;
+ } else {
+ if (node_prev)
+ node_prev->next = last->next;
+ else
+ list->head = last->next;
+ if (last == list->tail)
+ list->tail = NULL;
+ }
+ } else {
+ node_prev = node;
+ }
+ node = node_prev ? node_prev->next : list->head;
+ }
+
+ while (parser->active)
+ parser->active = _active_list_pop (parser->active);
+
+ list->non_space_tail = list->tail;
+}
+
+void
+_glcpp_parser_print_expanded_token_list (glcpp_parser_t *parser,
+ token_list_t *list)
+{
+ if (list == NULL)
+ return;
+
+ _glcpp_parser_expand_token_list (parser, list);
+
+ _token_list_trim_trailing_space (list);
+
+ _token_list_print (parser, list);
+}
+
+static void
+_check_for_reserved_macro_name (glcpp_parser_t *parser, YYLTYPE *loc,
+ const char *identifier)
+{
+ /* According to the GLSL specification, macro names starting with "__"
+ * or "GL_" are reserved for future use. So, don't allow them.
+ */
+ if (strncmp(identifier, "__", 2) == 0) {
+ glcpp_error (loc, parser, "Macro names starting with \"__\" are reserved.\n");
+ }
+ if (strncmp(identifier, "GL_", 3) == 0) {
+ glcpp_error (loc, parser, "Macro names starting with \"GL_\" are reserved.\n");
+ }
+}
+
+void
+_define_object_macro (glcpp_parser_t *parser,
+ YYLTYPE *loc,
+ const char *identifier,
+ token_list_t *replacements)
+{
+ macro_t *macro;
+
+ if (loc != NULL)
+ _check_for_reserved_macro_name(parser, loc, identifier);
+
+ macro = talloc (parser, macro_t);
+
+ macro->is_function = 0;
+ macro->parameters = NULL;
+ macro->identifier = talloc_strdup (macro, identifier);
+ macro->replacements = talloc_steal (macro, replacements);
+
+ hash_table_insert (parser->defines, macro, identifier);
+}
+
+void
+_define_function_macro (glcpp_parser_t *parser,
+ YYLTYPE *loc,
+ const char *identifier,
+ string_list_t *parameters,
+ token_list_t *replacements)
+{
+ macro_t *macro;
+
+ _check_for_reserved_macro_name(parser, loc, identifier);
+
+ macro = talloc (parser, macro_t);
+
+ macro->is_function = 1;
+ macro->parameters = talloc_steal (macro, parameters);
+ macro->identifier = talloc_strdup (macro, identifier);
+ macro->replacements = talloc_steal (macro, replacements);
+
+ hash_table_insert (parser->defines, macro, identifier);
+}
+
+static int
+glcpp_parser_lex (YYSTYPE *yylval, YYLTYPE *yylloc, glcpp_parser_t *parser)
+{
+ token_node_t *node;
+ int ret;
+
+ if (parser->lex_from_list == NULL) {
+ ret = glcpp_lex (yylval, yylloc, parser->scanner);
+
+ /* XXX: This ugly block of code exists for the sole
+ * purpose of converting a NEWLINE token into a SPACE
+ * token, but only in the case where we have seen a
+ * function-like macro name, but have not yet seen its
+ * closing parenthesis.
+ *
+ * There's perhaps a more compact way to do this with
+ * mid-rule actions in the grammar.
+ *
+ * I'm definitely not pleased with the complexity of
+ * this code here.
+ */
+ if (parser->newline_as_space)
+ {
+ if (ret == '(') {
+ parser->paren_count++;
+ } else if (ret == ')') {
+ parser->paren_count--;
+ if (parser->paren_count == 0)
+ parser->newline_as_space = 0;
+ } else if (ret == NEWLINE) {
+ ret = SPACE;
+ } else if (ret != SPACE) {
+ if (parser->paren_count == 0)
+ parser->newline_as_space = 0;
+ }
+ }
+ else if (parser->in_control_line)
+ {
+ if (ret == NEWLINE)
+ parser->in_control_line = 0;
+ }
+ else if (ret == HASH_DEFINE_OBJ || ret == HASH_DEFINE_FUNC ||
+ ret == HASH_UNDEF || ret == HASH_IF ||
+ ret == HASH_IFDEF || ret == HASH_IFNDEF ||
+ ret == HASH_ELIF || ret == HASH_ELSE ||
+ ret == HASH_ENDIF || ret == HASH)
+ {
+ parser->in_control_line = 1;
+ }
+ else if (ret == IDENTIFIER)
+ {
+ macro_t *macro;
+ macro = hash_table_find (parser->defines,
+ yylval->str);
+ if (macro && macro->is_function) {
+ parser->newline_as_space = 1;
+ parser->paren_count = 0;
+ }
+ }
+
+ return ret;
+ }
+
+ node = parser->lex_from_node;
+
+ if (node == NULL) {
+ talloc_free (parser->lex_from_list);
+ parser->lex_from_list = NULL;
+ return NEWLINE;
+ }
+
+ *yylval = node->token->value;
+ ret = node->token->type;
+
+ parser->lex_from_node = node->next;
+
+ return ret;
+}
+
+static void
+glcpp_parser_lex_from (glcpp_parser_t *parser, token_list_t *list)
+{
+ token_node_t *node;
+
+ assert (parser->lex_from_list == NULL);
+
+ /* Copy list, eliminating any space tokens. */
+ parser->lex_from_list = _token_list_create (parser);
+
+ for (node = list->head; node; node = node->next) {
+ if (node->token->type == SPACE)
+ continue;
+ _token_list_append (parser->lex_from_list, node->token);
+ }
+
+ talloc_free (list);
+
+ parser->lex_from_node = parser->lex_from_list->head;
+
+ /* It's possible the list consisted of nothing but whitespace. */
+ if (parser->lex_from_node == NULL) {
+ talloc_free (parser->lex_from_list);
+ parser->lex_from_list = NULL;
+ }
+}
+
+static void
+_glcpp_parser_skip_stack_push_if (glcpp_parser_t *parser, YYLTYPE *loc,
+ int condition)
+{
+ skip_type_t current = SKIP_NO_SKIP;
+ skip_node_t *node;
+
+ if (parser->skip_stack)
+ current = parser->skip_stack->type;
+
+ node = talloc (parser, skip_node_t);
+ node->loc = *loc;
+
+ if (current == SKIP_NO_SKIP) {
+ if (condition)
+ node->type = SKIP_NO_SKIP;
+ else
+ node->type = SKIP_TO_ELSE;
+ } else {
+ node->type = SKIP_TO_ENDIF;
+ }
+
+ node->next = parser->skip_stack;
+ parser->skip_stack = node;
+}
+
+static void
+_glcpp_parser_skip_stack_change_if (glcpp_parser_t *parser, YYLTYPE *loc,
+ const char *type, int condition)
+{
+ if (parser->skip_stack == NULL) {
+ glcpp_error (loc, parser, "%s without #if\n", type);
+ return;
+ }
+
+ if (parser->skip_stack->type == SKIP_TO_ELSE) {
+ if (condition)
+ parser->skip_stack->type = SKIP_NO_SKIP;
+ } else {
+ parser->skip_stack->type = SKIP_TO_ENDIF;
+ }
+}
+
+static void
+_glcpp_parser_skip_stack_pop (glcpp_parser_t *parser, YYLTYPE *loc)
+{
+ skip_node_t *node;
+
+ if (parser->skip_stack == NULL) {
+ glcpp_error (loc, parser, "#endif without #if\n");
+ return;
+ }
+
+ node = parser->skip_stack;
+ parser->skip_stack = node->next;
+ talloc_free (node);
+}
diff --git a/src/glsl/glcpp/glcpp.c b/src/glsl/glcpp/glcpp.c
new file mode 100644
index 00000000000..a245cb54060
--- /dev/null
+++ b/src/glsl/glcpp/glcpp.c
@@ -0,0 +1,85 @@
+/*
+ * Copyright © 2010 Intel Corporation
+ *
+ * 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 (including the next
+ * paragraph) 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
+ * THE AUTHORS OR COPYRIGHT HOLDERS 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.
+ */
+
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+#include <unistd.h>
+#include "glcpp.h"
+
+extern int yydebug;
+
+static char *
+load_text_file(void *ctx, const char *file_name)
+{
+ char *text = NULL;
+ struct stat st;
+ ssize_t total_read = 0;
+ int fd = file_name == NULL ? STDIN_FILENO : open(file_name, O_RDONLY);
+
+ if (fd < 0) {
+ return NULL;
+ }
+
+ if (fstat(fd, & st) == 0) {
+ text = (char *) talloc_size(ctx, st.st_size + 1);
+ if (text != NULL) {
+ do {
+ ssize_t bytes = read(fd, text + total_read,
+ st.st_size - total_read);
+ if (bytes < 0) {
+ text = NULL;
+ break;
+ }
+
+ if (bytes == 0) {
+ break;
+ }
+
+ total_read += bytes;
+ } while (total_read < st.st_size);
+
+ text[total_read] = '\0';
+ }
+ }
+
+ close(fd);
+
+ return text;
+}
+
+int
+main (void)
+{
+ void *ctx = talloc(NULL, void*);
+ const char *shader = load_text_file(ctx, NULL);
+ char *info_log = talloc_strdup(ctx, "");
+ int ret = preprocess(ctx, &shader, &info_log, NULL);
+
+ printf("%s", shader);
+ fprintf(stderr, "%s", info_log);
+
+ talloc_free(ctx);
+
+ return ret;
+}
diff --git a/src/glsl/glcpp/glcpp.h b/src/glsl/glcpp/glcpp.h
new file mode 100644
index 00000000000..0bebdb9ae8c
--- /dev/null
+++ b/src/glsl/glcpp/glcpp.h
@@ -0,0 +1,222 @@
+/*
+ * Copyright © 2010 Intel Corporation
+ *
+ * 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 (including the next
+ * paragraph) 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
+ * THE AUTHORS OR COPYRIGHT HOLDERS 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.
+ */
+
+#ifndef GLCPP_H
+#define GLCPP_H
+
+#include <stdint.h>
+
+#include <talloc.h>
+
+#include "program/hash_table.h"
+
+#define yyscan_t void*
+
+/* Some data types used for parser values. */
+
+typedef struct string_node {
+ const char *str;
+ struct string_node *next;
+} string_node_t;
+
+typedef struct string_list {
+ string_node_t *head;
+ string_node_t *tail;
+} string_list_t;
+
+typedef struct token token_t;
+typedef struct token_list token_list_t;
+
+typedef union YYSTYPE
+{
+ intmax_t ival;
+ char *str;
+ string_list_t *string_list;
+ token_t *token;
+ token_list_t *token_list;
+} YYSTYPE;
+
+# define YYSTYPE_IS_TRIVIAL 1
+# define YYSTYPE_IS_DECLARED 1
+
+typedef struct YYLTYPE {
+ int first_line;
+ int first_column;
+ int last_line;
+ int last_column;
+ unsigned source;
+} YYLTYPE;
+# define YYLTYPE_IS_DECLARED 1
+# define YYLTYPE_IS_TRIVIAL 1
+
+# define YYLLOC_DEFAULT(Current, Rhs, N) \
+do { \
+ if (N) \
+ { \
+ (Current).first_line = YYRHSLOC(Rhs, 1).first_line; \
+ (Current).first_column = YYRHSLOC(Rhs, 1).first_column; \
+ (Current).last_line = YYRHSLOC(Rhs, N).last_line; \
+ (Current).last_column = YYRHSLOC(Rhs, N).last_column; \
+ } \
+ else \
+ { \
+ (Current).first_line = (Current).last_line = \
+ YYRHSLOC(Rhs, 0).last_line; \
+ (Current).first_column = (Current).last_column = \
+ YYRHSLOC(Rhs, 0).last_column; \
+ } \
+ (Current).source = 0; \
+} while (0)
+
+struct token {
+ int type;
+ YYSTYPE value;
+ YYLTYPE location;
+};
+
+typedef struct token_node {
+ token_t *token;
+ struct token_node *next;
+} token_node_t;
+
+struct token_list {
+ token_node_t *head;
+ token_node_t *tail;
+ token_node_t *non_space_tail;
+};
+
+typedef struct argument_node {
+ token_list_t *argument;
+ struct argument_node *next;
+} argument_node_t;
+
+typedef struct argument_list {
+ argument_node_t *head;
+ argument_node_t *tail;
+} argument_list_t;
+
+typedef struct glcpp_parser glcpp_parser_t;
+
+typedef enum {
+ TOKEN_CLASS_IDENTIFIER,
+ TOKEN_CLASS_IDENTIFIER_FINALIZED,
+ TOKEN_CLASS_FUNC_MACRO,
+ TOKEN_CLASS_OBJ_MACRO
+} token_class_t;
+
+token_class_t
+glcpp_parser_classify_token (glcpp_parser_t *parser,
+ const char *identifier,
+ int *parameter_index);
+
+typedef struct {
+ int is_function;
+ string_list_t *parameters;
+ const char *identifier;
+ token_list_t *replacements;
+} macro_t;
+
+typedef struct expansion_node {
+ macro_t *macro;
+ token_node_t *replacements;
+ struct expansion_node *next;
+} expansion_node_t;
+
+typedef enum skip_type {
+ SKIP_NO_SKIP,
+ SKIP_TO_ELSE,
+ SKIP_TO_ENDIF
+} skip_type_t;
+
+typedef struct skip_node {
+ skip_type_t type;
+ YYLTYPE loc; /* location of the initial #if/#elif/... */
+ struct skip_node *next;
+} skip_node_t;
+
+typedef struct active_list {
+ const char *identifier;
+ token_node_t *marker;
+ struct active_list *next;
+} active_list_t;
+
+struct glcpp_parser {
+ yyscan_t scanner;
+ struct hash_table *defines;
+ active_list_t *active;
+ int lexing_if;
+ int space_tokens;
+ int newline_as_space;
+ int in_control_line;
+ int paren_count;
+ skip_node_t *skip_stack;
+ token_list_t *lex_from_list;
+ token_node_t *lex_from_node;
+ char *output;
+ char *info_log;
+ int error;
+};
+
+struct gl_extensions;
+
+glcpp_parser_t *
+glcpp_parser_create (const struct gl_extensions *extensions);
+
+int
+glcpp_parser_parse (glcpp_parser_t *parser);
+
+void
+glcpp_parser_destroy (glcpp_parser_t *parser);
+
+int
+preprocess(void *talloc_ctx, const char **shader, char **info_log,
+ const struct gl_extensions *extensions);
+
+/* Functions for writing to the info log */
+
+void
+glcpp_error (YYLTYPE *locp, glcpp_parser_t *parser, const char *fmt, ...);
+
+void
+glcpp_warning (YYLTYPE *locp, glcpp_parser_t *parser, const char *fmt, ...);
+
+/* Generated by glcpp-lex.l to glcpp-lex.c */
+
+int
+glcpp_lex_init_extra (glcpp_parser_t *parser, yyscan_t* scanner);
+
+void
+glcpp_lex_set_source_string(glcpp_parser_t *parser, const char *shader);
+
+int
+glcpp_lex (YYSTYPE *lvalp, YYLTYPE *llocp, yyscan_t scanner);
+
+int
+glcpp_lex_destroy (yyscan_t scanner);
+
+/* Generated by glcpp-parse.y to glcpp-parse.c */
+
+int
+yyparse (glcpp_parser_t *parser);
+
+#endif
diff --git a/src/glsl/glcpp/pp.c b/src/glsl/glcpp/pp.c
new file mode 100644
index 00000000000..7672490958d
--- /dev/null
+++ b/src/glsl/glcpp/pp.c
@@ -0,0 +1,166 @@
+/*
+ * Copyright © 2010 Intel Corporation
+ *
+ * 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 (including the next
+ * paragraph) 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
+ * THE AUTHORS OR COPYRIGHT HOLDERS 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.
+ */
+
+#include <assert.h>
+#include <string.h>
+#include <ctype.h>
+#include "glcpp.h"
+
+void
+glcpp_error (YYLTYPE *locp, glcpp_parser_t *parser, const char *fmt, ...)
+{
+ va_list ap;
+
+ parser->error = 1;
+ parser->info_log = talloc_asprintf_append(parser->info_log,
+ "%u:%u(%u): "
+ "preprocessor error: ",
+ locp->source,
+ locp->first_line,
+ locp->first_column);
+ va_start(ap, fmt);
+ parser->info_log = talloc_vasprintf_append(parser->info_log, fmt, ap);
+ va_end(ap);
+ parser->info_log = talloc_strdup_append(parser->info_log, "\n");
+}
+
+void
+glcpp_warning (YYLTYPE *locp, glcpp_parser_t *parser, const char *fmt, ...)
+{
+ va_list ap;
+
+ parser->info_log = talloc_asprintf_append(parser->info_log,
+ "%u:%u(%u): "
+ "preprocessor warning: ",
+ locp->source,
+ locp->first_line,
+ locp->first_column);
+ va_start(ap, fmt);
+ parser->info_log = talloc_vasprintf_append(parser->info_log, fmt, ap);
+ va_end(ap);
+ parser->info_log = talloc_strdup_append(parser->info_log, "\n");
+}
+
+/* Searches backwards for '^ *#' from a given starting point. */
+static int
+in_directive(const char *shader, const char *ptr)
+{
+ assert(ptr >= shader);
+
+ /* Search backwards for '#'. If we find a \n first, it doesn't count */
+ for (; ptr >= shader && *ptr != '#'; ptr--) {
+ if (*ptr == '\n')
+ return 0;
+ }
+ if (ptr >= shader) {
+ /* Found '#'...look for spaces preceded by a newline */
+ for (ptr--; ptr >= shader && isblank(*ptr); ptr--);
+ // FIXME: I don't think the '\n' case can happen
+ if (ptr < shader || *ptr == '\n')
+ return 1;
+ }
+ return 0;
+}
+
+/* Remove any line continuation characters in preprocessing directives.
+ * However, ignore any in GLSL code, as "There is no line continuation
+ * character" (1.30 page 9) in GLSL.
+ */
+static char *
+remove_line_continuations(glcpp_parser_t *ctx, const char *shader)
+{
+ int in_continued_line = 0;
+ int extra_newlines = 0;
+ char *clean = talloc_strdup(ctx, "");
+ const char *search_start = shader;
+ const char *newline;
+ while ((newline = strchr(search_start, '\n')) != NULL) {
+ const char *backslash = NULL;
+
+ /* # of characters preceding the newline. */
+ int n = newline - shader;
+
+ /* Find the preceding '\', if it exists */
+ if (n >= 1 && newline[-1] == '\\')
+ backslash = newline - 1;
+ else if (n >= 2 && newline[-1] == '\r' && newline[-2] == '\\')
+ backslash = newline - 2;
+
+ /* Double backslashes don't count (the backslash is escaped) */
+ if (backslash != NULL && backslash[-1] == '\\') {
+ backslash = NULL;
+ }
+
+ if (backslash != NULL) {
+ /* We found a line continuation, but do we care? */
+ if (!in_continued_line) {
+ if (in_directive(shader, backslash)) {
+ in_continued_line = 1;
+ extra_newlines = 0;
+ }
+ }
+ if (in_continued_line) {
+ /* Copy everything before the \ */
+ clean = talloc_strndup_append(clean, shader, backslash - shader);
+ shader = newline + 1;
+ extra_newlines++;
+ }
+ } else if (in_continued_line) {
+ /* Copy everything up to and including the \n */
+ clean = talloc_strndup_append(clean, shader, newline - shader + 1);
+ shader = newline + 1;
+ /* Output extra newlines to make line numbers match */
+ for (; extra_newlines > 0; extra_newlines--)
+ clean = talloc_strdup_append(clean, "\n");
+ in_continued_line = 0;
+ }
+ search_start = newline + 1;
+ }
+ clean = talloc_strdup_append(clean, shader);
+ return clean;
+}
+
+extern int
+preprocess(void *talloc_ctx, const char **shader, char **info_log,
+ const struct gl_extensions *extensions)
+{
+ int errors;
+ glcpp_parser_t *parser = glcpp_parser_create (extensions);
+ *shader = remove_line_continuations(parser, *shader);
+
+ glcpp_lex_set_source_string (parser, *shader);
+
+ glcpp_parser_parse (parser);
+
+ if (parser->skip_stack)
+ glcpp_error (&parser->skip_stack->loc, parser, "Unterminated #if\n");
+
+ *info_log = talloc_strdup_append(*info_log, parser->info_log);
+
+ talloc_steal(talloc_ctx, parser->output);
+ *shader = parser->output;
+
+ errors = parser->error;
+ glcpp_parser_destroy (parser);
+ return errors;
+}
diff --git a/src/glsl/glcpp/tests/000-content-with-spaces.c b/src/glsl/glcpp/tests/000-content-with-spaces.c
new file mode 100644
index 00000000000..696cb3a74fc
--- /dev/null
+++ b/src/glsl/glcpp/tests/000-content-with-spaces.c
@@ -0,0 +1 @@
+this is four tokens
diff --git a/src/glsl/glcpp/tests/000-content-with-spaces.c.expected b/src/glsl/glcpp/tests/000-content-with-spaces.c.expected
new file mode 100644
index 00000000000..83f7834d547
--- /dev/null
+++ b/src/glsl/glcpp/tests/000-content-with-spaces.c.expected
@@ -0,0 +1,2 @@
+this is four tokens
+
diff --git a/src/glsl/glcpp/tests/001-define.c b/src/glsl/glcpp/tests/001-define.c
new file mode 100644
index 00000000000..cbf2fee0e75
--- /dev/null
+++ b/src/glsl/glcpp/tests/001-define.c
@@ -0,0 +1,2 @@
+#define foo 1
+foo
diff --git a/src/glsl/glcpp/tests/001-define.c.expected b/src/glsl/glcpp/tests/001-define.c.expected
new file mode 100644
index 00000000000..878fd15d6f8
--- /dev/null
+++ b/src/glsl/glcpp/tests/001-define.c.expected
@@ -0,0 +1,3 @@
+
+1
+
diff --git a/src/glsl/glcpp/tests/002-define-chain.c b/src/glsl/glcpp/tests/002-define-chain.c
new file mode 100644
index 00000000000..87d75c68751
--- /dev/null
+++ b/src/glsl/glcpp/tests/002-define-chain.c
@@ -0,0 +1,3 @@
+#define foo 1
+#define bar foo
+bar
diff --git a/src/glsl/glcpp/tests/002-define-chain.c.expected b/src/glsl/glcpp/tests/002-define-chain.c.expected
new file mode 100644
index 00000000000..43d484d7131
--- /dev/null
+++ b/src/glsl/glcpp/tests/002-define-chain.c.expected
@@ -0,0 +1,4 @@
+
+
+1
+
diff --git a/src/glsl/glcpp/tests/003-define-chain-reverse.c b/src/glsl/glcpp/tests/003-define-chain-reverse.c
new file mode 100644
index 00000000000..a18b724eca0
--- /dev/null
+++ b/src/glsl/glcpp/tests/003-define-chain-reverse.c
@@ -0,0 +1,3 @@
+#define bar foo
+#define foo 1
+bar
diff --git a/src/glsl/glcpp/tests/003-define-chain-reverse.c.expected b/src/glsl/glcpp/tests/003-define-chain-reverse.c.expected
new file mode 100644
index 00000000000..43d484d7131
--- /dev/null
+++ b/src/glsl/glcpp/tests/003-define-chain-reverse.c.expected
@@ -0,0 +1,4 @@
+
+
+1
+
diff --git a/src/glsl/glcpp/tests/004-define-recursive.c b/src/glsl/glcpp/tests/004-define-recursive.c
new file mode 100644
index 00000000000..2ac56ea3dcf
--- /dev/null
+++ b/src/glsl/glcpp/tests/004-define-recursive.c
@@ -0,0 +1,6 @@
+#define foo bar
+#define bar baz
+#define baz foo
+foo
+bar
+baz
diff --git a/src/glsl/glcpp/tests/004-define-recursive.c.expected b/src/glsl/glcpp/tests/004-define-recursive.c.expected
new file mode 100644
index 00000000000..4d2698b7a7f
--- /dev/null
+++ b/src/glsl/glcpp/tests/004-define-recursive.c.expected
@@ -0,0 +1,7 @@
+
+
+
+foo
+bar
+baz
+
diff --git a/src/glsl/glcpp/tests/005-define-composite-chain.c b/src/glsl/glcpp/tests/005-define-composite-chain.c
new file mode 100644
index 00000000000..f5521df968d
--- /dev/null
+++ b/src/glsl/glcpp/tests/005-define-composite-chain.c
@@ -0,0 +1,3 @@
+#define foo 1
+#define bar a foo
+bar
diff --git a/src/glsl/glcpp/tests/005-define-composite-chain.c.expected b/src/glsl/glcpp/tests/005-define-composite-chain.c.expected
new file mode 100644
index 00000000000..c67358f4f69
--- /dev/null
+++ b/src/glsl/glcpp/tests/005-define-composite-chain.c.expected
@@ -0,0 +1,4 @@
+
+
+a 1
+
diff --git a/src/glsl/glcpp/tests/006-define-composite-chain-reverse.c b/src/glsl/glcpp/tests/006-define-composite-chain-reverse.c
new file mode 100644
index 00000000000..4bb91a1221a
--- /dev/null
+++ b/src/glsl/glcpp/tests/006-define-composite-chain-reverse.c
@@ -0,0 +1,3 @@
+#define bar a foo
+#define foo 1
+bar
diff --git a/src/glsl/glcpp/tests/006-define-composite-chain-reverse.c.expected b/src/glsl/glcpp/tests/006-define-composite-chain-reverse.c.expected
new file mode 100644
index 00000000000..c67358f4f69
--- /dev/null
+++ b/src/glsl/glcpp/tests/006-define-composite-chain-reverse.c.expected
@@ -0,0 +1,4 @@
+
+
+a 1
+
diff --git a/src/glsl/glcpp/tests/007-define-composite-recursive.c b/src/glsl/glcpp/tests/007-define-composite-recursive.c
new file mode 100644
index 00000000000..5784565bdf3
--- /dev/null
+++ b/src/glsl/glcpp/tests/007-define-composite-recursive.c
@@ -0,0 +1,6 @@
+#define foo a bar
+#define bar b baz
+#define baz c foo
+foo
+bar
+baz
diff --git a/src/glsl/glcpp/tests/007-define-composite-recursive.c.expected b/src/glsl/glcpp/tests/007-define-composite-recursive.c.expected
new file mode 100644
index 00000000000..30fe4dc1f62
--- /dev/null
+++ b/src/glsl/glcpp/tests/007-define-composite-recursive.c.expected
@@ -0,0 +1,7 @@
+
+
+
+a b c foo
+b c a bar
+c a b baz
+
diff --git a/src/glsl/glcpp/tests/008-define-empty.c b/src/glsl/glcpp/tests/008-define-empty.c
new file mode 100644
index 00000000000..b1bd17ec215
--- /dev/null
+++ b/src/glsl/glcpp/tests/008-define-empty.c
@@ -0,0 +1,2 @@
+#define foo
+foo
diff --git a/src/glsl/glcpp/tests/008-define-empty.c.expected b/src/glsl/glcpp/tests/008-define-empty.c.expected
new file mode 100644
index 00000000000..c0f53d75c71
--- /dev/null
+++ b/src/glsl/glcpp/tests/008-define-empty.c.expected
@@ -0,0 +1,3 @@
+
+
+
diff --git a/src/glsl/glcpp/tests/009-undef.c b/src/glsl/glcpp/tests/009-undef.c
new file mode 100644
index 00000000000..3fc1fb44243
--- /dev/null
+++ b/src/glsl/glcpp/tests/009-undef.c
@@ -0,0 +1,4 @@
+#define foo 1
+foo
+#undef foo
+foo
diff --git a/src/glsl/glcpp/tests/009-undef.c.expected b/src/glsl/glcpp/tests/009-undef.c.expected
new file mode 100644
index 00000000000..03a7061af03
--- /dev/null
+++ b/src/glsl/glcpp/tests/009-undef.c.expected
@@ -0,0 +1,5 @@
+
+1
+
+foo
+
diff --git a/src/glsl/glcpp/tests/010-undef-re-define.c b/src/glsl/glcpp/tests/010-undef-re-define.c
new file mode 100644
index 00000000000..32ff73798b1
--- /dev/null
+++ b/src/glsl/glcpp/tests/010-undef-re-define.c
@@ -0,0 +1,6 @@
+#define foo 1
+foo
+#undef foo
+foo
+#define foo 2
+foo
diff --git a/src/glsl/glcpp/tests/010-undef-re-define.c.expected b/src/glsl/glcpp/tests/010-undef-re-define.c.expected
new file mode 100644
index 00000000000..f4f7efdc2bf
--- /dev/null
+++ b/src/glsl/glcpp/tests/010-undef-re-define.c.expected
@@ -0,0 +1,7 @@
+
+1
+
+foo
+
+2
+
diff --git a/src/glsl/glcpp/tests/011-define-func-empty.c b/src/glsl/glcpp/tests/011-define-func-empty.c
new file mode 100644
index 00000000000..d9ce13c2284
--- /dev/null
+++ b/src/glsl/glcpp/tests/011-define-func-empty.c
@@ -0,0 +1,2 @@
+#define foo()
+foo()
diff --git a/src/glsl/glcpp/tests/011-define-func-empty.c.expected b/src/glsl/glcpp/tests/011-define-func-empty.c.expected
new file mode 100644
index 00000000000..c0f53d75c71
--- /dev/null
+++ b/src/glsl/glcpp/tests/011-define-func-empty.c.expected
@@ -0,0 +1,3 @@
+
+
+
diff --git a/src/glsl/glcpp/tests/012-define-func-no-args.c b/src/glsl/glcpp/tests/012-define-func-no-args.c
new file mode 100644
index 00000000000..c2bb730b115
--- /dev/null
+++ b/src/glsl/glcpp/tests/012-define-func-no-args.c
@@ -0,0 +1,2 @@
+#define foo() bar
+foo()
diff --git a/src/glsl/glcpp/tests/012-define-func-no-args.c.expected b/src/glsl/glcpp/tests/012-define-func-no-args.c.expected
new file mode 100644
index 00000000000..03537672974
--- /dev/null
+++ b/src/glsl/glcpp/tests/012-define-func-no-args.c.expected
@@ -0,0 +1,3 @@
+
+bar
+
diff --git a/src/glsl/glcpp/tests/013-define-func-1-arg-unused.c b/src/glsl/glcpp/tests/013-define-func-1-arg-unused.c
new file mode 100644
index 00000000000..f78fb8b118a
--- /dev/null
+++ b/src/glsl/glcpp/tests/013-define-func-1-arg-unused.c
@@ -0,0 +1,2 @@
+#define foo(x) 1
+foo(bar)
diff --git a/src/glsl/glcpp/tests/013-define-func-1-arg-unused.c.expected b/src/glsl/glcpp/tests/013-define-func-1-arg-unused.c.expected
new file mode 100644
index 00000000000..878fd15d6f8
--- /dev/null
+++ b/src/glsl/glcpp/tests/013-define-func-1-arg-unused.c.expected
@@ -0,0 +1,3 @@
+
+1
+
diff --git a/src/glsl/glcpp/tests/014-define-func-2-arg-unused.c b/src/glsl/glcpp/tests/014-define-func-2-arg-unused.c
new file mode 100644
index 00000000000..11feb2624b7
--- /dev/null
+++ b/src/glsl/glcpp/tests/014-define-func-2-arg-unused.c
@@ -0,0 +1,2 @@
+#define foo(x,y) 1
+foo(bar,baz)
diff --git a/src/glsl/glcpp/tests/014-define-func-2-arg-unused.c.expected b/src/glsl/glcpp/tests/014-define-func-2-arg-unused.c.expected
new file mode 100644
index 00000000000..878fd15d6f8
--- /dev/null
+++ b/src/glsl/glcpp/tests/014-define-func-2-arg-unused.c.expected
@@ -0,0 +1,3 @@
+
+1
+
diff --git a/src/glsl/glcpp/tests/015-define-object-with-parens.c b/src/glsl/glcpp/tests/015-define-object-with-parens.c
new file mode 100644
index 00000000000..558da9c617b
--- /dev/null
+++ b/src/glsl/glcpp/tests/015-define-object-with-parens.c
@@ -0,0 +1,4 @@
+#define foo ()1
+foo()
+#define bar ()2
+bar()
diff --git a/src/glsl/glcpp/tests/015-define-object-with-parens.c.expected b/src/glsl/glcpp/tests/015-define-object-with-parens.c.expected
new file mode 100644
index 00000000000..d6f8cb9dc61
--- /dev/null
+++ b/src/glsl/glcpp/tests/015-define-object-with-parens.c.expected
@@ -0,0 +1,5 @@
+
+()1()
+
+()2()
+
diff --git a/src/glsl/glcpp/tests/016-define-func-1-arg.c b/src/glsl/glcpp/tests/016-define-func-1-arg.c
new file mode 100644
index 00000000000..a2e2404c7c1
--- /dev/null
+++ b/src/glsl/glcpp/tests/016-define-func-1-arg.c
@@ -0,0 +1,2 @@
+#define foo(x) ((x)+1)
+foo(bar)
diff --git a/src/glsl/glcpp/tests/016-define-func-1-arg.c.expected b/src/glsl/glcpp/tests/016-define-func-1-arg.c.expected
new file mode 100644
index 00000000000..7f1828a3c61
--- /dev/null
+++ b/src/glsl/glcpp/tests/016-define-func-1-arg.c.expected
@@ -0,0 +1,3 @@
+
+((bar)+1)
+
diff --git a/src/glsl/glcpp/tests/017-define-func-2-args.c b/src/glsl/glcpp/tests/017-define-func-2-args.c
new file mode 100644
index 00000000000..c7253835278
--- /dev/null
+++ b/src/glsl/glcpp/tests/017-define-func-2-args.c
@@ -0,0 +1,2 @@
+#define foo(x,y) ((x)*(y))
+foo(bar,baz)
diff --git a/src/glsl/glcpp/tests/017-define-func-2-args.c.expected b/src/glsl/glcpp/tests/017-define-func-2-args.c.expected
new file mode 100644
index 00000000000..9f341dac00a
--- /dev/null
+++ b/src/glsl/glcpp/tests/017-define-func-2-args.c.expected
@@ -0,0 +1,3 @@
+
+((bar)*(baz))
+
diff --git a/src/glsl/glcpp/tests/018-define-func-macro-as-parameter.c b/src/glsl/glcpp/tests/018-define-func-macro-as-parameter.c
new file mode 100644
index 00000000000..668130b8f9b
--- /dev/null
+++ b/src/glsl/glcpp/tests/018-define-func-macro-as-parameter.c
@@ -0,0 +1,3 @@
+#define x 0
+#define foo(x) x
+foo(1)
diff --git a/src/glsl/glcpp/tests/018-define-func-macro-as-parameter.c.expected b/src/glsl/glcpp/tests/018-define-func-macro-as-parameter.c.expected
new file mode 100644
index 00000000000..43d484d7131
--- /dev/null
+++ b/src/glsl/glcpp/tests/018-define-func-macro-as-parameter.c.expected
@@ -0,0 +1,4 @@
+
+
+1
+
diff --git a/src/glsl/glcpp/tests/019-define-func-1-arg-multi.c b/src/glsl/glcpp/tests/019-define-func-1-arg-multi.c
new file mode 100644
index 00000000000..c4e62b25508
--- /dev/null
+++ b/src/glsl/glcpp/tests/019-define-func-1-arg-multi.c
@@ -0,0 +1,2 @@
+#define foo(x) (x)
+foo(this is more than one word)
diff --git a/src/glsl/glcpp/tests/019-define-func-1-arg-multi.c.expected b/src/glsl/glcpp/tests/019-define-func-1-arg-multi.c.expected
new file mode 100644
index 00000000000..4314fc88d83
--- /dev/null
+++ b/src/glsl/glcpp/tests/019-define-func-1-arg-multi.c.expected
@@ -0,0 +1,3 @@
+
+(this is more than one word)
+
diff --git a/src/glsl/glcpp/tests/020-define-func-2-arg-multi.c b/src/glsl/glcpp/tests/020-define-func-2-arg-multi.c
new file mode 100644
index 00000000000..3049ad15465
--- /dev/null
+++ b/src/glsl/glcpp/tests/020-define-func-2-arg-multi.c
@@ -0,0 +1,2 @@
+#define foo(x,y) x,two fish,red fish,y
+foo(one fish, blue fish)
diff --git a/src/glsl/glcpp/tests/020-define-func-2-arg-multi.c.expected b/src/glsl/glcpp/tests/020-define-func-2-arg-multi.c.expected
new file mode 100644
index 00000000000..5648e4fb9d4
--- /dev/null
+++ b/src/glsl/glcpp/tests/020-define-func-2-arg-multi.c.expected
@@ -0,0 +1,3 @@
+
+one fish,two fish,red fish,blue fish
+
diff --git a/src/glsl/glcpp/tests/021-define-func-compose.c b/src/glsl/glcpp/tests/021-define-func-compose.c
new file mode 100644
index 00000000000..21ddd0e65f9
--- /dev/null
+++ b/src/glsl/glcpp/tests/021-define-func-compose.c
@@ -0,0 +1,3 @@
+#define bar(x) (1+(x))
+#define foo(y) (2*(y))
+foo(bar(3))
diff --git a/src/glsl/glcpp/tests/021-define-func-compose.c.expected b/src/glsl/glcpp/tests/021-define-func-compose.c.expected
new file mode 100644
index 00000000000..1d62105de4c
--- /dev/null
+++ b/src/glsl/glcpp/tests/021-define-func-compose.c.expected
@@ -0,0 +1,4 @@
+
+
+(2*((1+(3))))
+
diff --git a/src/glsl/glcpp/tests/022-define-func-arg-with-parens.c b/src/glsl/glcpp/tests/022-define-func-arg-with-parens.c
new file mode 100644
index 00000000000..c20d73a4a28
--- /dev/null
+++ b/src/glsl/glcpp/tests/022-define-func-arg-with-parens.c
@@ -0,0 +1,2 @@
+#define foo(x) (x)
+foo(argument(including parens)for the win)
diff --git a/src/glsl/glcpp/tests/022-define-func-arg-with-parens.c.expected b/src/glsl/glcpp/tests/022-define-func-arg-with-parens.c.expected
new file mode 100644
index 00000000000..66c16581758
--- /dev/null
+++ b/src/glsl/glcpp/tests/022-define-func-arg-with-parens.c.expected
@@ -0,0 +1,3 @@
+
+(argument(including parens)for the win)
+
diff --git a/src/glsl/glcpp/tests/023-define-extra-whitespace.c b/src/glsl/glcpp/tests/023-define-extra-whitespace.c
new file mode 100644
index 00000000000..7ebfed6516c
--- /dev/null
+++ b/src/glsl/glcpp/tests/023-define-extra-whitespace.c
@@ -0,0 +1,8 @@
+#define noargs() 1
+# define onearg(foo) foo
+ # define twoargs( x , y ) x y
+ # define threeargs( a , b , c ) a b c
+noargs ( )
+onearg ( 2 )
+twoargs ( 3 , 4 )
+threeargs ( 5 , 6 , 7 )
diff --git a/src/glsl/glcpp/tests/023-define-extra-whitespace.c.expected b/src/glsl/glcpp/tests/023-define-extra-whitespace.c.expected
new file mode 100644
index 00000000000..573829c2d69
--- /dev/null
+++ b/src/glsl/glcpp/tests/023-define-extra-whitespace.c.expected
@@ -0,0 +1,9 @@
+
+
+
+
+1
+2
+3 4
+5 6 7
+
diff --git a/src/glsl/glcpp/tests/024-define-chain-to-self-recursion.c b/src/glsl/glcpp/tests/024-define-chain-to-self-recursion.c
new file mode 100644
index 00000000000..e788adce30c
--- /dev/null
+++ b/src/glsl/glcpp/tests/024-define-chain-to-self-recursion.c
@@ -0,0 +1,3 @@
+#define foo foo
+#define bar foo
+bar
diff --git a/src/glsl/glcpp/tests/024-define-chain-to-self-recursion.c.expected b/src/glsl/glcpp/tests/024-define-chain-to-self-recursion.c.expected
new file mode 100644
index 00000000000..ad955fce6ec
--- /dev/null
+++ b/src/glsl/glcpp/tests/024-define-chain-to-self-recursion.c.expected
@@ -0,0 +1,4 @@
+
+
+foo
+
diff --git a/src/glsl/glcpp/tests/025-func-macro-as-non-macro.c b/src/glsl/glcpp/tests/025-func-macro-as-non-macro.c
new file mode 100644
index 00000000000..b433671d1bf
--- /dev/null
+++ b/src/glsl/glcpp/tests/025-func-macro-as-non-macro.c
@@ -0,0 +1,2 @@
+#define foo(bar) bar
+foo bar
diff --git a/src/glsl/glcpp/tests/025-func-macro-as-non-macro.c.expected b/src/glsl/glcpp/tests/025-func-macro-as-non-macro.c.expected
new file mode 100644
index 00000000000..960f44511a9
--- /dev/null
+++ b/src/glsl/glcpp/tests/025-func-macro-as-non-macro.c.expected
@@ -0,0 +1,3 @@
+
+foo bar
+
diff --git a/src/glsl/glcpp/tests/026-define-func-extra-newlines.c b/src/glsl/glcpp/tests/026-define-func-extra-newlines.c
new file mode 100644
index 00000000000..0d837405309
--- /dev/null
+++ b/src/glsl/glcpp/tests/026-define-func-extra-newlines.c
@@ -0,0 +1,6 @@
+#define foo(a) bar
+
+foo
+(
+1
+)
diff --git a/src/glsl/glcpp/tests/026-define-func-extra-newlines.c.expected b/src/glsl/glcpp/tests/026-define-func-extra-newlines.c.expected
new file mode 100644
index 00000000000..f0888f21b94
--- /dev/null
+++ b/src/glsl/glcpp/tests/026-define-func-extra-newlines.c.expected
@@ -0,0 +1,4 @@
+
+
+bar
+
diff --git a/src/glsl/glcpp/tests/027-define-chain-obj-to-func.c b/src/glsl/glcpp/tests/027-define-chain-obj-to-func.c
new file mode 100644
index 00000000000..5ccb52caba5
--- /dev/null
+++ b/src/glsl/glcpp/tests/027-define-chain-obj-to-func.c
@@ -0,0 +1,3 @@
+#define failure() success
+#define foo failure()
+foo
diff --git a/src/glsl/glcpp/tests/027-define-chain-obj-to-func.c.expected b/src/glsl/glcpp/tests/027-define-chain-obj-to-func.c.expected
new file mode 100644
index 00000000000..aef762e1e69
--- /dev/null
+++ b/src/glsl/glcpp/tests/027-define-chain-obj-to-func.c.expected
@@ -0,0 +1,4 @@
+
+
+success
+
diff --git a/src/glsl/glcpp/tests/028-define-chain-obj-to-non-func.c b/src/glsl/glcpp/tests/028-define-chain-obj-to-non-func.c
new file mode 100644
index 00000000000..44962a71876
--- /dev/null
+++ b/src/glsl/glcpp/tests/028-define-chain-obj-to-non-func.c
@@ -0,0 +1,3 @@
+#define success() failure
+#define foo success
+foo
diff --git a/src/glsl/glcpp/tests/028-define-chain-obj-to-non-func.c.expected b/src/glsl/glcpp/tests/028-define-chain-obj-to-non-func.c.expected
new file mode 100644
index 00000000000..aef762e1e69
--- /dev/null
+++ b/src/glsl/glcpp/tests/028-define-chain-obj-to-non-func.c.expected
@@ -0,0 +1,4 @@
+
+
+success
+
diff --git a/src/glsl/glcpp/tests/029-define-chain-obj-to-func-with-args.c b/src/glsl/glcpp/tests/029-define-chain-obj-to-func-with-args.c
new file mode 100644
index 00000000000..261f7d28fc2
--- /dev/null
+++ b/src/glsl/glcpp/tests/029-define-chain-obj-to-func-with-args.c
@@ -0,0 +1,3 @@
+#define bar(failure) failure
+#define foo bar(success)
+foo
diff --git a/src/glsl/glcpp/tests/029-define-chain-obj-to-func-with-args.c.expected b/src/glsl/glcpp/tests/029-define-chain-obj-to-func-with-args.c.expected
new file mode 100644
index 00000000000..aef762e1e69
--- /dev/null
+++ b/src/glsl/glcpp/tests/029-define-chain-obj-to-func-with-args.c.expected
@@ -0,0 +1,4 @@
+
+
+success
+
diff --git a/src/glsl/glcpp/tests/030-define-chain-obj-to-func-compose.c b/src/glsl/glcpp/tests/030-define-chain-obj-to-func-compose.c
new file mode 100644
index 00000000000..e56fbefd62d
--- /dev/null
+++ b/src/glsl/glcpp/tests/030-define-chain-obj-to-func-compose.c
@@ -0,0 +1,4 @@
+#define baz(failure) failure
+#define bar(failure) failure
+#define foo bar(baz(success))
+foo
diff --git a/src/glsl/glcpp/tests/030-define-chain-obj-to-func-compose.c.expected b/src/glsl/glcpp/tests/030-define-chain-obj-to-func-compose.c.expected
new file mode 100644
index 00000000000..729bdd15f80
--- /dev/null
+++ b/src/glsl/glcpp/tests/030-define-chain-obj-to-func-compose.c.expected
@@ -0,0 +1,5 @@
+
+
+
+success
+
diff --git a/src/glsl/glcpp/tests/031-define-chain-func-to-func-compose.c b/src/glsl/glcpp/tests/031-define-chain-func-to-func-compose.c
new file mode 100644
index 00000000000..3f4c8744dff
--- /dev/null
+++ b/src/glsl/glcpp/tests/031-define-chain-func-to-func-compose.c
@@ -0,0 +1,4 @@
+#define baz(failure) failure
+#define bar(failure) failure
+#define foo() bar(baz(success))
+foo()
diff --git a/src/glsl/glcpp/tests/031-define-chain-func-to-func-compose.c.expected b/src/glsl/glcpp/tests/031-define-chain-func-to-func-compose.c.expected
new file mode 100644
index 00000000000..729bdd15f80
--- /dev/null
+++ b/src/glsl/glcpp/tests/031-define-chain-func-to-func-compose.c.expected
@@ -0,0 +1,5 @@
+
+
+
+success
+
diff --git a/src/glsl/glcpp/tests/032-define-func-self-recurse.c b/src/glsl/glcpp/tests/032-define-func-self-recurse.c
new file mode 100644
index 00000000000..b3ac70f499c
--- /dev/null
+++ b/src/glsl/glcpp/tests/032-define-func-self-recurse.c
@@ -0,0 +1,2 @@
+#define foo(a) foo(2*(a))
+foo(3)
diff --git a/src/glsl/glcpp/tests/032-define-func-self-recurse.c.expected b/src/glsl/glcpp/tests/032-define-func-self-recurse.c.expected
new file mode 100644
index 00000000000..541d44db7ab
--- /dev/null
+++ b/src/glsl/glcpp/tests/032-define-func-self-recurse.c.expected
@@ -0,0 +1,3 @@
+
+foo(2*(3))
+
diff --git a/src/glsl/glcpp/tests/033-define-func-self-compose.c b/src/glsl/glcpp/tests/033-define-func-self-compose.c
new file mode 100644
index 00000000000..f65e48286cf
--- /dev/null
+++ b/src/glsl/glcpp/tests/033-define-func-self-compose.c
@@ -0,0 +1,2 @@
+#define foo(a) foo(2*(a))
+foo(foo(3))
diff --git a/src/glsl/glcpp/tests/033-define-func-self-compose.c.expected b/src/glsl/glcpp/tests/033-define-func-self-compose.c.expected
new file mode 100644
index 00000000000..6ea6905d80b
--- /dev/null
+++ b/src/glsl/glcpp/tests/033-define-func-self-compose.c.expected
@@ -0,0 +1,3 @@
+
+foo(2*(foo(2*(3))))
+
diff --git a/src/glsl/glcpp/tests/034-define-func-self-compose-non-func.c b/src/glsl/glcpp/tests/034-define-func-self-compose-non-func.c
new file mode 100644
index 00000000000..209a5f7e07c
--- /dev/null
+++ b/src/glsl/glcpp/tests/034-define-func-self-compose-non-func.c
@@ -0,0 +1,2 @@
+#define foo(bar) bar
+foo(foo)
diff --git a/src/glsl/glcpp/tests/034-define-func-self-compose-non-func.c.expected b/src/glsl/glcpp/tests/034-define-func-self-compose-non-func.c.expected
new file mode 100644
index 00000000000..24823b1b673
--- /dev/null
+++ b/src/glsl/glcpp/tests/034-define-func-self-compose-non-func.c.expected
@@ -0,0 +1,3 @@
+
+foo
+
diff --git a/src/glsl/glcpp/tests/035-define-func-self-compose-non-func-multi-token-argument.c b/src/glsl/glcpp/tests/035-define-func-self-compose-non-func-multi-token-argument.c
new file mode 100644
index 00000000000..c307fbe830f
--- /dev/null
+++ b/src/glsl/glcpp/tests/035-define-func-self-compose-non-func-multi-token-argument.c
@@ -0,0 +1,2 @@
+#define foo(bar) bar
+foo(1+foo)
diff --git a/src/glsl/glcpp/tests/035-define-func-self-compose-non-func-multi-token-argument.c.expected b/src/glsl/glcpp/tests/035-define-func-self-compose-non-func-multi-token-argument.c.expected
new file mode 100644
index 00000000000..137a9ea2db8
--- /dev/null
+++ b/src/glsl/glcpp/tests/035-define-func-self-compose-non-func-multi-token-argument.c.expected
@@ -0,0 +1,3 @@
+
+1+foo
+
diff --git a/src/glsl/glcpp/tests/036-define-func-non-macro-multi-token-argument.c b/src/glsl/glcpp/tests/036-define-func-non-macro-multi-token-argument.c
new file mode 100644
index 00000000000..b21ff336738
--- /dev/null
+++ b/src/glsl/glcpp/tests/036-define-func-non-macro-multi-token-argument.c
@@ -0,0 +1,3 @@
+#define bar success
+#define foo(x) x
+foo(more bar)
diff --git a/src/glsl/glcpp/tests/036-define-func-non-macro-multi-token-argument.c.expected b/src/glsl/glcpp/tests/036-define-func-non-macro-multi-token-argument.c.expected
new file mode 100644
index 00000000000..ff6360bfe4e
--- /dev/null
+++ b/src/glsl/glcpp/tests/036-define-func-non-macro-multi-token-argument.c.expected
@@ -0,0 +1,4 @@
+
+
+more success
+
diff --git a/src/glsl/glcpp/tests/037-finalize-unexpanded-macro.c b/src/glsl/glcpp/tests/037-finalize-unexpanded-macro.c
new file mode 100644
index 00000000000..b3a2f37f1b9
--- /dev/null
+++ b/src/glsl/glcpp/tests/037-finalize-unexpanded-macro.c
@@ -0,0 +1,3 @@
+#define expand(x) expand(x once)
+#define foo(x) x
+foo(expand(just))
diff --git a/src/glsl/glcpp/tests/037-finalize-unexpanded-macro.c.expected b/src/glsl/glcpp/tests/037-finalize-unexpanded-macro.c.expected
new file mode 100644
index 00000000000..cbadee848a5
--- /dev/null
+++ b/src/glsl/glcpp/tests/037-finalize-unexpanded-macro.c.expected
@@ -0,0 +1,4 @@
+
+
+expand(just once)
+
diff --git a/src/glsl/glcpp/tests/038-func-arg-with-commas.c b/src/glsl/glcpp/tests/038-func-arg-with-commas.c
new file mode 100644
index 00000000000..1407c7d6e3c
--- /dev/null
+++ b/src/glsl/glcpp/tests/038-func-arg-with-commas.c
@@ -0,0 +1,2 @@
+#define foo(x) success
+foo(argument (with,embedded , commas) -- tricky)
diff --git a/src/glsl/glcpp/tests/038-func-arg-with-commas.c.expected b/src/glsl/glcpp/tests/038-func-arg-with-commas.c.expected
new file mode 100644
index 00000000000..5a28fb3b66c
--- /dev/null
+++ b/src/glsl/glcpp/tests/038-func-arg-with-commas.c.expected
@@ -0,0 +1,3 @@
+
+success
+
diff --git a/src/glsl/glcpp/tests/039-func-arg-obj-macro-with-comma.c b/src/glsl/glcpp/tests/039-func-arg-obj-macro-with-comma.c
new file mode 100644
index 00000000000..0f7fe632b56
--- /dev/null
+++ b/src/glsl/glcpp/tests/039-func-arg-obj-macro-with-comma.c
@@ -0,0 +1,3 @@
+#define foo(a) (a)
+#define bar two,words
+foo(bar)
diff --git a/src/glsl/glcpp/tests/039-func-arg-obj-macro-with-comma.c.expected b/src/glsl/glcpp/tests/039-func-arg-obj-macro-with-comma.c.expected
new file mode 100644
index 00000000000..b73869d0238
--- /dev/null
+++ b/src/glsl/glcpp/tests/039-func-arg-obj-macro-with-comma.c.expected
@@ -0,0 +1,4 @@
+
+
+(two,words)
+
diff --git a/src/glsl/glcpp/tests/040-token-pasting.c b/src/glsl/glcpp/tests/040-token-pasting.c
new file mode 100644
index 00000000000..caab3ba7368
--- /dev/null
+++ b/src/glsl/glcpp/tests/040-token-pasting.c
@@ -0,0 +1,2 @@
+#define paste(a,b) a ## b
+paste(one , token)
diff --git a/src/glsl/glcpp/tests/040-token-pasting.c.expected b/src/glsl/glcpp/tests/040-token-pasting.c.expected
new file mode 100644
index 00000000000..36f66992539
--- /dev/null
+++ b/src/glsl/glcpp/tests/040-token-pasting.c.expected
@@ -0,0 +1,3 @@
+
+onetoken
+
diff --git a/src/glsl/glcpp/tests/041-if-0.c b/src/glsl/glcpp/tests/041-if-0.c
new file mode 100644
index 00000000000..2cab677d3e8
--- /dev/null
+++ b/src/glsl/glcpp/tests/041-if-0.c
@@ -0,0 +1,5 @@
+success_1
+#if 0
+failure
+#endif
+success_2
diff --git a/src/glsl/glcpp/tests/041-if-0.c.expected b/src/glsl/glcpp/tests/041-if-0.c.expected
new file mode 100644
index 00000000000..3800024c6ff
--- /dev/null
+++ b/src/glsl/glcpp/tests/041-if-0.c.expected
@@ -0,0 +1,6 @@
+success_1
+
+
+
+success_2
+
diff --git a/src/glsl/glcpp/tests/042-if-1.c b/src/glsl/glcpp/tests/042-if-1.c
new file mode 100644
index 00000000000..874a25cf41b
--- /dev/null
+++ b/src/glsl/glcpp/tests/042-if-1.c
@@ -0,0 +1,5 @@
+success_1
+#if 1
+success_2
+#endif
+success_3
diff --git a/src/glsl/glcpp/tests/042-if-1.c.expected b/src/glsl/glcpp/tests/042-if-1.c.expected
new file mode 100644
index 00000000000..e591044adbb
--- /dev/null
+++ b/src/glsl/glcpp/tests/042-if-1.c.expected
@@ -0,0 +1,6 @@
+success_1
+
+success_2
+
+success_3
+
diff --git a/src/glsl/glcpp/tests/043-if-0-else.c b/src/glsl/glcpp/tests/043-if-0-else.c
new file mode 100644
index 00000000000..323351f9dbf
--- /dev/null
+++ b/src/glsl/glcpp/tests/043-if-0-else.c
@@ -0,0 +1,7 @@
+success_1
+#if 0
+failure
+#else
+success_2
+#endif
+success_3
diff --git a/src/glsl/glcpp/tests/043-if-0-else.c.expected b/src/glsl/glcpp/tests/043-if-0-else.c.expected
new file mode 100644
index 00000000000..ee9e677096e
--- /dev/null
+++ b/src/glsl/glcpp/tests/043-if-0-else.c.expected
@@ -0,0 +1,8 @@
+success_1
+
+
+
+success_2
+
+success_3
+
diff --git a/src/glsl/glcpp/tests/044-if-1-else.c b/src/glsl/glcpp/tests/044-if-1-else.c
new file mode 100644
index 00000000000..28dfc25c6f0
--- /dev/null
+++ b/src/glsl/glcpp/tests/044-if-1-else.c
@@ -0,0 +1,7 @@
+success_1
+#if 1
+success_2
+#else
+failure
+#endif
+success_3
diff --git a/src/glsl/glcpp/tests/044-if-1-else.c.expected b/src/glsl/glcpp/tests/044-if-1-else.c.expected
new file mode 100644
index 00000000000..129f5c8542e
--- /dev/null
+++ b/src/glsl/glcpp/tests/044-if-1-else.c.expected
@@ -0,0 +1,8 @@
+success_1
+
+success_2
+
+
+
+success_3
+
diff --git a/src/glsl/glcpp/tests/045-if-0-elif.c b/src/glsl/glcpp/tests/045-if-0-elif.c
new file mode 100644
index 00000000000..e50f686d461
--- /dev/null
+++ b/src/glsl/glcpp/tests/045-if-0-elif.c
@@ -0,0 +1,11 @@
+success_1
+#if 0
+failure_1
+#elif 0
+failure_2
+#elif 1
+success_3
+#elif 1
+failure_3
+#endif
+success_4
diff --git a/src/glsl/glcpp/tests/045-if-0-elif.c.expected b/src/glsl/glcpp/tests/045-if-0-elif.c.expected
new file mode 100644
index 00000000000..97a11b4472e
--- /dev/null
+++ b/src/glsl/glcpp/tests/045-if-0-elif.c.expected
@@ -0,0 +1,12 @@
+success_1
+
+
+
+
+
+success_3
+
+
+
+success_4
+
diff --git a/src/glsl/glcpp/tests/046-if-1-elsif.c b/src/glsl/glcpp/tests/046-if-1-elsif.c
new file mode 100644
index 00000000000..130515a01ea
--- /dev/null
+++ b/src/glsl/glcpp/tests/046-if-1-elsif.c
@@ -0,0 +1,11 @@
+success_1
+#if 1
+success_2
+#elif 0
+failure_1
+#elif 1
+failure_2
+#elif 0
+failure_3
+#endif
+success_3
diff --git a/src/glsl/glcpp/tests/046-if-1-elsif.c.expected b/src/glsl/glcpp/tests/046-if-1-elsif.c.expected
new file mode 100644
index 00000000000..b928b917e3d
--- /dev/null
+++ b/src/glsl/glcpp/tests/046-if-1-elsif.c.expected
@@ -0,0 +1,12 @@
+success_1
+
+success_2
+
+
+
+
+
+
+
+success_3
+
diff --git a/src/glsl/glcpp/tests/047-if-elif-else.c b/src/glsl/glcpp/tests/047-if-elif-else.c
new file mode 100644
index 00000000000..e8f0838a9ed
--- /dev/null
+++ b/src/glsl/glcpp/tests/047-if-elif-else.c
@@ -0,0 +1,11 @@
+success_1
+#if 0
+failure_1
+#elif 0
+failure_2
+#elif 0
+failure_3
+#else
+success_2
+#endif
+success_3
diff --git a/src/glsl/glcpp/tests/047-if-elif-else.c.expected b/src/glsl/glcpp/tests/047-if-elif-else.c.expected
new file mode 100644
index 00000000000..e5b53a3fa59
--- /dev/null
+++ b/src/glsl/glcpp/tests/047-if-elif-else.c.expected
@@ -0,0 +1,12 @@
+success_1
+
+
+
+
+
+
+
+success_2
+
+success_3
+
diff --git a/src/glsl/glcpp/tests/048-if-nested.c b/src/glsl/glcpp/tests/048-if-nested.c
new file mode 100644
index 00000000000..fc4679c3be4
--- /dev/null
+++ b/src/glsl/glcpp/tests/048-if-nested.c
@@ -0,0 +1,11 @@
+success_1
+#if 0
+failure_1
+#if 1
+failure_2
+#else
+failure_3
+#endif
+failure_4
+#endif
+success_2
diff --git a/src/glsl/glcpp/tests/048-if-nested.c.expected b/src/glsl/glcpp/tests/048-if-nested.c.expected
new file mode 100644
index 00000000000..c61fd0b3159
--- /dev/null
+++ b/src/glsl/glcpp/tests/048-if-nested.c.expected
@@ -0,0 +1,12 @@
+success_1
+
+
+
+
+
+
+
+
+
+success_2
+
diff --git a/src/glsl/glcpp/tests/049-if-expression-precedence.c b/src/glsl/glcpp/tests/049-if-expression-precedence.c
new file mode 100644
index 00000000000..833ea03882a
--- /dev/null
+++ b/src/glsl/glcpp/tests/049-if-expression-precedence.c
@@ -0,0 +1,5 @@
+#if 1 + 2 * 3 + - (25 % 17 - + 1)
+failure with operator precedence
+#else
+success
+#endif
diff --git a/src/glsl/glcpp/tests/049-if-expression-precedence.c.expected b/src/glsl/glcpp/tests/049-if-expression-precedence.c.expected
new file mode 100644
index 00000000000..569debb0bb6
--- /dev/null
+++ b/src/glsl/glcpp/tests/049-if-expression-precedence.c.expected
@@ -0,0 +1,6 @@
+
+
+
+success
+
+
diff --git a/src/glsl/glcpp/tests/050-if-defined.c b/src/glsl/glcpp/tests/050-if-defined.c
new file mode 100644
index 00000000000..34f0f95140e
--- /dev/null
+++ b/src/glsl/glcpp/tests/050-if-defined.c
@@ -0,0 +1,17 @@
+#if defined foo
+failure_1
+#else
+success_1
+#endif
+#define foo
+#if defined foo
+success_2
+#else
+failure_2
+#endif
+#undef foo
+#if defined foo
+failure_3
+#else
+success_3
+#endif
diff --git a/src/glsl/glcpp/tests/050-if-defined.c.expected b/src/glsl/glcpp/tests/050-if-defined.c.expected
new file mode 100644
index 00000000000..3f01955ee40
--- /dev/null
+++ b/src/glsl/glcpp/tests/050-if-defined.c.expected
@@ -0,0 +1,18 @@
+
+
+
+success_1
+
+
+
+success_2
+
+
+
+
+
+
+
+success_3
+
+
diff --git a/src/glsl/glcpp/tests/051-if-relational.c b/src/glsl/glcpp/tests/051-if-relational.c
new file mode 100644
index 00000000000..c3db488e0de
--- /dev/null
+++ b/src/glsl/glcpp/tests/051-if-relational.c
@@ -0,0 +1,35 @@
+#if 3 < 2
+failure_1
+#else
+success_1
+#endif
+
+#if 3 >= 2
+success_2
+#else
+failure_2
+#endif
+
+#if 2 + 3 <= 5
+success_3
+#else
+failure_3
+#endif
+
+#if 3 - 2 == 1
+success_3
+#else
+failure_3
+#endif
+
+#if 1 > 3
+failure_4
+#else
+success_4
+#endif
+
+#if 1 != 5
+success_5
+#else
+failure_5
+#endif
diff --git a/src/glsl/glcpp/tests/051-if-relational.c.expected b/src/glsl/glcpp/tests/051-if-relational.c.expected
new file mode 100644
index 00000000000..d2b76f14576
--- /dev/null
+++ b/src/glsl/glcpp/tests/051-if-relational.c.expected
@@ -0,0 +1,36 @@
+
+
+
+success_1
+
+
+
+success_2
+
+
+
+
+
+success_3
+
+
+
+
+
+success_3
+
+
+
+
+
+
+
+success_4
+
+
+
+success_5
+
+
+
+
diff --git a/src/glsl/glcpp/tests/052-if-bitwise.c b/src/glsl/glcpp/tests/052-if-bitwise.c
new file mode 100644
index 00000000000..2d8e45eb61e
--- /dev/null
+++ b/src/glsl/glcpp/tests/052-if-bitwise.c
@@ -0,0 +1,20 @@
+#if (0xaaaaaaaa | 0x55555555) != 4294967295
+failure_1
+#else
+success_1
+#endif
+#if (0x12345678 ^ 0xfdecba98) == 4023971040
+success_2
+#else
+failure_2
+#endif
+#if (~ 0xdeadbeef) != -3735928560
+failure_3
+#else
+success_3
+#endif
+#if (0667 & 0733) == 403
+success_4
+#else
+failure_4
+#endif
diff --git a/src/glsl/glcpp/tests/052-if-bitwise.c.expected b/src/glsl/glcpp/tests/052-if-bitwise.c.expected
new file mode 100644
index 00000000000..bb5d92e8d92
--- /dev/null
+++ b/src/glsl/glcpp/tests/052-if-bitwise.c.expected
@@ -0,0 +1,21 @@
+
+
+
+success_1
+
+
+success_2
+
+
+
+
+
+
+success_3
+
+
+success_4
+
+
+
+
diff --git a/src/glsl/glcpp/tests/053-if-divide-and-shift.c b/src/glsl/glcpp/tests/053-if-divide-and-shift.c
new file mode 100644
index 00000000000..d24c54a88d1
--- /dev/null
+++ b/src/glsl/glcpp/tests/053-if-divide-and-shift.c
@@ -0,0 +1,15 @@
+#if (15 / 2) != 7
+failure_1
+#else
+success_1
+#endif
+#if (1 << 12) == 4096
+success_2
+#else
+failure_2
+#endif
+#if (31762 >> 8) != 124
+failure_3
+#else
+success_3
+#endif
diff --git a/src/glsl/glcpp/tests/053-if-divide-and-shift.c.expected b/src/glsl/glcpp/tests/053-if-divide-and-shift.c.expected
new file mode 100644
index 00000000000..f97e93673cc
--- /dev/null
+++ b/src/glsl/glcpp/tests/053-if-divide-and-shift.c.expected
@@ -0,0 +1,16 @@
+
+
+
+success_1
+
+
+success_2
+
+
+
+
+
+
+success_3
+
+
diff --git a/src/glsl/glcpp/tests/054-if-with-macros.c b/src/glsl/glcpp/tests/054-if-with-macros.c
new file mode 100644
index 00000000000..3da79a0d96e
--- /dev/null
+++ b/src/glsl/glcpp/tests/054-if-with-macros.c
@@ -0,0 +1,34 @@
+#define one 1
+#define two 2
+#define three 3
+#define five 5
+#if five < two
+failure_1
+#else
+success_1
+#endif
+#if three >= two
+success_2
+#else
+failure_2
+#endif
+#if two + three <= five
+success_3
+#else
+failure_3
+#endif
+#if five - two == three
+success_4
+#else
+failure_4
+#endif
+#if one > three
+failure_5
+#else
+success_5
+#endif
+#if one != five
+success_6
+#else
+failure_6
+#endif
diff --git a/src/glsl/glcpp/tests/054-if-with-macros.c.expected b/src/glsl/glcpp/tests/054-if-with-macros.c.expected
new file mode 100644
index 00000000000..27ea4969628
--- /dev/null
+++ b/src/glsl/glcpp/tests/054-if-with-macros.c.expected
@@ -0,0 +1,35 @@
+
+
+
+
+
+
+
+success_1
+
+
+success_2
+
+
+
+
+success_3
+
+
+
+
+success_4
+
+
+
+
+
+
+success_5
+
+
+success_6
+
+
+
+
diff --git a/src/glsl/glcpp/tests/055-define-chain-obj-to-func-parens-in-text.c b/src/glsl/glcpp/tests/055-define-chain-obj-to-func-parens-in-text.c
new file mode 100644
index 00000000000..00f2c2346d6
--- /dev/null
+++ b/src/glsl/glcpp/tests/055-define-chain-obj-to-func-parens-in-text.c
@@ -0,0 +1,3 @@
+#define failure() success
+#define foo failure
+foo()
diff --git a/src/glsl/glcpp/tests/055-define-chain-obj-to-func-parens-in-text.c.expected b/src/glsl/glcpp/tests/055-define-chain-obj-to-func-parens-in-text.c.expected
new file mode 100644
index 00000000000..aef762e1e69
--- /dev/null
+++ b/src/glsl/glcpp/tests/055-define-chain-obj-to-func-parens-in-text.c.expected
@@ -0,0 +1,4 @@
+
+
+success
+
diff --git a/src/glsl/glcpp/tests/056-macro-argument-with-comma.c b/src/glsl/glcpp/tests/056-macro-argument-with-comma.c
new file mode 100644
index 00000000000..58701d1f25b
--- /dev/null
+++ b/src/glsl/glcpp/tests/056-macro-argument-with-comma.c
@@ -0,0 +1,4 @@
+#define bar with,embedded,commas
+#define function(x) success
+#define foo function
+foo(bar)
diff --git a/src/glsl/glcpp/tests/056-macro-argument-with-comma.c.expected b/src/glsl/glcpp/tests/056-macro-argument-with-comma.c.expected
new file mode 100644
index 00000000000..729bdd15f80
--- /dev/null
+++ b/src/glsl/glcpp/tests/056-macro-argument-with-comma.c.expected
@@ -0,0 +1,5 @@
+
+
+
+success
+
diff --git a/src/glsl/glcpp/tests/057-empty-arguments.c b/src/glsl/glcpp/tests/057-empty-arguments.c
new file mode 100644
index 00000000000..6140232865d
--- /dev/null
+++ b/src/glsl/glcpp/tests/057-empty-arguments.c
@@ -0,0 +1,6 @@
+#define zero() success
+zero()
+#define one(x) success
+one()
+#define two(x,y) success
+two(,)
diff --git a/src/glsl/glcpp/tests/057-empty-arguments.c.expected b/src/glsl/glcpp/tests/057-empty-arguments.c.expected
new file mode 100644
index 00000000000..4e3aad52173
--- /dev/null
+++ b/src/glsl/glcpp/tests/057-empty-arguments.c.expected
@@ -0,0 +1,7 @@
+
+success
+
+success
+
+success
+
diff --git a/src/glsl/glcpp/tests/058-token-pasting-empty-arguments.c b/src/glsl/glcpp/tests/058-token-pasting-empty-arguments.c
new file mode 100644
index 00000000000..8ac260c76b6
--- /dev/null
+++ b/src/glsl/glcpp/tests/058-token-pasting-empty-arguments.c
@@ -0,0 +1,5 @@
+#define paste(x,y) x ## y
+paste(a,b)
+paste(a,)
+paste(,b)
+paste(,)
diff --git a/src/glsl/glcpp/tests/058-token-pasting-empty-arguments.c.expected b/src/glsl/glcpp/tests/058-token-pasting-empty-arguments.c.expected
new file mode 100644
index 00000000000..a1c34e5c1f8
--- /dev/null
+++ b/src/glsl/glcpp/tests/058-token-pasting-empty-arguments.c.expected
@@ -0,0 +1,6 @@
+
+ab
+a
+b
+
+
diff --git a/src/glsl/glcpp/tests/059-token-pasting-integer.c b/src/glsl/glcpp/tests/059-token-pasting-integer.c
new file mode 100644
index 00000000000..37b895a4237
--- /dev/null
+++ b/src/glsl/glcpp/tests/059-token-pasting-integer.c
@@ -0,0 +1,4 @@
+#define paste(x,y) x ## y
+paste(1,2)
+paste(1,000)
+paste(identifier,2)
diff --git a/src/glsl/glcpp/tests/059-token-pasting-integer.c.expected b/src/glsl/glcpp/tests/059-token-pasting-integer.c.expected
new file mode 100644
index 00000000000..f1a2cd21c13
--- /dev/null
+++ b/src/glsl/glcpp/tests/059-token-pasting-integer.c.expected
@@ -0,0 +1,5 @@
+
+12
+1000
+identifier2
+
diff --git a/src/glsl/glcpp/tests/060-left-paren-in-macro-right-paren-in-text.c b/src/glsl/glcpp/tests/060-left-paren-in-macro-right-paren-in-text.c
new file mode 100644
index 00000000000..ed80ea879ce
--- /dev/null
+++ b/src/glsl/glcpp/tests/060-left-paren-in-macro-right-paren-in-text.c
@@ -0,0 +1,3 @@
+#define double(a) a*2
+#define foo double(
+foo 5)
diff --git a/src/glsl/glcpp/tests/060-left-paren-in-macro-right-paren-in-text.c.expected b/src/glsl/glcpp/tests/060-left-paren-in-macro-right-paren-in-text.c.expected
new file mode 100644
index 00000000000..c1f0d24a144
--- /dev/null
+++ b/src/glsl/glcpp/tests/060-left-paren-in-macro-right-paren-in-text.c.expected
@@ -0,0 +1,4 @@
+
+
+5*2
+
diff --git a/src/glsl/glcpp/tests/061-define-chain-obj-to-func-multi.c b/src/glsl/glcpp/tests/061-define-chain-obj-to-func-multi.c
new file mode 100644
index 00000000000..6dbfd1f62d1
--- /dev/null
+++ b/src/glsl/glcpp/tests/061-define-chain-obj-to-func-multi.c
@@ -0,0 +1,5 @@
+#define foo(x) success
+#define bar foo
+#define baz bar
+#define joe baz
+joe (failure)
diff --git a/src/glsl/glcpp/tests/061-define-chain-obj-to-func-multi.c.expected b/src/glsl/glcpp/tests/061-define-chain-obj-to-func-multi.c.expected
new file mode 100644
index 00000000000..111f7d10634
--- /dev/null
+++ b/src/glsl/glcpp/tests/061-define-chain-obj-to-func-multi.c.expected
@@ -0,0 +1,6 @@
+
+
+
+
+success
+
diff --git a/src/glsl/glcpp/tests/062-if-0-skips-garbage.c b/src/glsl/glcpp/tests/062-if-0-skips-garbage.c
new file mode 100644
index 00000000000..d9e439bb890
--- /dev/null
+++ b/src/glsl/glcpp/tests/062-if-0-skips-garbage.c
@@ -0,0 +1,5 @@
+#define foo(a,b)
+#if 0
+foo(bar)
+foo(
+#endif
diff --git a/src/glsl/glcpp/tests/062-if-0-skips-garbage.c.expected b/src/glsl/glcpp/tests/062-if-0-skips-garbage.c.expected
new file mode 100644
index 00000000000..6fb66a5e2f0
--- /dev/null
+++ b/src/glsl/glcpp/tests/062-if-0-skips-garbage.c.expected
@@ -0,0 +1,6 @@
+
+
+
+
+
+
diff --git a/src/glsl/glcpp/tests/063-comments.c b/src/glsl/glcpp/tests/063-comments.c
new file mode 100644
index 00000000000..e641d2f0f9e
--- /dev/null
+++ b/src/glsl/glcpp/tests/063-comments.c
@@ -0,0 +1,20 @@
+/* this is a comment */
+// so is this
+// */
+f = g/**//h;
+/*//*/l();
+m = n//**/o
++ p;
+/* this
+comment spans
+multiple lines and
+contains *** stars
+and slashes / *** /
+and other stuff.
+****/
+more code here
+/* Test that /* nested
+ comments */
+are not treated like comments.
+/*/ this is a comment */
+/*/*/
diff --git a/src/glsl/glcpp/tests/063-comments.c.expected b/src/glsl/glcpp/tests/063-comments.c.expected
new file mode 100644
index 00000000000..ed4feedd457
--- /dev/null
+++ b/src/glsl/glcpp/tests/063-comments.c.expected
@@ -0,0 +1,14 @@
+
+
+
+f = g /h;
+ l();
+m = n
++ p;
+
+more code here
+
+are not treated like comments.
+
+
+
diff --git a/src/glsl/glcpp/tests/064-version.c b/src/glsl/glcpp/tests/064-version.c
new file mode 100644
index 00000000000..21326481b87
--- /dev/null
+++ b/src/glsl/glcpp/tests/064-version.c
@@ -0,0 +1,2 @@
+#version 130
+#define FOO
diff --git a/src/glsl/glcpp/tests/064-version.c.expected b/src/glsl/glcpp/tests/064-version.c.expected
new file mode 100644
index 00000000000..1c534672705
--- /dev/null
+++ b/src/glsl/glcpp/tests/064-version.c.expected
@@ -0,0 +1,4 @@
+#version 130
+
+
+
diff --git a/src/glsl/glcpp/tests/065-if-defined-parens.c b/src/glsl/glcpp/tests/065-if-defined-parens.c
new file mode 100644
index 00000000000..48aa0f8c3ef
--- /dev/null
+++ b/src/glsl/glcpp/tests/065-if-defined-parens.c
@@ -0,0 +1,17 @@
+#if defined(foo)
+failure_1
+#else
+success_1
+#endif
+#define foo
+#if defined ( foo )
+success_2
+#else
+failure_2
+#endif
+#undef foo
+#if defined (foo)
+failure_3
+#else
+success_3
+#endif
diff --git a/src/glsl/glcpp/tests/065-if-defined-parens.c.expected b/src/glsl/glcpp/tests/065-if-defined-parens.c.expected
new file mode 100644
index 00000000000..3f01955ee40
--- /dev/null
+++ b/src/glsl/glcpp/tests/065-if-defined-parens.c.expected
@@ -0,0 +1,18 @@
+
+
+
+success_1
+
+
+
+success_2
+
+
+
+
+
+
+
+success_3
+
+
diff --git a/src/glsl/glcpp/tests/066-if-nospace-expression.c b/src/glsl/glcpp/tests/066-if-nospace-expression.c
new file mode 100644
index 00000000000..3b0b47349d0
--- /dev/null
+++ b/src/glsl/glcpp/tests/066-if-nospace-expression.c
@@ -0,0 +1,3 @@
+#if(1)
+success
+#endif
diff --git a/src/glsl/glcpp/tests/066-if-nospace-expression.c.expected b/src/glsl/glcpp/tests/066-if-nospace-expression.c.expected
new file mode 100644
index 00000000000..0e84a7cda39
--- /dev/null
+++ b/src/glsl/glcpp/tests/066-if-nospace-expression.c.expected
@@ -0,0 +1,4 @@
+
+success
+
+
diff --git a/src/glsl/glcpp/tests/067-nested-ifdef-ifndef.c b/src/glsl/glcpp/tests/067-nested-ifdef-ifndef.c
new file mode 100644
index 00000000000..f46cce4e60a
--- /dev/null
+++ b/src/glsl/glcpp/tests/067-nested-ifdef-ifndef.c
@@ -0,0 +1,40 @@
+#define D1
+#define D2
+
+#define result success
+
+#ifdef U1
+#ifdef U2
+#undef result
+#define result failure
+#endif
+#endif
+result
+
+#ifndef D1
+#ifndef D2
+#undef result
+#define result failure
+#endif
+#endif
+result
+
+#undef result
+#define result failure
+#ifdef D1
+#ifdef D2
+#undef result
+#define result success
+#endif
+#endif
+result
+
+#undef result
+#define result failure
+#ifndef U1
+#ifndef U2
+#undef result
+#define result success
+#endif
+#endif
+result
diff --git a/src/glsl/glcpp/tests/067-nested-ifdef-ifndef.c.expected b/src/glsl/glcpp/tests/067-nested-ifdef-ifndef.c.expected
new file mode 100644
index 00000000000..3340daaa1f9
--- /dev/null
+++ b/src/glsl/glcpp/tests/067-nested-ifdef-ifndef.c.expected
@@ -0,0 +1,41 @@
+
+
+
+
+
+
+
+
+
+
+
+success
+
+
+
+
+
+
+
+success
+
+
+
+
+
+
+
+
+
+success
+
+
+
+
+
+
+
+
+
+success
+
diff --git a/src/glsl/glcpp/tests/068-accidental-pasting.c b/src/glsl/glcpp/tests/068-accidental-pasting.c
new file mode 100644
index 00000000000..699ac5144e5
--- /dev/null
+++ b/src/glsl/glcpp/tests/068-accidental-pasting.c
@@ -0,0 +1,11 @@
+#define empty
+<empty<
+<empty=
+>empty>
+>empty=
+=empty=
+!empty=
+&empty&
+|empty|
++empty+
+-empty-
diff --git a/src/glsl/glcpp/tests/068-accidental-pasting.c.expected b/src/glsl/glcpp/tests/068-accidental-pasting.c.expected
new file mode 100644
index 00000000000..ce41cd6e524
--- /dev/null
+++ b/src/glsl/glcpp/tests/068-accidental-pasting.c.expected
@@ -0,0 +1,12 @@
+
+< <
+< =
+> >
+> =
+= =
+! =
+& &
+| |
++ +
+- -
+
diff --git a/src/glsl/glcpp/tests/069-repeated-argument.c b/src/glsl/glcpp/tests/069-repeated-argument.c
new file mode 100644
index 00000000000..2b46ead294c
--- /dev/null
+++ b/src/glsl/glcpp/tests/069-repeated-argument.c
@@ -0,0 +1,2 @@
+#define double(x) x x
+double(1)
diff --git a/src/glsl/glcpp/tests/069-repeated-argument.c.expected b/src/glsl/glcpp/tests/069-repeated-argument.c.expected
new file mode 100644
index 00000000000..755c4d4b56c
--- /dev/null
+++ b/src/glsl/glcpp/tests/069-repeated-argument.c.expected
@@ -0,0 +1,3 @@
+
+1 1
+
diff --git a/src/glsl/glcpp/tests/070-undefined-macro-in-expression.c b/src/glsl/glcpp/tests/070-undefined-macro-in-expression.c
new file mode 100644
index 00000000000..b6dc2ba075f
--- /dev/null
+++ b/src/glsl/glcpp/tests/070-undefined-macro-in-expression.c
@@ -0,0 +1,2 @@
+#if UNDEFINED_MACRO
+#endif
diff --git a/src/glsl/glcpp/tests/070-undefined-macro-in-expression.c.expected b/src/glsl/glcpp/tests/070-undefined-macro-in-expression.c.expected
new file mode 100644
index 00000000000..2bb38a1411e
--- /dev/null
+++ b/src/glsl/glcpp/tests/070-undefined-macro-in-expression.c.expected
@@ -0,0 +1,2 @@
+0:1(21): preprocessor error: syntax error, unexpected IDENTIFIER
+
diff --git a/src/glsl/glcpp/tests/071-punctuator.c b/src/glsl/glcpp/tests/071-punctuator.c
new file mode 100644
index 00000000000..959d6825988
--- /dev/null
+++ b/src/glsl/glcpp/tests/071-punctuator.c
@@ -0,0 +1 @@
+a = b
diff --git a/src/glsl/glcpp/tests/071-punctuator.c.expected b/src/glsl/glcpp/tests/071-punctuator.c.expected
new file mode 100644
index 00000000000..fee253b7452
--- /dev/null
+++ b/src/glsl/glcpp/tests/071-punctuator.c.expected
@@ -0,0 +1,2 @@
+a = b
+
diff --git a/src/glsl/glcpp/tests/072-token-pasting-same-line.c b/src/glsl/glcpp/tests/072-token-pasting-same-line.c
new file mode 100644
index 00000000000..e421e9d5e29
--- /dev/null
+++ b/src/glsl/glcpp/tests/072-token-pasting-same-line.c
@@ -0,0 +1,2 @@
+#define paste(x) success_ ## x
+paste(1) paste(2) paste(3)
diff --git a/src/glsl/glcpp/tests/072-token-pasting-same-line.c.expected b/src/glsl/glcpp/tests/072-token-pasting-same-line.c.expected
new file mode 100644
index 00000000000..c780b43d70f
--- /dev/null
+++ b/src/glsl/glcpp/tests/072-token-pasting-same-line.c.expected
@@ -0,0 +1,3 @@
+
+success_1 success_2 success_3
+
diff --git a/src/glsl/glcpp/tests/073-if-in-ifdef.c b/src/glsl/glcpp/tests/073-if-in-ifdef.c
new file mode 100644
index 00000000000..61a48097ca3
--- /dev/null
+++ b/src/glsl/glcpp/tests/073-if-in-ifdef.c
@@ -0,0 +1,4 @@
+#ifdef UNDEF
+#if UNDEF > 1
+#endif
+#endif
diff --git a/src/glsl/glcpp/tests/073-if-in-ifdef.c.expected b/src/glsl/glcpp/tests/073-if-in-ifdef.c.expected
new file mode 100644
index 00000000000..3f2ff2d6cc8
--- /dev/null
+++ b/src/glsl/glcpp/tests/073-if-in-ifdef.c.expected
@@ -0,0 +1,5 @@
+
+
+
+
+
diff --git a/src/glsl/glcpp/tests/074-elif-undef.c b/src/glsl/glcpp/tests/074-elif-undef.c
new file mode 100644
index 00000000000..67aac8977e0
--- /dev/null
+++ b/src/glsl/glcpp/tests/074-elif-undef.c
@@ -0,0 +1,3 @@
+#ifndef UNDEF
+#elif UNDEF < 0
+#endif
diff --git a/src/glsl/glcpp/tests/074-elif-undef.c.expected b/src/glsl/glcpp/tests/074-elif-undef.c.expected
new file mode 100644
index 00000000000..fd40910d9e7
--- /dev/null
+++ b/src/glsl/glcpp/tests/074-elif-undef.c.expected
@@ -0,0 +1,4 @@
+
+
+
+
diff --git a/src/glsl/glcpp/tests/075-elif-elif-undef.c b/src/glsl/glcpp/tests/075-elif-elif-undef.c
new file mode 100644
index 00000000000..264bc4f10ee
--- /dev/null
+++ b/src/glsl/glcpp/tests/075-elif-elif-undef.c
@@ -0,0 +1,4 @@
+#ifndef UNDEF
+#elif UNDEF < 0
+#elif UNDEF == 3
+#endif
diff --git a/src/glsl/glcpp/tests/075-elif-elif-undef.c.expected b/src/glsl/glcpp/tests/075-elif-elif-undef.c.expected
new file mode 100644
index 00000000000..3f2ff2d6cc8
--- /dev/null
+++ b/src/glsl/glcpp/tests/075-elif-elif-undef.c.expected
@@ -0,0 +1,5 @@
+
+
+
+
+
diff --git a/src/glsl/glcpp/tests/076-elif-undef-nested.c b/src/glsl/glcpp/tests/076-elif-undef-nested.c
new file mode 100644
index 00000000000..ebd550ed005
--- /dev/null
+++ b/src/glsl/glcpp/tests/076-elif-undef-nested.c
@@ -0,0 +1,5 @@
+#ifdef UNDEF
+#if UNDEF == 4
+#elif UNDEF == 5
+#endif
+#endif
diff --git a/src/glsl/glcpp/tests/076-elif-undef-nested.c.expected b/src/glsl/glcpp/tests/076-elif-undef-nested.c.expected
new file mode 100644
index 00000000000..6fb66a5e2f0
--- /dev/null
+++ b/src/glsl/glcpp/tests/076-elif-undef-nested.c.expected
@@ -0,0 +1,6 @@
+
+
+
+
+
+
diff --git a/src/glsl/glcpp/tests/077-else-without-if.c b/src/glsl/glcpp/tests/077-else-without-if.c
new file mode 100644
index 00000000000..81f00bfe278
--- /dev/null
+++ b/src/glsl/glcpp/tests/077-else-without-if.c
@@ -0,0 +1 @@
+#else
diff --git a/src/glsl/glcpp/tests/077-else-without-if.c.expected b/src/glsl/glcpp/tests/077-else-without-if.c.expected
new file mode 100644
index 00000000000..d289b363562
--- /dev/null
+++ b/src/glsl/glcpp/tests/077-else-without-if.c.expected
@@ -0,0 +1,4 @@
+0:1(2): preprocessor error: else without #if
+
+
+
diff --git a/src/glsl/glcpp/tests/078-elif-without-if.c b/src/glsl/glcpp/tests/078-elif-without-if.c
new file mode 100644
index 00000000000..60466b3890a
--- /dev/null
+++ b/src/glsl/glcpp/tests/078-elif-without-if.c
@@ -0,0 +1 @@
+#elif defined FOO
diff --git a/src/glsl/glcpp/tests/078-elif-without-if.c.expected b/src/glsl/glcpp/tests/078-elif-without-if.c.expected
new file mode 100644
index 00000000000..7d41f0ac794
--- /dev/null
+++ b/src/glsl/glcpp/tests/078-elif-without-if.c.expected
@@ -0,0 +1,4 @@
+0:1(2): preprocessor error: elif without #if
+
+
+
diff --git a/src/glsl/glcpp/tests/079-endif-without-if.c b/src/glsl/glcpp/tests/079-endif-without-if.c
new file mode 100644
index 00000000000..69331c3ca9d
--- /dev/null
+++ b/src/glsl/glcpp/tests/079-endif-without-if.c
@@ -0,0 +1 @@
+#endif
diff --git a/src/glsl/glcpp/tests/079-endif-without-if.c.expected b/src/glsl/glcpp/tests/079-endif-without-if.c.expected
new file mode 100644
index 00000000000..08dd33546f2
--- /dev/null
+++ b/src/glsl/glcpp/tests/079-endif-without-if.c.expected
@@ -0,0 +1,4 @@
+0:1(2): preprocessor error: #endif without #if
+
+
+
diff --git a/src/glsl/glcpp/tests/080-if-without-expression.c b/src/glsl/glcpp/tests/080-if-without-expression.c
new file mode 100644
index 00000000000..a27ba36a366
--- /dev/null
+++ b/src/glsl/glcpp/tests/080-if-without-expression.c
@@ -0,0 +1,4 @@
+/* Error message for unskipped #if with no expression. */
+#if
+#endif
+
diff --git a/src/glsl/glcpp/tests/080-if-without-expression.c.expected b/src/glsl/glcpp/tests/080-if-without-expression.c.expected
new file mode 100644
index 00000000000..768ba0f473f
--- /dev/null
+++ b/src/glsl/glcpp/tests/080-if-without-expression.c.expected
@@ -0,0 +1,6 @@
+0:2(1): preprocessor error: #if with no expression
+
+
+
+
+
diff --git a/src/glsl/glcpp/tests/081-elif-without-expression.c b/src/glsl/glcpp/tests/081-elif-without-expression.c
new file mode 100644
index 00000000000..79c78663dd3
--- /dev/null
+++ b/src/glsl/glcpp/tests/081-elif-without-expression.c
@@ -0,0 +1,3 @@
+#if 0
+#elif
+#endif
diff --git a/src/glsl/glcpp/tests/081-elif-without-expression.c.expected b/src/glsl/glcpp/tests/081-elif-without-expression.c.expected
new file mode 100644
index 00000000000..974f0f550eb
--- /dev/null
+++ b/src/glsl/glcpp/tests/081-elif-without-expression.c.expected
@@ -0,0 +1,5 @@
+0:2(1): preprocessor error: #elif with no expression
+
+
+
+
diff --git a/src/glsl/glcpp/tests/082-invalid-paste.c b/src/glsl/glcpp/tests/082-invalid-paste.c
new file mode 100644
index 00000000000..40bf64411c5
--- /dev/null
+++ b/src/glsl/glcpp/tests/082-invalid-paste.c
@@ -0,0 +1,2 @@
+#define PASTE(x,y) x ## y
+PASTE(<,>)
diff --git a/src/glsl/glcpp/tests/082-invalid-paste.c.expected b/src/glsl/glcpp/tests/082-invalid-paste.c.expected
new file mode 100644
index 00000000000..2c924406b59
--- /dev/null
+++ b/src/glsl/glcpp/tests/082-invalid-paste.c.expected
@@ -0,0 +1,5 @@
+0:2(7): preprocessor error:
+Pasting "<" and ">" does not give a valid preprocessing token.
+
+<
+
diff --git a/src/glsl/glcpp/tests/083-unterminated-if.c b/src/glsl/glcpp/tests/083-unterminated-if.c
new file mode 100644
index 00000000000..91806350927
--- /dev/null
+++ b/src/glsl/glcpp/tests/083-unterminated-if.c
@@ -0,0 +1,2 @@
+#if 1
+
diff --git a/src/glsl/glcpp/tests/083-unterminated-if.c.expected b/src/glsl/glcpp/tests/083-unterminated-if.c.expected
new file mode 100644
index 00000000000..a69f8bab582
--- /dev/null
+++ b/src/glsl/glcpp/tests/083-unterminated-if.c.expected
@@ -0,0 +1,5 @@
+0:1(7): preprocessor error: Unterminated #if
+
+
+
+
diff --git a/src/glsl/glcpp/tests/084-unbalanced-parentheses.c b/src/glsl/glcpp/tests/084-unbalanced-parentheses.c
new file mode 100644
index 00000000000..0789ba5e525
--- /dev/null
+++ b/src/glsl/glcpp/tests/084-unbalanced-parentheses.c
@@ -0,0 +1,2 @@
+#define FUNC(x) (2*(x))
+FUNC(23
diff --git a/src/glsl/glcpp/tests/085-incorrect-argument-count.c b/src/glsl/glcpp/tests/085-incorrect-argument-count.c
new file mode 100644
index 00000000000..91bea600612
--- /dev/null
+++ b/src/glsl/glcpp/tests/085-incorrect-argument-count.c
@@ -0,0 +1,5 @@
+#define MULT(x,y) ((x)*(y))
+MULT()
+MULT(1)
+MULT(1,2,3)
+
diff --git a/src/glsl/glcpp/tests/085-incorrect-argument-count.c.expected b/src/glsl/glcpp/tests/085-incorrect-argument-count.c.expected
new file mode 100644
index 00000000000..1df30cbb56f
--- /dev/null
+++ b/src/glsl/glcpp/tests/085-incorrect-argument-count.c.expected
@@ -0,0 +1,12 @@
+0:2(1): preprocessor error: Error: macro MULT invoked with 1 arguments (expected 2)
+
+0:3(1): preprocessor error: Error: macro MULT invoked with 1 arguments (expected 2)
+
+0:4(1): preprocessor error: Error: macro MULT invoked with 3 arguments (expected 2)
+
+
+MULT()
+MULT(1)
+MULT(1,2,3)
+
+
diff --git a/src/glsl/glcpp/tests/086-reserved-macro-names.c b/src/glsl/glcpp/tests/086-reserved-macro-names.c
new file mode 100644
index 00000000000..fd0c29f0c47
--- /dev/null
+++ b/src/glsl/glcpp/tests/086-reserved-macro-names.c
@@ -0,0 +1,2 @@
+#define __BAD reserved
+#define GL_ALSO_BAD() also reserved
diff --git a/src/glsl/glcpp/tests/086-reserved-macro-names.c.expected b/src/glsl/glcpp/tests/086-reserved-macro-names.c.expected
new file mode 100644
index 00000000000..6a9df682685
--- /dev/null
+++ b/src/glsl/glcpp/tests/086-reserved-macro-names.c.expected
@@ -0,0 +1,7 @@
+0:1(10): preprocessor error: Macro names starting with "__" are reserved.
+
+0:2(9): preprocessor error: Macro names starting with "GL_" are reserved.
+
+
+
+
diff --git a/src/glsl/glcpp/tests/099-c99-example.c b/src/glsl/glcpp/tests/099-c99-example.c
new file mode 100644
index 00000000000..d1976b1f265
--- /dev/null
+++ b/src/glsl/glcpp/tests/099-c99-example.c
@@ -0,0 +1,17 @@
+#define x 3
+#define f(a) f(x * (a))
+#undef x
+#define x 2
+#define g f
+#define z z[0]
+#define h g(~
+#define m(a) a(w)
+#define w 0,1
+#define t(a) a
+#define p() int
+#define q(x) x
+#define r(x,y) x ## y
+f(y+1) + f(f(z)) % t(t(g)(0) + t)(1);
+g(x +(3,4)-w) | h 5) & m
+ (f)^m(m);
+p() i[q()] = { q(1), r(2,3), r(4,), r(,5), r(,)};
diff --git a/src/glsl/glcpp/tests/099-c99-example.c.expected b/src/glsl/glcpp/tests/099-c99-example.c.expected
new file mode 100644
index 00000000000..19be7505552
--- /dev/null
+++ b/src/glsl/glcpp/tests/099-c99-example.c.expected
@@ -0,0 +1,17 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+f(2 * (y+1)) + f(2 * (f(2 * (z[0])))) % f(2 * (0)) + t(1);
+f(2 * (2 +(3,4)-0,1)) | f(2 * (~ 5)) & f(2 * (0,1))^m(0,1);
+int i[] = { 1, 23, 4, 5, };
+
diff --git a/src/glsl/glcpp/tests/glcpp-test b/src/glsl/glcpp/tests/glcpp-test
new file mode 100755
index 00000000000..6494d0c0e77
--- /dev/null
+++ b/src/glsl/glcpp/tests/glcpp-test
@@ -0,0 +1,49 @@
+#!/bin/sh
+
+trap 'rm $test.valgrind-errors; exit 1' INT QUIT
+
+total=0
+pass=0
+clean=0
+
+echo "====== Testing for correctness ======"
+for test in *.c; do
+ echo -n "Testing $test..."
+ ../glcpp < $test > $test.out 2>&1
+ total=$((total+1))
+ if cmp $test.expected $test.out >/dev/null 2>&1; then
+ echo "PASS"
+ pass=$((pass+1))
+ else
+ echo "FAIL"
+ diff -u $test.expected $test.out
+ fi
+done
+
+echo ""
+echo "$pass/$total tests returned correct results"
+echo ""
+
+echo "====== Testing for valgrind cleanliness ======"
+for test in *.c; do
+ echo -n "Testing $test with valgrind..."
+ if valgrind --error-exitcode=1 --log-file=$test.valgrind-errors ../glcpp < $test >/dev/null; then
+ echo "CLEAN"
+ clean=$((clean+1))
+ rm $test.valgrind-errors
+ else
+ echo "ERRORS"
+ cat $test.valgrind-errors
+ fi
+done
+
+echo ""
+echo "$pass/$total tests returned correct results"
+echo "$clean/$total tests are valgrind-clean"
+
+if [ "$pass" = "$total" ] && [ "$clean" = "$total" ]; then
+ exit 0
+else
+ exit 1
+fi
+
diff --git a/src/glsl/glsl_lexer.cpp b/src/glsl/glsl_lexer.cpp
new file mode 100644
index 00000000000..3cdce995e28
--- /dev/null
+++ b/src/glsl/glsl_lexer.cpp
@@ -0,0 +1,3416 @@
+#line 2 "glsl_lexer.cpp"
+
+#line 4 "glsl_lexer.cpp"
+
+#define YY_INT_ALIGNED short int
+
+/* A lexical scanner generated by flex */
+
+#define FLEX_SCANNER
+#define YY_FLEX_MAJOR_VERSION 2
+#define YY_FLEX_MINOR_VERSION 5
+#define YY_FLEX_SUBMINOR_VERSION 35
+#if YY_FLEX_SUBMINOR_VERSION > 0
+#define FLEX_BETA
+#endif
+
+/* First, we deal with platform-specific or compiler-specific issues. */
+
+/* begin standard C headers. */
+#include <stdio.h>
+#include <string.h>
+#include <errno.h>
+#include <stdlib.h>
+
+/* end standard C headers. */
+
+/* flex integer type definitions */
+
+#ifndef FLEXINT_H
+#define FLEXINT_H
+
+/* C99 systems have <inttypes.h>. Non-C99 systems may or may not. */
+
+#if defined (__STDC_VERSION__) && __STDC_VERSION__ >= 199901L
+
+/* C99 says to define __STDC_LIMIT_MACROS before including stdint.h,
+ * if you want the limit (max/min) macros for int types.
+ */
+#ifndef __STDC_LIMIT_MACROS
+#define __STDC_LIMIT_MACROS 1
+#endif
+
+#include <inttypes.h>
+typedef int8_t flex_int8_t;
+typedef uint8_t flex_uint8_t;
+typedef int16_t flex_int16_t;
+typedef uint16_t flex_uint16_t;
+typedef int32_t flex_int32_t;
+typedef uint32_t flex_uint32_t;
+#else
+typedef signed char flex_int8_t;
+typedef short int flex_int16_t;
+typedef int flex_int32_t;
+typedef unsigned char flex_uint8_t;
+typedef unsigned short int flex_uint16_t;
+typedef unsigned int flex_uint32_t;
+
+/* Limits of integral types. */
+#ifndef INT8_MIN
+#define INT8_MIN (-128)
+#endif
+#ifndef INT16_MIN
+#define INT16_MIN (-32767-1)
+#endif
+#ifndef INT32_MIN
+#define INT32_MIN (-2147483647-1)
+#endif
+#ifndef INT8_MAX
+#define INT8_MAX (127)
+#endif
+#ifndef INT16_MAX
+#define INT16_MAX (32767)
+#endif
+#ifndef INT32_MAX
+#define INT32_MAX (2147483647)
+#endif
+#ifndef UINT8_MAX
+#define UINT8_MAX (255U)
+#endif
+#ifndef UINT16_MAX
+#define UINT16_MAX (65535U)
+#endif
+#ifndef UINT32_MAX
+#define UINT32_MAX (4294967295U)
+#endif
+
+#endif /* ! C99 */
+
+#endif /* ! FLEXINT_H */
+
+#ifdef __cplusplus
+
+/* The "const" storage-class-modifier is valid. */
+#define YY_USE_CONST
+
+#else /* ! __cplusplus */
+
+/* C99 requires __STDC__ to be defined as 1. */
+#if defined (__STDC__)
+
+#define YY_USE_CONST
+
+#endif /* defined (__STDC__) */
+#endif /* ! __cplusplus */
+
+#ifdef YY_USE_CONST
+#define yyconst const
+#else
+#define yyconst
+#endif
+
+/* Returned upon end-of-file. */
+#define YY_NULL 0
+
+/* Promotes a possibly negative, possibly signed char to an unsigned
+ * integer for use as an array index. If the signed char is negative,
+ * we want to instead treat it as an 8-bit unsigned char, hence the
+ * double cast.
+ */
+#define YY_SC_TO_UI(c) ((unsigned int) (unsigned char) c)
+
+/* An opaque pointer. */
+#ifndef YY_TYPEDEF_YY_SCANNER_T
+#define YY_TYPEDEF_YY_SCANNER_T
+typedef void* yyscan_t;
+#endif
+
+/* For convenience, these vars (plus the bison vars far below)
+ are macros in the reentrant scanner. */
+#define yyin yyg->yyin_r
+#define yyout yyg->yyout_r
+#define yyextra yyg->yyextra_r
+#define yyleng yyg->yyleng_r
+#define yytext yyg->yytext_r
+#define yylineno (YY_CURRENT_BUFFER_LVALUE->yy_bs_lineno)
+#define yycolumn (YY_CURRENT_BUFFER_LVALUE->yy_bs_column)
+#define yy_flex_debug yyg->yy_flex_debug_r
+
+/* Enter a start condition. This macro really ought to take a parameter,
+ * but we do it the disgusting crufty way forced on us by the ()-less
+ * definition of BEGIN.
+ */
+#define BEGIN yyg->yy_start = 1 + 2 *
+
+/* Translate the current start state into a value that can be later handed
+ * to BEGIN to return to the state. The YYSTATE alias is for lex
+ * compatibility.
+ */
+#define YY_START ((yyg->yy_start - 1) / 2)
+#define YYSTATE YY_START
+
+/* Action number for EOF rule of a given start state. */
+#define YY_STATE_EOF(state) (YY_END_OF_BUFFER + state + 1)
+
+/* Special action meaning "start processing a new file". */
+#define YY_NEW_FILE _mesa_glsl_restart(yyin ,yyscanner )
+
+#define YY_END_OF_BUFFER_CHAR 0
+
+/* Size of default input buffer. */
+#ifndef YY_BUF_SIZE
+#ifdef __ia64__
+/* On IA-64, the buffer size is 16k, not 8k.
+ * Moreover, YY_BUF_SIZE is 2*YY_READ_BUF_SIZE in the general case.
+ * Ditto for the __ia64__ case accordingly.
+ */
+#define YY_BUF_SIZE 32768
+#else
+#define YY_BUF_SIZE 16384
+#endif /* __ia64__ */
+#endif
+
+/* The state buf must be large enough to hold one state per character in the main buffer.
+ */
+#define YY_STATE_BUF_SIZE ((YY_BUF_SIZE + 2) * sizeof(yy_state_type))
+
+#ifndef YY_TYPEDEF_YY_BUFFER_STATE
+#define YY_TYPEDEF_YY_BUFFER_STATE
+typedef struct yy_buffer_state *YY_BUFFER_STATE;
+#endif
+
+#define EOB_ACT_CONTINUE_SCAN 0
+#define EOB_ACT_END_OF_FILE 1
+#define EOB_ACT_LAST_MATCH 2
+
+ #define YY_LESS_LINENO(n)
+
+/* Return all but the first "n" matched characters back to the input stream. */
+#define yyless(n) \
+ do \
+ { \
+ /* Undo effects of setting up yytext. */ \
+ int yyless_macro_arg = (n); \
+ YY_LESS_LINENO(yyless_macro_arg);\
+ *yy_cp = yyg->yy_hold_char; \
+ YY_RESTORE_YY_MORE_OFFSET \
+ yyg->yy_c_buf_p = yy_cp = yy_bp + yyless_macro_arg - YY_MORE_ADJ; \
+ YY_DO_BEFORE_ACTION; /* set up yytext again */ \
+ } \
+ while ( 0 )
+
+#define unput(c) yyunput( c, yyg->yytext_ptr , yyscanner )
+
+#ifndef YY_TYPEDEF_YY_SIZE_T
+#define YY_TYPEDEF_YY_SIZE_T
+typedef size_t yy_size_t;
+#endif
+
+#ifndef YY_STRUCT_YY_BUFFER_STATE
+#define YY_STRUCT_YY_BUFFER_STATE
+struct yy_buffer_state
+ {
+ FILE *yy_input_file;
+
+ char *yy_ch_buf; /* input buffer */
+ char *yy_buf_pos; /* current position in input buffer */
+
+ /* Size of input buffer in bytes, not including room for EOB
+ * characters.
+ */
+ yy_size_t yy_buf_size;
+
+ /* Number of characters read into yy_ch_buf, not including EOB
+ * characters.
+ */
+ int yy_n_chars;
+
+ /* Whether we "own" the buffer - i.e., we know we created it,
+ * and can realloc() it to grow it, and should free() it to
+ * delete it.
+ */
+ int yy_is_our_buffer;
+
+ /* Whether this is an "interactive" input source; if so, and
+ * if we're using stdio for input, then we want to use getc()
+ * instead of fread(), to make sure we stop fetching input after
+ * each newline.
+ */
+ int yy_is_interactive;
+
+ /* Whether we're considered to be at the beginning of a line.
+ * If so, '^' rules will be active on the next match, otherwise
+ * not.
+ */
+ int yy_at_bol;
+
+ int yy_bs_lineno; /**< The line count. */
+ int yy_bs_column; /**< The column count. */
+
+ /* Whether to try to fill the input buffer when we reach the
+ * end of it.
+ */
+ int yy_fill_buffer;
+
+ int yy_buffer_status;
+
+#define YY_BUFFER_NEW 0
+#define YY_BUFFER_NORMAL 1
+ /* When an EOF's been seen but there's still some text to process
+ * then we mark the buffer as YY_EOF_PENDING, to indicate that we
+ * shouldn't try reading from the input source any more. We might
+ * still have a bunch of tokens to match, though, because of
+ * possible backing-up.
+ *
+ * When we actually see the EOF, we change the status to "new"
+ * (via _mesa_glsl_restart()), so that the user can continue scanning by
+ * just pointing yyin at a new input file.
+ */
+#define YY_BUFFER_EOF_PENDING 2
+
+ };
+#endif /* !YY_STRUCT_YY_BUFFER_STATE */
+
+/* We provide macros for accessing buffer states in case in the
+ * future we want to put the buffer states in a more general
+ * "scanner state".
+ *
+ * Returns the top of the stack, or NULL.
+ */
+#define YY_CURRENT_BUFFER ( yyg->yy_buffer_stack \
+ ? yyg->yy_buffer_stack[yyg->yy_buffer_stack_top] \
+ : NULL)
+
+/* Same as previous macro, but useful when we know that the buffer stack is not
+ * NULL or when we need an lvalue. For internal use only.
+ */
+#define YY_CURRENT_BUFFER_LVALUE yyg->yy_buffer_stack[yyg->yy_buffer_stack_top]
+
+void _mesa_glsl_restart (FILE *input_file ,yyscan_t yyscanner );
+void _mesa_glsl__switch_to_buffer (YY_BUFFER_STATE new_buffer ,yyscan_t yyscanner );
+YY_BUFFER_STATE _mesa_glsl__create_buffer (FILE *file,int size ,yyscan_t yyscanner );
+void _mesa_glsl__delete_buffer (YY_BUFFER_STATE b ,yyscan_t yyscanner );
+void _mesa_glsl__flush_buffer (YY_BUFFER_STATE b ,yyscan_t yyscanner );
+void _mesa_glsl_push_buffer_state (YY_BUFFER_STATE new_buffer ,yyscan_t yyscanner );
+void _mesa_glsl_pop_buffer_state (yyscan_t yyscanner );
+
+static void _mesa_glsl_ensure_buffer_stack (yyscan_t yyscanner );
+static void _mesa_glsl__load_buffer_state (yyscan_t yyscanner );
+static void _mesa_glsl__init_buffer (YY_BUFFER_STATE b,FILE *file ,yyscan_t yyscanner );
+
+#define YY_FLUSH_BUFFER _mesa_glsl__flush_buffer(YY_CURRENT_BUFFER ,yyscanner)
+
+YY_BUFFER_STATE _mesa_glsl__scan_buffer (char *base,yy_size_t size ,yyscan_t yyscanner );
+YY_BUFFER_STATE _mesa_glsl__scan_string (yyconst char *yy_str ,yyscan_t yyscanner );
+YY_BUFFER_STATE _mesa_glsl__scan_bytes (yyconst char *bytes,int len ,yyscan_t yyscanner );
+
+void *_mesa_glsl_alloc (yy_size_t ,yyscan_t yyscanner );
+void *_mesa_glsl_realloc (void *,yy_size_t ,yyscan_t yyscanner );
+void _mesa_glsl_free (void * ,yyscan_t yyscanner );
+
+#define yy_new_buffer _mesa_glsl__create_buffer
+
+#define yy_set_interactive(is_interactive) \
+ { \
+ if ( ! YY_CURRENT_BUFFER ){ \
+ _mesa_glsl_ensure_buffer_stack (yyscanner); \
+ YY_CURRENT_BUFFER_LVALUE = \
+ _mesa_glsl__create_buffer(yyin,YY_BUF_SIZE ,yyscanner); \
+ } \
+ YY_CURRENT_BUFFER_LVALUE->yy_is_interactive = is_interactive; \
+ }
+
+#define yy_set_bol(at_bol) \
+ { \
+ if ( ! YY_CURRENT_BUFFER ){\
+ _mesa_glsl_ensure_buffer_stack (yyscanner); \
+ YY_CURRENT_BUFFER_LVALUE = \
+ _mesa_glsl__create_buffer(yyin,YY_BUF_SIZE ,yyscanner); \
+ } \
+ YY_CURRENT_BUFFER_LVALUE->yy_at_bol = at_bol; \
+ }
+
+#define YY_AT_BOL() (YY_CURRENT_BUFFER_LVALUE->yy_at_bol)
+
+/* Begin user sect3 */
+
+#define _mesa_glsl_wrap(n) 1
+#define YY_SKIP_YYWRAP
+
+typedef unsigned char YY_CHAR;
+
+typedef int yy_state_type;
+
+#define yytext_ptr yytext_r
+
+static yy_state_type yy_get_previous_state (yyscan_t yyscanner );
+static yy_state_type yy_try_NUL_trans (yy_state_type current_state ,yyscan_t yyscanner);
+static int yy_get_next_buffer (yyscan_t yyscanner );
+static void yy_fatal_error (yyconst char msg[] ,yyscan_t yyscanner );
+
+/* Done after the current pattern has been matched and before the
+ * corresponding action - sets up yytext.
+ */
+#define YY_DO_BEFORE_ACTION \
+ yyg->yytext_ptr = yy_bp; \
+ yyleng = (size_t) (yy_cp - yy_bp); \
+ yyg->yy_hold_char = *yy_cp; \
+ *yy_cp = '\0'; \
+ yyg->yy_c_buf_p = yy_cp;
+
+#define YY_NUM_RULES 177
+#define YY_END_OF_BUFFER 178
+/* This struct is not used in this scanner,
+ but its presence is necessary. */
+struct yy_trans_info
+ {
+ flex_int32_t yy_verify;
+ flex_int32_t yy_nxt;
+ };
+static yyconst flex_int16_t yy_accept[668] =
+ { 0,
+ 0, 0, 9, 9, 178, 176, 1, 14, 176, 176,
+ 176, 176, 176, 176, 176, 176, 90, 88, 176, 176,
+ 176, 175, 176, 175, 175, 175, 175, 175, 175, 175,
+ 175, 175, 175, 175, 175, 175, 175, 175, 175, 175,
+ 175, 175, 175, 176, 1, 176, 85, 177, 9, 13,
+ 177, 12, 10, 11, 1, 74, 81, 75, 84, 78,
+ 69, 80, 70, 87, 92, 79, 93, 90, 0, 0,
+ 95, 0, 88, 0, 71, 73, 72, 0, 175, 77,
+ 175, 175, 175, 175, 175, 175, 175, 175, 175, 175,
+ 175, 175, 22, 175, 175, 175, 175, 175, 175, 175,
+
+ 175, 175, 175, 175, 175, 175, 26, 175, 175, 50,
+ 175, 175, 175, 175, 175, 175, 175, 175, 175, 175,
+ 175, 175, 175, 175, 175, 175, 175, 175, 175, 175,
+ 175, 175, 175, 175, 175, 175, 175, 175, 175, 175,
+ 175, 86, 76, 1, 0, 0, 2, 0, 0, 0,
+ 0, 9, 8, 12, 11, 0, 92, 91, 0, 93,
+ 0, 94, 89, 82, 83, 175, 98, 175, 175, 175,
+ 175, 175, 175, 175, 175, 175, 175, 175, 175, 175,
+ 175, 175, 175, 175, 175, 175, 175, 175, 25, 175,
+ 175, 175, 175, 175, 175, 175, 175, 175, 175, 19,
+
+ 175, 175, 175, 175, 175, 175, 175, 175, 175, 175,
+ 51, 175, 175, 175, 175, 175, 175, 175, 175, 175,
+ 175, 175, 175, 175, 175, 175, 175, 175, 175, 175,
+ 175, 175, 175, 175, 175, 175, 175, 175, 0, 0,
+ 0, 0, 8, 0, 92, 0, 91, 0, 93, 94,
+ 175, 175, 17, 175, 175, 138, 175, 175, 175, 175,
+ 175, 175, 175, 175, 175, 24, 101, 175, 175, 175,
+ 175, 57, 175, 175, 106, 120, 175, 175, 175, 175,
+ 175, 175, 175, 175, 175, 175, 175, 117, 141, 38,
+ 39, 40, 175, 175, 175, 175, 175, 175, 175, 175,
+
+ 175, 175, 175, 175, 175, 175, 175, 175, 175, 175,
+ 175, 175, 104, 96, 175, 175, 175, 175, 175, 175,
+ 175, 35, 36, 37, 67, 175, 175, 0, 0, 0,
+ 0, 0, 91, 175, 175, 20, 29, 30, 31, 175,
+ 99, 175, 16, 175, 175, 175, 175, 128, 129, 130,
+ 175, 97, 175, 121, 18, 131, 132, 133, 143, 125,
+ 126, 127, 175, 175, 175, 52, 123, 175, 175, 32,
+ 33, 34, 175, 175, 175, 175, 175, 175, 175, 175,
+ 175, 175, 175, 175, 175, 175, 175, 175, 118, 175,
+ 175, 175, 175, 175, 175, 175, 175, 175, 175, 100,
+
+ 175, 140, 175, 175, 23, 0, 0, 0, 0, 147,
+ 175, 175, 145, 175, 175, 175, 119, 114, 150, 175,
+ 175, 175, 175, 175, 175, 109, 175, 175, 68, 41,
+ 42, 43, 44, 45, 46, 47, 48, 49, 175, 175,
+ 175, 175, 124, 105, 175, 175, 112, 28, 175, 175,
+ 137, 58, 113, 66, 148, 107, 175, 175, 175, 175,
+ 175, 175, 175, 0, 0, 0, 0, 175, 175, 175,
+ 108, 27, 175, 175, 175, 175, 175, 175, 151, 152,
+ 153, 175, 175, 175, 175, 142, 175, 175, 175, 175,
+ 175, 175, 175, 175, 102, 175, 175, 175, 175, 175,
+
+ 53, 175, 54, 175, 0, 0, 0, 7, 0, 175,
+ 55, 21, 115, 155, 156, 157, 175, 175, 175, 175,
+ 175, 175, 175, 175, 175, 175, 175, 110, 175, 175,
+ 175, 175, 175, 175, 175, 175, 175, 103, 159, 160,
+ 161, 175, 175, 122, 111, 0, 0, 6, 0, 0,
+ 0, 3, 15, 175, 175, 175, 175, 175, 175, 175,
+ 175, 175, 154, 116, 56, 139, 175, 146, 144, 174,
+ 60, 61, 62, 175, 175, 175, 175, 175, 175, 0,
+ 0, 0, 0, 175, 175, 175, 158, 175, 175, 175,
+ 175, 175, 175, 175, 175, 175, 175, 175, 175, 175,
+
+ 175, 175, 162, 4, 0, 5, 0, 0, 0, 175,
+ 175, 175, 175, 175, 175, 175, 171, 175, 175, 175,
+ 175, 175, 175, 63, 175, 175, 175, 0, 175, 175,
+ 172, 163, 175, 164, 175, 175, 175, 175, 175, 175,
+ 175, 175, 175, 173, 165, 166, 169, 170, 59, 175,
+ 134, 175, 135, 149, 167, 168, 175, 175, 175, 64,
+ 175, 65, 175, 175, 175, 136, 0
+ } ;
+
+static yyconst flex_int32_t yy_ec[256] =
+ { 0,
+ 1, 1, 1, 1, 1, 1, 1, 1, 2, 3,
+ 1, 1, 4, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 2, 5, 1, 6, 1, 7, 8, 1, 1,
+ 1, 9, 10, 1, 11, 12, 13, 14, 15, 16,
+ 17, 18, 19, 19, 19, 20, 20, 21, 1, 22,
+ 23, 24, 1, 1, 25, 26, 27, 28, 29, 30,
+ 31, 31, 31, 31, 31, 31, 31, 31, 31, 31,
+ 31, 32, 33, 31, 31, 31, 31, 34, 31, 31,
+ 1, 1, 1, 35, 36, 1, 37, 38, 39, 40,
+
+ 41, 42, 43, 44, 45, 46, 47, 48, 49, 50,
+ 51, 52, 31, 53, 54, 55, 56, 57, 58, 59,
+ 60, 61, 1, 62, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1
+ } ;
+
+static yyconst flex_int32_t yy_meta[63] =
+ { 0,
+ 1, 2, 3, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 4, 4, 4, 4, 4, 4, 5,
+ 1, 1, 1, 1, 6, 6, 6, 6, 5, 5,
+ 7, 7, 7, 8, 1, 7, 6, 6, 6, 6,
+ 5, 5, 7, 7, 7, 7, 7, 7, 7, 7,
+ 7, 7, 7, 7, 7, 7, 7, 7, 8, 7,
+ 7, 1
+ } ;
+
+static yyconst flex_int16_t yy_base[678] =
+ { 0,
+ 0, 61, 84, 0, 1012, 1013, 62, 1013, 988, 987,
+ 57, 986, 58, 59, 57, 985, 135, 183, 56, 984,
+ 133, 0, 971, 119, 109, 130, 134, 111, 135, 954,
+ 151, 165, 32, 152, 131, 948, 153, 170, 182, 176,
+ 178, 193, 959, 125, 237, 243, 979, 1013, 214, 1013,
+ 988, 233, 1013, 0, 231, 1013, 1013, 1013, 1013, 1013,
+ 1013, 1013, 1013, 1013, 225, 1013, 227, 224, 289, 260,
+ 1013, 0, 0, 977, 1013, 1013, 1013, 976, 0, 1013,
+ 943, 948, 941, 944, 953, 952, 938, 941, 953, 155,
+ 947, 934, 931, 945, 931, 928, 928, 934, 213, 222,
+
+ 928, 939, 924, 930, 934, 935, 0, 926, 937, 237,
+ 932, 912, 232, 916, 930, 920, 241, 913, 257, 926,
+ 928, 910, 906, 914, 911, 900, 909, 228, 907, 913,
+ 908, 911, 899, 902, 904, 257, 907, 898, 911, 215,
+ 904, 1013, 1013, 310, 295, 318, 1013, 889, 902, 893,
+ 904, 260, 0, 308, 0, 362, 1013, 303, 373, 1013,
+ 380, 387, 0, 1013, 1013, 899, 0, 890, 894, 904,
+ 901, 884, 883, 883, 887, 280, 898, 895, 895, 893,
+ 890, 881, 888, 874, 872, 885, 870, 887, 0, 884,
+ 871, 879, 876, 880, 881, 874, 871, 859, 858, 872,
+
+ 875, 872, 859, 866, 856, 321, 862, 865, 855, 863,
+ 851, 855, 846, 861, 851, 842, 861, 844, 842, 853,
+ 842, 837, 835, 849, 834, 836, 833, 845, 844, 847,
+ 298, 838, 832, 821, 337, 840, 842, 830, 822, 826,
+ 838, 821, 0, 394, 404, 421, 1013, 433, 440, 1013,
+ 816, 827, 0, 824, 340, 0, 817, 815, 817, 812,
+ 821, 809, 827, 815, 344, 0, 0, 809, 820, 819,
+ 819, 0, 803, 347, 0, 0, 805, 351, 813, 814,
+ 804, 798, 797, 798, 797, 409, 793, 0, 0, 789,
+ 788, 787, 789, 790, 795, 789, 785, 799, 794, 793,
+
+ 792, 783, 786, 786, 778, 781, 776, 785, 790, 775,
+ 788, 778, 0, 0, 785, 781, 772, 772, 778, 777,
+ 774, 0, 0, 0, 0, 763, 776, 775, 774, 771,
+ 759, 447, 457, 771, 773, 0, 0, 0, 0, 759,
+ 0, 759, 0, 758, 759, 753, 764, 0, 0, 0,
+ 754, 0, 750, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 761, 463, 760, 0, 0, 758, 754, 0,
+ 0, 0, 743, 426, 467, 475, 748, 744, 750, 740,
+ 738, 752, 736, 736, 750, 738, 750, 745, 0, 743,
+ 740, 744, 727, 729, 736, 742, 737, 736, 723, 0,
+
+ 725, 0, 724, 728, 0, 722, 769, 721, 724, 0,
+ 712, 722, 0, 710, 710, 724, 0, 726, 0, 479,
+ 734, 733, 732, 703, 702, 0, 720, 719, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 703, 717,
+ 703, 700, 0, 0, 706, 705, 0, 0, 703, 695,
+ 0, 0, 0, 0, 0, 0, 692, 704, 485, 696,
+ 703, 700, 694, 687, 501, 703, 688, 683, 697, 695,
+ 0, 0, 687, 706, 705, 704, 675, 674, 317, 489,
+ 0, 687, 690, 688, 676, 0, 686, 683, 682, 671,
+ 670, 669, 508, 678, 0, 690, 689, 688, 659, 658,
+
+ 0, 673, 0, 671, 666, 495, 524, 1013, 660, 668,
+ 0, 0, 0, 683, 682, 0, 664, 667, 651, 659,
+ 649, 657, 658, 658, 657, 642, 655, 0, 656, 644,
+ 643, 639, 663, 662, 661, 632, 631, 0, 661, 660,
+ 0, 642, 645, 0, 0, 631, 543, 1013, 534, 0,
+ 553, 1013, 0, 628, 627, 637, 637, 624, 639, 622,
+ 637, 632, 0, 0, 0, 0, 617, 0, 0, 0,
+ 638, 353, 638, 627, 630, 614, 613, 623, 623, 613,
+ 530, 563, 413, 609, 608, 619, 0, 622, 618, 620,
+ 616, 602, 609, 605, 607, 603, 598, 596, 596, 575,
+
+ 542, 553, 0, 1013, 466, 1013, 582, 0, 588, 556,
+ 555, 535, 527, 535, 516, 524, 0, 517, 510, 492,
+ 493, 489, 472, 0, 473, 472, 451, 505, 428, 426,
+ 0, 0, 423, 0, 387, 392, 390, 373, 334, 316,
+ 298, 288, 286, 0, 0, 0, 0, 0, 0, 290,
+ 296, 266, 0, 0, 0, 0, 257, 269, 241, 0,
+ 250, 0, 202, 133, 105, 0, 1013, 605, 610, 615,
+ 617, 619, 625, 632, 637, 642, 647
+ } ;
+
+static yyconst flex_int16_t yy_def[678] =
+ { 0,
+ 667, 1, 667, 3, 667, 667, 667, 667, 667, 667,
+ 667, 667, 667, 667, 667, 667, 667, 667, 667, 667,
+ 667, 668, 667, 668, 668, 668, 668, 668, 668, 668,
+ 668, 668, 668, 668, 668, 668, 668, 668, 668, 668,
+ 668, 668, 668, 667, 667, 667, 667, 667, 667, 667,
+ 667, 667, 667, 669, 667, 667, 667, 667, 667, 667,
+ 667, 667, 667, 667, 670, 667, 671, 17, 667, 667,
+ 667, 672, 18, 667, 667, 667, 667, 667, 668, 667,
+ 668, 668, 668, 668, 668, 668, 668, 668, 668, 668,
+ 668, 668, 668, 668, 668, 668, 668, 668, 668, 668,
+
+ 668, 668, 668, 668, 668, 668, 668, 668, 668, 668,
+ 668, 668, 668, 668, 668, 668, 668, 668, 668, 668,
+ 668, 668, 668, 668, 668, 668, 668, 668, 668, 668,
+ 668, 668, 668, 668, 668, 668, 668, 668, 668, 668,
+ 668, 667, 667, 667, 667, 667, 667, 667, 667, 667,
+ 667, 667, 673, 667, 669, 667, 667, 671, 667, 667,
+ 667, 667, 672, 667, 667, 668, 668, 668, 668, 668,
+ 668, 668, 668, 668, 668, 668, 668, 668, 668, 668,
+ 668, 668, 668, 668, 668, 668, 668, 668, 668, 668,
+ 668, 668, 668, 668, 668, 668, 668, 668, 668, 668,
+
+ 668, 668, 668, 668, 668, 668, 668, 668, 668, 668,
+ 668, 668, 668, 668, 668, 668, 668, 668, 668, 668,
+ 668, 668, 668, 668, 668, 668, 668, 668, 668, 668,
+ 668, 668, 668, 668, 668, 668, 668, 668, 667, 667,
+ 667, 667, 673, 667, 667, 667, 667, 667, 667, 667,
+ 668, 668, 668, 668, 668, 668, 668, 668, 668, 668,
+ 668, 668, 668, 668, 668, 668, 668, 668, 668, 668,
+ 668, 668, 668, 668, 668, 668, 668, 668, 668, 668,
+ 668, 668, 668, 668, 668, 668, 668, 668, 668, 668,
+ 668, 668, 668, 668, 668, 668, 668, 668, 668, 668,
+
+ 668, 668, 668, 668, 668, 668, 668, 668, 668, 668,
+ 668, 668, 668, 668, 668, 668, 668, 668, 668, 668,
+ 668, 668, 668, 668, 668, 668, 668, 667, 667, 667,
+ 667, 667, 667, 668, 668, 668, 668, 668, 668, 668,
+ 668, 668, 668, 668, 668, 668, 668, 668, 668, 668,
+ 668, 668, 668, 668, 668, 668, 668, 668, 668, 668,
+ 668, 668, 668, 668, 668, 668, 668, 668, 668, 668,
+ 668, 668, 668, 668, 668, 668, 668, 668, 668, 668,
+ 668, 668, 668, 668, 668, 668, 668, 668, 668, 668,
+ 668, 668, 668, 668, 668, 668, 668, 668, 668, 668,
+
+ 668, 668, 668, 668, 668, 667, 667, 667, 667, 668,
+ 668, 668, 668, 668, 668, 668, 668, 668, 668, 668,
+ 668, 668, 668, 668, 668, 668, 668, 668, 668, 668,
+ 668, 668, 668, 668, 668, 668, 668, 668, 668, 668,
+ 668, 668, 668, 668, 668, 668, 668, 668, 668, 668,
+ 668, 668, 668, 668, 668, 668, 668, 668, 668, 668,
+ 668, 668, 668, 667, 667, 667, 667, 668, 668, 668,
+ 668, 668, 668, 668, 668, 668, 668, 668, 668, 668,
+ 668, 668, 668, 668, 668, 668, 668, 668, 668, 668,
+ 668, 668, 668, 668, 668, 668, 668, 668, 668, 668,
+
+ 668, 668, 668, 668, 667, 674, 667, 667, 667, 668,
+ 668, 668, 668, 668, 668, 668, 668, 668, 668, 668,
+ 668, 668, 668, 668, 668, 668, 668, 668, 668, 668,
+ 668, 668, 668, 668, 668, 668, 668, 668, 668, 668,
+ 668, 668, 668, 668, 668, 667, 667, 667, 667, 675,
+ 667, 667, 668, 668, 668, 668, 668, 668, 668, 668,
+ 668, 668, 668, 668, 668, 668, 668, 668, 668, 668,
+ 668, 668, 668, 668, 668, 668, 668, 668, 668, 667,
+ 676, 667, 675, 668, 668, 668, 668, 668, 668, 668,
+ 668, 668, 668, 668, 668, 668, 668, 668, 668, 668,
+
+ 668, 668, 668, 667, 667, 667, 667, 677, 667, 668,
+ 668, 668, 668, 668, 668, 668, 668, 668, 668, 668,
+ 668, 668, 668, 668, 668, 668, 668, 677, 668, 668,
+ 668, 668, 668, 668, 668, 668, 668, 668, 668, 668,
+ 668, 668, 668, 668, 668, 668, 668, 668, 668, 668,
+ 668, 668, 668, 668, 668, 668, 668, 668, 668, 668,
+ 668, 668, 668, 668, 668, 668, 0, 667, 667, 667,
+ 667, 667, 667, 667, 667, 667, 667
+ } ;
+
+static yyconst flex_int16_t yy_nxt[1076] =
+ { 0,
+ 6, 7, 8, 7, 9, 6, 10, 11, 12, 13,
+ 14, 15, 16, 17, 18, 18, 18, 18, 18, 18,
+ 6, 19, 20, 21, 22, 22, 22, 22, 22, 22,
+ 22, 22, 22, 22, 23, 22, 24, 25, 26, 27,
+ 28, 29, 30, 31, 32, 22, 22, 33, 34, 35,
+ 36, 37, 38, 39, 40, 41, 42, 43, 22, 22,
+ 22, 44, 45, 55, 58, 55, 46, 61, 112, 63,
+ 65, 65, 65, 65, 65, 65, 65, 74, 75, 59,
+ 62, 64, 113, 47, 48, 49, 50, 49, 48, 48,
+ 48, 48, 48, 48, 48, 48, 51, 48, 52, 52,
+
+ 52, 52, 52, 52, 53, 48, 48, 48, 54, 54,
+ 54, 54, 54, 54, 54, 54, 54, 54, 48, 54,
+ 54, 54, 54, 54, 54, 54, 54, 54, 54, 54,
+ 54, 54, 54, 54, 54, 54, 54, 54, 54, 54,
+ 54, 54, 54, 54, 54, 48, 67, 142, 68, 68,
+ 68, 68, 68, 68, 69, 77, 78, 81, 95, 84,
+ 96, 85, 666, 70, 71, 86, 87, 116, 72, 97,
+ 88, 98, 82, 83, 91, 70, 71, 89, 92, 99,
+ 90, 117, 100, 665, 93, 101, 143, 104, 114, 119,
+ 94, 102, 115, 72, 67, 105, 73, 73, 73, 73,
+
+ 73, 73, 73, 175, 176, 120, 107, 106, 121, 108,
+ 122, 70, 71, 109, 110, 152, 131, 152, 124, 132,
+ 123, 111, 135, 70, 71, 125, 126, 136, 133, 138,
+ 127, 137, 55, 139, 55, 134, 128, 129, 144, 130,
+ 55, 664, 145, 140, 146, 147, 154, 154, 154, 154,
+ 154, 154, 154, 156, 157, 159, 160, 667, 187, 236,
+ 185, 152, 237, 152, 222, 156, 157, 159, 160, 161,
+ 161, 186, 188, 162, 162, 162, 162, 162, 162, 162,
+ 223, 204, 667, 148, 197, 209, 663, 198, 199, 205,
+ 149, 200, 210, 201, 150, 212, 146, 147, 662, 151,
+
+ 67, 231, 69, 69, 69, 69, 69, 69, 69, 213,
+ 232, 144, 661, 55, 660, 145, 659, 70, 71, 146,
+ 147, 154, 154, 154, 154, 154, 154, 154, 658, 70,
+ 71, 246, 247, 260, 261, 148, 290, 291, 292, 317,
+ 657, 519, 149, 246, 247, 656, 150, 655, 318, 520,
+ 654, 151, 322, 323, 324, 337, 338, 339, 148, 348,
+ 349, 350, 356, 357, 358, 149, 360, 361, 362, 150,
+ 653, 244, 244, 652, 151, 245, 245, 245, 245, 245,
+ 245, 245, 248, 248, 595, 596, 249, 249, 249, 249,
+ 249, 249, 249, 162, 162, 162, 162, 162, 162, 162,
+
+ 162, 162, 162, 162, 162, 162, 162, 245, 245, 245,
+ 245, 245, 245, 245, 547, 548, 250, 245, 245, 245,
+ 245, 245, 245, 245, 370, 371, 372, 651, 250, 650,
+ 332, 332, 649, 157, 333, 333, 333, 333, 333, 333,
+ 333, 430, 431, 432, 648, 157, 249, 249, 249, 249,
+ 249, 249, 249, 249, 249, 249, 249, 249, 249, 249,
+ 333, 333, 333, 333, 333, 333, 333, 605, 606, 160,
+ 333, 333, 333, 333, 333, 333, 333, 421, 422, 423,
+ 647, 160, 433, 434, 435, 646, 247, 645, 424, 425,
+ 436, 437, 438, 474, 475, 476, 547, 548, 247, 496,
+
+ 497, 498, 465, 644, 477, 478, 605, 606, 643, 642,
+ 499, 500, 641, 521, 506, 507, 507, 507, 507, 507,
+ 507, 522, 533, 534, 535, 547, 548, 640, 550, 639,
+ 638, 605, 606, 536, 537, 547, 548, 551, 551, 551,
+ 551, 551, 551, 551, 547, 548, 637, 549, 549, 549,
+ 549, 549, 549, 550, 547, 548, 581, 582, 582, 582,
+ 582, 582, 582, 608, 605, 606, 551, 551, 551, 551,
+ 551, 551, 551, 636, 635, 634, 609, 609, 609, 609,
+ 609, 609, 609, 605, 606, 633, 632, 631, 608, 605,
+ 606, 630, 629, 627, 626, 607, 607, 607, 607, 607,
+
+ 607, 609, 609, 609, 609, 609, 609, 609, 79, 79,
+ 79, 79, 79, 155, 155, 155, 155, 155, 65, 65,
+ 158, 158, 163, 163, 163, 243, 243, 625, 243, 243,
+ 243, 243, 243, 549, 549, 549, 624, 623, 622, 549,
+ 583, 583, 583, 607, 607, 607, 621, 620, 619, 607,
+ 628, 628, 628, 618, 617, 616, 615, 614, 613, 612,
+ 611, 610, 604, 603, 602, 601, 600, 599, 598, 597,
+ 594, 593, 592, 591, 590, 589, 588, 587, 586, 585,
+ 584, 580, 579, 578, 577, 576, 575, 574, 573, 572,
+ 571, 570, 569, 568, 567, 566, 565, 564, 563, 562,
+
+ 561, 560, 559, 558, 557, 556, 555, 554, 553, 552,
+ 546, 545, 544, 543, 542, 541, 540, 539, 538, 532,
+ 531, 530, 529, 528, 527, 526, 525, 524, 523, 518,
+ 517, 516, 515, 514, 513, 512, 511, 510, 509, 508,
+ 505, 504, 503, 502, 501, 495, 494, 493, 492, 491,
+ 490, 489, 488, 487, 486, 485, 484, 483, 482, 481,
+ 480, 479, 473, 472, 471, 470, 469, 468, 467, 466,
+ 465, 464, 463, 462, 461, 460, 459, 458, 457, 456,
+ 455, 454, 453, 452, 451, 450, 449, 448, 447, 446,
+ 445, 444, 443, 442, 441, 440, 439, 429, 428, 427,
+
+ 426, 420, 419, 418, 417, 416, 415, 414, 413, 412,
+ 411, 410, 409, 408, 407, 406, 405, 404, 403, 402,
+ 401, 400, 399, 398, 397, 396, 395, 394, 393, 392,
+ 391, 390, 389, 388, 387, 386, 385, 384, 383, 382,
+ 381, 380, 379, 378, 377, 376, 375, 374, 373, 369,
+ 368, 367, 366, 365, 364, 363, 359, 355, 354, 353,
+ 352, 351, 347, 346, 345, 344, 343, 342, 341, 340,
+ 336, 335, 334, 331, 330, 329, 328, 327, 326, 325,
+ 321, 320, 319, 316, 315, 314, 313, 312, 311, 310,
+ 309, 308, 307, 306, 305, 304, 303, 302, 301, 300,
+
+ 299, 298, 297, 296, 295, 294, 293, 289, 288, 287,
+ 286, 285, 284, 283, 282, 281, 280, 279, 278, 277,
+ 276, 275, 274, 273, 272, 271, 270, 269, 268, 267,
+ 266, 265, 264, 263, 262, 259, 258, 257, 256, 255,
+ 254, 253, 252, 251, 242, 241, 240, 239, 238, 235,
+ 234, 233, 230, 229, 228, 227, 226, 225, 224, 221,
+ 220, 219, 218, 217, 216, 215, 214, 211, 208, 207,
+ 206, 203, 202, 196, 195, 194, 193, 192, 191, 190,
+ 189, 184, 183, 182, 181, 180, 179, 178, 177, 174,
+ 173, 172, 171, 170, 169, 168, 167, 166, 165, 164,
+
+ 153, 76, 141, 118, 103, 80, 76, 66, 60, 57,
+ 56, 667, 5, 667, 667, 667, 667, 667, 667, 667,
+ 667, 667, 667, 667, 667, 667, 667, 667, 667, 667,
+ 667, 667, 667, 667, 667, 667, 667, 667, 667, 667,
+ 667, 667, 667, 667, 667, 667, 667, 667, 667, 667,
+ 667, 667, 667, 667, 667, 667, 667, 667, 667, 667,
+ 667, 667, 667, 667, 667, 667, 667, 667, 667, 667,
+ 667, 667, 667, 667, 667
+ } ;
+
+static yyconst flex_int16_t yy_chk[1076] =
+ { 0,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 2, 7, 11, 7, 2, 13, 33, 14,
+ 15, 15, 15, 15, 15, 15, 15, 19, 19, 11,
+ 13, 14, 33, 2, 3, 3, 3, 3, 3, 3,
+ 3, 3, 3, 3, 3, 3, 3, 3, 3, 3,
+
+ 3, 3, 3, 3, 3, 3, 3, 3, 3, 3,
+ 3, 3, 3, 3, 3, 3, 3, 3, 3, 3,
+ 3, 3, 3, 3, 3, 3, 3, 3, 3, 3,
+ 3, 3, 3, 3, 3, 3, 3, 3, 3, 3,
+ 3, 3, 3, 3, 3, 3, 17, 44, 17, 17,
+ 17, 17, 17, 17, 17, 21, 21, 24, 28, 25,
+ 28, 25, 665, 17, 17, 25, 26, 35, 17, 28,
+ 26, 29, 24, 24, 27, 17, 17, 26, 27, 29,
+ 26, 35, 29, 664, 27, 29, 44, 31, 34, 37,
+ 27, 29, 34, 17, 18, 31, 18, 18, 18, 18,
+
+ 18, 18, 18, 90, 90, 37, 32, 31, 37, 32,
+ 38, 18, 18, 32, 32, 49, 40, 49, 39, 40,
+ 38, 32, 41, 18, 18, 39, 39, 41, 40, 42,
+ 39, 41, 55, 42, 55, 40, 39, 39, 45, 39,
+ 45, 663, 45, 42, 46, 46, 52, 52, 52, 52,
+ 52, 52, 52, 65, 65, 67, 67, 68, 100, 140,
+ 99, 152, 140, 152, 128, 65, 65, 67, 67, 70,
+ 70, 99, 100, 70, 70, 70, 70, 70, 70, 70,
+ 128, 113, 68, 46, 110, 117, 661, 110, 110, 113,
+ 46, 110, 117, 110, 46, 119, 145, 145, 659, 46,
+
+ 69, 136, 69, 69, 69, 69, 69, 69, 69, 119,
+ 136, 144, 658, 144, 657, 144, 652, 69, 69, 146,
+ 146, 154, 154, 154, 154, 154, 154, 154, 651, 69,
+ 69, 158, 158, 176, 176, 145, 206, 206, 206, 231,
+ 650, 479, 145, 158, 158, 643, 145, 642, 231, 479,
+ 641, 145, 235, 235, 235, 255, 255, 255, 146, 265,
+ 265, 265, 274, 274, 274, 146, 278, 278, 278, 146,
+ 640, 156, 156, 639, 146, 156, 156, 156, 156, 156,
+ 156, 156, 159, 159, 572, 572, 159, 159, 159, 159,
+ 159, 159, 159, 161, 161, 161, 161, 161, 161, 161,
+
+ 162, 162, 162, 162, 162, 162, 162, 244, 244, 244,
+ 244, 244, 244, 244, 583, 583, 162, 245, 245, 245,
+ 245, 245, 245, 245, 286, 286, 286, 638, 162, 637,
+ 246, 246, 636, 245, 246, 246, 246, 246, 246, 246,
+ 246, 374, 374, 374, 635, 245, 248, 248, 248, 248,
+ 248, 248, 248, 249, 249, 249, 249, 249, 249, 249,
+ 332, 332, 332, 332, 332, 332, 332, 605, 605, 249,
+ 333, 333, 333, 333, 333, 333, 333, 364, 364, 364,
+ 633, 249, 375, 375, 375, 630, 333, 629, 364, 364,
+ 376, 376, 376, 420, 420, 420, 506, 506, 333, 459,
+
+ 459, 459, 465, 627, 420, 420, 628, 628, 626, 625,
+ 459, 459, 623, 480, 465, 465, 465, 465, 465, 465,
+ 465, 480, 493, 493, 493, 507, 507, 622, 506, 621,
+ 620, 581, 581, 493, 493, 549, 549, 507, 507, 507,
+ 507, 507, 507, 507, 547, 547, 619, 549, 549, 549,
+ 549, 549, 549, 506, 551, 551, 547, 547, 547, 547,
+ 547, 547, 547, 581, 582, 582, 551, 551, 551, 551,
+ 551, 551, 551, 618, 616, 615, 582, 582, 582, 582,
+ 582, 582, 582, 607, 607, 614, 613, 612, 581, 609,
+ 609, 611, 610, 602, 601, 607, 607, 607, 607, 607,
+
+ 607, 609, 609, 609, 609, 609, 609, 609, 668, 668,
+ 668, 668, 668, 669, 669, 669, 669, 669, 670, 670,
+ 671, 671, 672, 672, 672, 673, 673, 600, 673, 673,
+ 673, 673, 673, 674, 674, 674, 599, 598, 597, 674,
+ 675, 675, 675, 676, 676, 676, 596, 595, 594, 676,
+ 677, 677, 677, 593, 592, 591, 590, 589, 588, 586,
+ 585, 584, 580, 579, 578, 577, 576, 575, 574, 573,
+ 571, 567, 562, 561, 560, 559, 558, 557, 556, 555,
+ 554, 546, 543, 542, 540, 539, 537, 536, 535, 534,
+ 533, 532, 531, 530, 529, 527, 526, 525, 524, 523,
+
+ 522, 521, 520, 519, 518, 517, 515, 514, 510, 509,
+ 505, 504, 502, 500, 499, 498, 497, 496, 494, 492,
+ 491, 490, 489, 488, 487, 485, 484, 483, 482, 478,
+ 477, 476, 475, 474, 473, 470, 469, 468, 467, 466,
+ 464, 463, 462, 461, 460, 458, 457, 450, 449, 446,
+ 445, 442, 441, 440, 439, 428, 427, 425, 424, 423,
+ 422, 421, 418, 416, 415, 414, 412, 411, 409, 408,
+ 407, 406, 404, 403, 401, 399, 398, 397, 396, 395,
+ 394, 393, 392, 391, 390, 388, 387, 386, 385, 384,
+ 383, 382, 381, 380, 379, 378, 377, 373, 369, 368,
+
+ 365, 363, 353, 351, 347, 346, 345, 344, 342, 340,
+ 335, 334, 331, 330, 329, 328, 327, 326, 321, 320,
+ 319, 318, 317, 316, 315, 312, 311, 310, 309, 308,
+ 307, 306, 305, 304, 303, 302, 301, 300, 299, 298,
+ 297, 296, 295, 294, 293, 292, 291, 290, 287, 285,
+ 284, 283, 282, 281, 280, 279, 277, 273, 271, 270,
+ 269, 268, 264, 263, 262, 261, 260, 259, 258, 257,
+ 254, 252, 251, 242, 241, 240, 239, 238, 237, 236,
+ 234, 233, 232, 230, 229, 228, 227, 226, 225, 224,
+ 223, 222, 221, 220, 219, 218, 217, 216, 215, 214,
+
+ 213, 212, 211, 210, 209, 208, 207, 205, 204, 203,
+ 202, 201, 200, 199, 198, 197, 196, 195, 194, 193,
+ 192, 191, 190, 188, 187, 186, 185, 184, 183, 182,
+ 181, 180, 179, 178, 177, 175, 174, 173, 172, 171,
+ 170, 169, 168, 166, 151, 150, 149, 148, 141, 139,
+ 138, 137, 135, 134, 133, 132, 131, 130, 129, 127,
+ 126, 125, 124, 123, 122, 121, 120, 118, 116, 115,
+ 114, 112, 111, 109, 108, 106, 105, 104, 103, 102,
+ 101, 98, 97, 96, 95, 94, 93, 92, 91, 89,
+ 88, 87, 86, 85, 84, 83, 82, 81, 78, 74,
+
+ 51, 47, 43, 36, 30, 23, 20, 16, 12, 10,
+ 9, 5, 667, 667, 667, 667, 667, 667, 667, 667,
+ 667, 667, 667, 667, 667, 667, 667, 667, 667, 667,
+ 667, 667, 667, 667, 667, 667, 667, 667, 667, 667,
+ 667, 667, 667, 667, 667, 667, 667, 667, 667, 667,
+ 667, 667, 667, 667, 667, 667, 667, 667, 667, 667,
+ 667, 667, 667, 667, 667, 667, 667, 667, 667, 667,
+ 667, 667, 667, 667, 667
+ } ;
+
+/* The intent behind this definition is that it'll catch
+ * any uses of REJECT which flex missed.
+ */
+#define REJECT reject_used_but_not_detected
+#define yymore() yymore_used_but_not_detected
+#define YY_MORE_ADJ 0
+#define YY_RESTORE_YY_MORE_OFFSET
+#line 1 "glsl_lexer.lpp"
+#line 2 "glsl_lexer.lpp"
+/*
+ * Copyright © 2008, 2009 Intel Corporation
+ *
+ * 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 (including the next
+ * paragraph) 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
+ * THE AUTHORS OR COPYRIGHT HOLDERS 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.
+ */
+#include <ctype.h>
+#include "ast.h"
+#include "glsl_parser_extras.h"
+#include "glsl_parser.h"
+
+#define YY_USER_ACTION \
+ do { \
+ yylloc->source = 0; \
+ yylloc->first_column = yycolumn + 1; \
+ yylloc->first_line = yylineno + 1; \
+ yycolumn += yyleng; \
+ } while(0);
+
+#define YY_USER_INIT yylineno = 0; yycolumn = 0;
+
+#define TOKEN_OR_IDENTIFIER(version, token) \
+ do { \
+ if (yyextra->language_version >= version) { \
+ return token; \
+ } else { \
+ yylval->identifier = strdup(yytext); \
+ return IDENTIFIER; \
+ } \
+ } while (0)
+
+#define RESERVED_WORD(version, token) \
+ do { \
+ if (yyextra->language_version >= version) { \
+ return token; \
+ } else { \
+ _mesa_glsl_error(yylloc, yyextra, \
+ "Illegal use of reserved word `%s'", yytext); \
+ return ERROR_TOK; \
+ } \
+ } while (0)
+
+#line 958 "glsl_lexer.cpp"
+
+#define INITIAL 0
+#define PP 1
+
+#define YY_EXTRA_TYPE struct _mesa_glsl_parse_state *
+
+/* Holds the entire state of the reentrant scanner. */
+struct yyguts_t
+ {
+
+ /* User-defined. Not touched by flex. */
+ YY_EXTRA_TYPE yyextra_r;
+
+ /* The rest are the same as the globals declared in the non-reentrant scanner. */
+ FILE *yyin_r, *yyout_r;
+ size_t yy_buffer_stack_top; /**< index of top of stack. */
+ size_t yy_buffer_stack_max; /**< capacity of stack. */
+ YY_BUFFER_STATE * yy_buffer_stack; /**< Stack as an array. */
+ char yy_hold_char;
+ int yy_n_chars;
+ int yyleng_r;
+ char *yy_c_buf_p;
+ int yy_init;
+ int yy_start;
+ int yy_did_buffer_switch_on_eof;
+ int yy_start_stack_ptr;
+ int yy_start_stack_depth;
+ int *yy_start_stack;
+ yy_state_type yy_last_accepting_state;
+ char* yy_last_accepting_cpos;
+
+ int yylineno_r;
+ int yy_flex_debug_r;
+
+ char *yytext_r;
+ int yy_more_flag;
+ int yy_more_len;
+
+ YYSTYPE * yylval_r;
+
+ YYLTYPE * yylloc_r;
+
+ }; /* end struct yyguts_t */
+
+static int yy_init_globals (yyscan_t yyscanner );
+
+ /* This must go here because YYSTYPE and YYLTYPE are included
+ * from bison output in section 1.*/
+ # define yylval yyg->yylval_r
+
+ # define yylloc yyg->yylloc_r
+
+int _mesa_glsl_lex_init (yyscan_t* scanner);
+
+int _mesa_glsl_lex_init_extra (YY_EXTRA_TYPE user_defined,yyscan_t* scanner);
+
+/* Accessor methods to globals.
+ These are made visible to non-reentrant scanners for convenience. */
+
+int _mesa_glsl_lex_destroy (yyscan_t yyscanner );
+
+int _mesa_glsl_get_debug (yyscan_t yyscanner );
+
+void _mesa_glsl_set_debug (int debug_flag ,yyscan_t yyscanner );
+
+YY_EXTRA_TYPE _mesa_glsl_get_extra (yyscan_t yyscanner );
+
+void _mesa_glsl_set_extra (YY_EXTRA_TYPE user_defined ,yyscan_t yyscanner );
+
+FILE *_mesa_glsl_get_in (yyscan_t yyscanner );
+
+void _mesa_glsl_set_in (FILE * in_str ,yyscan_t yyscanner );
+
+FILE *_mesa_glsl_get_out (yyscan_t yyscanner );
+
+void _mesa_glsl_set_out (FILE * out_str ,yyscan_t yyscanner );
+
+int _mesa_glsl_get_leng (yyscan_t yyscanner );
+
+char *_mesa_glsl_get_text (yyscan_t yyscanner );
+
+int _mesa_glsl_get_lineno (yyscan_t yyscanner );
+
+void _mesa_glsl_set_lineno (int line_number ,yyscan_t yyscanner );
+
+YYSTYPE * _mesa_glsl_get_lval (yyscan_t yyscanner );
+
+void _mesa_glsl_set_lval (YYSTYPE * yylval_param ,yyscan_t yyscanner );
+
+ YYLTYPE *_mesa_glsl_get_lloc (yyscan_t yyscanner );
+
+ void _mesa_glsl_set_lloc (YYLTYPE * yylloc_param ,yyscan_t yyscanner );
+
+/* Macros after this point can all be overridden by user definitions in
+ * section 1.
+ */
+
+#ifndef YY_SKIP_YYWRAP
+#ifdef __cplusplus
+extern "C" int _mesa_glsl_wrap (yyscan_t yyscanner );
+#else
+extern int _mesa_glsl_wrap (yyscan_t yyscanner );
+#endif
+#endif
+
+#ifndef yytext_ptr
+static void yy_flex_strncpy (char *,yyconst char *,int ,yyscan_t yyscanner);
+#endif
+
+#ifdef YY_NEED_STRLEN
+static int yy_flex_strlen (yyconst char * ,yyscan_t yyscanner);
+#endif
+
+#ifndef YY_NO_INPUT
+
+#ifdef __cplusplus
+static int yyinput (yyscan_t yyscanner );
+#else
+static int input (yyscan_t yyscanner );
+#endif
+
+#endif
+
+/* Amount of stuff to slurp up with each read. */
+#ifndef YY_READ_BUF_SIZE
+#ifdef __ia64__
+/* On IA-64, the buffer size is 16k, not 8k */
+#define YY_READ_BUF_SIZE 16384
+#else
+#define YY_READ_BUF_SIZE 8192
+#endif /* __ia64__ */
+#endif
+
+/* Copy whatever the last rule matched to the standard output. */
+#ifndef ECHO
+/* This used to be an fputs(), but since the string might contain NUL's,
+ * we now use fwrite().
+ */
+#define ECHO do { if (fwrite( yytext, yyleng, 1, yyout )) {} } while (0)
+#endif
+
+/* Gets input and stuffs it into "buf". number of characters read, or YY_NULL,
+ * is returned in "result".
+ */
+#ifndef YY_INPUT
+#define YY_INPUT(buf,result,max_size) \
+ if ( YY_CURRENT_BUFFER_LVALUE->yy_is_interactive ) \
+ { \
+ int c = '*'; \
+ size_t n; \
+ for ( n = 0; n < max_size && \
+ (c = getc( yyin )) != EOF && c != '\n'; ++n ) \
+ buf[n] = (char) c; \
+ if ( c == '\n' ) \
+ buf[n++] = (char) c; \
+ if ( c == EOF && ferror( yyin ) ) \
+ YY_FATAL_ERROR( "input in flex scanner failed" ); \
+ result = n; \
+ } \
+ else \
+ { \
+ errno=0; \
+ while ( (result = fread(buf, 1, max_size, yyin))==0 && ferror(yyin)) \
+ { \
+ if( errno != EINTR) \
+ { \
+ YY_FATAL_ERROR( "input in flex scanner failed" ); \
+ break; \
+ } \
+ errno=0; \
+ clearerr(yyin); \
+ } \
+ }\
+\
+
+#endif
+
+/* No semi-colon after return; correct usage is to write "yyterminate();" -
+ * we don't want an extra ';' after the "return" because that will cause
+ * some compilers to complain about unreachable statements.
+ */
+#ifndef yyterminate
+#define yyterminate() return YY_NULL
+#endif
+
+/* Number of entries by which start-condition stack grows. */
+#ifndef YY_START_STACK_INCR
+#define YY_START_STACK_INCR 25
+#endif
+
+/* Report a fatal error. */
+#ifndef YY_FATAL_ERROR
+#define YY_FATAL_ERROR(msg) yy_fatal_error( msg , yyscanner)
+#endif
+
+/* end tables serialization structures and prototypes */
+
+/* Default declaration of generated scanner - a define so the user can
+ * easily add parameters.
+ */
+#ifndef YY_DECL
+#define YY_DECL_IS_OURS 1
+
+extern int _mesa_glsl_lex \
+ (YYSTYPE * yylval_param,YYLTYPE * yylloc_param ,yyscan_t yyscanner);
+
+#define YY_DECL int _mesa_glsl_lex \
+ (YYSTYPE * yylval_param, YYLTYPE * yylloc_param , yyscan_t yyscanner)
+#endif /* !YY_DECL */
+
+/* Code executed at the beginning of each rule, after yytext and yyleng
+ * have been set up.
+ */
+#ifndef YY_USER_ACTION
+#define YY_USER_ACTION
+#endif
+
+/* Code executed at the end of each rule. */
+#ifndef YY_BREAK
+#define YY_BREAK break;
+#endif
+
+#define YY_RULE_SETUP \
+ if ( yyleng > 0 ) \
+ YY_CURRENT_BUFFER_LVALUE->yy_at_bol = \
+ (yytext[yyleng - 1] == '\n'); \
+ YY_USER_ACTION
+
+/** The main scanner function which does all the work.
+ */
+YY_DECL
+{
+ register yy_state_type yy_current_state;
+ register char *yy_cp, *yy_bp;
+ register int yy_act;
+ struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
+
+#line 76 "glsl_lexer.lpp"
+
+
+#line 1199 "glsl_lexer.cpp"
+
+ yylval = yylval_param;
+
+ yylloc = yylloc_param;
+
+ if ( !yyg->yy_init )
+ {
+ yyg->yy_init = 1;
+
+#ifdef YY_USER_INIT
+ YY_USER_INIT;
+#endif
+
+ if ( ! yyg->yy_start )
+ yyg->yy_start = 1; /* first start state */
+
+ if ( ! yyin )
+ yyin = stdin;
+
+ if ( ! yyout )
+ yyout = stdout;
+
+ if ( ! YY_CURRENT_BUFFER ) {
+ _mesa_glsl_ensure_buffer_stack (yyscanner);
+ YY_CURRENT_BUFFER_LVALUE =
+ _mesa_glsl__create_buffer(yyin,YY_BUF_SIZE ,yyscanner);
+ }
+
+ _mesa_glsl__load_buffer_state(yyscanner );
+ }
+
+ while ( 1 ) /* loops until end-of-file is reached */
+ {
+ yy_cp = yyg->yy_c_buf_p;
+
+ /* Support of yytext. */
+ *yy_cp = yyg->yy_hold_char;
+
+ /* yy_bp points to the position in yy_ch_buf of the start of
+ * the current run.
+ */
+ yy_bp = yy_cp;
+
+ yy_current_state = yyg->yy_start;
+ yy_current_state += YY_AT_BOL();
+yy_match:
+ do
+ {
+ register YY_CHAR yy_c = yy_ec[YY_SC_TO_UI(*yy_cp)];
+ if ( yy_accept[yy_current_state] )
+ {
+ yyg->yy_last_accepting_state = yy_current_state;
+ yyg->yy_last_accepting_cpos = yy_cp;
+ }
+ while ( yy_chk[yy_base[yy_current_state] + yy_c] != yy_current_state )
+ {
+ yy_current_state = (int) yy_def[yy_current_state];
+ if ( yy_current_state >= 668 )
+ yy_c = yy_meta[(unsigned int) yy_c];
+ }
+ yy_current_state = yy_nxt[yy_base[yy_current_state] + (unsigned int) yy_c];
+ ++yy_cp;
+ }
+ while ( yy_current_state != 667 );
+ yy_cp = yyg->yy_last_accepting_cpos;
+ yy_current_state = yyg->yy_last_accepting_state;
+
+yy_find_action:
+ yy_act = yy_accept[yy_current_state];
+
+ YY_DO_BEFORE_ACTION;
+
+do_action: /* This label is used only to access EOF actions. */
+
+ switch ( yy_act )
+ { /* beginning of action switch */
+ case 0: /* must back up */
+ /* undo the effects of YY_DO_BEFORE_ACTION */
+ *yy_cp = yyg->yy_hold_char;
+ yy_cp = yyg->yy_last_accepting_cpos;
+ yy_current_state = yyg->yy_last_accepting_state;
+ goto yy_find_action;
+
+case 1:
+YY_RULE_SETUP
+#line 78 "glsl_lexer.lpp"
+;
+ YY_BREAK
+/* Preprocessor tokens. */
+case 2:
+*yy_cp = yyg->yy_hold_char; /* undo effects of setting up yytext */
+yyg->yy_c_buf_p = yy_cp -= 1;
+YY_DO_BEFORE_ACTION; /* set up yytext again */
+YY_RULE_SETUP
+#line 81 "glsl_lexer.lpp"
+;
+ YY_BREAK
+case 3:
+YY_RULE_SETUP
+#line 82 "glsl_lexer.lpp"
+{ BEGIN PP; return VERSION; }
+ YY_BREAK
+case 4:
+YY_RULE_SETUP
+#line 83 "glsl_lexer.lpp"
+{ BEGIN PP; return EXTENSION; }
+ YY_BREAK
+case 5:
+*yy_cp = yyg->yy_hold_char; /* undo effects of setting up yytext */
+yyg->yy_c_buf_p = yy_cp -= 1;
+YY_DO_BEFORE_ACTION; /* set up yytext again */
+YY_RULE_SETUP
+#line 84 "glsl_lexer.lpp"
+{
+ /* Eat characters until the first digit is
+ * encountered
+ */
+ char *ptr = yytext;
+ while (!isdigit(*ptr))
+ ptr++;
+
+ /* Subtract one from the line number because
+ * yylineno is zero-based instead of
+ * one-based.
+ */
+ yylineno = strtol(ptr, &ptr, 0) - 1;
+ yylloc->source = strtol(ptr, NULL, 0);
+ }
+ YY_BREAK
+case 6:
+*yy_cp = yyg->yy_hold_char; /* undo effects of setting up yytext */
+yyg->yy_c_buf_p = yy_cp -= 1;
+YY_DO_BEFORE_ACTION; /* set up yytext again */
+YY_RULE_SETUP
+#line 99 "glsl_lexer.lpp"
+{
+ /* Eat characters until the first digit is
+ * encountered
+ */
+ char *ptr = yytext;
+ while (!isdigit(*ptr))
+ ptr++;
+
+ /* Subtract one from the line number because
+ * yylineno is zero-based instead of
+ * one-based.
+ */
+ yylineno = strtol(ptr, &ptr, 0) - 1;
+ }
+ YY_BREAK
+case 7:
+YY_RULE_SETUP
+#line 113 "glsl_lexer.lpp"
+{ BEGIN PP; return PRAGMA; }
+ YY_BREAK
+case 8:
+YY_RULE_SETUP
+#line 114 "glsl_lexer.lpp"
+{ }
+ YY_BREAK
+case 9:
+YY_RULE_SETUP
+#line 115 "glsl_lexer.lpp"
+{ }
+ YY_BREAK
+case 10:
+YY_RULE_SETUP
+#line 116 "glsl_lexer.lpp"
+return COLON;
+ YY_BREAK
+case 11:
+YY_RULE_SETUP
+#line 117 "glsl_lexer.lpp"
+{
+ yylval->identifier = strdup(yytext);
+ return IDENTIFIER;
+ }
+ YY_BREAK
+case 12:
+YY_RULE_SETUP
+#line 121 "glsl_lexer.lpp"
+{
+ yylval->n = strtol(yytext, NULL, 10);
+ return INTCONSTANT;
+ }
+ YY_BREAK
+case 13:
+/* rule 13 can match eol */
+YY_RULE_SETUP
+#line 125 "glsl_lexer.lpp"
+{ BEGIN 0; yylineno++; yycolumn = 0; return EOL; }
+ YY_BREAK
+case 14:
+/* rule 14 can match eol */
+YY_RULE_SETUP
+#line 127 "glsl_lexer.lpp"
+{ yylineno++; yycolumn = 0; }
+ YY_BREAK
+case 15:
+YY_RULE_SETUP
+#line 129 "glsl_lexer.lpp"
+return ATTRIBUTE;
+ YY_BREAK
+case 16:
+YY_RULE_SETUP
+#line 130 "glsl_lexer.lpp"
+return CONST_TOK;
+ YY_BREAK
+case 17:
+YY_RULE_SETUP
+#line 131 "glsl_lexer.lpp"
+return BOOL_TOK;
+ YY_BREAK
+case 18:
+YY_RULE_SETUP
+#line 132 "glsl_lexer.lpp"
+return FLOAT_TOK;
+ YY_BREAK
+case 19:
+YY_RULE_SETUP
+#line 133 "glsl_lexer.lpp"
+return INT_TOK;
+ YY_BREAK
+case 20:
+YY_RULE_SETUP
+#line 135 "glsl_lexer.lpp"
+return BREAK;
+ YY_BREAK
+case 21:
+YY_RULE_SETUP
+#line 136 "glsl_lexer.lpp"
+return CONTINUE;
+ YY_BREAK
+case 22:
+YY_RULE_SETUP
+#line 137 "glsl_lexer.lpp"
+return DO;
+ YY_BREAK
+case 23:
+YY_RULE_SETUP
+#line 138 "glsl_lexer.lpp"
+return WHILE;
+ YY_BREAK
+case 24:
+YY_RULE_SETUP
+#line 139 "glsl_lexer.lpp"
+return ELSE;
+ YY_BREAK
+case 25:
+YY_RULE_SETUP
+#line 140 "glsl_lexer.lpp"
+return FOR;
+ YY_BREAK
+case 26:
+YY_RULE_SETUP
+#line 141 "glsl_lexer.lpp"
+return IF;
+ YY_BREAK
+case 27:
+YY_RULE_SETUP
+#line 142 "glsl_lexer.lpp"
+return DISCARD;
+ YY_BREAK
+case 28:
+YY_RULE_SETUP
+#line 143 "glsl_lexer.lpp"
+return RETURN;
+ YY_BREAK
+case 29:
+YY_RULE_SETUP
+#line 145 "glsl_lexer.lpp"
+return BVEC2;
+ YY_BREAK
+case 30:
+YY_RULE_SETUP
+#line 146 "glsl_lexer.lpp"
+return BVEC3;
+ YY_BREAK
+case 31:
+YY_RULE_SETUP
+#line 147 "glsl_lexer.lpp"
+return BVEC4;
+ YY_BREAK
+case 32:
+YY_RULE_SETUP
+#line 148 "glsl_lexer.lpp"
+return IVEC2;
+ YY_BREAK
+case 33:
+YY_RULE_SETUP
+#line 149 "glsl_lexer.lpp"
+return IVEC3;
+ YY_BREAK
+case 34:
+YY_RULE_SETUP
+#line 150 "glsl_lexer.lpp"
+return IVEC4;
+ YY_BREAK
+case 35:
+YY_RULE_SETUP
+#line 151 "glsl_lexer.lpp"
+return VEC2;
+ YY_BREAK
+case 36:
+YY_RULE_SETUP
+#line 152 "glsl_lexer.lpp"
+return VEC3;
+ YY_BREAK
+case 37:
+YY_RULE_SETUP
+#line 153 "glsl_lexer.lpp"
+return VEC4;
+ YY_BREAK
+case 38:
+YY_RULE_SETUP
+#line 154 "glsl_lexer.lpp"
+return MAT2X2;
+ YY_BREAK
+case 39:
+YY_RULE_SETUP
+#line 155 "glsl_lexer.lpp"
+return MAT3X3;
+ YY_BREAK
+case 40:
+YY_RULE_SETUP
+#line 156 "glsl_lexer.lpp"
+return MAT4X4;
+ YY_BREAK
+case 41:
+YY_RULE_SETUP
+#line 157 "glsl_lexer.lpp"
+TOKEN_OR_IDENTIFIER(120, MAT2X2);
+ YY_BREAK
+case 42:
+YY_RULE_SETUP
+#line 158 "glsl_lexer.lpp"
+TOKEN_OR_IDENTIFIER(120, MAT2X3);
+ YY_BREAK
+case 43:
+YY_RULE_SETUP
+#line 159 "glsl_lexer.lpp"
+TOKEN_OR_IDENTIFIER(120, MAT2X4);
+ YY_BREAK
+case 44:
+YY_RULE_SETUP
+#line 160 "glsl_lexer.lpp"
+TOKEN_OR_IDENTIFIER(120, MAT3X2);
+ YY_BREAK
+case 45:
+YY_RULE_SETUP
+#line 161 "glsl_lexer.lpp"
+TOKEN_OR_IDENTIFIER(120, MAT3X3);
+ YY_BREAK
+case 46:
+YY_RULE_SETUP
+#line 162 "glsl_lexer.lpp"
+TOKEN_OR_IDENTIFIER(120, MAT3X4);
+ YY_BREAK
+case 47:
+YY_RULE_SETUP
+#line 163 "glsl_lexer.lpp"
+TOKEN_OR_IDENTIFIER(120, MAT4X2);
+ YY_BREAK
+case 48:
+YY_RULE_SETUP
+#line 164 "glsl_lexer.lpp"
+TOKEN_OR_IDENTIFIER(120, MAT4X3);
+ YY_BREAK
+case 49:
+YY_RULE_SETUP
+#line 165 "glsl_lexer.lpp"
+TOKEN_OR_IDENTIFIER(120, MAT4X4);
+ YY_BREAK
+case 50:
+YY_RULE_SETUP
+#line 167 "glsl_lexer.lpp"
+return IN_TOK;
+ YY_BREAK
+case 51:
+YY_RULE_SETUP
+#line 168 "glsl_lexer.lpp"
+return OUT_TOK;
+ YY_BREAK
+case 52:
+YY_RULE_SETUP
+#line 169 "glsl_lexer.lpp"
+return INOUT_TOK;
+ YY_BREAK
+case 53:
+YY_RULE_SETUP
+#line 170 "glsl_lexer.lpp"
+return UNIFORM;
+ YY_BREAK
+case 54:
+YY_RULE_SETUP
+#line 171 "glsl_lexer.lpp"
+return VARYING;
+ YY_BREAK
+case 55:
+YY_RULE_SETUP
+#line 172 "glsl_lexer.lpp"
+TOKEN_OR_IDENTIFIER(120, CENTROID);
+ YY_BREAK
+case 56:
+YY_RULE_SETUP
+#line 173 "glsl_lexer.lpp"
+TOKEN_OR_IDENTIFIER(120, INVARIANT);
+ YY_BREAK
+case 57:
+YY_RULE_SETUP
+#line 175 "glsl_lexer.lpp"
+TOKEN_OR_IDENTIFIER(130, FLAT);
+ YY_BREAK
+case 58:
+YY_RULE_SETUP
+#line 176 "glsl_lexer.lpp"
+TOKEN_OR_IDENTIFIER(130, SMOOTH);
+ YY_BREAK
+case 59:
+YY_RULE_SETUP
+#line 177 "glsl_lexer.lpp"
+TOKEN_OR_IDENTIFIER(130, NOPERSPECTIVE);
+ YY_BREAK
+case 60:
+YY_RULE_SETUP
+#line 179 "glsl_lexer.lpp"
+return SAMPLER1D;
+ YY_BREAK
+case 61:
+YY_RULE_SETUP
+#line 180 "glsl_lexer.lpp"
+return SAMPLER2D;
+ YY_BREAK
+case 62:
+YY_RULE_SETUP
+#line 181 "glsl_lexer.lpp"
+return SAMPLER3D;
+ YY_BREAK
+case 63:
+YY_RULE_SETUP
+#line 182 "glsl_lexer.lpp"
+return SAMPLERCUBE;
+ YY_BREAK
+case 64:
+YY_RULE_SETUP
+#line 183 "glsl_lexer.lpp"
+return SAMPLER1DSHADOW;
+ YY_BREAK
+case 65:
+YY_RULE_SETUP
+#line 184 "glsl_lexer.lpp"
+return SAMPLER2DSHADOW;
+ YY_BREAK
+case 66:
+YY_RULE_SETUP
+#line 186 "glsl_lexer.lpp"
+return STRUCT;
+ YY_BREAK
+case 67:
+YY_RULE_SETUP
+#line 187 "glsl_lexer.lpp"
+return VOID_TOK;
+ YY_BREAK
+case 68:
+YY_RULE_SETUP
+#line 189 "glsl_lexer.lpp"
+{
+ if ((yyextra->language_version >= 140)
+ || (yyextra->ARB_fragment_coord_conventions_enable)){
+ return LAYOUT_TOK;
+ } else {
+ yylval->identifier = strdup(yytext);
+ return IDENTIFIER;
+ }
+ }
+ YY_BREAK
+case 69:
+YY_RULE_SETUP
+#line 199 "glsl_lexer.lpp"
+return INC_OP;
+ YY_BREAK
+case 70:
+YY_RULE_SETUP
+#line 200 "glsl_lexer.lpp"
+return DEC_OP;
+ YY_BREAK
+case 71:
+YY_RULE_SETUP
+#line 201 "glsl_lexer.lpp"
+return LE_OP;
+ YY_BREAK
+case 72:
+YY_RULE_SETUP
+#line 202 "glsl_lexer.lpp"
+return GE_OP;
+ YY_BREAK
+case 73:
+YY_RULE_SETUP
+#line 203 "glsl_lexer.lpp"
+return EQ_OP;
+ YY_BREAK
+case 74:
+YY_RULE_SETUP
+#line 204 "glsl_lexer.lpp"
+return NE_OP;
+ YY_BREAK
+case 75:
+YY_RULE_SETUP
+#line 205 "glsl_lexer.lpp"
+return AND_OP;
+ YY_BREAK
+case 76:
+YY_RULE_SETUP
+#line 206 "glsl_lexer.lpp"
+return OR_OP;
+ YY_BREAK
+case 77:
+YY_RULE_SETUP
+#line 207 "glsl_lexer.lpp"
+return XOR_OP;
+ YY_BREAK
+case 78:
+YY_RULE_SETUP
+#line 209 "glsl_lexer.lpp"
+return MUL_ASSIGN;
+ YY_BREAK
+case 79:
+YY_RULE_SETUP
+#line 210 "glsl_lexer.lpp"
+return DIV_ASSIGN;
+ YY_BREAK
+case 80:
+YY_RULE_SETUP
+#line 211 "glsl_lexer.lpp"
+return ADD_ASSIGN;
+ YY_BREAK
+case 81:
+YY_RULE_SETUP
+#line 212 "glsl_lexer.lpp"
+return MOD_ASSIGN;
+ YY_BREAK
+case 82:
+YY_RULE_SETUP
+#line 213 "glsl_lexer.lpp"
+return LEFT_ASSIGN;
+ YY_BREAK
+case 83:
+YY_RULE_SETUP
+#line 214 "glsl_lexer.lpp"
+return RIGHT_ASSIGN;
+ YY_BREAK
+case 84:
+YY_RULE_SETUP
+#line 215 "glsl_lexer.lpp"
+return AND_ASSIGN;
+ YY_BREAK
+case 85:
+YY_RULE_SETUP
+#line 216 "glsl_lexer.lpp"
+return XOR_ASSIGN;
+ YY_BREAK
+case 86:
+YY_RULE_SETUP
+#line 217 "glsl_lexer.lpp"
+return OR_ASSIGN;
+ YY_BREAK
+case 87:
+YY_RULE_SETUP
+#line 218 "glsl_lexer.lpp"
+return SUB_ASSIGN;
+ YY_BREAK
+case 88:
+YY_RULE_SETUP
+#line 220 "glsl_lexer.lpp"
+{
+ yylval->n = strtol(yytext, NULL, 10);
+ return INTCONSTANT;
+ }
+ YY_BREAK
+case 89:
+YY_RULE_SETUP
+#line 224 "glsl_lexer.lpp"
+{
+ yylval->n = strtol(yytext + 2, NULL, 16);
+ return INTCONSTANT;
+ }
+ YY_BREAK
+case 90:
+YY_RULE_SETUP
+#line 228 "glsl_lexer.lpp"
+{
+ yylval->n = strtol(yytext, NULL, 8);
+ return INTCONSTANT;
+ }
+ YY_BREAK
+case 91:
+YY_RULE_SETUP
+#line 233 "glsl_lexer.lpp"
+{
+ yylval->real = strtod(yytext, NULL);
+ return FLOATCONSTANT;
+ }
+ YY_BREAK
+case 92:
+YY_RULE_SETUP
+#line 237 "glsl_lexer.lpp"
+{
+ yylval->real = strtod(yytext, NULL);
+ return FLOATCONSTANT;
+ }
+ YY_BREAK
+case 93:
+YY_RULE_SETUP
+#line 241 "glsl_lexer.lpp"
+{
+ yylval->real = strtod(yytext, NULL);
+ return FLOATCONSTANT;
+ }
+ YY_BREAK
+case 94:
+YY_RULE_SETUP
+#line 245 "glsl_lexer.lpp"
+{
+ yylval->real = strtod(yytext, NULL);
+ return FLOATCONSTANT;
+ }
+ YY_BREAK
+case 95:
+YY_RULE_SETUP
+#line 249 "glsl_lexer.lpp"
+{
+ yylval->real = strtod(yytext, NULL);
+ return FLOATCONSTANT;
+ }
+ YY_BREAK
+case 96:
+YY_RULE_SETUP
+#line 254 "glsl_lexer.lpp"
+{
+ yylval->n = 1;
+ return BOOLCONSTANT;
+ }
+ YY_BREAK
+case 97:
+YY_RULE_SETUP
+#line 258 "glsl_lexer.lpp"
+{
+ yylval->n = 0;
+ return BOOLCONSTANT;
+ }
+ YY_BREAK
+/* Reserved words in GLSL 1.10. */
+case 98:
+YY_RULE_SETUP
+#line 265 "glsl_lexer.lpp"
+RESERVED_WORD(999, ASM);
+ YY_BREAK
+case 99:
+YY_RULE_SETUP
+#line 266 "glsl_lexer.lpp"
+RESERVED_WORD(999, CLASS);
+ YY_BREAK
+case 100:
+YY_RULE_SETUP
+#line 267 "glsl_lexer.lpp"
+RESERVED_WORD(999, UNION);
+ YY_BREAK
+case 101:
+YY_RULE_SETUP
+#line 268 "glsl_lexer.lpp"
+RESERVED_WORD(999, ENUM);
+ YY_BREAK
+case 102:
+YY_RULE_SETUP
+#line 269 "glsl_lexer.lpp"
+RESERVED_WORD(999, TYPEDEF);
+ YY_BREAK
+case 103:
+YY_RULE_SETUP
+#line 270 "glsl_lexer.lpp"
+RESERVED_WORD(999, TEMPLATE);
+ YY_BREAK
+case 104:
+YY_RULE_SETUP
+#line 271 "glsl_lexer.lpp"
+RESERVED_WORD(999, THIS);
+ YY_BREAK
+case 105:
+YY_RULE_SETUP
+#line 272 "glsl_lexer.lpp"
+RESERVED_WORD(999, PACKED_TOK);
+ YY_BREAK
+case 106:
+YY_RULE_SETUP
+#line 273 "glsl_lexer.lpp"
+RESERVED_WORD(999, GOTO);
+ YY_BREAK
+case 107:
+YY_RULE_SETUP
+#line 274 "glsl_lexer.lpp"
+RESERVED_WORD(130, SWITCH);
+ YY_BREAK
+case 108:
+YY_RULE_SETUP
+#line 275 "glsl_lexer.lpp"
+RESERVED_WORD(130, DEFAULT);
+ YY_BREAK
+case 109:
+YY_RULE_SETUP
+#line 276 "glsl_lexer.lpp"
+RESERVED_WORD(999, INLINE_TOK);
+ YY_BREAK
+case 110:
+YY_RULE_SETUP
+#line 277 "glsl_lexer.lpp"
+RESERVED_WORD(999, NOINLINE);
+ YY_BREAK
+case 111:
+YY_RULE_SETUP
+#line 278 "glsl_lexer.lpp"
+RESERVED_WORD(999, VOLATILE);
+ YY_BREAK
+case 112:
+YY_RULE_SETUP
+#line 279 "glsl_lexer.lpp"
+RESERVED_WORD(999, PUBLIC_TOK);
+ YY_BREAK
+case 113:
+YY_RULE_SETUP
+#line 280 "glsl_lexer.lpp"
+RESERVED_WORD(999, STATIC);
+ YY_BREAK
+case 114:
+YY_RULE_SETUP
+#line 281 "glsl_lexer.lpp"
+RESERVED_WORD(999, EXTERN);
+ YY_BREAK
+case 115:
+YY_RULE_SETUP
+#line 282 "glsl_lexer.lpp"
+RESERVED_WORD(999, EXTERNAL);
+ YY_BREAK
+case 116:
+YY_RULE_SETUP
+#line 283 "glsl_lexer.lpp"
+RESERVED_WORD(999, INTERFACE);
+ YY_BREAK
+case 117:
+YY_RULE_SETUP
+#line 284 "glsl_lexer.lpp"
+RESERVED_WORD(999, LONG_TOK);
+ YY_BREAK
+case 118:
+YY_RULE_SETUP
+#line 285 "glsl_lexer.lpp"
+RESERVED_WORD(999, SHORT_TOK);
+ YY_BREAK
+case 119:
+YY_RULE_SETUP
+#line 286 "glsl_lexer.lpp"
+RESERVED_WORD(999, DOUBLE_TOK);
+ YY_BREAK
+case 120:
+YY_RULE_SETUP
+#line 287 "glsl_lexer.lpp"
+RESERVED_WORD(999, HALF);
+ YY_BREAK
+case 121:
+YY_RULE_SETUP
+#line 288 "glsl_lexer.lpp"
+RESERVED_WORD(999, FIXED_TOK);
+ YY_BREAK
+case 122:
+YY_RULE_SETUP
+#line 289 "glsl_lexer.lpp"
+RESERVED_WORD(999, UNSIGNED);
+ YY_BREAK
+case 123:
+YY_RULE_SETUP
+#line 290 "glsl_lexer.lpp"
+RESERVED_WORD(999, INPUT_TOK);
+ YY_BREAK
+case 124:
+YY_RULE_SETUP
+#line 291 "glsl_lexer.lpp"
+RESERVED_WORD(999, OUTPUT);
+ YY_BREAK
+case 125:
+YY_RULE_SETUP
+#line 292 "glsl_lexer.lpp"
+RESERVED_WORD(999, HVEC2);
+ YY_BREAK
+case 126:
+YY_RULE_SETUP
+#line 293 "glsl_lexer.lpp"
+RESERVED_WORD(999, HVEC3);
+ YY_BREAK
+case 127:
+YY_RULE_SETUP
+#line 294 "glsl_lexer.lpp"
+RESERVED_WORD(999, HVEC4);
+ YY_BREAK
+case 128:
+YY_RULE_SETUP
+#line 295 "glsl_lexer.lpp"
+RESERVED_WORD(999, DVEC2);
+ YY_BREAK
+case 129:
+YY_RULE_SETUP
+#line 296 "glsl_lexer.lpp"
+RESERVED_WORD(999, DVEC3);
+ YY_BREAK
+case 130:
+YY_RULE_SETUP
+#line 297 "glsl_lexer.lpp"
+RESERVED_WORD(999, DVEC4);
+ YY_BREAK
+case 131:
+YY_RULE_SETUP
+#line 298 "glsl_lexer.lpp"
+RESERVED_WORD(999, FVEC2);
+ YY_BREAK
+case 132:
+YY_RULE_SETUP
+#line 299 "glsl_lexer.lpp"
+RESERVED_WORD(999, FVEC3);
+ YY_BREAK
+case 133:
+YY_RULE_SETUP
+#line 300 "glsl_lexer.lpp"
+RESERVED_WORD(999, FVEC4);
+ YY_BREAK
+case 134:
+YY_RULE_SETUP
+#line 301 "glsl_lexer.lpp"
+return SAMPLER2DRECT;
+ YY_BREAK
+case 135:
+YY_RULE_SETUP
+#line 302 "glsl_lexer.lpp"
+RESERVED_WORD(999, SAMPLER3DRECT);
+ YY_BREAK
+case 136:
+YY_RULE_SETUP
+#line 303 "glsl_lexer.lpp"
+return SAMPLER2DRECTSHADOW;
+ YY_BREAK
+case 137:
+YY_RULE_SETUP
+#line 304 "glsl_lexer.lpp"
+RESERVED_WORD(999, SIZEOF);
+ YY_BREAK
+case 138:
+YY_RULE_SETUP
+#line 305 "glsl_lexer.lpp"
+RESERVED_WORD(999, CAST);
+ YY_BREAK
+case 139:
+YY_RULE_SETUP
+#line 306 "glsl_lexer.lpp"
+RESERVED_WORD(999, NAMESPACE);
+ YY_BREAK
+case 140:
+YY_RULE_SETUP
+#line 307 "glsl_lexer.lpp"
+RESERVED_WORD(999, USING);
+ YY_BREAK
+/* Additional reserved words in GLSL 1.20. */
+case 141:
+YY_RULE_SETUP
+#line 310 "glsl_lexer.lpp"
+TOKEN_OR_IDENTIFIER(120, LOWP);
+ YY_BREAK
+case 142:
+YY_RULE_SETUP
+#line 311 "glsl_lexer.lpp"
+TOKEN_OR_IDENTIFIER(120, MEDIUMP);
+ YY_BREAK
+case 143:
+YY_RULE_SETUP
+#line 312 "glsl_lexer.lpp"
+TOKEN_OR_IDENTIFIER(120, HIGHP);
+ YY_BREAK
+case 144:
+YY_RULE_SETUP
+#line 313 "glsl_lexer.lpp"
+TOKEN_OR_IDENTIFIER(120, PRECISION);
+ YY_BREAK
+/* Additional reserved words in GLSL 1.30. */
+case 145:
+YY_RULE_SETUP
+#line 316 "glsl_lexer.lpp"
+TOKEN_OR_IDENTIFIER(130, COMMON);
+ YY_BREAK
+case 146:
+YY_RULE_SETUP
+#line 317 "glsl_lexer.lpp"
+TOKEN_OR_IDENTIFIER(130, PARTITION);
+ YY_BREAK
+case 147:
+YY_RULE_SETUP
+#line 318 "glsl_lexer.lpp"
+TOKEN_OR_IDENTIFIER(130, ACTIVE);
+ YY_BREAK
+case 148:
+YY_RULE_SETUP
+#line 319 "glsl_lexer.lpp"
+TOKEN_OR_IDENTIFIER(130, SUPERP);
+ YY_BREAK
+case 149:
+YY_RULE_SETUP
+#line 320 "glsl_lexer.lpp"
+TOKEN_OR_IDENTIFIER(130, SAMPLERBUFFER);
+ YY_BREAK
+case 150:
+YY_RULE_SETUP
+#line 321 "glsl_lexer.lpp"
+TOKEN_OR_IDENTIFIER(130, FILTER);
+ YY_BREAK
+case 151:
+YY_RULE_SETUP
+#line 322 "glsl_lexer.lpp"
+TOKEN_OR_IDENTIFIER(130, IMAGE1D);
+ YY_BREAK
+case 152:
+YY_RULE_SETUP
+#line 323 "glsl_lexer.lpp"
+TOKEN_OR_IDENTIFIER(130, IMAGE2D);
+ YY_BREAK
+case 153:
+YY_RULE_SETUP
+#line 324 "glsl_lexer.lpp"
+TOKEN_OR_IDENTIFIER(130, IMAGE3D);
+ YY_BREAK
+case 154:
+YY_RULE_SETUP
+#line 325 "glsl_lexer.lpp"
+TOKEN_OR_IDENTIFIER(130, IMAGECUBE);
+ YY_BREAK
+case 155:
+YY_RULE_SETUP
+#line 326 "glsl_lexer.lpp"
+TOKEN_OR_IDENTIFIER(130, IIMAGE1D);
+ YY_BREAK
+case 156:
+YY_RULE_SETUP
+#line 327 "glsl_lexer.lpp"
+TOKEN_OR_IDENTIFIER(130, IIMAGE2D);
+ YY_BREAK
+case 157:
+YY_RULE_SETUP
+#line 328 "glsl_lexer.lpp"
+TOKEN_OR_IDENTIFIER(130, IIMAGE3D);
+ YY_BREAK
+case 158:
+YY_RULE_SETUP
+#line 329 "glsl_lexer.lpp"
+TOKEN_OR_IDENTIFIER(130, IIMAGECUBE);
+ YY_BREAK
+case 159:
+YY_RULE_SETUP
+#line 330 "glsl_lexer.lpp"
+TOKEN_OR_IDENTIFIER(130, UIMAGE1D);
+ YY_BREAK
+case 160:
+YY_RULE_SETUP
+#line 331 "glsl_lexer.lpp"
+TOKEN_OR_IDENTIFIER(130, UIMAGE2D);
+ YY_BREAK
+case 161:
+YY_RULE_SETUP
+#line 332 "glsl_lexer.lpp"
+TOKEN_OR_IDENTIFIER(130, UIMAGE3D);
+ YY_BREAK
+case 162:
+YY_RULE_SETUP
+#line 333 "glsl_lexer.lpp"
+TOKEN_OR_IDENTIFIER(130, UIMAGECUBE);
+ YY_BREAK
+case 163:
+YY_RULE_SETUP
+#line 334 "glsl_lexer.lpp"
+TOKEN_OR_IDENTIFIER(130, IMAGE1DARRAY);
+ YY_BREAK
+case 164:
+YY_RULE_SETUP
+#line 335 "glsl_lexer.lpp"
+TOKEN_OR_IDENTIFIER(130, IMAGE2DARRAY);
+ YY_BREAK
+case 165:
+YY_RULE_SETUP
+#line 336 "glsl_lexer.lpp"
+TOKEN_OR_IDENTIFIER(130, IIMAGE1DARRAY);
+ YY_BREAK
+case 166:
+YY_RULE_SETUP
+#line 337 "glsl_lexer.lpp"
+TOKEN_OR_IDENTIFIER(130, IIMAGE2DARRAY);
+ YY_BREAK
+case 167:
+YY_RULE_SETUP
+#line 338 "glsl_lexer.lpp"
+TOKEN_OR_IDENTIFIER(130, UIMAGE1DARRAY);
+ YY_BREAK
+case 168:
+YY_RULE_SETUP
+#line 339 "glsl_lexer.lpp"
+TOKEN_OR_IDENTIFIER(130, UIMAGE2DARRAY);
+ YY_BREAK
+case 169:
+YY_RULE_SETUP
+#line 340 "glsl_lexer.lpp"
+TOKEN_OR_IDENTIFIER(130, IMAGE1DSHADOW);
+ YY_BREAK
+case 170:
+YY_RULE_SETUP
+#line 341 "glsl_lexer.lpp"
+TOKEN_OR_IDENTIFIER(130, IMAGE2DSHADOW);
+ YY_BREAK
+case 171:
+YY_RULE_SETUP
+#line 342 "glsl_lexer.lpp"
+TOKEN_OR_IDENTIFIER(130, IMAGEBUFFER);
+ YY_BREAK
+case 172:
+YY_RULE_SETUP
+#line 343 "glsl_lexer.lpp"
+TOKEN_OR_IDENTIFIER(130, IIMAGEBUFFER);
+ YY_BREAK
+case 173:
+YY_RULE_SETUP
+#line 344 "glsl_lexer.lpp"
+TOKEN_OR_IDENTIFIER(130, UIMAGEBUFFER);
+ YY_BREAK
+case 174:
+YY_RULE_SETUP
+#line 345 "glsl_lexer.lpp"
+TOKEN_OR_IDENTIFIER(130, ROW_MAJOR);
+ YY_BREAK
+case 175:
+YY_RULE_SETUP
+#line 347 "glsl_lexer.lpp"
+{
+ struct _mesa_glsl_parse_state *state = yyextra;
+ void *ctx = state;
+ yylval->identifier = talloc_strdup(ctx, yytext);
+ return IDENTIFIER;
+ }
+ YY_BREAK
+case 176:
+YY_RULE_SETUP
+#line 354 "glsl_lexer.lpp"
+{ return yytext[0]; }
+ YY_BREAK
+case 177:
+YY_RULE_SETUP
+#line 356 "glsl_lexer.lpp"
+ECHO;
+ YY_BREAK
+#line 2259 "glsl_lexer.cpp"
+case YY_STATE_EOF(INITIAL):
+case YY_STATE_EOF(PP):
+ yyterminate();
+
+ case YY_END_OF_BUFFER:
+ {
+ /* Amount of text matched not including the EOB char. */
+ int yy_amount_of_matched_text = (int) (yy_cp - yyg->yytext_ptr) - 1;
+
+ /* Undo the effects of YY_DO_BEFORE_ACTION. */
+ *yy_cp = yyg->yy_hold_char;
+ YY_RESTORE_YY_MORE_OFFSET
+
+ if ( YY_CURRENT_BUFFER_LVALUE->yy_buffer_status == YY_BUFFER_NEW )
+ {
+ /* We're scanning a new file or input source. It's
+ * possible that this happened because the user
+ * just pointed yyin at a new source and called
+ * _mesa_glsl_lex(). If so, then we have to assure
+ * consistency between YY_CURRENT_BUFFER and our
+ * globals. Here is the right place to do so, because
+ * this is the first action (other than possibly a
+ * back-up) that will match for the new input source.
+ */
+ yyg->yy_n_chars = YY_CURRENT_BUFFER_LVALUE->yy_n_chars;
+ YY_CURRENT_BUFFER_LVALUE->yy_input_file = yyin;
+ YY_CURRENT_BUFFER_LVALUE->yy_buffer_status = YY_BUFFER_NORMAL;
+ }
+
+ /* Note that here we test for yy_c_buf_p "<=" to the position
+ * of the first EOB in the buffer, since yy_c_buf_p will
+ * already have been incremented past the NUL character
+ * (since all states make transitions on EOB to the
+ * end-of-buffer state). Contrast this with the test
+ * in input().
+ */
+ if ( yyg->yy_c_buf_p <= &YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[yyg->yy_n_chars] )
+ { /* This was really a NUL. */
+ yy_state_type yy_next_state;
+
+ yyg->yy_c_buf_p = yyg->yytext_ptr + yy_amount_of_matched_text;
+
+ yy_current_state = yy_get_previous_state( yyscanner );
+
+ /* Okay, we're now positioned to make the NUL
+ * transition. We couldn't have
+ * yy_get_previous_state() go ahead and do it
+ * for us because it doesn't know how to deal
+ * with the possibility of jamming (and we don't
+ * want to build jamming into it because then it
+ * will run more slowly).
+ */
+
+ yy_next_state = yy_try_NUL_trans( yy_current_state , yyscanner);
+
+ yy_bp = yyg->yytext_ptr + YY_MORE_ADJ;
+
+ if ( yy_next_state )
+ {
+ /* Consume the NUL. */
+ yy_cp = ++yyg->yy_c_buf_p;
+ yy_current_state = yy_next_state;
+ goto yy_match;
+ }
+
+ else
+ {
+ yy_cp = yyg->yy_last_accepting_cpos;
+ yy_current_state = yyg->yy_last_accepting_state;
+ goto yy_find_action;
+ }
+ }
+
+ else switch ( yy_get_next_buffer( yyscanner ) )
+ {
+ case EOB_ACT_END_OF_FILE:
+ {
+ yyg->yy_did_buffer_switch_on_eof = 0;
+
+ if ( _mesa_glsl_wrap(yyscanner ) )
+ {
+ /* Note: because we've taken care in
+ * yy_get_next_buffer() to have set up
+ * yytext, we can now set up
+ * yy_c_buf_p so that if some total
+ * hoser (like flex itself) wants to
+ * call the scanner after we return the
+ * YY_NULL, it'll still work - another
+ * YY_NULL will get returned.
+ */
+ yyg->yy_c_buf_p = yyg->yytext_ptr + YY_MORE_ADJ;
+
+ yy_act = YY_STATE_EOF(YY_START);
+ goto do_action;
+ }
+
+ else
+ {
+ if ( ! yyg->yy_did_buffer_switch_on_eof )
+ YY_NEW_FILE;
+ }
+ break;
+ }
+
+ case EOB_ACT_CONTINUE_SCAN:
+ yyg->yy_c_buf_p =
+ yyg->yytext_ptr + yy_amount_of_matched_text;
+
+ yy_current_state = yy_get_previous_state( yyscanner );
+
+ yy_cp = yyg->yy_c_buf_p;
+ yy_bp = yyg->yytext_ptr + YY_MORE_ADJ;
+ goto yy_match;
+
+ case EOB_ACT_LAST_MATCH:
+ yyg->yy_c_buf_p =
+ &YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[yyg->yy_n_chars];
+
+ yy_current_state = yy_get_previous_state( yyscanner );
+
+ yy_cp = yyg->yy_c_buf_p;
+ yy_bp = yyg->yytext_ptr + YY_MORE_ADJ;
+ goto yy_find_action;
+ }
+ break;
+ }
+
+ default:
+ YY_FATAL_ERROR(
+ "fatal flex scanner internal error--no action found" );
+ } /* end of action switch */
+ } /* end of scanning one token */
+} /* end of _mesa_glsl_lex */
+
+/* yy_get_next_buffer - try to read in a new buffer
+ *
+ * Returns a code representing an action:
+ * EOB_ACT_LAST_MATCH -
+ * EOB_ACT_CONTINUE_SCAN - continue scanning from current position
+ * EOB_ACT_END_OF_FILE - end of file
+ */
+static int yy_get_next_buffer (yyscan_t yyscanner)
+{
+ struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
+ register char *dest = YY_CURRENT_BUFFER_LVALUE->yy_ch_buf;
+ register char *source = yyg->yytext_ptr;
+ register int number_to_move, i;
+ int ret_val;
+
+ if ( yyg->yy_c_buf_p > &YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[yyg->yy_n_chars + 1] )
+ YY_FATAL_ERROR(
+ "fatal flex scanner internal error--end of buffer missed" );
+
+ if ( YY_CURRENT_BUFFER_LVALUE->yy_fill_buffer == 0 )
+ { /* Don't try to fill the buffer, so this is an EOF. */
+ if ( yyg->yy_c_buf_p - yyg->yytext_ptr - YY_MORE_ADJ == 1 )
+ {
+ /* We matched a single character, the EOB, so
+ * treat this as a final EOF.
+ */
+ return EOB_ACT_END_OF_FILE;
+ }
+
+ else
+ {
+ /* We matched some text prior to the EOB, first
+ * process it.
+ */
+ return EOB_ACT_LAST_MATCH;
+ }
+ }
+
+ /* Try to read more data. */
+
+ /* First move last chars to start of buffer. */
+ number_to_move = (int) (yyg->yy_c_buf_p - yyg->yytext_ptr) - 1;
+
+ for ( i = 0; i < number_to_move; ++i )
+ *(dest++) = *(source++);
+
+ if ( YY_CURRENT_BUFFER_LVALUE->yy_buffer_status == YY_BUFFER_EOF_PENDING )
+ /* don't do the read, it's not guaranteed to return an EOF,
+ * just force an EOF
+ */
+ YY_CURRENT_BUFFER_LVALUE->yy_n_chars = yyg->yy_n_chars = 0;
+
+ else
+ {
+ int num_to_read =
+ YY_CURRENT_BUFFER_LVALUE->yy_buf_size - number_to_move - 1;
+
+ while ( num_to_read <= 0 )
+ { /* Not enough room in the buffer - grow it. */
+
+ /* just a shorter name for the current buffer */
+ YY_BUFFER_STATE b = YY_CURRENT_BUFFER;
+
+ int yy_c_buf_p_offset =
+ (int) (yyg->yy_c_buf_p - b->yy_ch_buf);
+
+ if ( b->yy_is_our_buffer )
+ {
+ int new_size = b->yy_buf_size * 2;
+
+ if ( new_size <= 0 )
+ b->yy_buf_size += b->yy_buf_size / 8;
+ else
+ b->yy_buf_size *= 2;
+
+ b->yy_ch_buf = (char *)
+ /* Include room in for 2 EOB chars. */
+ _mesa_glsl_realloc((void *) b->yy_ch_buf,b->yy_buf_size + 2 ,yyscanner );
+ }
+ else
+ /* Can't grow it, we don't own it. */
+ b->yy_ch_buf = 0;
+
+ if ( ! b->yy_ch_buf )
+ YY_FATAL_ERROR(
+ "fatal error - scanner input buffer overflow" );
+
+ yyg->yy_c_buf_p = &b->yy_ch_buf[yy_c_buf_p_offset];
+
+ num_to_read = YY_CURRENT_BUFFER_LVALUE->yy_buf_size -
+ number_to_move - 1;
+
+ }
+
+ if ( num_to_read > YY_READ_BUF_SIZE )
+ num_to_read = YY_READ_BUF_SIZE;
+
+ /* Read in more data. */
+ YY_INPUT( (&YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[number_to_move]),
+ yyg->yy_n_chars, (size_t) num_to_read );
+
+ YY_CURRENT_BUFFER_LVALUE->yy_n_chars = yyg->yy_n_chars;
+ }
+
+ if ( yyg->yy_n_chars == 0 )
+ {
+ if ( number_to_move == YY_MORE_ADJ )
+ {
+ ret_val = EOB_ACT_END_OF_FILE;
+ _mesa_glsl_restart(yyin ,yyscanner);
+ }
+
+ else
+ {
+ ret_val = EOB_ACT_LAST_MATCH;
+ YY_CURRENT_BUFFER_LVALUE->yy_buffer_status =
+ YY_BUFFER_EOF_PENDING;
+ }
+ }
+
+ else
+ ret_val = EOB_ACT_CONTINUE_SCAN;
+
+ if ((yy_size_t) (yyg->yy_n_chars + number_to_move) > YY_CURRENT_BUFFER_LVALUE->yy_buf_size) {
+ /* Extend the array by 50%, plus the number we really need. */
+ yy_size_t new_size = yyg->yy_n_chars + number_to_move + (yyg->yy_n_chars >> 1);
+ YY_CURRENT_BUFFER_LVALUE->yy_ch_buf = (char *) _mesa_glsl_realloc((void *) YY_CURRENT_BUFFER_LVALUE->yy_ch_buf,new_size ,yyscanner );
+ if ( ! YY_CURRENT_BUFFER_LVALUE->yy_ch_buf )
+ YY_FATAL_ERROR( "out of dynamic memory in yy_get_next_buffer()" );
+ }
+
+ yyg->yy_n_chars += number_to_move;
+ YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[yyg->yy_n_chars] = YY_END_OF_BUFFER_CHAR;
+ YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[yyg->yy_n_chars + 1] = YY_END_OF_BUFFER_CHAR;
+
+ yyg->yytext_ptr = &YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[0];
+
+ return ret_val;
+}
+
+/* yy_get_previous_state - get the state just before the EOB char was reached */
+
+ static yy_state_type yy_get_previous_state (yyscan_t yyscanner)
+{
+ register yy_state_type yy_current_state;
+ register char *yy_cp;
+ struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
+
+ yy_current_state = yyg->yy_start;
+ yy_current_state += YY_AT_BOL();
+
+ for ( yy_cp = yyg->yytext_ptr + YY_MORE_ADJ; yy_cp < yyg->yy_c_buf_p; ++yy_cp )
+ {
+ register YY_CHAR yy_c = (*yy_cp ? yy_ec[YY_SC_TO_UI(*yy_cp)] : 1);
+ if ( yy_accept[yy_current_state] )
+ {
+ yyg->yy_last_accepting_state = yy_current_state;
+ yyg->yy_last_accepting_cpos = yy_cp;
+ }
+ while ( yy_chk[yy_base[yy_current_state] + yy_c] != yy_current_state )
+ {
+ yy_current_state = (int) yy_def[yy_current_state];
+ if ( yy_current_state >= 668 )
+ yy_c = yy_meta[(unsigned int) yy_c];
+ }
+ yy_current_state = yy_nxt[yy_base[yy_current_state] + (unsigned int) yy_c];
+ }
+
+ return yy_current_state;
+}
+
+/* yy_try_NUL_trans - try to make a transition on the NUL character
+ *
+ * synopsis
+ * next_state = yy_try_NUL_trans( current_state );
+ */
+ static yy_state_type yy_try_NUL_trans (yy_state_type yy_current_state , yyscan_t yyscanner)
+{
+ register int yy_is_jam;
+ struct yyguts_t * yyg = (struct yyguts_t*)yyscanner; /* This var may be unused depending upon options. */
+ register char *yy_cp = yyg->yy_c_buf_p;
+
+ register YY_CHAR yy_c = 1;
+ if ( yy_accept[yy_current_state] )
+ {
+ yyg->yy_last_accepting_state = yy_current_state;
+ yyg->yy_last_accepting_cpos = yy_cp;
+ }
+ while ( yy_chk[yy_base[yy_current_state] + yy_c] != yy_current_state )
+ {
+ yy_current_state = (int) yy_def[yy_current_state];
+ if ( yy_current_state >= 668 )
+ yy_c = yy_meta[(unsigned int) yy_c];
+ }
+ yy_current_state = yy_nxt[yy_base[yy_current_state] + (unsigned int) yy_c];
+ yy_is_jam = (yy_current_state == 667);
+
+ return yy_is_jam ? 0 : yy_current_state;
+}
+
+#ifndef YY_NO_INPUT
+#ifdef __cplusplus
+ static int yyinput (yyscan_t yyscanner)
+#else
+ static int input (yyscan_t yyscanner)
+#endif
+
+{
+ int c;
+ struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
+
+ *yyg->yy_c_buf_p = yyg->yy_hold_char;
+
+ if ( *yyg->yy_c_buf_p == YY_END_OF_BUFFER_CHAR )
+ {
+ /* yy_c_buf_p now points to the character we want to return.
+ * If this occurs *before* the EOB characters, then it's a
+ * valid NUL; if not, then we've hit the end of the buffer.
+ */
+ if ( yyg->yy_c_buf_p < &YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[yyg->yy_n_chars] )
+ /* This was really a NUL. */
+ *yyg->yy_c_buf_p = '\0';
+
+ else
+ { /* need more input */
+ int offset = yyg->yy_c_buf_p - yyg->yytext_ptr;
+ ++yyg->yy_c_buf_p;
+
+ switch ( yy_get_next_buffer( yyscanner ) )
+ {
+ case EOB_ACT_LAST_MATCH:
+ /* This happens because yy_g_n_b()
+ * sees that we've accumulated a
+ * token and flags that we need to
+ * try matching the token before
+ * proceeding. But for input(),
+ * there's no matching to consider.
+ * So convert the EOB_ACT_LAST_MATCH
+ * to EOB_ACT_END_OF_FILE.
+ */
+
+ /* Reset buffer status. */
+ _mesa_glsl_restart(yyin ,yyscanner);
+
+ /*FALLTHROUGH*/
+
+ case EOB_ACT_END_OF_FILE:
+ {
+ if ( _mesa_glsl_wrap(yyscanner ) )
+ return EOF;
+
+ if ( ! yyg->yy_did_buffer_switch_on_eof )
+ YY_NEW_FILE;
+#ifdef __cplusplus
+ return yyinput(yyscanner);
+#else
+ return input(yyscanner);
+#endif
+ }
+
+ case EOB_ACT_CONTINUE_SCAN:
+ yyg->yy_c_buf_p = yyg->yytext_ptr + offset;
+ break;
+ }
+ }
+ }
+
+ c = *(unsigned char *) yyg->yy_c_buf_p; /* cast for 8-bit char's */
+ *yyg->yy_c_buf_p = '\0'; /* preserve yytext */
+ yyg->yy_hold_char = *++yyg->yy_c_buf_p;
+
+ YY_CURRENT_BUFFER_LVALUE->yy_at_bol = (c == '\n');
+
+ return c;
+}
+#endif /* ifndef YY_NO_INPUT */
+
+/** Immediately switch to a different input stream.
+ * @param input_file A readable stream.
+ * @param yyscanner The scanner object.
+ * @note This function does not reset the start condition to @c INITIAL .
+ */
+ void _mesa_glsl_restart (FILE * input_file , yyscan_t yyscanner)
+{
+ struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
+
+ if ( ! YY_CURRENT_BUFFER ){
+ _mesa_glsl_ensure_buffer_stack (yyscanner);
+ YY_CURRENT_BUFFER_LVALUE =
+ _mesa_glsl__create_buffer(yyin,YY_BUF_SIZE ,yyscanner);
+ }
+
+ _mesa_glsl__init_buffer(YY_CURRENT_BUFFER,input_file ,yyscanner);
+ _mesa_glsl__load_buffer_state(yyscanner );
+}
+
+/** Switch to a different input buffer.
+ * @param new_buffer The new input buffer.
+ * @param yyscanner The scanner object.
+ */
+ void _mesa_glsl__switch_to_buffer (YY_BUFFER_STATE new_buffer , yyscan_t yyscanner)
+{
+ struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
+
+ /* TODO. We should be able to replace this entire function body
+ * with
+ * _mesa_glsl_pop_buffer_state();
+ * _mesa_glsl_push_buffer_state(new_buffer);
+ */
+ _mesa_glsl_ensure_buffer_stack (yyscanner);
+ if ( YY_CURRENT_BUFFER == new_buffer )
+ return;
+
+ if ( YY_CURRENT_BUFFER )
+ {
+ /* Flush out information for old buffer. */
+ *yyg->yy_c_buf_p = yyg->yy_hold_char;
+ YY_CURRENT_BUFFER_LVALUE->yy_buf_pos = yyg->yy_c_buf_p;
+ YY_CURRENT_BUFFER_LVALUE->yy_n_chars = yyg->yy_n_chars;
+ }
+
+ YY_CURRENT_BUFFER_LVALUE = new_buffer;
+ _mesa_glsl__load_buffer_state(yyscanner );
+
+ /* We don't actually know whether we did this switch during
+ * EOF (_mesa_glsl_wrap()) processing, but the only time this flag
+ * is looked at is after _mesa_glsl_wrap() is called, so it's safe
+ * to go ahead and always set it.
+ */
+ yyg->yy_did_buffer_switch_on_eof = 1;
+}
+
+static void _mesa_glsl__load_buffer_state (yyscan_t yyscanner)
+{
+ struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
+ yyg->yy_n_chars = YY_CURRENT_BUFFER_LVALUE->yy_n_chars;
+ yyg->yytext_ptr = yyg->yy_c_buf_p = YY_CURRENT_BUFFER_LVALUE->yy_buf_pos;
+ yyin = YY_CURRENT_BUFFER_LVALUE->yy_input_file;
+ yyg->yy_hold_char = *yyg->yy_c_buf_p;
+}
+
+/** Allocate and initialize an input buffer state.
+ * @param file A readable stream.
+ * @param size The character buffer size in bytes. When in doubt, use @c YY_BUF_SIZE.
+ * @param yyscanner The scanner object.
+ * @return the allocated buffer state.
+ */
+ YY_BUFFER_STATE _mesa_glsl__create_buffer (FILE * file, int size , yyscan_t yyscanner)
+{
+ YY_BUFFER_STATE b;
+
+ b = (YY_BUFFER_STATE) _mesa_glsl_alloc(sizeof( struct yy_buffer_state ) ,yyscanner );
+ if ( ! b )
+ YY_FATAL_ERROR( "out of dynamic memory in _mesa_glsl__create_buffer()" );
+
+ b->yy_buf_size = size;
+
+ /* yy_ch_buf has to be 2 characters longer than the size given because
+ * we need to put in 2 end-of-buffer characters.
+ */
+ b->yy_ch_buf = (char *) _mesa_glsl_alloc(b->yy_buf_size + 2 ,yyscanner );
+ if ( ! b->yy_ch_buf )
+ YY_FATAL_ERROR( "out of dynamic memory in _mesa_glsl__create_buffer()" );
+
+ b->yy_is_our_buffer = 1;
+
+ _mesa_glsl__init_buffer(b,file ,yyscanner);
+
+ return b;
+}
+
+/** Destroy the buffer.
+ * @param b a buffer created with _mesa_glsl__create_buffer()
+ * @param yyscanner The scanner object.
+ */
+ void _mesa_glsl__delete_buffer (YY_BUFFER_STATE b , yyscan_t yyscanner)
+{
+ struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
+
+ if ( ! b )
+ return;
+
+ if ( b == YY_CURRENT_BUFFER ) /* Not sure if we should pop here. */
+ YY_CURRENT_BUFFER_LVALUE = (YY_BUFFER_STATE) 0;
+
+ if ( b->yy_is_our_buffer )
+ _mesa_glsl_free((void *) b->yy_ch_buf ,yyscanner );
+
+ _mesa_glsl_free((void *) b ,yyscanner );
+}
+
+/* Initializes or reinitializes a buffer.
+ * This function is sometimes called more than once on the same buffer,
+ * such as during a _mesa_glsl_restart() or at EOF.
+ */
+ static void _mesa_glsl__init_buffer (YY_BUFFER_STATE b, FILE * file , yyscan_t yyscanner)
+
+{
+ int oerrno = errno;
+ struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
+
+ _mesa_glsl__flush_buffer(b ,yyscanner);
+
+ b->yy_input_file = file;
+ b->yy_fill_buffer = 1;
+
+ /* If b is the current buffer, then _mesa_glsl__init_buffer was _probably_
+ * called from _mesa_glsl_restart() or through yy_get_next_buffer.
+ * In that case, we don't want to reset the lineno or column.
+ */
+ if (b != YY_CURRENT_BUFFER){
+ b->yy_bs_lineno = 1;
+ b->yy_bs_column = 0;
+ }
+
+ b->yy_is_interactive = 0;
+
+ errno = oerrno;
+}
+
+/** Discard all buffered characters. On the next scan, YY_INPUT will be called.
+ * @param b the buffer state to be flushed, usually @c YY_CURRENT_BUFFER.
+ * @param yyscanner The scanner object.
+ */
+ void _mesa_glsl__flush_buffer (YY_BUFFER_STATE b , yyscan_t yyscanner)
+{
+ struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
+ if ( ! b )
+ return;
+
+ b->yy_n_chars = 0;
+
+ /* We always need two end-of-buffer characters. The first causes
+ * a transition to the end-of-buffer state. The second causes
+ * a jam in that state.
+ */
+ b->yy_ch_buf[0] = YY_END_OF_BUFFER_CHAR;
+ b->yy_ch_buf[1] = YY_END_OF_BUFFER_CHAR;
+
+ b->yy_buf_pos = &b->yy_ch_buf[0];
+
+ b->yy_at_bol = 1;
+ b->yy_buffer_status = YY_BUFFER_NEW;
+
+ if ( b == YY_CURRENT_BUFFER )
+ _mesa_glsl__load_buffer_state(yyscanner );
+}
+
+/** Pushes the new state onto the stack. The new state becomes
+ * the current state. This function will allocate the stack
+ * if necessary.
+ * @param new_buffer The new state.
+ * @param yyscanner The scanner object.
+ */
+void _mesa_glsl_push_buffer_state (YY_BUFFER_STATE new_buffer , yyscan_t yyscanner)
+{
+ struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
+ if (new_buffer == NULL)
+ return;
+
+ _mesa_glsl_ensure_buffer_stack(yyscanner);
+
+ /* This block is copied from _mesa_glsl__switch_to_buffer. */
+ if ( YY_CURRENT_BUFFER )
+ {
+ /* Flush out information for old buffer. */
+ *yyg->yy_c_buf_p = yyg->yy_hold_char;
+ YY_CURRENT_BUFFER_LVALUE->yy_buf_pos = yyg->yy_c_buf_p;
+ YY_CURRENT_BUFFER_LVALUE->yy_n_chars = yyg->yy_n_chars;
+ }
+
+ /* Only push if top exists. Otherwise, replace top. */
+ if (YY_CURRENT_BUFFER)
+ yyg->yy_buffer_stack_top++;
+ YY_CURRENT_BUFFER_LVALUE = new_buffer;
+
+ /* copied from _mesa_glsl__switch_to_buffer. */
+ _mesa_glsl__load_buffer_state(yyscanner );
+ yyg->yy_did_buffer_switch_on_eof = 1;
+}
+
+/** Removes and deletes the top of the stack, if present.
+ * The next element becomes the new top.
+ * @param yyscanner The scanner object.
+ */
+void _mesa_glsl_pop_buffer_state (yyscan_t yyscanner)
+{
+ struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
+ if (!YY_CURRENT_BUFFER)
+ return;
+
+ _mesa_glsl__delete_buffer(YY_CURRENT_BUFFER ,yyscanner);
+ YY_CURRENT_BUFFER_LVALUE = NULL;
+ if (yyg->yy_buffer_stack_top > 0)
+ --yyg->yy_buffer_stack_top;
+
+ if (YY_CURRENT_BUFFER) {
+ _mesa_glsl__load_buffer_state(yyscanner );
+ yyg->yy_did_buffer_switch_on_eof = 1;
+ }
+}
+
+/* Allocates the stack if it does not exist.
+ * Guarantees space for at least one push.
+ */
+static void _mesa_glsl_ensure_buffer_stack (yyscan_t yyscanner)
+{
+ int num_to_alloc;
+ struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
+
+ if (!yyg->yy_buffer_stack) {
+
+ /* First allocation is just for 2 elements, since we don't know if this
+ * scanner will even need a stack. We use 2 instead of 1 to avoid an
+ * immediate realloc on the next call.
+ */
+ num_to_alloc = 1;
+ yyg->yy_buffer_stack = (struct yy_buffer_state**)_mesa_glsl_alloc
+ (num_to_alloc * sizeof(struct yy_buffer_state*)
+ , yyscanner);
+ if ( ! yyg->yy_buffer_stack )
+ YY_FATAL_ERROR( "out of dynamic memory in _mesa_glsl_ensure_buffer_stack()" );
+
+ memset(yyg->yy_buffer_stack, 0, num_to_alloc * sizeof(struct yy_buffer_state*));
+
+ yyg->yy_buffer_stack_max = num_to_alloc;
+ yyg->yy_buffer_stack_top = 0;
+ return;
+ }
+
+ if (yyg->yy_buffer_stack_top >= (yyg->yy_buffer_stack_max) - 1){
+
+ /* Increase the buffer to prepare for a possible push. */
+ int grow_size = 8 /* arbitrary grow size */;
+
+ num_to_alloc = yyg->yy_buffer_stack_max + grow_size;
+ yyg->yy_buffer_stack = (struct yy_buffer_state**)_mesa_glsl_realloc
+ (yyg->yy_buffer_stack,
+ num_to_alloc * sizeof(struct yy_buffer_state*)
+ , yyscanner);
+ if ( ! yyg->yy_buffer_stack )
+ YY_FATAL_ERROR( "out of dynamic memory in _mesa_glsl_ensure_buffer_stack()" );
+
+ /* zero only the new slots.*/
+ memset(yyg->yy_buffer_stack + yyg->yy_buffer_stack_max, 0, grow_size * sizeof(struct yy_buffer_state*));
+ yyg->yy_buffer_stack_max = num_to_alloc;
+ }
+}
+
+/** Setup the input buffer state to scan directly from a user-specified character buffer.
+ * @param base the character buffer
+ * @param size the size in bytes of the character buffer
+ * @param yyscanner The scanner object.
+ * @return the newly allocated buffer state object.
+ */
+YY_BUFFER_STATE _mesa_glsl__scan_buffer (char * base, yy_size_t size , yyscan_t yyscanner)
+{
+ YY_BUFFER_STATE b;
+
+ if ( size < 2 ||
+ base[size-2] != YY_END_OF_BUFFER_CHAR ||
+ base[size-1] != YY_END_OF_BUFFER_CHAR )
+ /* They forgot to leave room for the EOB's. */
+ return 0;
+
+ b = (YY_BUFFER_STATE) _mesa_glsl_alloc(sizeof( struct yy_buffer_state ) ,yyscanner );
+ if ( ! b )
+ YY_FATAL_ERROR( "out of dynamic memory in _mesa_glsl__scan_buffer()" );
+
+ b->yy_buf_size = size - 2; /* "- 2" to take care of EOB's */
+ b->yy_buf_pos = b->yy_ch_buf = base;
+ b->yy_is_our_buffer = 0;
+ b->yy_input_file = 0;
+ b->yy_n_chars = b->yy_buf_size;
+ b->yy_is_interactive = 0;
+ b->yy_at_bol = 1;
+ b->yy_fill_buffer = 0;
+ b->yy_buffer_status = YY_BUFFER_NEW;
+
+ _mesa_glsl__switch_to_buffer(b ,yyscanner );
+
+ return b;
+}
+
+/** Setup the input buffer state to scan a string. The next call to _mesa_glsl_lex() will
+ * scan from a @e copy of @a str.
+ * @param yystr a NUL-terminated string to scan
+ * @param yyscanner The scanner object.
+ * @return the newly allocated buffer state object.
+ * @note If you want to scan bytes that may contain NUL values, then use
+ * _mesa_glsl__scan_bytes() instead.
+ */
+YY_BUFFER_STATE _mesa_glsl__scan_string (yyconst char * yystr , yyscan_t yyscanner)
+{
+
+ return _mesa_glsl__scan_bytes(yystr,strlen(yystr) ,yyscanner);
+}
+
+/** Setup the input buffer state to scan the given bytes. The next call to _mesa_glsl_lex() will
+ * scan from a @e copy of @a bytes.
+ * @param yybytes the byte buffer to scan
+ * @param _yybytes_len the number of bytes in the buffer pointed to by @a bytes.
+ * @param yyscanner The scanner object.
+ * @return the newly allocated buffer state object.
+ */
+YY_BUFFER_STATE _mesa_glsl__scan_bytes (yyconst char * yybytes, int _yybytes_len , yyscan_t yyscanner)
+{
+ YY_BUFFER_STATE b;
+ char *buf;
+ yy_size_t n;
+ int i;
+
+ /* Get memory for full buffer, including space for trailing EOB's. */
+ n = _yybytes_len + 2;
+ buf = (char *) _mesa_glsl_alloc(n ,yyscanner );
+ if ( ! buf )
+ YY_FATAL_ERROR( "out of dynamic memory in _mesa_glsl__scan_bytes()" );
+
+ for ( i = 0; i < _yybytes_len; ++i )
+ buf[i] = yybytes[i];
+
+ buf[_yybytes_len] = buf[_yybytes_len+1] = YY_END_OF_BUFFER_CHAR;
+
+ b = _mesa_glsl__scan_buffer(buf,n ,yyscanner);
+ if ( ! b )
+ YY_FATAL_ERROR( "bad buffer in _mesa_glsl__scan_bytes()" );
+
+ /* It's okay to grow etc. this buffer, and we should throw it
+ * away when we're done.
+ */
+ b->yy_is_our_buffer = 1;
+
+ return b;
+}
+
+#ifndef YY_EXIT_FAILURE
+#define YY_EXIT_FAILURE 2
+#endif
+
+static void yy_fatal_error (yyconst char* msg , yyscan_t yyscanner)
+{
+ (void) fprintf( stderr, "%s\n", msg );
+ exit( YY_EXIT_FAILURE );
+}
+
+/* Redefine yyless() so it works in section 3 code. */
+
+#undef yyless
+#define yyless(n) \
+ do \
+ { \
+ /* Undo effects of setting up yytext. */ \
+ int yyless_macro_arg = (n); \
+ YY_LESS_LINENO(yyless_macro_arg);\
+ yytext[yyleng] = yyg->yy_hold_char; \
+ yyg->yy_c_buf_p = yytext + yyless_macro_arg; \
+ yyg->yy_hold_char = *yyg->yy_c_buf_p; \
+ *yyg->yy_c_buf_p = '\0'; \
+ yyleng = yyless_macro_arg; \
+ } \
+ while ( 0 )
+
+/* Accessor methods (get/set functions) to struct members. */
+
+/** Get the user-defined data for this scanner.
+ * @param yyscanner The scanner object.
+ */
+YY_EXTRA_TYPE _mesa_glsl_get_extra (yyscan_t yyscanner)
+{
+ struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
+ return yyextra;
+}
+
+/** Get the current line number.
+ * @param yyscanner The scanner object.
+ */
+int _mesa_glsl_get_lineno (yyscan_t yyscanner)
+{
+ struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
+
+ if (! YY_CURRENT_BUFFER)
+ return 0;
+
+ return yylineno;
+}
+
+/** Get the current column number.
+ * @param yyscanner The scanner object.
+ */
+int _mesa_glsl_get_column (yyscan_t yyscanner)
+{
+ struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
+
+ if (! YY_CURRENT_BUFFER)
+ return 0;
+
+ return yycolumn;
+}
+
+/** Get the input stream.
+ * @param yyscanner The scanner object.
+ */
+FILE *_mesa_glsl_get_in (yyscan_t yyscanner)
+{
+ struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
+ return yyin;
+}
+
+/** Get the output stream.
+ * @param yyscanner The scanner object.
+ */
+FILE *_mesa_glsl_get_out (yyscan_t yyscanner)
+{
+ struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
+ return yyout;
+}
+
+/** Get the length of the current token.
+ * @param yyscanner The scanner object.
+ */
+int _mesa_glsl_get_leng (yyscan_t yyscanner)
+{
+ struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
+ return yyleng;
+}
+
+/** Get the current token.
+ * @param yyscanner The scanner object.
+ */
+
+char *_mesa_glsl_get_text (yyscan_t yyscanner)
+{
+ struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
+ return yytext;
+}
+
+/** Set the user-defined data. This data is never touched by the scanner.
+ * @param user_defined The data to be associated with this scanner.
+ * @param yyscanner The scanner object.
+ */
+void _mesa_glsl_set_extra (YY_EXTRA_TYPE user_defined , yyscan_t yyscanner)
+{
+ struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
+ yyextra = user_defined ;
+}
+
+/** Set the current line number.
+ * @param line_number
+ * @param yyscanner The scanner object.
+ */
+void _mesa_glsl_set_lineno (int line_number , yyscan_t yyscanner)
+{
+ struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
+
+ /* lineno is only valid if an input buffer exists. */
+ if (! YY_CURRENT_BUFFER )
+ yy_fatal_error( "_mesa_glsl_set_lineno called with no buffer" , yyscanner);
+
+ yylineno = line_number;
+}
+
+/** Set the current column.
+ * @param line_number
+ * @param yyscanner The scanner object.
+ */
+void _mesa_glsl_set_column (int column_no , yyscan_t yyscanner)
+{
+ struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
+
+ /* column is only valid if an input buffer exists. */
+ if (! YY_CURRENT_BUFFER )
+ yy_fatal_error( "_mesa_glsl_set_column called with no buffer" , yyscanner);
+
+ yycolumn = column_no;
+}
+
+/** Set the input stream. This does not discard the current
+ * input buffer.
+ * @param in_str A readable stream.
+ * @param yyscanner The scanner object.
+ * @see _mesa_glsl__switch_to_buffer
+ */
+void _mesa_glsl_set_in (FILE * in_str , yyscan_t yyscanner)
+{
+ struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
+ yyin = in_str ;
+}
+
+void _mesa_glsl_set_out (FILE * out_str , yyscan_t yyscanner)
+{
+ struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
+ yyout = out_str ;
+}
+
+int _mesa_glsl_get_debug (yyscan_t yyscanner)
+{
+ struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
+ return yy_flex_debug;
+}
+
+void _mesa_glsl_set_debug (int bdebug , yyscan_t yyscanner)
+{
+ struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
+ yy_flex_debug = bdebug ;
+}
+
+/* Accessor methods for yylval and yylloc */
+
+YYSTYPE * _mesa_glsl_get_lval (yyscan_t yyscanner)
+{
+ struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
+ return yylval;
+}
+
+void _mesa_glsl_set_lval (YYSTYPE * yylval_param , yyscan_t yyscanner)
+{
+ struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
+ yylval = yylval_param;
+}
+
+YYLTYPE *_mesa_glsl_get_lloc (yyscan_t yyscanner)
+{
+ struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
+ return yylloc;
+}
+
+void _mesa_glsl_set_lloc (YYLTYPE * yylloc_param , yyscan_t yyscanner)
+{
+ struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
+ yylloc = yylloc_param;
+}
+
+/* User-visible API */
+
+/* _mesa_glsl_lex_init is special because it creates the scanner itself, so it is
+ * the ONLY reentrant function that doesn't take the scanner as the last argument.
+ * That's why we explicitly handle the declaration, instead of using our macros.
+ */
+
+int _mesa_glsl_lex_init(yyscan_t* ptr_yy_globals)
+
+{
+ if (ptr_yy_globals == NULL){
+ errno = EINVAL;
+ return 1;
+ }
+
+ *ptr_yy_globals = (yyscan_t) _mesa_glsl_alloc ( sizeof( struct yyguts_t ), NULL );
+
+ if (*ptr_yy_globals == NULL){
+ errno = ENOMEM;
+ return 1;
+ }
+
+ /* By setting to 0xAA, we expose bugs in yy_init_globals. Leave at 0x00 for releases. */
+ memset(*ptr_yy_globals,0x00,sizeof(struct yyguts_t));
+
+ return yy_init_globals ( *ptr_yy_globals );
+}
+
+/* _mesa_glsl_lex_init_extra has the same functionality as _mesa_glsl_lex_init, but follows the
+ * convention of taking the scanner as the last argument. Note however, that
+ * this is a *pointer* to a scanner, as it will be allocated by this call (and
+ * is the reason, too, why this function also must handle its own declaration).
+ * The user defined value in the first argument will be available to _mesa_glsl_alloc in
+ * the yyextra field.
+ */
+
+int _mesa_glsl_lex_init_extra(YY_EXTRA_TYPE yy_user_defined,yyscan_t* ptr_yy_globals )
+
+{
+ struct yyguts_t dummy_yyguts;
+
+ _mesa_glsl_set_extra (yy_user_defined, &dummy_yyguts);
+
+ if (ptr_yy_globals == NULL){
+ errno = EINVAL;
+ return 1;
+ }
+
+ *ptr_yy_globals = (yyscan_t) _mesa_glsl_alloc ( sizeof( struct yyguts_t ), &dummy_yyguts );
+
+ if (*ptr_yy_globals == NULL){
+ errno = ENOMEM;
+ return 1;
+ }
+
+ /* By setting to 0xAA, we expose bugs in
+ yy_init_globals. Leave at 0x00 for releases. */
+ memset(*ptr_yy_globals,0x00,sizeof(struct yyguts_t));
+
+ _mesa_glsl_set_extra (yy_user_defined, *ptr_yy_globals);
+
+ return yy_init_globals ( *ptr_yy_globals );
+}
+
+static int yy_init_globals (yyscan_t yyscanner)
+{
+ struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
+ /* Initialization is the same as for the non-reentrant scanner.
+ * This function is called from _mesa_glsl_lex_destroy(), so don't allocate here.
+ */
+
+ yyg->yy_buffer_stack = 0;
+ yyg->yy_buffer_stack_top = 0;
+ yyg->yy_buffer_stack_max = 0;
+ yyg->yy_c_buf_p = (char *) 0;
+ yyg->yy_init = 0;
+ yyg->yy_start = 0;
+
+ yyg->yy_start_stack_ptr = 0;
+ yyg->yy_start_stack_depth = 0;
+ yyg->yy_start_stack = NULL;
+
+/* Defined in main.c */
+#ifdef YY_STDINIT
+ yyin = stdin;
+ yyout = stdout;
+#else
+ yyin = (FILE *) 0;
+ yyout = (FILE *) 0;
+#endif
+
+ /* For future reference: Set errno on error, since we are called by
+ * _mesa_glsl_lex_init()
+ */
+ return 0;
+}
+
+/* _mesa_glsl_lex_destroy is for both reentrant and non-reentrant scanners. */
+int _mesa_glsl_lex_destroy (yyscan_t yyscanner)
+{
+ struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
+
+ /* Pop the buffer stack, destroying each element. */
+ while(YY_CURRENT_BUFFER){
+ _mesa_glsl__delete_buffer(YY_CURRENT_BUFFER ,yyscanner );
+ YY_CURRENT_BUFFER_LVALUE = NULL;
+ _mesa_glsl_pop_buffer_state(yyscanner);
+ }
+
+ /* Destroy the stack itself. */
+ _mesa_glsl_free(yyg->yy_buffer_stack ,yyscanner);
+ yyg->yy_buffer_stack = NULL;
+
+ /* Destroy the start condition stack. */
+ _mesa_glsl_free(yyg->yy_start_stack ,yyscanner );
+ yyg->yy_start_stack = NULL;
+
+ /* Reset the globals. This is important in a non-reentrant scanner so the next time
+ * _mesa_glsl_lex() is called, initialization will occur. */
+ yy_init_globals( yyscanner);
+
+ /* Destroy the main struct (reentrant only). */
+ _mesa_glsl_free ( yyscanner , yyscanner );
+ yyscanner = NULL;
+ return 0;
+}
+
+/*
+ * Internal utility routines.
+ */
+
+#ifndef yytext_ptr
+static void yy_flex_strncpy (char* s1, yyconst char * s2, int n , yyscan_t yyscanner)
+{
+ register int i;
+ for ( i = 0; i < n; ++i )
+ s1[i] = s2[i];
+}
+#endif
+
+#ifdef YY_NEED_STRLEN
+static int yy_flex_strlen (yyconst char * s , yyscan_t yyscanner)
+{
+ register int n;
+ for ( n = 0; s[n]; ++n )
+ ;
+
+ return n;
+}
+#endif
+
+void *_mesa_glsl_alloc (yy_size_t size , yyscan_t yyscanner)
+{
+ return (void *) malloc( size );
+}
+
+void *_mesa_glsl_realloc (void * ptr, yy_size_t size , yyscan_t yyscanner)
+{
+ /* The cast to (char *) in the following accommodates both
+ * implementations that use char* generic pointers, and those
+ * that use void* generic pointers. It works with the latter
+ * because both ANSI C and C++ allow castless assignment from
+ * any pointer type to void*, and deal with argument conversions
+ * as though doing an assignment.
+ */
+ return (void *) realloc( (char *) ptr, size );
+}
+
+void _mesa_glsl_free (void * ptr , yyscan_t yyscanner)
+{
+ free( (char *) ptr ); /* see _mesa_glsl_realloc() for (char *) cast */
+}
+
+#define YYTABLES_NAME "yytables"
+
+#line 356 "glsl_lexer.lpp"
+
+
+
+void
+_mesa_glsl_lexer_ctor(struct _mesa_glsl_parse_state *state, const char *string)
+{
+ _mesa_glsl_lex_init_extra(state,& state->scanner);
+ _mesa_glsl__scan_string(string,state->scanner);
+}
+
+void
+_mesa_glsl_lexer_dtor(struct _mesa_glsl_parse_state *state)
+{
+ _mesa_glsl_lex_destroy(state->scanner);
+}
+
diff --git a/src/glsl/glsl_lexer.lpp b/src/glsl/glsl_lexer.lpp
new file mode 100644
index 00000000000..3128cdd3a78
--- /dev/null
+++ b/src/glsl/glsl_lexer.lpp
@@ -0,0 +1,369 @@
+%{
+/*
+ * Copyright © 2008, 2009 Intel Corporation
+ *
+ * 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 (including the next
+ * paragraph) 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
+ * THE AUTHORS OR COPYRIGHT HOLDERS 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.
+ */
+#include <ctype.h>
+#include "ast.h"
+#include "glsl_parser_extras.h"
+#include "glsl_parser.h"
+
+#define YY_USER_ACTION \
+ do { \
+ yylloc->source = 0; \
+ yylloc->first_column = yycolumn + 1; \
+ yylloc->first_line = yylineno + 1; \
+ yycolumn += yyleng; \
+ } while(0);
+
+#define YY_USER_INIT yylineno = 0; yycolumn = 0;
+
+#define TOKEN_OR_IDENTIFIER(version, token) \
+ do { \
+ if (yyextra->language_version >= version) { \
+ return token; \
+ } else { \
+ yylval->identifier = strdup(yytext); \
+ return IDENTIFIER; \
+ } \
+ } while (0)
+
+#define RESERVED_WORD(version, token) \
+ do { \
+ if (yyextra->language_version >= version) { \
+ return token; \
+ } else { \
+ _mesa_glsl_error(yylloc, yyextra, \
+ "Illegal use of reserved word `%s'", yytext); \
+ return ERROR_TOK; \
+ } \
+ } while (0)
+%}
+
+%option bison-bridge bison-locations reentrant noyywrap
+%option nounput noyy_top_state
+%option never-interactive
+%option prefix="_mesa_glsl_"
+%option extra-type="struct _mesa_glsl_parse_state *"
+
+%x PP
+
+DEC_INT [1-9][0-9]*
+HEX_INT 0[xX][0-9a-fA-F]+
+OCT_INT 0[0-7]*
+INT ({DEC_INT}|{HEX_INT}|{OCT_INT})
+SPC [ \t]*
+SPCP [ \t]+
+HASH ^{SPC}#{SPC}
+%%
+
+[ \r\t]+ ;
+
+ /* Preprocessor tokens. */
+^[ \t]*#[ \t]*$ ;
+^[ \t]*#[ \t]*version { BEGIN PP; return VERSION; }
+^[ \t]*#[ \t]*extension { BEGIN PP; return EXTENSION; }
+{HASH}line{SPCP}{INT}{SPCP}{INT}{SPC}$ {
+ /* Eat characters until the first digit is
+ * encountered
+ */
+ char *ptr = yytext;
+ while (!isdigit(*ptr))
+ ptr++;
+
+ /* Subtract one from the line number because
+ * yylineno is zero-based instead of
+ * one-based.
+ */
+ yylineno = strtol(ptr, &ptr, 0) - 1;
+ yylloc->source = strtol(ptr, NULL, 0);
+ }
+{HASH}line{SPCP}{INT}{SPC}$ {
+ /* Eat characters until the first digit is
+ * encountered
+ */
+ char *ptr = yytext;
+ while (!isdigit(*ptr))
+ ptr++;
+
+ /* Subtract one from the line number because
+ * yylineno is zero-based instead of
+ * one-based.
+ */
+ yylineno = strtol(ptr, &ptr, 0) - 1;
+ }
+^[ \t]*#[ \t]*pragma { BEGIN PP; return PRAGMA; }
+<PP>\/\/[^\n]* { }
+<PP>[ \t\r]* { }
+<PP>: return COLON;
+<PP>[_a-zA-Z][_a-zA-Z0-9]* {
+ yylval->identifier = strdup(yytext);
+ return IDENTIFIER;
+ }
+<PP>[1-9][0-9]* {
+ yylval->n = strtol(yytext, NULL, 10);
+ return INTCONSTANT;
+ }
+<PP>\n { BEGIN 0; yylineno++; yycolumn = 0; return EOL; }
+
+\n { yylineno++; yycolumn = 0; }
+
+attribute return ATTRIBUTE;
+const return CONST_TOK;
+bool return BOOL_TOK;
+float return FLOAT_TOK;
+int return INT_TOK;
+
+break return BREAK;
+continue return CONTINUE;
+do return DO;
+while return WHILE;
+else return ELSE;
+for return FOR;
+if return IF;
+discard return DISCARD;
+return return RETURN;
+
+bvec2 return BVEC2;
+bvec3 return BVEC3;
+bvec4 return BVEC4;
+ivec2 return IVEC2;
+ivec3 return IVEC3;
+ivec4 return IVEC4;
+vec2 return VEC2;
+vec3 return VEC3;
+vec4 return VEC4;
+mat2 return MAT2X2;
+mat3 return MAT3X3;
+mat4 return MAT4X4;
+mat2x2 TOKEN_OR_IDENTIFIER(120, MAT2X2);
+mat2x3 TOKEN_OR_IDENTIFIER(120, MAT2X3);
+mat2x4 TOKEN_OR_IDENTIFIER(120, MAT2X4);
+mat3x2 TOKEN_OR_IDENTIFIER(120, MAT3X2);
+mat3x3 TOKEN_OR_IDENTIFIER(120, MAT3X3);
+mat3x4 TOKEN_OR_IDENTIFIER(120, MAT3X4);
+mat4x2 TOKEN_OR_IDENTIFIER(120, MAT4X2);
+mat4x3 TOKEN_OR_IDENTIFIER(120, MAT4X3);
+mat4x4 TOKEN_OR_IDENTIFIER(120, MAT4X4);
+
+in return IN_TOK;
+out return OUT_TOK;
+inout return INOUT_TOK;
+uniform return UNIFORM;
+varying return VARYING;
+centroid TOKEN_OR_IDENTIFIER(120, CENTROID);
+invariant TOKEN_OR_IDENTIFIER(120, INVARIANT);
+
+flat TOKEN_OR_IDENTIFIER(130, FLAT);
+smooth TOKEN_OR_IDENTIFIER(130, SMOOTH);
+noperspective TOKEN_OR_IDENTIFIER(130, NOPERSPECTIVE);
+
+sampler1D return SAMPLER1D;
+sampler2D return SAMPLER2D;
+sampler3D return SAMPLER3D;
+samplerCube return SAMPLERCUBE;
+sampler1DShadow return SAMPLER1DSHADOW;
+sampler2DShadow return SAMPLER2DSHADOW;
+
+struct return STRUCT;
+void return VOID_TOK;
+
+layout {
+ if ((yyextra->language_version >= 140)
+ || (yyextra->ARB_fragment_coord_conventions_enable)){
+ return LAYOUT_TOK;
+ } else {
+ yylval->identifier = strdup(yytext);
+ return IDENTIFIER;
+ }
+ }
+
+\+\+ return INC_OP;
+-- return DEC_OP;
+\<= return LE_OP;
+>= return GE_OP;
+== return EQ_OP;
+!= return NE_OP;
+&& return AND_OP;
+\|\| return OR_OP;
+"^^" return XOR_OP;
+
+\*= return MUL_ASSIGN;
+\/= return DIV_ASSIGN;
+\+= return ADD_ASSIGN;
+\%= return MOD_ASSIGN;
+\<\<= return LEFT_ASSIGN;
+>>= return RIGHT_ASSIGN;
+&= return AND_ASSIGN;
+^= return XOR_ASSIGN;
+\|= return OR_ASSIGN;
+-= return SUB_ASSIGN;
+
+[1-9][0-9]* {
+ yylval->n = strtol(yytext, NULL, 10);
+ return INTCONSTANT;
+ }
+0[xX][0-9a-fA-F]+ {
+ yylval->n = strtol(yytext + 2, NULL, 16);
+ return INTCONSTANT;
+ }
+0[0-7]* {
+ yylval->n = strtol(yytext, NULL, 8);
+ return INTCONSTANT;
+ }
+
+[0-9]+\.[0-9]+([eE][+-]?[0-9]+)?[fF]? {
+ yylval->real = strtod(yytext, NULL);
+ return FLOATCONSTANT;
+ }
+\.[0-9]+([eE][+-]?[0-9]+)?[fF]? {
+ yylval->real = strtod(yytext, NULL);
+ return FLOATCONSTANT;
+ }
+[0-9]+\.([eE][+-]?[0-9]+)?[fF]? {
+ yylval->real = strtod(yytext, NULL);
+ return FLOATCONSTANT;
+ }
+[0-9]+[eE][+-]?[0-9]+[fF]? {
+ yylval->real = strtod(yytext, NULL);
+ return FLOATCONSTANT;
+ }
+[0-9]+[fF] {
+ yylval->real = strtod(yytext, NULL);
+ return FLOATCONSTANT;
+ }
+
+true {
+ yylval->n = 1;
+ return BOOLCONSTANT;
+ }
+false {
+ yylval->n = 0;
+ return BOOLCONSTANT;
+ }
+
+
+ /* Reserved words in GLSL 1.10. */
+asm RESERVED_WORD(999, ASM);
+class RESERVED_WORD(999, CLASS);
+union RESERVED_WORD(999, UNION);
+enum RESERVED_WORD(999, ENUM);
+typedef RESERVED_WORD(999, TYPEDEF);
+template RESERVED_WORD(999, TEMPLATE);
+this RESERVED_WORD(999, THIS);
+packed RESERVED_WORD(999, PACKED_TOK);
+goto RESERVED_WORD(999, GOTO);
+switch RESERVED_WORD(130, SWITCH);
+default RESERVED_WORD(130, DEFAULT);
+inline RESERVED_WORD(999, INLINE_TOK);
+noinline RESERVED_WORD(999, NOINLINE);
+volatile RESERVED_WORD(999, VOLATILE);
+public RESERVED_WORD(999, PUBLIC_TOK);
+static RESERVED_WORD(999, STATIC);
+extern RESERVED_WORD(999, EXTERN);
+external RESERVED_WORD(999, EXTERNAL);
+interface RESERVED_WORD(999, INTERFACE);
+long RESERVED_WORD(999, LONG_TOK);
+short RESERVED_WORD(999, SHORT_TOK);
+double RESERVED_WORD(999, DOUBLE_TOK);
+half RESERVED_WORD(999, HALF);
+fixed RESERVED_WORD(999, FIXED_TOK);
+unsigned RESERVED_WORD(999, UNSIGNED);
+input RESERVED_WORD(999, INPUT_TOK);
+output RESERVED_WORD(999, OUTPUT);
+hvec2 RESERVED_WORD(999, HVEC2);
+hvec3 RESERVED_WORD(999, HVEC3);
+hvec4 RESERVED_WORD(999, HVEC4);
+dvec2 RESERVED_WORD(999, DVEC2);
+dvec3 RESERVED_WORD(999, DVEC3);
+dvec4 RESERVED_WORD(999, DVEC4);
+fvec2 RESERVED_WORD(999, FVEC2);
+fvec3 RESERVED_WORD(999, FVEC3);
+fvec4 RESERVED_WORD(999, FVEC4);
+sampler2DRect return SAMPLER2DRECT;
+sampler3DRect RESERVED_WORD(999, SAMPLER3DRECT);
+sampler2DRectShadow return SAMPLER2DRECTSHADOW;
+sizeof RESERVED_WORD(999, SIZEOF);
+cast RESERVED_WORD(999, CAST);
+namespace RESERVED_WORD(999, NAMESPACE);
+using RESERVED_WORD(999, USING);
+
+ /* Additional reserved words in GLSL 1.20. */
+lowp TOKEN_OR_IDENTIFIER(120, LOWP);
+mediump TOKEN_OR_IDENTIFIER(120, MEDIUMP);
+highp TOKEN_OR_IDENTIFIER(120, HIGHP);
+precision TOKEN_OR_IDENTIFIER(120, PRECISION);
+
+ /* Additional reserved words in GLSL 1.30. */
+common TOKEN_OR_IDENTIFIER(130, COMMON);
+partition TOKEN_OR_IDENTIFIER(130, PARTITION);
+active TOKEN_OR_IDENTIFIER(130, ACTIVE);
+superp TOKEN_OR_IDENTIFIER(130, SUPERP);
+samplerBuffer TOKEN_OR_IDENTIFIER(130, SAMPLERBUFFER);
+filter TOKEN_OR_IDENTIFIER(130, FILTER);
+image1D TOKEN_OR_IDENTIFIER(130, IMAGE1D);
+image2D TOKEN_OR_IDENTIFIER(130, IMAGE2D);
+image3D TOKEN_OR_IDENTIFIER(130, IMAGE3D);
+imageCube TOKEN_OR_IDENTIFIER(130, IMAGECUBE);
+iimage1D TOKEN_OR_IDENTIFIER(130, IIMAGE1D);
+iimage2D TOKEN_OR_IDENTIFIER(130, IIMAGE2D);
+iimage3D TOKEN_OR_IDENTIFIER(130, IIMAGE3D);
+iimageCube TOKEN_OR_IDENTIFIER(130, IIMAGECUBE);
+uimage1D TOKEN_OR_IDENTIFIER(130, UIMAGE1D);
+uimage2D TOKEN_OR_IDENTIFIER(130, UIMAGE2D);
+uimage3D TOKEN_OR_IDENTIFIER(130, UIMAGE3D);
+uimageCube TOKEN_OR_IDENTIFIER(130, UIMAGECUBE);
+image1DArray TOKEN_OR_IDENTIFIER(130, IMAGE1DARRAY);
+image2DArray TOKEN_OR_IDENTIFIER(130, IMAGE2DARRAY);
+iimage1DArray TOKEN_OR_IDENTIFIER(130, IIMAGE1DARRAY);
+iimage2DArray TOKEN_OR_IDENTIFIER(130, IIMAGE2DARRAY);
+uimage1DArray TOKEN_OR_IDENTIFIER(130, UIMAGE1DARRAY);
+uimage2DArray TOKEN_OR_IDENTIFIER(130, UIMAGE2DARRAY);
+image1DShadow TOKEN_OR_IDENTIFIER(130, IMAGE1DSHADOW);
+image2DShadow TOKEN_OR_IDENTIFIER(130, IMAGE2DSHADOW);
+imageBuffer TOKEN_OR_IDENTIFIER(130, IMAGEBUFFER);
+iimageBuffer TOKEN_OR_IDENTIFIER(130, IIMAGEBUFFER);
+uimageBuffer TOKEN_OR_IDENTIFIER(130, UIMAGEBUFFER);
+row_major TOKEN_OR_IDENTIFIER(130, ROW_MAJOR);
+
+[_a-zA-Z][_a-zA-Z0-9]* {
+ struct _mesa_glsl_parse_state *state = yyextra;
+ void *ctx = state;
+ yylval->identifier = talloc_strdup(ctx, yytext);
+ return IDENTIFIER;
+ }
+
+. { return yytext[0]; }
+
+%%
+
+void
+_mesa_glsl_lexer_ctor(struct _mesa_glsl_parse_state *state, const char *string)
+{
+ yylex_init_extra(state, & state->scanner);
+ yy_scan_string(string, state->scanner);
+}
+
+void
+_mesa_glsl_lexer_dtor(struct _mesa_glsl_parse_state *state)
+{
+ yylex_destroy(state->scanner);
+}
diff --git a/src/glsl/glsl_parser.cpp b/src/glsl/glsl_parser.cpp
new file mode 100644
index 00000000000..7df9e96d16f
--- /dev/null
+++ b/src/glsl/glsl_parser.cpp
@@ -0,0 +1,5245 @@
+
+/* A Bison parser, made by GNU Bison 2.4.1. */
+
+/* Skeleton implementation for Bison's Yacc-like parsers in C
+
+ Copyright (C) 1984, 1989, 1990, 2000, 2001, 2002, 2003, 2004, 2005, 2006
+ Free Software Foundation, Inc.
+
+ This program is free software: you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program. If not, see <http://www.gnu.org/licenses/>. */
+
+/* As a special exception, you may create a larger work that contains
+ part or all of the Bison parser skeleton and distribute that work
+ under terms of your choice, so long as that work isn't itself a
+ parser generator using the skeleton or a modified version thereof
+ as a parser skeleton. Alternatively, if you modify or redistribute
+ the parser skeleton itself, you may (at your option) remove this
+ special exception, which will cause the skeleton and the resulting
+ Bison output files to be licensed under the GNU General Public
+ License without this special exception.
+
+ This special exception was added by the Free Software Foundation in
+ version 2.2 of Bison. */
+
+/* C LALR(1) parser skeleton written by Richard Stallman, by
+ simplifying the original so-called "semantic" parser. */
+
+/* All symbols defined below should begin with yy or YY, to avoid
+ infringing on user name space. This should be done even for local
+ variables, as they might otherwise be expanded by user macros.
+ There are some unavoidable exceptions within include files to
+ define necessary library symbols; they are noted "INFRINGES ON
+ USER NAME SPACE" below. */
+
+/* Identify Bison output. */
+#define YYBISON 1
+
+/* Bison version. */
+#define YYBISON_VERSION "2.4.1"
+
+/* Skeleton name. */
+#define YYSKELETON_NAME "yacc.c"
+
+/* Pure parsers. */
+#define YYPURE 1
+
+/* Push parsers. */
+#define YYPUSH 0
+
+/* Pull parsers. */
+#define YYPULL 1
+
+/* Using locations. */
+#define YYLSP_NEEDED 1
+
+/* Substitute the variable and function names. */
+#define yyparse _mesa_glsl_parse
+#define yylex _mesa_glsl_lex
+#define yyerror _mesa_glsl_error
+#define yylval _mesa_glsl_lval
+#define yychar _mesa_glsl_char
+#define yydebug _mesa_glsl_debug
+#define yynerrs _mesa_glsl_nerrs
+#define yylloc _mesa_glsl_lloc
+
+/* Copy the first part of user declarations. */
+
+/* Line 189 of yacc.c */
+#line 1 "glsl_parser.ypp"
+
+/*
+ * Copyright © 2008, 2009 Intel Corporation
+ *
+ * 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 (including the next
+ * paragraph) 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
+ * THE AUTHORS OR COPYRIGHT HOLDERS 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.
+ */
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <assert.h>
+
+#include "ast.h"
+#include "glsl_parser_extras.h"
+#include "glsl_types.h"
+
+#define YYLEX_PARAM state->scanner
+
+
+
+/* Line 189 of yacc.c */
+#line 118 "glsl_parser.cpp"
+
+/* Enabling traces. */
+#ifndef YYDEBUG
+# define YYDEBUG 0
+#endif
+
+/* Enabling verbose error messages. */
+#ifdef YYERROR_VERBOSE
+# undef YYERROR_VERBOSE
+# define YYERROR_VERBOSE 1
+#else
+# define YYERROR_VERBOSE 1
+#endif
+
+/* Enabling the token table. */
+#ifndef YYTOKEN_TABLE
+# define YYTOKEN_TABLE 0
+#endif
+
+
+/* Tokens. */
+#ifndef YYTOKENTYPE
+# define YYTOKENTYPE
+ /* Put the tokens into the symbol table, so that GDB and other debuggers
+ know about them. */
+ enum yytokentype {
+ ATTRIBUTE = 258,
+ CONST_TOK = 259,
+ BOOL_TOK = 260,
+ FLOAT_TOK = 261,
+ INT_TOK = 262,
+ UINT_TOK = 263,
+ BREAK = 264,
+ CONTINUE = 265,
+ DO = 266,
+ ELSE = 267,
+ FOR = 268,
+ IF = 269,
+ DISCARD = 270,
+ RETURN = 271,
+ SWITCH = 272,
+ CASE = 273,
+ DEFAULT = 274,
+ BVEC2 = 275,
+ BVEC3 = 276,
+ BVEC4 = 277,
+ IVEC2 = 278,
+ IVEC3 = 279,
+ IVEC4 = 280,
+ UVEC2 = 281,
+ UVEC3 = 282,
+ UVEC4 = 283,
+ VEC2 = 284,
+ VEC3 = 285,
+ VEC4 = 286,
+ CENTROID = 287,
+ IN_TOK = 288,
+ OUT_TOK = 289,
+ INOUT_TOK = 290,
+ UNIFORM = 291,
+ VARYING = 292,
+ NOPERSPECTIVE = 293,
+ FLAT = 294,
+ SMOOTH = 295,
+ MAT2X2 = 296,
+ MAT2X3 = 297,
+ MAT2X4 = 298,
+ MAT3X2 = 299,
+ MAT3X3 = 300,
+ MAT3X4 = 301,
+ MAT4X2 = 302,
+ MAT4X3 = 303,
+ MAT4X4 = 304,
+ SAMPLER1D = 305,
+ SAMPLER2D = 306,
+ SAMPLER3D = 307,
+ SAMPLERCUBE = 308,
+ SAMPLER1DSHADOW = 309,
+ SAMPLER2DSHADOW = 310,
+ SAMPLERCUBESHADOW = 311,
+ SAMPLER1DARRAY = 312,
+ SAMPLER2DARRAY = 313,
+ SAMPLER1DARRAYSHADOW = 314,
+ SAMPLER2DARRAYSHADOW = 315,
+ ISAMPLER1D = 316,
+ ISAMPLER2D = 317,
+ ISAMPLER3D = 318,
+ ISAMPLERCUBE = 319,
+ ISAMPLER1DARRAY = 320,
+ ISAMPLER2DARRAY = 321,
+ USAMPLER1D = 322,
+ USAMPLER2D = 323,
+ USAMPLER3D = 324,
+ USAMPLERCUBE = 325,
+ USAMPLER1DARRAY = 326,
+ USAMPLER2DARRAY = 327,
+ STRUCT = 328,
+ VOID_TOK = 329,
+ WHILE = 330,
+ IDENTIFIER = 331,
+ FLOATCONSTANT = 332,
+ INTCONSTANT = 333,
+ UINTCONSTANT = 334,
+ BOOLCONSTANT = 335,
+ FIELD_SELECTION = 336,
+ LEFT_OP = 337,
+ RIGHT_OP = 338,
+ INC_OP = 339,
+ DEC_OP = 340,
+ LE_OP = 341,
+ GE_OP = 342,
+ EQ_OP = 343,
+ NE_OP = 344,
+ AND_OP = 345,
+ OR_OP = 346,
+ XOR_OP = 347,
+ MUL_ASSIGN = 348,
+ DIV_ASSIGN = 349,
+ ADD_ASSIGN = 350,
+ MOD_ASSIGN = 351,
+ LEFT_ASSIGN = 352,
+ RIGHT_ASSIGN = 353,
+ AND_ASSIGN = 354,
+ XOR_ASSIGN = 355,
+ OR_ASSIGN = 356,
+ SUB_ASSIGN = 357,
+ INVARIANT = 358,
+ LOWP = 359,
+ MEDIUMP = 360,
+ HIGHP = 361,
+ SUPERP = 362,
+ PRECISION = 363,
+ VERSION = 364,
+ EXTENSION = 365,
+ LINE = 366,
+ PRAGMA = 367,
+ COLON = 368,
+ EOL = 369,
+ INTERFACE = 370,
+ OUTPUT = 371,
+ LAYOUT_TOK = 372,
+ ASM = 373,
+ CLASS = 374,
+ UNION = 375,
+ ENUM = 376,
+ TYPEDEF = 377,
+ TEMPLATE = 378,
+ THIS = 379,
+ PACKED_TOK = 380,
+ GOTO = 381,
+ INLINE_TOK = 382,
+ NOINLINE = 383,
+ VOLATILE = 384,
+ PUBLIC_TOK = 385,
+ STATIC = 386,
+ EXTERN = 387,
+ EXTERNAL = 388,
+ LONG_TOK = 389,
+ SHORT_TOK = 390,
+ DOUBLE_TOK = 391,
+ HALF = 392,
+ FIXED_TOK = 393,
+ UNSIGNED = 394,
+ INPUT_TOK = 395,
+ OUPTUT = 396,
+ HVEC2 = 397,
+ HVEC3 = 398,
+ HVEC4 = 399,
+ DVEC2 = 400,
+ DVEC3 = 401,
+ DVEC4 = 402,
+ FVEC2 = 403,
+ FVEC3 = 404,
+ FVEC4 = 405,
+ SAMPLER2DRECT = 406,
+ SAMPLER3DRECT = 407,
+ SAMPLER2DRECTSHADOW = 408,
+ SIZEOF = 409,
+ CAST = 410,
+ NAMESPACE = 411,
+ USING = 412,
+ ERROR_TOK = 413,
+ COMMON = 414,
+ PARTITION = 415,
+ ACTIVE = 416,
+ SAMPLERBUFFER = 417,
+ FILTER = 418,
+ IMAGE1D = 419,
+ IMAGE2D = 420,
+ IMAGE3D = 421,
+ IMAGECUBE = 422,
+ IMAGE1DARRAY = 423,
+ IMAGE2DARRAY = 424,
+ IIMAGE1D = 425,
+ IIMAGE2D = 426,
+ IIMAGE3D = 427,
+ IIMAGECUBE = 428,
+ IIMAGE1DARRAY = 429,
+ IIMAGE2DARRAY = 430,
+ UIMAGE1D = 431,
+ UIMAGE2D = 432,
+ UIMAGE3D = 433,
+ UIMAGECUBE = 434,
+ UIMAGE1DARRAY = 435,
+ UIMAGE2DARRAY = 436,
+ IMAGE1DSHADOW = 437,
+ IMAGE2DSHADOW = 438,
+ IMAGEBUFFER = 439,
+ IIMAGEBUFFER = 440,
+ UIMAGEBUFFER = 441,
+ ROW_MAJOR = 442
+ };
+#endif
+
+
+
+#if ! defined YYSTYPE && ! defined YYSTYPE_IS_DECLARED
+typedef union YYSTYPE
+{
+
+/* Line 214 of yacc.c */
+#line 52 "glsl_parser.ypp"
+
+ int n;
+ float real;
+ char *identifier;
+
+ union {
+ struct ast_type_qualifier q;
+ unsigned i;
+ } type_qualifier;
+
+ ast_node *node;
+ ast_type_specifier *type_specifier;
+ ast_fully_specified_type *fully_specified_type;
+ ast_function *function;
+ ast_parameter_declarator *parameter_declarator;
+ ast_function_definition *function_definition;
+ ast_compound_statement *compound_statement;
+ ast_expression *expression;
+ ast_declarator_list *declarator_list;
+ ast_struct_specifier *struct_specifier;
+ ast_declaration *declaration;
+
+ struct {
+ ast_node *cond;
+ ast_expression *rest;
+ } for_rest_statement;
+
+
+
+/* Line 214 of yacc.c */
+#line 371 "glsl_parser.cpp"
+} YYSTYPE;
+# define YYSTYPE_IS_TRIVIAL 1
+# define yystype YYSTYPE /* obsolescent; will be withdrawn */
+# define YYSTYPE_IS_DECLARED 1
+#endif
+
+#if ! defined YYLTYPE && ! defined YYLTYPE_IS_DECLARED
+typedef struct YYLTYPE
+{
+ int first_line;
+ int first_column;
+ int last_line;
+ int last_column;
+} YYLTYPE;
+# define yyltype YYLTYPE /* obsolescent; will be withdrawn */
+# define YYLTYPE_IS_DECLARED 1
+# define YYLTYPE_IS_TRIVIAL 1
+#endif
+
+
+/* Copy the second part of user declarations. */
+
+
+/* Line 264 of yacc.c */
+#line 396 "glsl_parser.cpp"
+
+#ifdef short
+# undef short
+#endif
+
+#ifdef YYTYPE_UINT8
+typedef YYTYPE_UINT8 yytype_uint8;
+#else
+typedef unsigned char yytype_uint8;
+#endif
+
+#ifdef YYTYPE_INT8
+typedef YYTYPE_INT8 yytype_int8;
+#elif (defined __STDC__ || defined __C99__FUNC__ \
+ || defined __cplusplus || defined _MSC_VER)
+typedef signed char yytype_int8;
+#else
+typedef short int yytype_int8;
+#endif
+
+#ifdef YYTYPE_UINT16
+typedef YYTYPE_UINT16 yytype_uint16;
+#else
+typedef unsigned short int yytype_uint16;
+#endif
+
+#ifdef YYTYPE_INT16
+typedef YYTYPE_INT16 yytype_int16;
+#else
+typedef short int yytype_int16;
+#endif
+
+#ifndef YYSIZE_T
+# ifdef __SIZE_TYPE__
+# define YYSIZE_T __SIZE_TYPE__
+# elif defined size_t
+# define YYSIZE_T size_t
+# elif ! defined YYSIZE_T && (defined __STDC__ || defined __C99__FUNC__ \
+ || defined __cplusplus || defined _MSC_VER)
+# include <stddef.h> /* INFRINGES ON USER NAME SPACE */
+# define YYSIZE_T size_t
+# else
+# define YYSIZE_T unsigned int
+# endif
+#endif
+
+#define YYSIZE_MAXIMUM ((YYSIZE_T) -1)
+
+#ifndef YY_
+# if YYENABLE_NLS
+# if ENABLE_NLS
+# include <libintl.h> /* INFRINGES ON USER NAME SPACE */
+# define YY_(msgid) dgettext ("bison-runtime", msgid)
+# endif
+# endif
+# ifndef YY_
+# define YY_(msgid) msgid
+# endif
+#endif
+
+/* Suppress unused-variable warnings by "using" E. */
+#if ! defined lint || defined __GNUC__
+# define YYUSE(e) ((void) (e))
+#else
+# define YYUSE(e) /* empty */
+#endif
+
+/* Identity function, used to suppress warnings about constant conditions. */
+#ifndef lint
+# define YYID(n) (n)
+#else
+#if (defined __STDC__ || defined __C99__FUNC__ \
+ || defined __cplusplus || defined _MSC_VER)
+static int
+YYID (int yyi)
+#else
+static int
+YYID (yyi)
+ int yyi;
+#endif
+{
+ return yyi;
+}
+#endif
+
+#if ! defined yyoverflow || YYERROR_VERBOSE
+
+/* The parser invokes alloca or malloc; define the necessary symbols. */
+
+# ifdef YYSTACK_USE_ALLOCA
+# if YYSTACK_USE_ALLOCA
+# ifdef __GNUC__
+# define YYSTACK_ALLOC __builtin_alloca
+# elif defined __BUILTIN_VA_ARG_INCR
+# include <alloca.h> /* INFRINGES ON USER NAME SPACE */
+# elif defined _AIX
+# define YYSTACK_ALLOC __alloca
+# elif defined _MSC_VER
+# include <malloc.h> /* INFRINGES ON USER NAME SPACE */
+# define alloca _alloca
+# else
+# define YYSTACK_ALLOC alloca
+# if ! defined _ALLOCA_H && ! defined _STDLIB_H && (defined __STDC__ || defined __C99__FUNC__ \
+ || defined __cplusplus || defined _MSC_VER)
+# include <stdlib.h> /* INFRINGES ON USER NAME SPACE */
+# ifndef _STDLIB_H
+# define _STDLIB_H 1
+# endif
+# endif
+# endif
+# endif
+# endif
+
+# ifdef YYSTACK_ALLOC
+ /* Pacify GCC's `empty if-body' warning. */
+# define YYSTACK_FREE(Ptr) do { /* empty */; } while (YYID (0))
+# ifndef YYSTACK_ALLOC_MAXIMUM
+ /* The OS might guarantee only one guard page at the bottom of the stack,
+ and a page size can be as small as 4096 bytes. So we cannot safely
+ invoke alloca (N) if N exceeds 4096. Use a slightly smaller number
+ to allow for a few compiler-allocated temporary stack slots. */
+# define YYSTACK_ALLOC_MAXIMUM 4032 /* reasonable circa 2006 */
+# endif
+# else
+# define YYSTACK_ALLOC YYMALLOC
+# define YYSTACK_FREE YYFREE
+# ifndef YYSTACK_ALLOC_MAXIMUM
+# define YYSTACK_ALLOC_MAXIMUM YYSIZE_MAXIMUM
+# endif
+# if (defined __cplusplus && ! defined _STDLIB_H \
+ && ! ((defined YYMALLOC || defined malloc) \
+ && (defined YYFREE || defined free)))
+# include <stdlib.h> /* INFRINGES ON USER NAME SPACE */
+# ifndef _STDLIB_H
+# define _STDLIB_H 1
+# endif
+# endif
+# ifndef YYMALLOC
+# define YYMALLOC malloc
+# if ! defined malloc && ! defined _STDLIB_H && (defined __STDC__ || defined __C99__FUNC__ \
+ || defined __cplusplus || defined _MSC_VER)
+void *malloc (YYSIZE_T); /* INFRINGES ON USER NAME SPACE */
+# endif
+# endif
+# ifndef YYFREE
+# define YYFREE free
+# if ! defined free && ! defined _STDLIB_H && (defined __STDC__ || defined __C99__FUNC__ \
+ || defined __cplusplus || defined _MSC_VER)
+void free (void *); /* INFRINGES ON USER NAME SPACE */
+# endif
+# endif
+# endif
+#endif /* ! defined yyoverflow || YYERROR_VERBOSE */
+
+
+#if (! defined yyoverflow \
+ && (! defined __cplusplus \
+ || (defined YYLTYPE_IS_TRIVIAL && YYLTYPE_IS_TRIVIAL \
+ && defined YYSTYPE_IS_TRIVIAL && YYSTYPE_IS_TRIVIAL)))
+
+/* A type that is properly aligned for any stack member. */
+union yyalloc
+{
+ yytype_int16 yyss_alloc;
+ YYSTYPE yyvs_alloc;
+ YYLTYPE yyls_alloc;
+};
+
+/* The size of the maximum gap between one aligned stack and the next. */
+# define YYSTACK_GAP_MAXIMUM (sizeof (union yyalloc) - 1)
+
+/* The size of an array large to enough to hold all stacks, each with
+ N elements. */
+# define YYSTACK_BYTES(N) \
+ ((N) * (sizeof (yytype_int16) + sizeof (YYSTYPE) + sizeof (YYLTYPE)) \
+ + 2 * YYSTACK_GAP_MAXIMUM)
+
+/* Copy COUNT objects from FROM to TO. The source and destination do
+ not overlap. */
+# ifndef YYCOPY
+# if defined __GNUC__ && 1 < __GNUC__
+# define YYCOPY(To, From, Count) \
+ __builtin_memcpy (To, From, (Count) * sizeof (*(From)))
+# else
+# define YYCOPY(To, From, Count) \
+ do \
+ { \
+ YYSIZE_T yyi; \
+ for (yyi = 0; yyi < (Count); yyi++) \
+ (To)[yyi] = (From)[yyi]; \
+ } \
+ while (YYID (0))
+# endif
+# endif
+
+/* Relocate STACK from its old location to the new one. The
+ local variables YYSIZE and YYSTACKSIZE give the old and new number of
+ elements in the stack, and YYPTR gives the new location of the
+ stack. Advance YYPTR to a properly aligned location for the next
+ stack. */
+# define YYSTACK_RELOCATE(Stack_alloc, Stack) \
+ do \
+ { \
+ YYSIZE_T yynewbytes; \
+ YYCOPY (&yyptr->Stack_alloc, Stack, yysize); \
+ Stack = &yyptr->Stack_alloc; \
+ yynewbytes = yystacksize * sizeof (*Stack) + YYSTACK_GAP_MAXIMUM; \
+ yyptr += yynewbytes / sizeof (*yyptr); \
+ } \
+ while (YYID (0))
+
+#endif
+
+/* YYFINAL -- State number of the termination state. */
+#define YYFINAL 5
+/* YYLAST -- Last index in YYTABLE. */
+#define YYLAST 4096
+
+/* YYNTOKENS -- Number of terminals. */
+#define YYNTOKENS 212
+/* YYNNTS -- Number of nonterminals. */
+#define YYNNTS 89
+/* YYNRULES -- Number of rules. */
+#define YYNRULES 273
+/* YYNRULES -- Number of states. */
+#define YYNSTATES 410
+
+/* YYTRANSLATE(YYLEX) -- Bison symbol number corresponding to YYLEX. */
+#define YYUNDEFTOK 2
+#define YYMAXUTOK 442
+
+#define YYTRANSLATE(YYX) \
+ ((unsigned int) (YYX) <= YYMAXUTOK ? yytranslate[YYX] : YYUNDEFTOK)
+
+/* YYTRANSLATE[YYLEX] -- Bison symbol number corresponding to YYLEX. */
+static const yytype_uint8 yytranslate[] =
+{
+ 0, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 196, 2, 2, 2, 200, 203, 2,
+ 188, 189, 198, 194, 193, 195, 192, 199, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 207, 209,
+ 201, 208, 202, 206, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 190, 2, 191, 204, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 210, 205, 211, 197, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 1, 2, 3, 4,
+ 5, 6, 7, 8, 9, 10, 11, 12, 13, 14,
+ 15, 16, 17, 18, 19, 20, 21, 22, 23, 24,
+ 25, 26, 27, 28, 29, 30, 31, 32, 33, 34,
+ 35, 36, 37, 38, 39, 40, 41, 42, 43, 44,
+ 45, 46, 47, 48, 49, 50, 51, 52, 53, 54,
+ 55, 56, 57, 58, 59, 60, 61, 62, 63, 64,
+ 65, 66, 67, 68, 69, 70, 71, 72, 73, 74,
+ 75, 76, 77, 78, 79, 80, 81, 82, 83, 84,
+ 85, 86, 87, 88, 89, 90, 91, 92, 93, 94,
+ 95, 96, 97, 98, 99, 100, 101, 102, 103, 104,
+ 105, 106, 107, 108, 109, 110, 111, 112, 113, 114,
+ 115, 116, 117, 118, 119, 120, 121, 122, 123, 124,
+ 125, 126, 127, 128, 129, 130, 131, 132, 133, 134,
+ 135, 136, 137, 138, 139, 140, 141, 142, 143, 144,
+ 145, 146, 147, 148, 149, 150, 151, 152, 153, 154,
+ 155, 156, 157, 158, 159, 160, 161, 162, 163, 164,
+ 165, 166, 167, 168, 169, 170, 171, 172, 173, 174,
+ 175, 176, 177, 178, 179, 180, 181, 182, 183, 184,
+ 185, 186, 187
+};
+
+#if YYDEBUG
+/* YYPRHS[YYN] -- Index of the first RHS symbol of rule number YYN in
+ YYRHS. */
+static const yytype_uint16 yyprhs[] =
+{
+ 0, 0, 3, 4, 9, 10, 14, 15, 18, 24,
+ 26, 29, 31, 33, 35, 37, 39, 41, 45, 47,
+ 52, 54, 58, 61, 64, 66, 68, 70, 74, 77,
+ 80, 83, 85, 88, 92, 95, 97, 99, 101, 103,
+ 106, 109, 112, 114, 116, 118, 120, 122, 126, 130,
+ 134, 136, 140, 144, 146, 150, 154, 156, 160, 164,
+ 168, 172, 174, 178, 182, 184, 188, 190, 194, 196,
+ 200, 202, 206, 208, 212, 214, 218, 220, 226, 228,
+ 232, 234, 236, 238, 240, 242, 244, 246, 248, 250,
+ 252, 254, 256, 260, 262, 265, 268, 273, 276, 278,
+ 280, 283, 287, 291, 294, 300, 304, 307, 311, 314,
+ 315, 317, 319, 321, 323, 325, 329, 335, 342, 350,
+ 359, 365, 367, 370, 375, 381, 388, 396, 401, 404,
+ 406, 409, 410, 412, 417, 419, 423, 425, 427, 429,
+ 431, 433, 435, 438, 441, 443, 445, 448, 451, 454,
+ 456, 459, 462, 464, 466, 469, 471, 475, 480, 482,
+ 484, 486, 488, 490, 492, 494, 496, 498, 500, 502,
+ 504, 506, 508, 510, 512, 514, 516, 518, 520, 522,
+ 524, 526, 528, 530, 532, 534, 536, 538, 540, 542,
+ 544, 546, 548, 550, 552, 554, 556, 558, 560, 562,
+ 564, 566, 568, 570, 572, 574, 576, 578, 580, 582,
+ 584, 586, 588, 590, 592, 594, 600, 605, 607, 610,
+ 614, 616, 620, 622, 627, 629, 631, 633, 635, 637,
+ 639, 641, 643, 645, 647, 649, 651, 653, 655, 658,
+ 662, 664, 666, 669, 673, 675, 678, 680, 683, 691,
+ 697, 703, 711, 713, 718, 724, 728, 731, 737, 745,
+ 752, 754, 756, 758, 759, 762, 766, 769, 772, 775,
+ 779, 782, 784, 786
+};
+
+/* YYRHS -- A `-1'-separated list of the rules' RHS. */
+static const yytype_int16 yyrhs[] =
+{
+ 213, 0, -1, -1, 215, 216, 214, 218, -1, -1,
+ 109, 78, 114, -1, -1, 216, 217, -1, 110, 76,
+ 113, 76, 114, -1, 299, -1, 218, 299, -1, 76,
+ -1, 219, -1, 78, -1, 79, -1, 77, -1, 80,
+ -1, 188, 246, 189, -1, 220, -1, 221, 190, 222,
+ 191, -1, 223, -1, 221, 192, 76, -1, 221, 84,
+ -1, 221, 85, -1, 246, -1, 224, -1, 225, -1,
+ 221, 192, 225, -1, 227, 189, -1, 226, 189, -1,
+ 228, 74, -1, 228, -1, 228, 244, -1, 227, 193,
+ 244, -1, 229, 188, -1, 268, -1, 76, -1, 81,
+ -1, 221, -1, 84, 230, -1, 85, 230, -1, 231,
+ 230, -1, 194, -1, 195, -1, 196, -1, 197, -1,
+ 230, -1, 232, 198, 230, -1, 232, 199, 230, -1,
+ 232, 200, 230, -1, 232, -1, 233, 194, 232, -1,
+ 233, 195, 232, -1, 233, -1, 234, 82, 233, -1,
+ 234, 83, 233, -1, 234, -1, 235, 201, 234, -1,
+ 235, 202, 234, -1, 235, 86, 234, -1, 235, 87,
+ 234, -1, 235, -1, 236, 88, 235, -1, 236, 89,
+ 235, -1, 236, -1, 237, 203, 236, -1, 237, -1,
+ 238, 204, 237, -1, 238, -1, 239, 205, 238, -1,
+ 239, -1, 240, 90, 239, -1, 240, -1, 241, 92,
+ 240, -1, 241, -1, 242, 91, 241, -1, 242, -1,
+ 242, 206, 246, 207, 244, -1, 243, -1, 230, 245,
+ 244, -1, 208, -1, 93, -1, 94, -1, 96, -1,
+ 95, -1, 102, -1, 97, -1, 98, -1, 99, -1,
+ 100, -1, 101, -1, 244, -1, 246, 193, 244, -1,
+ 243, -1, 249, 209, -1, 257, 209, -1, 108, 272,
+ 269, 209, -1, 250, 189, -1, 252, -1, 251, -1,
+ 252, 254, -1, 251, 193, 254, -1, 259, 76, 188,
+ -1, 268, 76, -1, 268, 76, 190, 247, 191, -1,
+ 265, 255, 253, -1, 255, 253, -1, 265, 255, 256,
+ -1, 255, 256, -1, -1, 33, -1, 34, -1, 35,
+ -1, 268, -1, 258, -1, 257, 193, 76, -1, 257,
+ 193, 76, 190, 191, -1, 257, 193, 76, 190, 247,
+ 191, -1, 257, 193, 76, 190, 191, 208, 278, -1,
+ 257, 193, 76, 190, 247, 191, 208, 278, -1, 257,
+ 193, 76, 208, 278, -1, 259, -1, 259, 76, -1,
+ 259, 76, 190, 191, -1, 259, 76, 190, 247, 191,
+ -1, 259, 76, 190, 191, 208, 278, -1, 259, 76,
+ 190, 247, 191, 208, 278, -1, 259, 76, 208, 278,
+ -1, 103, 76, -1, 268, -1, 266, 268, -1, -1,
+ 261, -1, 117, 188, 262, 189, -1, 263, -1, 262,
+ 193, 263, -1, 76, -1, 40, -1, 39, -1, 38,
+ -1, 4, -1, 267, -1, 264, 266, -1, 103, 266,
+ -1, 4, -1, 3, -1, 260, 37, -1, 32, 37,
+ -1, 260, 33, -1, 34, -1, 32, 33, -1, 32,
+ 34, -1, 36, -1, 269, -1, 272, 269, -1, 270,
+ -1, 270, 190, 191, -1, 270, 190, 247, 191, -1,
+ 271, -1, 273, -1, 76, -1, 74, -1, 6, -1,
+ 7, -1, 8, -1, 5, -1, 29, -1, 30, -1,
+ 31, -1, 20, -1, 21, -1, 22, -1, 23, -1,
+ 24, -1, 25, -1, 26, -1, 27, -1, 28, -1,
+ 41, -1, 42, -1, 43, -1, 44, -1, 45, -1,
+ 46, -1, 47, -1, 48, -1, 49, -1, 50, -1,
+ 51, -1, 151, -1, 52, -1, 53, -1, 54, -1,
+ 55, -1, 153, -1, 56, -1, 57, -1, 58, -1,
+ 59, -1, 60, -1, 61, -1, 62, -1, 63, -1,
+ 64, -1, 65, -1, 66, -1, 67, -1, 68, -1,
+ 69, -1, 70, -1, 71, -1, 72, -1, 106, -1,
+ 105, -1, 104, -1, 73, 76, 210, 274, 211, -1,
+ 73, 210, 274, 211, -1, 275, -1, 274, 275, -1,
+ 268, 276, 209, -1, 277, -1, 276, 193, 277, -1,
+ 76, -1, 76, 190, 247, 191, -1, 244, -1, 248,
+ -1, 281, -1, 282, -1, 284, -1, 283, -1, 290,
+ -1, 279, -1, 288, -1, 289, -1, 292, -1, 293,
+ -1, 294, -1, 298, -1, 210, 211, -1, 210, 287,
+ 211, -1, 286, -1, 283, -1, 210, 211, -1, 210,
+ 287, 211, -1, 280, -1, 287, 280, -1, 209, -1,
+ 246, 209, -1, 14, 188, 246, 189, 281, 12, 281,
+ -1, 14, 188, 246, 189, 281, -1, 14, 188, 246,
+ 189, 282, -1, 14, 188, 246, 189, 281, 12, 282,
+ -1, 246, -1, 259, 76, 208, 278, -1, 17, 188,
+ 246, 189, 284, -1, 18, 246, 207, -1, 19, 207,
+ -1, 75, 188, 291, 189, 285, -1, 11, 280, 75,
+ 188, 246, 189, 209, -1, 13, 188, 295, 297, 189,
+ 285, -1, 288, -1, 279, -1, 291, -1, -1, 296,
+ 209, -1, 296, 209, 246, -1, 10, 209, -1, 9,
+ 209, -1, 16, 209, -1, 16, 246, 209, -1, 15,
+ 209, -1, 300, -1, 248, -1, 249, 286, -1
+};
+
+/* YYRLINE[YYN] -- source line where rule number YYN was defined. */
+static const yytype_uint16 yyrline[] =
+{
+ 0, 209, 209, 208, 217, 220, 237, 239, 243, 252,
+ 260, 271, 275, 282, 289, 296, 303, 310, 317, 318,
+ 324, 328, 335, 341, 350, 354, 358, 359, 368, 369,
+ 373, 374, 378, 384, 396, 400, 406, 413, 424, 425,
+ 431, 437, 447, 448, 449, 450, 454, 455, 461, 467,
+ 476, 477, 483, 492, 493, 499, 508, 509, 515, 521,
+ 527, 536, 537, 543, 552, 553, 562, 563, 572, 573,
+ 582, 583, 592, 593, 602, 603, 612, 613, 622, 623,
+ 632, 633, 634, 635, 636, 637, 638, 639, 640, 641,
+ 642, 646, 650, 666, 670, 674, 678, 692, 696, 697,
+ 701, 706, 714, 725, 735, 750, 757, 762, 773, 785,
+ 786, 787, 788, 792, 796, 797, 806, 815, 824, 833,
+ 842, 855, 866, 875, 884, 893, 902, 911, 920, 934,
+ 941, 952, 953, 957, 964, 965, 972, 1006, 1007, 1008,
+ 1012, 1016, 1017, 1021, 1029, 1030, 1031, 1032, 1033, 1034,
+ 1035, 1036, 1037, 1041, 1042, 1050, 1051, 1057, 1066, 1072,
+ 1078, 1087, 1088, 1089, 1090, 1091, 1092, 1093, 1094, 1095,
+ 1096, 1097, 1098, 1099, 1100, 1101, 1102, 1103, 1104, 1105,
+ 1106, 1107, 1108, 1109, 1110, 1111, 1112, 1113, 1114, 1115,
+ 1116, 1117, 1118, 1119, 1120, 1121, 1122, 1123, 1124, 1125,
+ 1126, 1127, 1128, 1129, 1130, 1131, 1132, 1133, 1134, 1135,
+ 1136, 1137, 1141, 1152, 1163, 1177, 1183, 1192, 1197, 1205,
+ 1220, 1225, 1233, 1239, 1248, 1252, 1258, 1259, 1263, 1264,
+ 1268, 1272, 1273, 1274, 1275, 1276, 1277, 1278, 1282, 1288,
+ 1297, 1298, 1302, 1308, 1317, 1327, 1339, 1345, 1354, 1363,
+ 1369, 1375, 1384, 1388, 1402, 1406, 1407, 1411, 1418, 1425,
+ 1435, 1436, 1440, 1442, 1448, 1453, 1462, 1468, 1474, 1480,
+ 1486, 1495, 1496, 1500
+};
+#endif
+
+#if YYDEBUG || YYERROR_VERBOSE || YYTOKEN_TABLE
+/* YYTNAME[SYMBOL-NUM] -- String name of the symbol SYMBOL-NUM.
+ First, the terminals, then, starting at YYNTOKENS, nonterminals. */
+static const char *const yytname[] =
+{
+ "$end", "error", "$undefined", "ATTRIBUTE", "CONST_TOK", "BOOL_TOK",
+ "FLOAT_TOK", "INT_TOK", "UINT_TOK", "BREAK", "CONTINUE", "DO", "ELSE",
+ "FOR", "IF", "DISCARD", "RETURN", "SWITCH", "CASE", "DEFAULT", "BVEC2",
+ "BVEC3", "BVEC4", "IVEC2", "IVEC3", "IVEC4", "UVEC2", "UVEC3", "UVEC4",
+ "VEC2", "VEC3", "VEC4", "CENTROID", "IN_TOK", "OUT_TOK", "INOUT_TOK",
+ "UNIFORM", "VARYING", "NOPERSPECTIVE", "FLAT", "SMOOTH", "MAT2X2",
+ "MAT2X3", "MAT2X4", "MAT3X2", "MAT3X3", "MAT3X4", "MAT4X2", "MAT4X3",
+ "MAT4X4", "SAMPLER1D", "SAMPLER2D", "SAMPLER3D", "SAMPLERCUBE",
+ "SAMPLER1DSHADOW", "SAMPLER2DSHADOW", "SAMPLERCUBESHADOW",
+ "SAMPLER1DARRAY", "SAMPLER2DARRAY", "SAMPLER1DARRAYSHADOW",
+ "SAMPLER2DARRAYSHADOW", "ISAMPLER1D", "ISAMPLER2D", "ISAMPLER3D",
+ "ISAMPLERCUBE", "ISAMPLER1DARRAY", "ISAMPLER2DARRAY", "USAMPLER1D",
+ "USAMPLER2D", "USAMPLER3D", "USAMPLERCUBE", "USAMPLER1DARRAY",
+ "USAMPLER2DARRAY", "STRUCT", "VOID_TOK", "WHILE", "IDENTIFIER",
+ "FLOATCONSTANT", "INTCONSTANT", "UINTCONSTANT", "BOOLCONSTANT",
+ "FIELD_SELECTION", "LEFT_OP", "RIGHT_OP", "INC_OP", "DEC_OP", "LE_OP",
+ "GE_OP", "EQ_OP", "NE_OP", "AND_OP", "OR_OP", "XOR_OP", "MUL_ASSIGN",
+ "DIV_ASSIGN", "ADD_ASSIGN", "MOD_ASSIGN", "LEFT_ASSIGN", "RIGHT_ASSIGN",
+ "AND_ASSIGN", "XOR_ASSIGN", "OR_ASSIGN", "SUB_ASSIGN", "INVARIANT",
+ "LOWP", "MEDIUMP", "HIGHP", "SUPERP", "PRECISION", "VERSION",
+ "EXTENSION", "LINE", "PRAGMA", "COLON", "EOL", "INTERFACE", "OUTPUT",
+ "LAYOUT_TOK", "ASM", "CLASS", "UNION", "ENUM", "TYPEDEF", "TEMPLATE",
+ "THIS", "PACKED_TOK", "GOTO", "INLINE_TOK", "NOINLINE", "VOLATILE",
+ "PUBLIC_TOK", "STATIC", "EXTERN", "EXTERNAL", "LONG_TOK", "SHORT_TOK",
+ "DOUBLE_TOK", "HALF", "FIXED_TOK", "UNSIGNED", "INPUT_TOK", "OUPTUT",
+ "HVEC2", "HVEC3", "HVEC4", "DVEC2", "DVEC3", "DVEC4", "FVEC2", "FVEC3",
+ "FVEC4", "SAMPLER2DRECT", "SAMPLER3DRECT", "SAMPLER2DRECTSHADOW",
+ "SIZEOF", "CAST", "NAMESPACE", "USING", "ERROR_TOK", "COMMON",
+ "PARTITION", "ACTIVE", "SAMPLERBUFFER", "FILTER", "IMAGE1D", "IMAGE2D",
+ "IMAGE3D", "IMAGECUBE", "IMAGE1DARRAY", "IMAGE2DARRAY", "IIMAGE1D",
+ "IIMAGE2D", "IIMAGE3D", "IIMAGECUBE", "IIMAGE1DARRAY", "IIMAGE2DARRAY",
+ "UIMAGE1D", "UIMAGE2D", "UIMAGE3D", "UIMAGECUBE", "UIMAGE1DARRAY",
+ "UIMAGE2DARRAY", "IMAGE1DSHADOW", "IMAGE2DSHADOW", "IMAGEBUFFER",
+ "IIMAGEBUFFER", "UIMAGEBUFFER", "ROW_MAJOR", "'('", "')'", "'['", "']'",
+ "'.'", "','", "'+'", "'-'", "'!'", "'~'", "'*'", "'/'", "'%'", "'<'",
+ "'>'", "'&'", "'^'", "'|'", "'?'", "':'", "'='", "';'", "'{'", "'}'",
+ "$accept", "translation_unit", "$@1", "version_statement",
+ "extension_statement_list", "extension_statement",
+ "external_declaration_list", "variable_identifier", "primary_expression",
+ "postfix_expression", "integer_expression", "function_call",
+ "function_call_or_method", "function_call_generic",
+ "function_call_header_no_parameters",
+ "function_call_header_with_parameters", "function_call_header",
+ "function_identifier", "unary_expression", "unary_operator",
+ "multiplicative_expression", "additive_expression", "shift_expression",
+ "relational_expression", "equality_expression", "and_expression",
+ "exclusive_or_expression", "inclusive_or_expression",
+ "logical_and_expression", "logical_xor_expression",
+ "logical_or_expression", "conditional_expression",
+ "assignment_expression", "assignment_operator", "expression",
+ "constant_expression", "declaration", "function_prototype",
+ "function_declarator", "function_header_with_parameters",
+ "function_header", "parameter_declarator", "parameter_declaration",
+ "parameter_qualifier", "parameter_type_specifier",
+ "init_declarator_list", "single_declaration", "fully_specified_type",
+ "opt_layout_qualifier", "layout_qualifier", "layout_qualifier_id_list",
+ "layout_qualifier_id", "interpolation_qualifier",
+ "parameter_type_qualifier", "type_qualifier", "storage_qualifier",
+ "type_specifier", "type_specifier_no_prec", "type_specifier_nonarray",
+ "basic_type_specifier_nonarray", "precision_qualifier",
+ "struct_specifier", "struct_declaration_list", "struct_declaration",
+ "struct_declarator_list", "struct_declarator", "initializer",
+ "declaration_statement", "statement", "statement_matched",
+ "statement_unmatched", "simple_statement", "compound_statement",
+ "statement_no_new_scope", "compound_statement_no_new_scope",
+ "statement_list", "expression_statement", "selection_statement_matched",
+ "selection_statement_unmatched", "condition", "switch_statement",
+ "case_label", "iteration_statement", "for_init_statement",
+ "conditionopt", "for_rest_statement", "jump_statement",
+ "external_declaration", "function_definition", 0
+};
+#endif
+
+# ifdef YYPRINT
+/* YYTOKNUM[YYLEX-NUM] -- Internal token number corresponding to
+ token YYLEX-NUM. */
+static const yytype_uint16 yytoknum[] =
+{
+ 0, 256, 257, 258, 259, 260, 261, 262, 263, 264,
+ 265, 266, 267, 268, 269, 270, 271, 272, 273, 274,
+ 275, 276, 277, 278, 279, 280, 281, 282, 283, 284,
+ 285, 286, 287, 288, 289, 290, 291, 292, 293, 294,
+ 295, 296, 297, 298, 299, 300, 301, 302, 303, 304,
+ 305, 306, 307, 308, 309, 310, 311, 312, 313, 314,
+ 315, 316, 317, 318, 319, 320, 321, 322, 323, 324,
+ 325, 326, 327, 328, 329, 330, 331, 332, 333, 334,
+ 335, 336, 337, 338, 339, 340, 341, 342, 343, 344,
+ 345, 346, 347, 348, 349, 350, 351, 352, 353, 354,
+ 355, 356, 357, 358, 359, 360, 361, 362, 363, 364,
+ 365, 366, 367, 368, 369, 370, 371, 372, 373, 374,
+ 375, 376, 377, 378, 379, 380, 381, 382, 383, 384,
+ 385, 386, 387, 388, 389, 390, 391, 392, 393, 394,
+ 395, 396, 397, 398, 399, 400, 401, 402, 403, 404,
+ 405, 406, 407, 408, 409, 410, 411, 412, 413, 414,
+ 415, 416, 417, 418, 419, 420, 421, 422, 423, 424,
+ 425, 426, 427, 428, 429, 430, 431, 432, 433, 434,
+ 435, 436, 437, 438, 439, 440, 441, 442, 40, 41,
+ 91, 93, 46, 44, 43, 45, 33, 126, 42, 47,
+ 37, 60, 62, 38, 94, 124, 63, 58, 61, 59,
+ 123, 125
+};
+# endif
+
+/* YYR1[YYN] -- Symbol number of symbol that rule YYN derives. */
+static const yytype_uint16 yyr1[] =
+{
+ 0, 212, 214, 213, 215, 215, 216, 216, 217, 218,
+ 218, 219, 220, 220, 220, 220, 220, 220, 221, 221,
+ 221, 221, 221, 221, 222, 223, 224, 224, 225, 225,
+ 226, 226, 227, 227, 228, 229, 229, 229, 230, 230,
+ 230, 230, 231, 231, 231, 231, 232, 232, 232, 232,
+ 233, 233, 233, 234, 234, 234, 235, 235, 235, 235,
+ 235, 236, 236, 236, 237, 237, 238, 238, 239, 239,
+ 240, 240, 241, 241, 242, 242, 243, 243, 244, 244,
+ 245, 245, 245, 245, 245, 245, 245, 245, 245, 245,
+ 245, 246, 246, 247, 248, 248, 248, 249, 250, 250,
+ 251, 251, 252, 253, 253, 254, 254, 254, 254, 255,
+ 255, 255, 255, 256, 257, 257, 257, 257, 257, 257,
+ 257, 258, 258, 258, 258, 258, 258, 258, 258, 259,
+ 259, 260, 260, 261, 262, 262, 263, 264, 264, 264,
+ 265, 266, 266, 266, 267, 267, 267, 267, 267, 267,
+ 267, 267, 267, 268, 268, 269, 269, 269, 270, 270,
+ 270, 271, 271, 271, 271, 271, 271, 271, 271, 271,
+ 271, 271, 271, 271, 271, 271, 271, 271, 271, 271,
+ 271, 271, 271, 271, 271, 271, 271, 271, 271, 271,
+ 271, 271, 271, 271, 271, 271, 271, 271, 271, 271,
+ 271, 271, 271, 271, 271, 271, 271, 271, 271, 271,
+ 271, 271, 272, 272, 272, 273, 273, 274, 274, 275,
+ 276, 276, 277, 277, 278, 279, 280, 280, 281, 281,
+ 282, 283, 283, 283, 283, 283, 283, 283, 284, 284,
+ 285, 285, 286, 286, 287, 287, 288, 288, 289, 290,
+ 290, 290, 291, 291, 292, 293, 293, 294, 294, 294,
+ 295, 295, 296, 296, 297, 297, 298, 298, 298, 298,
+ 298, 299, 299, 300
+};
+
+/* YYR2[YYN] -- Number of symbols composing right hand side of rule YYN. */
+static const yytype_uint8 yyr2[] =
+{
+ 0, 2, 0, 4, 0, 3, 0, 2, 5, 1,
+ 2, 1, 1, 1, 1, 1, 1, 3, 1, 4,
+ 1, 3, 2, 2, 1, 1, 1, 3, 2, 2,
+ 2, 1, 2, 3, 2, 1, 1, 1, 1, 2,
+ 2, 2, 1, 1, 1, 1, 1, 3, 3, 3,
+ 1, 3, 3, 1, 3, 3, 1, 3, 3, 3,
+ 3, 1, 3, 3, 1, 3, 1, 3, 1, 3,
+ 1, 3, 1, 3, 1, 3, 1, 5, 1, 3,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 3, 1, 2, 2, 4, 2, 1, 1,
+ 2, 3, 3, 2, 5, 3, 2, 3, 2, 0,
+ 1, 1, 1, 1, 1, 3, 5, 6, 7, 8,
+ 5, 1, 2, 4, 5, 6, 7, 4, 2, 1,
+ 2, 0, 1, 4, 1, 3, 1, 1, 1, 1,
+ 1, 1, 2, 2, 1, 1, 2, 2, 2, 1,
+ 2, 2, 1, 1, 2, 1, 3, 4, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 5, 4, 1, 2, 3,
+ 1, 3, 1, 4, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 2, 3,
+ 1, 1, 2, 3, 1, 2, 1, 2, 7, 5,
+ 5, 7, 1, 4, 5, 3, 2, 5, 7, 6,
+ 1, 1, 1, 0, 2, 3, 2, 2, 2, 3,
+ 2, 1, 1, 2
+};
+
+/* YYDEFACT[STATE-NAME] -- Default rule to reduce with in state
+ STATE-NUM when YYTABLE doesn't specify something else to do. Zero
+ means the default is an error. */
+static const yytype_uint16 yydefact[] =
+{
+ 4, 0, 0, 6, 0, 1, 2, 5, 0, 131,
+ 7, 0, 145, 144, 165, 162, 163, 164, 169, 170,
+ 171, 172, 173, 174, 175, 176, 177, 166, 167, 168,
+ 0, 149, 152, 139, 138, 137, 178, 179, 180, 181,
+ 182, 183, 184, 185, 186, 187, 188, 190, 191, 192,
+ 193, 195, 196, 197, 198, 199, 200, 201, 202, 203,
+ 204, 205, 206, 207, 208, 209, 210, 211, 0, 161,
+ 160, 131, 214, 213, 212, 0, 0, 189, 194, 131,
+ 272, 0, 0, 99, 109, 0, 114, 121, 0, 132,
+ 131, 0, 141, 129, 153, 155, 158, 0, 159, 9,
+ 271, 0, 150, 151, 147, 0, 0, 128, 131, 143,
+ 0, 0, 10, 94, 131, 273, 97, 109, 140, 110,
+ 111, 112, 100, 0, 109, 0, 95, 122, 148, 146,
+ 142, 130, 0, 154, 0, 0, 0, 0, 217, 0,
+ 136, 0, 134, 0, 0, 131, 0, 0, 0, 0,
+ 0, 0, 0, 0, 11, 15, 13, 14, 16, 37,
+ 0, 0, 0, 42, 43, 44, 45, 246, 131, 242,
+ 12, 18, 38, 20, 25, 26, 0, 0, 31, 0,
+ 46, 0, 50, 53, 56, 61, 64, 66, 68, 70,
+ 72, 74, 76, 78, 91, 0, 225, 0, 129, 231,
+ 244, 226, 227, 229, 228, 131, 232, 233, 230, 234,
+ 235, 236, 237, 101, 106, 108, 113, 0, 115, 102,
+ 0, 0, 156, 46, 93, 0, 35, 8, 0, 222,
+ 0, 220, 216, 218, 96, 133, 0, 267, 266, 0,
+ 131, 0, 270, 268, 0, 0, 0, 256, 131, 39,
+ 40, 0, 238, 131, 22, 23, 0, 0, 29, 28,
+ 0, 161, 32, 34, 81, 82, 84, 83, 86, 87,
+ 88, 89, 90, 85, 80, 0, 41, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 247, 243,
+ 245, 103, 105, 107, 0, 0, 123, 0, 224, 127,
+ 157, 215, 0, 0, 219, 135, 0, 261, 260, 131,
+ 0, 269, 0, 255, 252, 0, 0, 17, 239, 0,
+ 24, 21, 27, 33, 79, 47, 48, 49, 51, 52,
+ 54, 55, 59, 60, 57, 58, 62, 63, 65, 67,
+ 69, 71, 73, 75, 0, 92, 0, 116, 0, 120,
+ 0, 124, 0, 221, 0, 262, 0, 0, 131, 0,
+ 0, 131, 19, 0, 0, 0, 117, 125, 0, 223,
+ 0, 264, 131, 249, 250, 254, 0, 0, 241, 257,
+ 240, 77, 104, 118, 0, 126, 0, 265, 259, 131,
+ 253, 0, 119, 258, 248, 251, 0, 131, 0, 131
+};
+
+/* YYDEFGOTO[NTERM-NUM]. */
+static const yytype_int16 yydefgoto[] =
+{
+ -1, 2, 9, 3, 6, 10, 79, 170, 171, 172,
+ 329, 173, 174, 175, 176, 177, 178, 179, 180, 181,
+ 182, 183, 184, 185, 186, 187, 188, 189, 190, 191,
+ 192, 193, 194, 275, 195, 225, 196, 197, 82, 83,
+ 84, 214, 122, 123, 215, 85, 86, 87, 88, 89,
+ 141, 142, 90, 124, 91, 92, 226, 94, 95, 96,
+ 97, 98, 137, 138, 230, 231, 309, 199, 200, 201,
+ 202, 203, 204, 389, 390, 205, 206, 207, 208, 326,
+ 209, 210, 211, 319, 366, 367, 212, 99, 100
+};
+
+/* YYPACT[STATE-NUM] -- Index in YYTABLE of the portion describing
+ STATE-NUM. */
+#define YYPACT_NINF -345
+static const yytype_int16 yypact[] =
+{
+ -30, 29, 120, -345, 15, -345, 22, -345, 59, 3758,
+ -345, 25, -345, -345, -345, -345, -345, -345, -345, -345,
+ -345, -345, -345, -345, -345, -345, -345, -345, -345, -345,
+ 79, -345, -345, -345, -345, -345, -345, -345, -345, -345,
+ -345, -345, -345, -345, -345, -345, -345, -345, -345, -345,
+ -345, -345, -345, -345, -345, -345, -345, -345, -345, -345,
+ -345, -345, -345, -345, -345, -345, -345, -345, -71, -345,
+ -345, 130, -345, -345, -345, -79, -42, -345, -345, 3642,
+ -345, -5, -38, -32, 4, -181, -345, 87, 62, -345,
+ 27, 3871, -345, -345, -345, -25, -345, 3943, -345, -345,
+ -345, 91, -345, -345, -345, -37, 3871, -345, 27, -345,
+ 3943, 95, -345, -345, 398, -345, -345, 19, -345, -345,
+ -345, -345, -345, 3871, 0, 119, -345, -128, -345, -345,
+ -345, -345, 2752, -345, 86, 3871, 131, 2153, -345, 11,
+ -345, -87, -345, 21, 23, 1234, 40, 50, 36, 2379,
+ 63, 3286, 43, 64, -73, -345, -345, -345, -345, -345,
+ 3286, 3286, 3286, -345, -345, -345, -345, -345, 607, -345,
+ -345, -345, -67, -345, -345, -345, 78, -62, 3464, 80,
+ -53, 3286, -1, 20, 140, -80, 136, 66, 67, 65,
+ 182, 181, -82, -345, -345, -173, -345, 103, 125, -345,
+ -345, -345, -345, -345, -345, 816, -345, -345, -345, -345,
+ -345, -345, -345, -345, -345, -345, 198, 3871, -140, -345,
+ 2930, 3286, -345, -345, -345, 84, -345, -345, 2266, 124,
+ -137, -345, -345, -345, -345, -345, 95, -345, -345, 240,
+ 1845, 3286, -345, -345, -118, 3286, -120, -345, 2574, -345,
+ -345, -48, -345, 1025, -345, -345, 3286, 235, -345, -345,
+ 3286, 128, -345, -345, -345, -345, -345, -345, -345, -345,
+ -345, -345, -345, -345, -345, 3286, -345, 3286, 3286, 3286,
+ 3286, 3286, 3286, 3286, 3286, 3286, 3286, 3286, 3286, 3286,
+ 3286, 3286, 3286, 3286, 3286, 3286, 3286, 3286, -345, -345,
+ -345, 129, -345, -345, 3108, 3286, 110, 132, -345, -345,
+ -345, -345, 3286, 131, -345, -345, 133, -345, -345, 2040,
+ -46, -345, -36, -345, 127, 246, 135, -345, -345, 134,
+ 127, 138, -345, -345, -345, -345, -345, -345, -1, -1,
+ 20, 20, 140, 140, 140, 140, -80, -80, 136, 66,
+ 67, 65, 182, 181, -117, -345, 3286, 121, 137, -345,
+ 3286, 122, 141, -345, 3286, -345, 118, 142, 1234, 123,
+ 126, 1442, -345, 3286, 144, 3286, 139, -345, 3286, -345,
+ -35, 3286, 1442, 324, -345, -345, 3286, 149, -345, -345,
+ -345, -345, -345, -345, 3286, -345, 143, 127, -345, 1234,
+ -345, 3286, -345, -345, -345, -345, -33, 1650, 326, 1650
+};
+
+/* YYPGOTO[NTERM-NUM]. */
+static const yytype_int16 yypgoto[] =
+{
+ -345, -345, -345, -345, -345, -345, -345, -345, -345, -345,
+ -345, -345, -345, 85, -345, -345, -345, -345, -103, -345,
+ -54, -47, -74, -40, 53, 54, 52, 55, 56, 51,
+ -345, -110, -157, -345, -147, -219, 5, 7, -345, -345,
+ -345, 146, 232, 227, 147, -345, -345, -238, -345, -345,
+ -345, 117, -345, -345, -39, -345, -9, -14, -345, -345,
+ 279, -345, 220, -124, -345, 44, -286, 116, -134, -257,
+ -344, -294, -11, -22, 280, 197, 145, -345, -345, 47,
+ -345, -345, -345, -345, -345, -345, -345, 288, -345
+};
+
+/* YYTABLE[YYPACT[STATE-NUM]]. What to do in state STATE-NUM. If
+ positive, shift that token. If negative, reduce the rule which
+ number is the opposite. If zero, do what YYDEFACT says.
+ If YYTABLE_NINF, syntax error. */
+#define YYTABLE_NINF -264
+static const yytype_int16 yytable[] =
+{
+ 93, 307, 244, -160, 246, 105, 284, 285, 118, 295,
+ 325, 239, 125, 233, 80, 251, 81, 254, 255, 359,
+ 297, 262, 224, 118, 384, 72, 73, 74, 126, 223,
+ 12, 13, 109, 119, 120, 121, 298, 119, 120, 121,
+ 264, 265, 266, 267, 268, 269, 270, 271, 272, 273,
+ 304, 130, 119, 120, 121, 405, 313, 249, 250, 30,
+ 219, 31, 220, 32, 308, 33, 34, 35, 305, 109,
+ 93, 300, 314, 297, 377, 297, 297, 388, 276, 1,
+ 221, 325, 131, 133, 80, 358, 81, 323, 388, 393,
+ 373, 321, 395, 362, 320, 128, 139, 136, 322, 129,
+ 400, 324, 235, 333, 233, 198, 236, 4, 402, 330,
+ 224, 383, 102, 103, 216, -36, 104, 223, 334, 300,
+ 5, 286, 287, 256, 296, 257, 136, 259, 136, 7,
+ 108, 260, 8, 12, 13, 11, 198, 374, 101, 106,
+ 355, 327, 404, 368, 76, 297, 111, 297, 308, 354,
+ 408, 116, 404, 369, 396, 274, 407, 297, 297, 198,
+ 297, 117, 30, 127, 31, 132, 32, 134, 33, 34,
+ 35, 140, 324, 135, 335, 336, 337, 223, 223, 223,
+ 223, 223, 223, 223, 223, 223, 223, 223, 223, 223,
+ 223, 223, 223, -98, 224, 218, 198, 277, 278, 279,
+ 227, 223, 224, 308, 113, 114, 107, 229, 216, 223,
+ 342, 343, 344, 345, 280, 281, 391, 380, 308, 136,
+ 234, 308, 282, 283, 288, 289, 338, 339, 240, 308,
+ 237, 198, 238, 108, 397, 340, 341, 308, 241, 198,
+ 14, 15, 16, 17, 198, 242, 224, 76, 346, 347,
+ 247, 245, 248, 223, 406, 18, 19, 20, 21, 22,
+ 23, 24, 25, 26, 27, 28, 29, 258, 263, 290,
+ 292, 291, 293, 294, 301, 310, 36, 37, 38, 39,
+ 40, 41, 42, 43, 44, 45, 46, 47, 48, 49,
+ 50, 51, 52, 53, 54, 55, 56, 57, 58, 59,
+ 60, 61, 62, 63, 64, 65, 66, 67, 68, 69,
+ 198, 331, 113, -35, 312, 316, 159, -30, 360, 356,
+ 297, 364, 370, 361, 371, 372, -36, 381, 376, 375,
+ 378, 382, 379, 168, 386, 392, 399, 401, 409, 72,
+ 73, 74, 332, 348, 350, 349, 353, 394, 351, 213,
+ 352, 217, 403, 315, 110, 228, 317, 363, 385, 198,
+ 398, 115, 198, 302, 303, 253, 365, 112, 0, 0,
+ 0, 0, 0, 198, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 318, 77, 0, 78, 0,
+ 198, 0, 0, 0, 0, 0, 0, 0, 198, 0,
+ 198, 12, 13, 14, 15, 16, 17, 143, 144, 145,
+ 0, 146, 147, 148, 149, 150, 151, 152, 18, 19,
+ 20, 21, 22, 23, 24, 25, 26, 27, 28, 29,
+ 30, 0, 31, 0, 32, 0, 33, 34, 35, 36,
+ 37, 38, 39, 40, 41, 42, 43, 44, 45, 46,
+ 47, 48, 49, 50, 51, 52, 53, 54, 55, 56,
+ 57, 58, 59, 60, 61, 62, 63, 64, 65, 66,
+ 67, 68, 69, 153, 154, 155, 156, 157, 158, 159,
+ 0, 0, 160, 161, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 71, 72, 73, 74, 0, 75, 0, 0, 0,
+ 0, 0, 0, 0, 0, 76, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 77,
+ 0, 78, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 162, 0, 0, 0,
+ 0, 0, 163, 164, 165, 166, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 167, 168, 169,
+ 12, 13, 14, 15, 16, 17, 143, 144, 145, 0,
+ 146, 147, 148, 149, 150, 151, 152, 18, 19, 20,
+ 21, 22, 23, 24, 25, 26, 27, 28, 29, 30,
+ 0, 31, 0, 32, 0, 33, 34, 35, 36, 37,
+ 38, 39, 40, 41, 42, 43, 44, 45, 46, 47,
+ 48, 49, 50, 51, 52, 53, 54, 55, 56, 57,
+ 58, 59, 60, 61, 62, 63, 64, 65, 66, 67,
+ 68, 69, 153, 154, 155, 156, 157, 158, 159, 0,
+ 0, 160, 161, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 71, 72, 73, 74, 0, 75, 0, 0, 0, 0,
+ 0, 0, 0, 0, 76, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 77, 0,
+ 78, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 162, 0, 0, 0, 0,
+ 0, 163, 164, 165, 166, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 167, 168, 252, 12,
+ 13, 14, 15, 16, 17, 143, 144, 145, 0, 146,
+ 147, 148, 149, 150, 151, 152, 18, 19, 20, 21,
+ 22, 23, 24, 25, 26, 27, 28, 29, 30, 0,
+ 31, 0, 32, 0, 33, 34, 35, 36, 37, 38,
+ 39, 40, 41, 42, 43, 44, 45, 46, 47, 48,
+ 49, 50, 51, 52, 53, 54, 55, 56, 57, 58,
+ 59, 60, 61, 62, 63, 64, 65, 66, 67, 68,
+ 69, 153, 154, 155, 156, 157, 158, 159, 0, 0,
+ 160, 161, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 71,
+ 72, 73, 74, 0, 75, 0, 0, 0, 0, 0,
+ 0, 0, 0, 76, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 77, 0, 78,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 162, 0, 0, 0, 0, 0,
+ 163, 164, 165, 166, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 167, 168, 299, 12, 13,
+ 14, 15, 16, 17, 143, 144, 145, 0, 146, 147,
+ 148, 149, 150, 151, 152, 18, 19, 20, 21, 22,
+ 23, 24, 25, 26, 27, 28, 29, 30, 0, 31,
+ 0, 32, 0, 33, 34, 35, 36, 37, 38, 39,
+ 40, 41, 42, 43, 44, 45, 46, 47, 48, 49,
+ 50, 51, 52, 53, 54, 55, 56, 57, 58, 59,
+ 60, 61, 62, 63, 64, 65, 66, 67, 68, 69,
+ 153, 154, 155, 156, 157, 158, 159, 0, 0, 160,
+ 161, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 71, 72,
+ 73, 74, 0, 75, 0, 0, 0, 0, 0, 0,
+ 0, 0, 76, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 77, 0, 78, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 162, 0, 0, 0, 0, 0, 163,
+ 164, 165, 166, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 167, 168, 328, 12, 13, 14,
+ 15, 16, 17, 143, 144, 145, 0, 146, 147, 148,
+ 149, 150, 151, 152, 18, 19, 20, 21, 22, 23,
+ 24, 25, 26, 27, 28, 29, 30, 0, 31, 0,
+ 32, 0, 33, 34, 35, 36, 37, 38, 39, 40,
+ 41, 42, 43, 44, 45, 46, 47, 48, 49, 50,
+ 51, 52, 53, 54, 55, 56, 57, 58, 59, 60,
+ 61, 62, 63, 64, 65, 66, 67, 68, 69, 153,
+ 154, 155, 156, 157, 158, 159, 0, 0, 160, 161,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 71, 72, 73,
+ 74, 0, 75, 0, 0, 0, 0, 0, 0, 0,
+ 0, 76, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 77, 0, 78, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 162, 0, 0, 0, 0, 0, 163, 164,
+ 165, 166, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 167, 168, 12, 13, 14, 15, 16,
+ 17, 143, 144, 145, 0, 146, 387, 148, 149, 150,
+ 151, 152, 18, 19, 20, 21, 22, 23, 24, 25,
+ 26, 27, 28, 29, 30, 0, 31, 0, 32, 0,
+ 33, 34, 35, 36, 37, 38, 39, 40, 41, 42,
+ 43, 44, 45, 46, 47, 48, 49, 50, 51, 52,
+ 53, 54, 55, 56, 57, 58, 59, 60, 61, 62,
+ 63, 64, 65, 66, 67, 68, 69, 153, 154, 155,
+ 156, 157, 158, 159, 0, 0, 160, 161, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 71, 72, 73, 74, 0,
+ 75, 0, 0, 0, 0, 0, 0, 0, 0, 76,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 77, 0, 78, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 162, 0, 0, 0, 0, 0, 163, 164, 165, 166,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 167, 114, 12, 13, 14, 15, 16, 17, 143,
+ 144, 145, 0, 146, 387, 148, 149, 150, 151, 152,
+ 18, 19, 20, 21, 22, 23, 24, 25, 26, 27,
+ 28, 29, 30, 0, 31, 0, 32, 0, 33, 34,
+ 35, 36, 37, 38, 39, 40, 41, 42, 43, 44,
+ 45, 46, 47, 48, 49, 50, 51, 52, 53, 54,
+ 55, 56, 57, 58, 59, 60, 61, 62, 63, 64,
+ 65, 66, 67, 68, 69, 153, 154, 155, 156, 157,
+ 158, 159, 0, 0, 160, 161, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 71, 72, 73, 74, 0, 75, 0,
+ 0, 0, 0, 0, 0, 0, 0, 76, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 77, 0, 78, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 162, 0,
+ 0, 0, 0, 0, 163, 164, 165, 166, 12, 13,
+ 14, 15, 16, 17, 0, 0, 0, 0, 0, 167,
+ 168, 0, 0, 0, 0, 18, 19, 20, 21, 22,
+ 23, 24, 25, 26, 27, 28, 29, 30, 0, 31,
+ 0, 32, 0, 33, 34, 35, 36, 37, 38, 39,
+ 40, 41, 42, 43, 44, 45, 46, 47, 48, 49,
+ 50, 51, 52, 53, 54, 55, 56, 57, 58, 59,
+ 60, 61, 62, 63, 64, 65, 66, 67, 68, 69,
+ 0, 154, 155, 156, 157, 158, 159, 0, 0, 160,
+ 161, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 71, 72,
+ 73, 74, 0, 75, 0, 0, 0, 0, 0, 0,
+ 0, 0, 76, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 77, 0, 78, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 162, 0, 0, 0, 0, 0, 163,
+ 164, 165, 166, 12, 13, 14, 15, 16, 17, 0,
+ 0, 0, 0, 0, 167, 0, 0, 0, 0, 0,
+ 18, 19, 20, 21, 22, 23, 24, 25, 26, 27,
+ 28, 29, 30, 0, 31, 0, 32, 0, 33, 34,
+ 35, 36, 37, 38, 39, 40, 41, 42, 43, 44,
+ 45, 46, 47, 48, 49, 50, 51, 52, 53, 54,
+ 55, 56, 57, 58, 59, 60, 61, 62, 63, 64,
+ 65, 66, 67, 68, 69, 0, 154, 155, 156, 157,
+ 158, 159, 0, 0, 160, 161, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 108, 72, 73, 74, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 76, 14, 15,
+ 16, 17, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 18, 19, 20, 21, 22, 23, 24,
+ 25, 26, 27, 28, 29, 0, 0, 0, 0, 0,
+ 0, 77, 0, 78, 36, 37, 38, 39, 40, 41,
+ 42, 43, 44, 45, 46, 47, 48, 49, 50, 51,
+ 52, 53, 54, 55, 56, 57, 58, 59, 60, 61,
+ 62, 63, 64, 65, 66, 67, 68, 69, 162, 70,
+ 0, 0, 0, 0, 163, 164, 165, 166, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, -263,
+ 0, 0, 0, 0, 0, 0, 0, 72, 73, 74,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 14, 15, 16, 17, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 18, 19, 20, 21,
+ 22, 23, 24, 25, 26, 27, 28, 29, 0, 0,
+ 0, 0, 0, 0, 77, 0, 78, 36, 37, 38,
+ 39, 40, 41, 42, 43, 44, 45, 46, 47, 48,
+ 49, 50, 51, 52, 53, 54, 55, 56, 57, 58,
+ 59, 60, 61, 62, 63, 64, 65, 66, 67, 68,
+ 69, 0, 70, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 232, 0, 0, 0, 0, 0,
+ 72, 73, 74, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 14, 15, 16, 17, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 18,
+ 19, 20, 21, 22, 23, 24, 25, 26, 27, 28,
+ 29, 0, 0, 0, 0, 0, 0, 77, 0, 78,
+ 36, 37, 38, 39, 40, 41, 42, 43, 44, 45,
+ 46, 47, 48, 49, 50, 51, 52, 53, 54, 55,
+ 56, 57, 58, 59, 60, 61, 62, 63, 64, 65,
+ 66, 67, 68, 69, 0, 154, 155, 156, 157, 158,
+ 159, 0, 0, 160, 161, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 311, 0, 0,
+ 0, 0, 0, 72, 73, 74, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 77, 0, 78, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 162, 0, 0,
+ 0, 0, 0, 163, 164, 165, 166, 12, 13, 14,
+ 15, 16, 17, 0, 0, 0, 0, 0, 243, 0,
+ 0, 0, 0, 0, 18, 19, 20, 21, 22, 23,
+ 24, 25, 26, 27, 28, 29, 30, 0, 31, 0,
+ 32, 0, 33, 34, 35, 36, 37, 38, 39, 40,
+ 41, 42, 43, 44, 45, 46, 47, 48, 49, 50,
+ 51, 52, 53, 54, 55, 56, 57, 58, 59, 60,
+ 61, 62, 63, 64, 65, 66, 67, 68, 69, 0,
+ 154, 155, 156, 157, 158, 159, 0, 0, 160, 161,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 108, 72, 73,
+ 74, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 76, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 77, 0, 78, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 14, 15, 16,
+ 17, 0, 162, 0, 0, 0, 0, 0, 163, 164,
+ 165, 166, 18, 19, 20, 21, 22, 23, 24, 25,
+ 26, 27, 28, 29, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 36, 37, 38, 39, 40, 41, 42,
+ 43, 44, 45, 46, 47, 48, 49, 50, 51, 52,
+ 53, 54, 55, 56, 57, 58, 59, 60, 61, 62,
+ 63, 64, 65, 66, 67, 68, 69, 0, 154, 155,
+ 156, 157, 158, 159, 0, 0, 160, 161, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 72, 73, 74, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 77, 0, 78, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 14, 15, 16, 17, 0,
+ 162, 0, 0, 222, 0, 0, 163, 164, 165, 166,
+ 18, 19, 20, 21, 22, 23, 24, 25, 26, 27,
+ 28, 29, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 36, 37, 38, 39, 40, 41, 42, 43, 44,
+ 45, 46, 47, 48, 49, 50, 51, 52, 53, 54,
+ 55, 56, 57, 58, 59, 60, 61, 62, 63, 64,
+ 65, 66, 67, 68, 69, 0, 154, 155, 156, 157,
+ 158, 159, 0, 0, 160, 161, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 72, 73, 74, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 77, 0, 78, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 14, 15, 16, 17, 0, 162, 0,
+ 0, 306, 0, 0, 163, 164, 165, 166, 18, 19,
+ 20, 21, 22, 23, 24, 25, 26, 27, 28, 29,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 36,
+ 37, 38, 39, 40, 41, 42, 43, 44, 45, 46,
+ 47, 48, 49, 50, 51, 52, 53, 54, 55, 56,
+ 57, 58, 59, 60, 61, 62, 63, 64, 65, 66,
+ 67, 68, 69, 0, 154, 155, 156, 157, 158, 159,
+ 0, 0, 160, 161, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 72, 73, 74, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 77,
+ 0, 78, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 14, 15, 16, 17, 0, 162, 0, 0, 357,
+ 0, 0, 163, 164, 165, 166, 18, 19, 20, 21,
+ 22, 23, 24, 25, 26, 27, 28, 29, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 36, 37, 38,
+ 39, 40, 41, 42, 43, 44, 45, 46, 47, 48,
+ 49, 50, 51, 52, 53, 54, 55, 56, 57, 58,
+ 59, 60, 61, 62, 63, 64, 65, 66, 67, 68,
+ 69, 0, 154, 155, 156, 157, 158, 159, 0, 0,
+ 160, 161, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 72, 73, 74, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 77, 0, 78,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 14,
+ 15, 16, 17, 0, 162, 0, 0, 0, 0, 0,
+ 163, 164, 165, 166, 18, 19, 20, 21, 22, 23,
+ 24, 25, 26, 27, 28, 29, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 36, 37, 38, 39, 40,
+ 41, 42, 43, 44, 45, 46, 47, 48, 49, 50,
+ 51, 52, 53, 54, 55, 56, 57, 58, 59, 60,
+ 61, 62, 63, 64, 65, 66, 67, 68, 261, 0,
+ 154, 155, 156, 157, 158, 159, 0, 0, 160, 161,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 72, 73,
+ 74, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 77, 0, 78, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, -3, 0, 0, 12, 13, 14, 15, 16,
+ 17, 0, 162, 0, 0, 0, 0, 0, 163, 164,
+ 165, 166, 18, 19, 20, 21, 22, 23, 24, 25,
+ 26, 27, 28, 29, 30, 0, 31, 0, 32, 0,
+ 33, 34, 35, 36, 37, 38, 39, 40, 41, 42,
+ 43, 44, 45, 46, 47, 48, 49, 50, 51, 52,
+ 53, 54, 55, 56, 57, 58, 59, 60, 61, 62,
+ 63, 64, 65, 66, 67, 68, 69, 0, 70, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 71, 72, 73, 74, 0,
+ 75, 0, 0, 0, 0, 0, 0, 0, 0, 76,
+ 0, 12, 13, 14, 15, 16, 17, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 18, 19,
+ 20, 21, 22, 23, 24, 25, 26, 27, 28, 29,
+ 30, 0, 31, 77, 32, 78, 33, 34, 35, 36,
+ 37, 38, 39, 40, 41, 42, 43, 44, 45, 46,
+ 47, 48, 49, 50, 51, 52, 53, 54, 55, 56,
+ 57, 58, 59, 60, 61, 62, 63, 64, 65, 66,
+ 67, 68, 69, 0, 70, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 71, 72, 73, 74, 0, 75, 0, 0, 0,
+ 0, 0, 0, 0, 0, 76, 14, 15, 16, 17,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 18, 19, 20, 21, 22, 23, 24, 25, 26,
+ 27, 28, 29, 0, 0, 0, 0, 0, 0, 77,
+ 0, 78, 36, 37, 38, 39, 40, 41, 42, 43,
+ 44, 45, 46, 47, 48, 49, 50, 51, 52, 53,
+ 54, 55, 56, 57, 58, 59, 60, 61, 62, 63,
+ 64, 65, 66, 67, 68, 69, 0, 70, 14, 15,
+ 16, 17, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 18, 19, 20, 21, 22, 23, 24,
+ 25, 26, 27, 28, 29, 72, 73, 74, 0, 0,
+ 0, 0, 0, 0, 36, 37, 38, 39, 40, 41,
+ 42, 43, 44, 45, 46, 47, 48, 49, 50, 51,
+ 52, 53, 54, 55, 56, 57, 58, 59, 60, 61,
+ 62, 63, 64, 65, 66, 67, 68, 69, 0, 70,
+ 0, 0, 77, 0, 78, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 77, 0, 78
+};
+
+static const yytype_int16 yycheck[] =
+{
+ 9, 220, 149, 76, 151, 76, 86, 87, 4, 91,
+ 248, 145, 193, 137, 9, 162, 9, 84, 85, 305,
+ 193, 178, 132, 4, 368, 104, 105, 106, 209, 132,
+ 3, 4, 71, 33, 34, 35, 209, 33, 34, 35,
+ 93, 94, 95, 96, 97, 98, 99, 100, 101, 102,
+ 190, 90, 33, 34, 35, 399, 193, 160, 161, 32,
+ 188, 34, 190, 36, 221, 38, 39, 40, 208, 108,
+ 79, 205, 209, 193, 360, 193, 193, 371, 181, 109,
+ 208, 319, 91, 97, 79, 304, 79, 207, 382, 375,
+ 207, 209, 378, 312, 241, 33, 110, 106, 245, 37,
+ 386, 248, 189, 260, 228, 114, 193, 78, 394, 256,
+ 220, 368, 33, 34, 123, 188, 37, 220, 275, 253,
+ 0, 201, 202, 190, 206, 192, 135, 189, 137, 114,
+ 103, 193, 110, 3, 4, 76, 145, 356, 113, 210,
+ 297, 189, 399, 189, 117, 193, 188, 193, 305, 296,
+ 407, 189, 409, 189, 189, 208, 189, 193, 193, 168,
+ 193, 193, 32, 76, 34, 190, 36, 76, 38, 39,
+ 40, 76, 319, 210, 277, 278, 279, 280, 281, 282,
+ 283, 284, 285, 286, 287, 288, 289, 290, 291, 292,
+ 293, 294, 295, 189, 304, 76, 205, 198, 199, 200,
+ 114, 304, 312, 360, 209, 210, 76, 76, 217, 312,
+ 284, 285, 286, 287, 194, 195, 373, 364, 375, 228,
+ 209, 378, 82, 83, 88, 89, 280, 281, 188, 386,
+ 209, 240, 209, 103, 381, 282, 283, 394, 188, 248,
+ 5, 6, 7, 8, 253, 209, 356, 117, 288, 289,
+ 207, 188, 188, 356, 401, 20, 21, 22, 23, 24,
+ 25, 26, 27, 28, 29, 30, 31, 189, 188, 203,
+ 205, 204, 90, 92, 76, 191, 41, 42, 43, 44,
+ 45, 46, 47, 48, 49, 50, 51, 52, 53, 54,
+ 55, 56, 57, 58, 59, 60, 61, 62, 63, 64,
+ 65, 66, 67, 68, 69, 70, 71, 72, 73, 74,
+ 319, 76, 209, 188, 190, 75, 81, 189, 208, 190,
+ 193, 188, 76, 191, 189, 191, 188, 209, 191, 208,
+ 208, 189, 191, 210, 208, 191, 12, 188, 12, 104,
+ 105, 106, 257, 290, 292, 291, 295, 208, 293, 117,
+ 294, 124, 209, 236, 75, 135, 240, 313, 369, 368,
+ 382, 81, 371, 217, 217, 168, 319, 79, -1, -1,
+ -1, -1, -1, 382, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, 240, 151, -1, 153, -1,
+ 399, -1, -1, -1, -1, -1, -1, -1, 407, -1,
+ 409, 3, 4, 5, 6, 7, 8, 9, 10, 11,
+ -1, 13, 14, 15, 16, 17, 18, 19, 20, 21,
+ 22, 23, 24, 25, 26, 27, 28, 29, 30, 31,
+ 32, -1, 34, -1, 36, -1, 38, 39, 40, 41,
+ 42, 43, 44, 45, 46, 47, 48, 49, 50, 51,
+ 52, 53, 54, 55, 56, 57, 58, 59, 60, 61,
+ 62, 63, 64, 65, 66, 67, 68, 69, 70, 71,
+ 72, 73, 74, 75, 76, 77, 78, 79, 80, 81,
+ -1, -1, 84, 85, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, 103, 104, 105, 106, -1, 108, -1, -1, -1,
+ -1, -1, -1, -1, -1, 117, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, 151,
+ -1, 153, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, 188, -1, -1, -1,
+ -1, -1, 194, 195, 196, 197, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, 209, 210, 211,
+ 3, 4, 5, 6, 7, 8, 9, 10, 11, -1,
+ 13, 14, 15, 16, 17, 18, 19, 20, 21, 22,
+ 23, 24, 25, 26, 27, 28, 29, 30, 31, 32,
+ -1, 34, -1, 36, -1, 38, 39, 40, 41, 42,
+ 43, 44, 45, 46, 47, 48, 49, 50, 51, 52,
+ 53, 54, 55, 56, 57, 58, 59, 60, 61, 62,
+ 63, 64, 65, 66, 67, 68, 69, 70, 71, 72,
+ 73, 74, 75, 76, 77, 78, 79, 80, 81, -1,
+ -1, 84, 85, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ 103, 104, 105, 106, -1, 108, -1, -1, -1, -1,
+ -1, -1, -1, -1, 117, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, 151, -1,
+ 153, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, 188, -1, -1, -1, -1,
+ -1, 194, 195, 196, 197, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, 209, 210, 211, 3,
+ 4, 5, 6, 7, 8, 9, 10, 11, -1, 13,
+ 14, 15, 16, 17, 18, 19, 20, 21, 22, 23,
+ 24, 25, 26, 27, 28, 29, 30, 31, 32, -1,
+ 34, -1, 36, -1, 38, 39, 40, 41, 42, 43,
+ 44, 45, 46, 47, 48, 49, 50, 51, 52, 53,
+ 54, 55, 56, 57, 58, 59, 60, 61, 62, 63,
+ 64, 65, 66, 67, 68, 69, 70, 71, 72, 73,
+ 74, 75, 76, 77, 78, 79, 80, 81, -1, -1,
+ 84, 85, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, 103,
+ 104, 105, 106, -1, 108, -1, -1, -1, -1, -1,
+ -1, -1, -1, 117, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, 151, -1, 153,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, 188, -1, -1, -1, -1, -1,
+ 194, 195, 196, 197, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, 209, 210, 211, 3, 4,
+ 5, 6, 7, 8, 9, 10, 11, -1, 13, 14,
+ 15, 16, 17, 18, 19, 20, 21, 22, 23, 24,
+ 25, 26, 27, 28, 29, 30, 31, 32, -1, 34,
+ -1, 36, -1, 38, 39, 40, 41, 42, 43, 44,
+ 45, 46, 47, 48, 49, 50, 51, 52, 53, 54,
+ 55, 56, 57, 58, 59, 60, 61, 62, 63, 64,
+ 65, 66, 67, 68, 69, 70, 71, 72, 73, 74,
+ 75, 76, 77, 78, 79, 80, 81, -1, -1, 84,
+ 85, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, 103, 104,
+ 105, 106, -1, 108, -1, -1, -1, -1, -1, -1,
+ -1, -1, 117, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, 151, -1, 153, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, 188, -1, -1, -1, -1, -1, 194,
+ 195, 196, 197, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, 209, 210, 211, 3, 4, 5,
+ 6, 7, 8, 9, 10, 11, -1, 13, 14, 15,
+ 16, 17, 18, 19, 20, 21, 22, 23, 24, 25,
+ 26, 27, 28, 29, 30, 31, 32, -1, 34, -1,
+ 36, -1, 38, 39, 40, 41, 42, 43, 44, 45,
+ 46, 47, 48, 49, 50, 51, 52, 53, 54, 55,
+ 56, 57, 58, 59, 60, 61, 62, 63, 64, 65,
+ 66, 67, 68, 69, 70, 71, 72, 73, 74, 75,
+ 76, 77, 78, 79, 80, 81, -1, -1, 84, 85,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, 103, 104, 105,
+ 106, -1, 108, -1, -1, -1, -1, -1, -1, -1,
+ -1, 117, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, 151, -1, 153, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, 188, -1, -1, -1, -1, -1, 194, 195,
+ 196, 197, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, 209, 210, 3, 4, 5, 6, 7,
+ 8, 9, 10, 11, -1, 13, 14, 15, 16, 17,
+ 18, 19, 20, 21, 22, 23, 24, 25, 26, 27,
+ 28, 29, 30, 31, 32, -1, 34, -1, 36, -1,
+ 38, 39, 40, 41, 42, 43, 44, 45, 46, 47,
+ 48, 49, 50, 51, 52, 53, 54, 55, 56, 57,
+ 58, 59, 60, 61, 62, 63, 64, 65, 66, 67,
+ 68, 69, 70, 71, 72, 73, 74, 75, 76, 77,
+ 78, 79, 80, 81, -1, -1, 84, 85, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, 103, 104, 105, 106, -1,
+ 108, -1, -1, -1, -1, -1, -1, -1, -1, 117,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, 151, -1, 153, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ 188, -1, -1, -1, -1, -1, 194, 195, 196, 197,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, 209, 210, 3, 4, 5, 6, 7, 8, 9,
+ 10, 11, -1, 13, 14, 15, 16, 17, 18, 19,
+ 20, 21, 22, 23, 24, 25, 26, 27, 28, 29,
+ 30, 31, 32, -1, 34, -1, 36, -1, 38, 39,
+ 40, 41, 42, 43, 44, 45, 46, 47, 48, 49,
+ 50, 51, 52, 53, 54, 55, 56, 57, 58, 59,
+ 60, 61, 62, 63, 64, 65, 66, 67, 68, 69,
+ 70, 71, 72, 73, 74, 75, 76, 77, 78, 79,
+ 80, 81, -1, -1, 84, 85, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, 103, 104, 105, 106, -1, 108, -1,
+ -1, -1, -1, -1, -1, -1, -1, 117, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, 151, -1, 153, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, 188, -1,
+ -1, -1, -1, -1, 194, 195, 196, 197, 3, 4,
+ 5, 6, 7, 8, -1, -1, -1, -1, -1, 209,
+ 210, -1, -1, -1, -1, 20, 21, 22, 23, 24,
+ 25, 26, 27, 28, 29, 30, 31, 32, -1, 34,
+ -1, 36, -1, 38, 39, 40, 41, 42, 43, 44,
+ 45, 46, 47, 48, 49, 50, 51, 52, 53, 54,
+ 55, 56, 57, 58, 59, 60, 61, 62, 63, 64,
+ 65, 66, 67, 68, 69, 70, 71, 72, 73, 74,
+ -1, 76, 77, 78, 79, 80, 81, -1, -1, 84,
+ 85, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, 103, 104,
+ 105, 106, -1, 108, -1, -1, -1, -1, -1, -1,
+ -1, -1, 117, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, 151, -1, 153, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, 188, -1, -1, -1, -1, -1, 194,
+ 195, 196, 197, 3, 4, 5, 6, 7, 8, -1,
+ -1, -1, -1, -1, 209, -1, -1, -1, -1, -1,
+ 20, 21, 22, 23, 24, 25, 26, 27, 28, 29,
+ 30, 31, 32, -1, 34, -1, 36, -1, 38, 39,
+ 40, 41, 42, 43, 44, 45, 46, 47, 48, 49,
+ 50, 51, 52, 53, 54, 55, 56, 57, 58, 59,
+ 60, 61, 62, 63, 64, 65, 66, 67, 68, 69,
+ 70, 71, 72, 73, 74, -1, 76, 77, 78, 79,
+ 80, 81, -1, -1, 84, 85, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, 103, 104, 105, 106, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, 117, 5, 6,
+ 7, 8, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, 20, 21, 22, 23, 24, 25, 26,
+ 27, 28, 29, 30, 31, -1, -1, -1, -1, -1,
+ -1, 151, -1, 153, 41, 42, 43, 44, 45, 46,
+ 47, 48, 49, 50, 51, 52, 53, 54, 55, 56,
+ 57, 58, 59, 60, 61, 62, 63, 64, 65, 66,
+ 67, 68, 69, 70, 71, 72, 73, 74, 188, 76,
+ -1, -1, -1, -1, 194, 195, 196, 197, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, 209,
+ -1, -1, -1, -1, -1, -1, -1, 104, 105, 106,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, 5, 6, 7, 8, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, 20, 21, 22, 23,
+ 24, 25, 26, 27, 28, 29, 30, 31, -1, -1,
+ -1, -1, -1, -1, 151, -1, 153, 41, 42, 43,
+ 44, 45, 46, 47, 48, 49, 50, 51, 52, 53,
+ 54, 55, 56, 57, 58, 59, 60, 61, 62, 63,
+ 64, 65, 66, 67, 68, 69, 70, 71, 72, 73,
+ 74, -1, 76, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, 211, -1, -1, -1, -1, -1,
+ 104, 105, 106, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, 5, 6, 7, 8, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, 20,
+ 21, 22, 23, 24, 25, 26, 27, 28, 29, 30,
+ 31, -1, -1, -1, -1, -1, -1, 151, -1, 153,
+ 41, 42, 43, 44, 45, 46, 47, 48, 49, 50,
+ 51, 52, 53, 54, 55, 56, 57, 58, 59, 60,
+ 61, 62, 63, 64, 65, 66, 67, 68, 69, 70,
+ 71, 72, 73, 74, -1, 76, 77, 78, 79, 80,
+ 81, -1, -1, 84, 85, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, 211, -1, -1,
+ -1, -1, -1, 104, 105, 106, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ 151, -1, 153, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, 188, -1, -1,
+ -1, -1, -1, 194, 195, 196, 197, 3, 4, 5,
+ 6, 7, 8, -1, -1, -1, -1, -1, 209, -1,
+ -1, -1, -1, -1, 20, 21, 22, 23, 24, 25,
+ 26, 27, 28, 29, 30, 31, 32, -1, 34, -1,
+ 36, -1, 38, 39, 40, 41, 42, 43, 44, 45,
+ 46, 47, 48, 49, 50, 51, 52, 53, 54, 55,
+ 56, 57, 58, 59, 60, 61, 62, 63, 64, 65,
+ 66, 67, 68, 69, 70, 71, 72, 73, 74, -1,
+ 76, 77, 78, 79, 80, 81, -1, -1, 84, 85,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, 103, 104, 105,
+ 106, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, 117, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, 151, -1, 153, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, 5, 6, 7,
+ 8, -1, 188, -1, -1, -1, -1, -1, 194, 195,
+ 196, 197, 20, 21, 22, 23, 24, 25, 26, 27,
+ 28, 29, 30, 31, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, 41, 42, 43, 44, 45, 46, 47,
+ 48, 49, 50, 51, 52, 53, 54, 55, 56, 57,
+ 58, 59, 60, 61, 62, 63, 64, 65, 66, 67,
+ 68, 69, 70, 71, 72, 73, 74, -1, 76, 77,
+ 78, 79, 80, 81, -1, -1, 84, 85, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, 104, 105, 106, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, 151, -1, 153, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, 5, 6, 7, 8, -1,
+ 188, -1, -1, 191, -1, -1, 194, 195, 196, 197,
+ 20, 21, 22, 23, 24, 25, 26, 27, 28, 29,
+ 30, 31, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, 41, 42, 43, 44, 45, 46, 47, 48, 49,
+ 50, 51, 52, 53, 54, 55, 56, 57, 58, 59,
+ 60, 61, 62, 63, 64, 65, 66, 67, 68, 69,
+ 70, 71, 72, 73, 74, -1, 76, 77, 78, 79,
+ 80, 81, -1, -1, 84, 85, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, 104, 105, 106, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, 151, -1, 153, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, 5, 6, 7, 8, -1, 188, -1,
+ -1, 191, -1, -1, 194, 195, 196, 197, 20, 21,
+ 22, 23, 24, 25, 26, 27, 28, 29, 30, 31,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, 41,
+ 42, 43, 44, 45, 46, 47, 48, 49, 50, 51,
+ 52, 53, 54, 55, 56, 57, 58, 59, 60, 61,
+ 62, 63, 64, 65, 66, 67, 68, 69, 70, 71,
+ 72, 73, 74, -1, 76, 77, 78, 79, 80, 81,
+ -1, -1, 84, 85, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, 104, 105, 106, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, 151,
+ -1, 153, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, 5, 6, 7, 8, -1, 188, -1, -1, 191,
+ -1, -1, 194, 195, 196, 197, 20, 21, 22, 23,
+ 24, 25, 26, 27, 28, 29, 30, 31, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, 41, 42, 43,
+ 44, 45, 46, 47, 48, 49, 50, 51, 52, 53,
+ 54, 55, 56, 57, 58, 59, 60, 61, 62, 63,
+ 64, 65, 66, 67, 68, 69, 70, 71, 72, 73,
+ 74, -1, 76, 77, 78, 79, 80, 81, -1, -1,
+ 84, 85, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ 104, 105, 106, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, 151, -1, 153,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, 5,
+ 6, 7, 8, -1, 188, -1, -1, -1, -1, -1,
+ 194, 195, 196, 197, 20, 21, 22, 23, 24, 25,
+ 26, 27, 28, 29, 30, 31, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, 41, 42, 43, 44, 45,
+ 46, 47, 48, 49, 50, 51, 52, 53, 54, 55,
+ 56, 57, 58, 59, 60, 61, 62, 63, 64, 65,
+ 66, 67, 68, 69, 70, 71, 72, 73, 74, -1,
+ 76, 77, 78, 79, 80, 81, -1, -1, 84, 85,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, 104, 105,
+ 106, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, 151, -1, 153, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, 0, -1, -1, 3, 4, 5, 6, 7,
+ 8, -1, 188, -1, -1, -1, -1, -1, 194, 195,
+ 196, 197, 20, 21, 22, 23, 24, 25, 26, 27,
+ 28, 29, 30, 31, 32, -1, 34, -1, 36, -1,
+ 38, 39, 40, 41, 42, 43, 44, 45, 46, 47,
+ 48, 49, 50, 51, 52, 53, 54, 55, 56, 57,
+ 58, 59, 60, 61, 62, 63, 64, 65, 66, 67,
+ 68, 69, 70, 71, 72, 73, 74, -1, 76, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, 103, 104, 105, 106, -1,
+ 108, -1, -1, -1, -1, -1, -1, -1, -1, 117,
+ -1, 3, 4, 5, 6, 7, 8, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, 20, 21,
+ 22, 23, 24, 25, 26, 27, 28, 29, 30, 31,
+ 32, -1, 34, 151, 36, 153, 38, 39, 40, 41,
+ 42, 43, 44, 45, 46, 47, 48, 49, 50, 51,
+ 52, 53, 54, 55, 56, 57, 58, 59, 60, 61,
+ 62, 63, 64, 65, 66, 67, 68, 69, 70, 71,
+ 72, 73, 74, -1, 76, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, 103, 104, 105, 106, -1, 108, -1, -1, -1,
+ -1, -1, -1, -1, -1, 117, 5, 6, 7, 8,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, 20, 21, 22, 23, 24, 25, 26, 27, 28,
+ 29, 30, 31, -1, -1, -1, -1, -1, -1, 151,
+ -1, 153, 41, 42, 43, 44, 45, 46, 47, 48,
+ 49, 50, 51, 52, 53, 54, 55, 56, 57, 58,
+ 59, 60, 61, 62, 63, 64, 65, 66, 67, 68,
+ 69, 70, 71, 72, 73, 74, -1, 76, 5, 6,
+ 7, 8, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, 20, 21, 22, 23, 24, 25, 26,
+ 27, 28, 29, 30, 31, 104, 105, 106, -1, -1,
+ -1, -1, -1, -1, 41, 42, 43, 44, 45, 46,
+ 47, 48, 49, 50, 51, 52, 53, 54, 55, 56,
+ 57, 58, 59, 60, 61, 62, 63, 64, 65, 66,
+ 67, 68, 69, 70, 71, 72, 73, 74, -1, 76,
+ -1, -1, 151, -1, 153, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, 151, -1, 153
+};
+
+/* YYSTOS[STATE-NUM] -- The (internal number of the) accessing
+ symbol of state STATE-NUM. */
+static const yytype_uint16 yystos[] =
+{
+ 0, 109, 213, 215, 78, 0, 216, 114, 110, 214,
+ 217, 76, 3, 4, 5, 6, 7, 8, 20, 21,
+ 22, 23, 24, 25, 26, 27, 28, 29, 30, 31,
+ 32, 34, 36, 38, 39, 40, 41, 42, 43, 44,
+ 45, 46, 47, 48, 49, 50, 51, 52, 53, 54,
+ 55, 56, 57, 58, 59, 60, 61, 62, 63, 64,
+ 65, 66, 67, 68, 69, 70, 71, 72, 73, 74,
+ 76, 103, 104, 105, 106, 108, 117, 151, 153, 218,
+ 248, 249, 250, 251, 252, 257, 258, 259, 260, 261,
+ 264, 266, 267, 268, 269, 270, 271, 272, 273, 299,
+ 300, 113, 33, 34, 37, 76, 210, 76, 103, 266,
+ 272, 188, 299, 209, 210, 286, 189, 193, 4, 33,
+ 34, 35, 254, 255, 265, 193, 209, 76, 33, 37,
+ 266, 268, 190, 269, 76, 210, 268, 274, 275, 269,
+ 76, 262, 263, 9, 10, 11, 13, 14, 15, 16,
+ 17, 18, 19, 75, 76, 77, 78, 79, 80, 81,
+ 84, 85, 188, 194, 195, 196, 197, 209, 210, 211,
+ 219, 220, 221, 223, 224, 225, 226, 227, 228, 229,
+ 230, 231, 232, 233, 234, 235, 236, 237, 238, 239,
+ 240, 241, 242, 243, 244, 246, 248, 249, 268, 279,
+ 280, 281, 282, 283, 284, 287, 288, 289, 290, 292,
+ 293, 294, 298, 254, 253, 256, 268, 255, 76, 188,
+ 190, 208, 191, 230, 243, 247, 268, 114, 274, 76,
+ 276, 277, 211, 275, 209, 189, 193, 209, 209, 280,
+ 188, 188, 209, 209, 246, 188, 246, 207, 188, 230,
+ 230, 246, 211, 287, 84, 85, 190, 192, 189, 189,
+ 193, 74, 244, 188, 93, 94, 95, 96, 97, 98,
+ 99, 100, 101, 102, 208, 245, 230, 198, 199, 200,
+ 194, 195, 82, 83, 86, 87, 201, 202, 88, 89,
+ 203, 204, 205, 90, 92, 91, 206, 193, 209, 211,
+ 280, 76, 253, 256, 190, 208, 191, 247, 244, 278,
+ 191, 211, 190, 193, 209, 263, 75, 279, 288, 295,
+ 246, 209, 246, 207, 246, 259, 291, 189, 211, 222,
+ 246, 76, 225, 244, 244, 230, 230, 230, 232, 232,
+ 233, 233, 234, 234, 234, 234, 235, 235, 236, 237,
+ 238, 239, 240, 241, 246, 244, 190, 191, 247, 278,
+ 208, 191, 247, 277, 188, 291, 296, 297, 189, 189,
+ 76, 189, 191, 207, 247, 208, 191, 278, 208, 191,
+ 246, 209, 189, 281, 282, 284, 208, 14, 283, 285,
+ 286, 244, 191, 278, 208, 278, 189, 246, 285, 12,
+ 278, 188, 278, 209, 281, 282, 246, 189, 281, 12
+};
+
+#define yyerrok (yyerrstatus = 0)
+#define yyclearin (yychar = YYEMPTY)
+#define YYEMPTY (-2)
+#define YYEOF 0
+
+#define YYACCEPT goto yyacceptlab
+#define YYABORT goto yyabortlab
+#define YYERROR goto yyerrorlab
+
+
+/* Like YYERROR except do call yyerror. This remains here temporarily
+ to ease the transition to the new meaning of YYERROR, for GCC.
+ Once GCC version 2 has supplanted version 1, this can go. */
+
+#define YYFAIL goto yyerrlab
+
+#define YYRECOVERING() (!!yyerrstatus)
+
+#define YYBACKUP(Token, Value) \
+do \
+ if (yychar == YYEMPTY && yylen == 1) \
+ { \
+ yychar = (Token); \
+ yylval = (Value); \
+ yytoken = YYTRANSLATE (yychar); \
+ YYPOPSTACK (1); \
+ goto yybackup; \
+ } \
+ else \
+ { \
+ yyerror (&yylloc, state, YY_("syntax error: cannot back up")); \
+ YYERROR; \
+ } \
+while (YYID (0))
+
+
+#define YYTERROR 1
+#define YYERRCODE 256
+
+
+/* YYLLOC_DEFAULT -- Set CURRENT to span from RHS[1] to RHS[N].
+ If N is 0, then set CURRENT to the empty location which ends
+ the previous symbol: RHS[0] (always defined). */
+
+#define YYRHSLOC(Rhs, K) ((Rhs)[K])
+#ifndef YYLLOC_DEFAULT
+# define YYLLOC_DEFAULT(Current, Rhs, N) \
+ do \
+ if (YYID (N)) \
+ { \
+ (Current).first_line = YYRHSLOC (Rhs, 1).first_line; \
+ (Current).first_column = YYRHSLOC (Rhs, 1).first_column; \
+ (Current).last_line = YYRHSLOC (Rhs, N).last_line; \
+ (Current).last_column = YYRHSLOC (Rhs, N).last_column; \
+ } \
+ else \
+ { \
+ (Current).first_line = (Current).last_line = \
+ YYRHSLOC (Rhs, 0).last_line; \
+ (Current).first_column = (Current).last_column = \
+ YYRHSLOC (Rhs, 0).last_column; \
+ } \
+ while (YYID (0))
+#endif
+
+
+/* YY_LOCATION_PRINT -- Print the location on the stream.
+ This macro was not mandated originally: define only if we know
+ we won't break user code: when these are the locations we know. */
+
+#ifndef YY_LOCATION_PRINT
+# if YYLTYPE_IS_TRIVIAL
+# define YY_LOCATION_PRINT(File, Loc) \
+ fprintf (File, "%d.%d-%d.%d", \
+ (Loc).first_line, (Loc).first_column, \
+ (Loc).last_line, (Loc).last_column)
+# else
+# define YY_LOCATION_PRINT(File, Loc) ((void) 0)
+# endif
+#endif
+
+
+/* YYLEX -- calling `yylex' with the right arguments. */
+
+#ifdef YYLEX_PARAM
+# define YYLEX yylex (&yylval, &yylloc, YYLEX_PARAM)
+#else
+# define YYLEX yylex (&yylval, &yylloc, scanner)
+#endif
+
+/* Enable debugging if requested. */
+#if YYDEBUG
+
+# ifndef YYFPRINTF
+# include <stdio.h> /* INFRINGES ON USER NAME SPACE */
+# define YYFPRINTF fprintf
+# endif
+
+# define YYDPRINTF(Args) \
+do { \
+ if (yydebug) \
+ YYFPRINTF Args; \
+} while (YYID (0))
+
+# define YY_SYMBOL_PRINT(Title, Type, Value, Location) \
+do { \
+ if (yydebug) \
+ { \
+ YYFPRINTF (stderr, "%s ", Title); \
+ yy_symbol_print (stderr, \
+ Type, Value, Location, state); \
+ YYFPRINTF (stderr, "\n"); \
+ } \
+} while (YYID (0))
+
+
+/*--------------------------------.
+| Print this symbol on YYOUTPUT. |
+`--------------------------------*/
+
+/*ARGSUSED*/
+#if (defined __STDC__ || defined __C99__FUNC__ \
+ || defined __cplusplus || defined _MSC_VER)
+static void
+yy_symbol_value_print (FILE *yyoutput, int yytype, YYSTYPE const * const yyvaluep, YYLTYPE const * const yylocationp, struct _mesa_glsl_parse_state *state)
+#else
+static void
+yy_symbol_value_print (yyoutput, yytype, yyvaluep, yylocationp, state)
+ FILE *yyoutput;
+ int yytype;
+ YYSTYPE const * const yyvaluep;
+ YYLTYPE const * const yylocationp;
+ struct _mesa_glsl_parse_state *state;
+#endif
+{
+ if (!yyvaluep)
+ return;
+ YYUSE (yylocationp);
+ YYUSE (state);
+# ifdef YYPRINT
+ if (yytype < YYNTOKENS)
+ YYPRINT (yyoutput, yytoknum[yytype], *yyvaluep);
+# else
+ YYUSE (yyoutput);
+# endif
+ switch (yytype)
+ {
+ default:
+ break;
+ }
+}
+
+
+/*--------------------------------.
+| Print this symbol on YYOUTPUT. |
+`--------------------------------*/
+
+#if (defined __STDC__ || defined __C99__FUNC__ \
+ || defined __cplusplus || defined _MSC_VER)
+static void
+yy_symbol_print (FILE *yyoutput, int yytype, YYSTYPE const * const yyvaluep, YYLTYPE const * const yylocationp, struct _mesa_glsl_parse_state *state)
+#else
+static void
+yy_symbol_print (yyoutput, yytype, yyvaluep, yylocationp, state)
+ FILE *yyoutput;
+ int yytype;
+ YYSTYPE const * const yyvaluep;
+ YYLTYPE const * const yylocationp;
+ struct _mesa_glsl_parse_state *state;
+#endif
+{
+ if (yytype < YYNTOKENS)
+ YYFPRINTF (yyoutput, "token %s (", yytname[yytype]);
+ else
+ YYFPRINTF (yyoutput, "nterm %s (", yytname[yytype]);
+
+ YY_LOCATION_PRINT (yyoutput, *yylocationp);
+ YYFPRINTF (yyoutput, ": ");
+ yy_symbol_value_print (yyoutput, yytype, yyvaluep, yylocationp, state);
+ YYFPRINTF (yyoutput, ")");
+}
+
+/*------------------------------------------------------------------.
+| yy_stack_print -- Print the state stack from its BOTTOM up to its |
+| TOP (included). |
+`------------------------------------------------------------------*/
+
+#if (defined __STDC__ || defined __C99__FUNC__ \
+ || defined __cplusplus || defined _MSC_VER)
+static void
+yy_stack_print (yytype_int16 *yybottom, yytype_int16 *yytop)
+#else
+static void
+yy_stack_print (yybottom, yytop)
+ yytype_int16 *yybottom;
+ yytype_int16 *yytop;
+#endif
+{
+ YYFPRINTF (stderr, "Stack now");
+ for (; yybottom <= yytop; yybottom++)
+ {
+ int yybot = *yybottom;
+ YYFPRINTF (stderr, " %d", yybot);
+ }
+ YYFPRINTF (stderr, "\n");
+}
+
+# define YY_STACK_PRINT(Bottom, Top) \
+do { \
+ if (yydebug) \
+ yy_stack_print ((Bottom), (Top)); \
+} while (YYID (0))
+
+
+/*------------------------------------------------.
+| Report that the YYRULE is going to be reduced. |
+`------------------------------------------------*/
+
+#if (defined __STDC__ || defined __C99__FUNC__ \
+ || defined __cplusplus || defined _MSC_VER)
+static void
+yy_reduce_print (YYSTYPE *yyvsp, YYLTYPE *yylsp, int yyrule, struct _mesa_glsl_parse_state *state)
+#else
+static void
+yy_reduce_print (yyvsp, yylsp, yyrule, state)
+ YYSTYPE *yyvsp;
+ YYLTYPE *yylsp;
+ int yyrule;
+ struct _mesa_glsl_parse_state *state;
+#endif
+{
+ int yynrhs = yyr2[yyrule];
+ int yyi;
+ unsigned long int yylno = yyrline[yyrule];
+ YYFPRINTF (stderr, "Reducing stack by rule %d (line %lu):\n",
+ yyrule - 1, yylno);
+ /* The symbols being reduced. */
+ for (yyi = 0; yyi < yynrhs; yyi++)
+ {
+ YYFPRINTF (stderr, " $%d = ", yyi + 1);
+ yy_symbol_print (stderr, yyrhs[yyprhs[yyrule] + yyi],
+ &(yyvsp[(yyi + 1) - (yynrhs)])
+ , &(yylsp[(yyi + 1) - (yynrhs)]) , state);
+ YYFPRINTF (stderr, "\n");
+ }
+}
+
+# define YY_REDUCE_PRINT(Rule) \
+do { \
+ if (yydebug) \
+ yy_reduce_print (yyvsp, yylsp, Rule, state); \
+} while (YYID (0))
+
+/* Nonzero means print parse trace. It is left uninitialized so that
+ multiple parsers can coexist. */
+int yydebug;
+#else /* !YYDEBUG */
+# define YYDPRINTF(Args)
+# define YY_SYMBOL_PRINT(Title, Type, Value, Location)
+# define YY_STACK_PRINT(Bottom, Top)
+# define YY_REDUCE_PRINT(Rule)
+#endif /* !YYDEBUG */
+
+
+/* YYINITDEPTH -- initial size of the parser's stacks. */
+#ifndef YYINITDEPTH
+# define YYINITDEPTH 200
+#endif
+
+/* YYMAXDEPTH -- maximum size the stacks can grow to (effective only
+ if the built-in stack extension method is used).
+
+ Do not make this value too large; the results are undefined if
+ YYSTACK_ALLOC_MAXIMUM < YYSTACK_BYTES (YYMAXDEPTH)
+ evaluated with infinite-precision integer arithmetic. */
+
+#ifndef YYMAXDEPTH
+# define YYMAXDEPTH 10000
+#endif
+
+
+
+#if YYERROR_VERBOSE
+
+# ifndef yystrlen
+# if defined __GLIBC__ && defined _STRING_H
+# define yystrlen strlen
+# else
+/* Return the length of YYSTR. */
+#if (defined __STDC__ || defined __C99__FUNC__ \
+ || defined __cplusplus || defined _MSC_VER)
+static YYSIZE_T
+yystrlen (const char *yystr)
+#else
+static YYSIZE_T
+yystrlen (yystr)
+ const char *yystr;
+#endif
+{
+ YYSIZE_T yylen;
+ for (yylen = 0; yystr[yylen]; yylen++)
+ continue;
+ return yylen;
+}
+# endif
+# endif
+
+# ifndef yystpcpy
+# if defined __GLIBC__ && defined _STRING_H && defined _GNU_SOURCE
+# define yystpcpy stpcpy
+# else
+/* Copy YYSRC to YYDEST, returning the address of the terminating '\0' in
+ YYDEST. */
+#if (defined __STDC__ || defined __C99__FUNC__ \
+ || defined __cplusplus || defined _MSC_VER)
+static char *
+yystpcpy (char *yydest, const char *yysrc)
+#else
+static char *
+yystpcpy (yydest, yysrc)
+ char *yydest;
+ const char *yysrc;
+#endif
+{
+ char *yyd = yydest;
+ const char *yys = yysrc;
+
+ while ((*yyd++ = *yys++) != '\0')
+ continue;
+
+ return yyd - 1;
+}
+# endif
+# endif
+
+# ifndef yytnamerr
+/* Copy to YYRES the contents of YYSTR after stripping away unnecessary
+ quotes and backslashes, so that it's suitable for yyerror. The
+ heuristic is that double-quoting is unnecessary unless the string
+ contains an apostrophe, a comma, or backslash (other than
+ backslash-backslash). YYSTR is taken from yytname. If YYRES is
+ null, do not copy; instead, return the length of what the result
+ would have been. */
+static YYSIZE_T
+yytnamerr (char *yyres, const char *yystr)
+{
+ if (*yystr == '"')
+ {
+ YYSIZE_T yyn = 0;
+ char const *yyp = yystr;
+
+ for (;;)
+ switch (*++yyp)
+ {
+ case '\'':
+ case ',':
+ goto do_not_strip_quotes;
+
+ case '\\':
+ if (*++yyp != '\\')
+ goto do_not_strip_quotes;
+ /* Fall through. */
+ default:
+ if (yyres)
+ yyres[yyn] = *yyp;
+ yyn++;
+ break;
+
+ case '"':
+ if (yyres)
+ yyres[yyn] = '\0';
+ return yyn;
+ }
+ do_not_strip_quotes: ;
+ }
+
+ if (! yyres)
+ return yystrlen (yystr);
+
+ return yystpcpy (yyres, yystr) - yyres;
+}
+# endif
+
+/* Copy into YYRESULT an error message about the unexpected token
+ YYCHAR while in state YYSTATE. Return the number of bytes copied,
+ including the terminating null byte. If YYRESULT is null, do not
+ copy anything; just return the number of bytes that would be
+ copied. As a special case, return 0 if an ordinary "syntax error"
+ message will do. Return YYSIZE_MAXIMUM if overflow occurs during
+ size calculation. */
+static YYSIZE_T
+yysyntax_error (char *yyresult, int yystate, int yychar)
+{
+ int yyn = yypact[yystate];
+
+ if (! (YYPACT_NINF < yyn && yyn <= YYLAST))
+ return 0;
+ else
+ {
+ int yytype = YYTRANSLATE (yychar);
+ YYSIZE_T yysize0 = yytnamerr (0, yytname[yytype]);
+ YYSIZE_T yysize = yysize0;
+ YYSIZE_T yysize1;
+ int yysize_overflow = 0;
+ enum { YYERROR_VERBOSE_ARGS_MAXIMUM = 5 };
+ char const *yyarg[YYERROR_VERBOSE_ARGS_MAXIMUM];
+ int yyx;
+
+# if 0
+ /* This is so xgettext sees the translatable formats that are
+ constructed on the fly. */
+ YY_("syntax error, unexpected %s");
+ YY_("syntax error, unexpected %s, expecting %s");
+ YY_("syntax error, unexpected %s, expecting %s or %s");
+ YY_("syntax error, unexpected %s, expecting %s or %s or %s");
+ YY_("syntax error, unexpected %s, expecting %s or %s or %s or %s");
+# endif
+ char *yyfmt;
+ char const *yyf;
+ static char const yyunexpected[] = "syntax error, unexpected %s";
+ static char const yyexpecting[] = ", expecting %s";
+ static char const yyor[] = " or %s";
+ char yyformat[sizeof yyunexpected
+ + sizeof yyexpecting - 1
+ + ((YYERROR_VERBOSE_ARGS_MAXIMUM - 2)
+ * (sizeof yyor - 1))];
+ char const *yyprefix = yyexpecting;
+
+ /* Start YYX at -YYN if negative to avoid negative indexes in
+ YYCHECK. */
+ int yyxbegin = yyn < 0 ? -yyn : 0;
+
+ /* Stay within bounds of both yycheck and yytname. */
+ int yychecklim = YYLAST - yyn + 1;
+ int yyxend = yychecklim < YYNTOKENS ? yychecklim : YYNTOKENS;
+ int yycount = 1;
+
+ yyarg[0] = yytname[yytype];
+ yyfmt = yystpcpy (yyformat, yyunexpected);
+
+ for (yyx = yyxbegin; yyx < yyxend; ++yyx)
+ if (yycheck[yyx + yyn] == yyx && yyx != YYTERROR)
+ {
+ if (yycount == YYERROR_VERBOSE_ARGS_MAXIMUM)
+ {
+ yycount = 1;
+ yysize = yysize0;
+ yyformat[sizeof yyunexpected - 1] = '\0';
+ break;
+ }
+ yyarg[yycount++] = yytname[yyx];
+ yysize1 = yysize + yytnamerr (0, yytname[yyx]);
+ yysize_overflow |= (yysize1 < yysize);
+ yysize = yysize1;
+ yyfmt = yystpcpy (yyfmt, yyprefix);
+ yyprefix = yyor;
+ }
+
+ yyf = YY_(yyformat);
+ yysize1 = yysize + yystrlen (yyf);
+ yysize_overflow |= (yysize1 < yysize);
+ yysize = yysize1;
+
+ if (yysize_overflow)
+ return YYSIZE_MAXIMUM;
+
+ if (yyresult)
+ {
+ /* Avoid sprintf, as that infringes on the user's name space.
+ Don't have undefined behavior even if the translation
+ produced a string with the wrong number of "%s"s. */
+ char *yyp = yyresult;
+ int yyi = 0;
+ while ((*yyp = *yyf) != '\0')
+ {
+ if (*yyp == '%' && yyf[1] == 's' && yyi < yycount)
+ {
+ yyp += yytnamerr (yyp, yyarg[yyi++]);
+ yyf += 2;
+ }
+ else
+ {
+ yyp++;
+ yyf++;
+ }
+ }
+ }
+ return yysize;
+ }
+}
+#endif /* YYERROR_VERBOSE */
+
+
+/*-----------------------------------------------.
+| Release the memory associated to this symbol. |
+`-----------------------------------------------*/
+
+/*ARGSUSED*/
+#if (defined __STDC__ || defined __C99__FUNC__ \
+ || defined __cplusplus || defined _MSC_VER)
+static void
+yydestruct (const char *yymsg, int yytype, YYSTYPE *yyvaluep, YYLTYPE *yylocationp, struct _mesa_glsl_parse_state *state)
+#else
+static void
+yydestruct (yymsg, yytype, yyvaluep, yylocationp, state)
+ const char *yymsg;
+ int yytype;
+ YYSTYPE *yyvaluep;
+ YYLTYPE *yylocationp;
+ struct _mesa_glsl_parse_state *state;
+#endif
+{
+ YYUSE (yyvaluep);
+ YYUSE (yylocationp);
+ YYUSE (state);
+
+ if (!yymsg)
+ yymsg = "Deleting";
+ YY_SYMBOL_PRINT (yymsg, yytype, yyvaluep, yylocationp);
+
+ switch (yytype)
+ {
+
+ default:
+ break;
+ }
+}
+
+/* Prevent warnings from -Wmissing-prototypes. */
+#ifdef YYPARSE_PARAM
+#if defined __STDC__ || defined __cplusplus
+int yyparse (void *YYPARSE_PARAM);
+#else
+int yyparse ();
+#endif
+#else /* ! YYPARSE_PARAM */
+#if defined __STDC__ || defined __cplusplus
+int yyparse (struct _mesa_glsl_parse_state *state);
+#else
+int yyparse ();
+#endif
+#endif /* ! YYPARSE_PARAM */
+
+
+
+
+
+/*-------------------------.
+| yyparse or yypush_parse. |
+`-------------------------*/
+
+#ifdef YYPARSE_PARAM
+#if (defined __STDC__ || defined __C99__FUNC__ \
+ || defined __cplusplus || defined _MSC_VER)
+int
+yyparse (void *YYPARSE_PARAM)
+#else
+int
+yyparse (YYPARSE_PARAM)
+ void *YYPARSE_PARAM;
+#endif
+#else /* ! YYPARSE_PARAM */
+#if (defined __STDC__ || defined __C99__FUNC__ \
+ || defined __cplusplus || defined _MSC_VER)
+int
+yyparse (struct _mesa_glsl_parse_state *state)
+#else
+int
+yyparse (state)
+ struct _mesa_glsl_parse_state *state;
+#endif
+#endif
+{
+/* The lookahead symbol. */
+int yychar;
+
+/* The semantic value of the lookahead symbol. */
+YYSTYPE yylval;
+
+/* Location data for the lookahead symbol. */
+YYLTYPE yylloc;
+
+ /* Number of syntax errors so far. */
+ int yynerrs;
+
+ int yystate;
+ /* Number of tokens to shift before error messages enabled. */
+ int yyerrstatus;
+
+ /* The stacks and their tools:
+ `yyss': related to states.
+ `yyvs': related to semantic values.
+ `yyls': related to locations.
+
+ Refer to the stacks thru separate pointers, to allow yyoverflow
+ to reallocate them elsewhere. */
+
+ /* The state stack. */
+ yytype_int16 yyssa[YYINITDEPTH];
+ yytype_int16 *yyss;
+ yytype_int16 *yyssp;
+
+ /* The semantic value stack. */
+ YYSTYPE yyvsa[YYINITDEPTH];
+ YYSTYPE *yyvs;
+ YYSTYPE *yyvsp;
+
+ /* The location stack. */
+ YYLTYPE yylsa[YYINITDEPTH];
+ YYLTYPE *yyls;
+ YYLTYPE *yylsp;
+
+ /* The locations where the error started and ended. */
+ YYLTYPE yyerror_range[2];
+
+ YYSIZE_T yystacksize;
+
+ int yyn;
+ int yyresult;
+ /* Lookahead token as an internal (translated) token number. */
+ int yytoken;
+ /* The variables used to return semantic value and location from the
+ action routines. */
+ YYSTYPE yyval;
+ YYLTYPE yyloc;
+
+#if YYERROR_VERBOSE
+ /* Buffer for error messages, and its allocated size. */
+ char yymsgbuf[128];
+ char *yymsg = yymsgbuf;
+ YYSIZE_T yymsg_alloc = sizeof yymsgbuf;
+#endif
+
+#define YYPOPSTACK(N) (yyvsp -= (N), yyssp -= (N), yylsp -= (N))
+
+ /* The number of symbols on the RHS of the reduced rule.
+ Keep to zero when no symbol should be popped. */
+ int yylen = 0;
+
+ yytoken = 0;
+ yyss = yyssa;
+ yyvs = yyvsa;
+ yyls = yylsa;
+ yystacksize = YYINITDEPTH;
+
+ YYDPRINTF ((stderr, "Starting parse\n"));
+
+ yystate = 0;
+ yyerrstatus = 0;
+ yynerrs = 0;
+ yychar = YYEMPTY; /* Cause a token to be read. */
+
+ /* Initialize stack pointers.
+ Waste one element of value and location stack
+ so that they stay on the same level as the state stack.
+ The wasted elements are never initialized. */
+ yyssp = yyss;
+ yyvsp = yyvs;
+ yylsp = yyls;
+
+#if YYLTYPE_IS_TRIVIAL
+ /* Initialize the default location before parsing starts. */
+ yylloc.first_line = yylloc.last_line = 1;
+ yylloc.first_column = yylloc.last_column = 1;
+#endif
+
+/* User initialization code. */
+
+/* Line 1242 of yacc.c */
+#line 41 "glsl_parser.ypp"
+{
+ yylloc.first_line = 1;
+ yylloc.first_column = 1;
+ yylloc.last_line = 1;
+ yylloc.last_column = 1;
+ yylloc.source = 0;
+}
+
+/* Line 1242 of yacc.c */
+#line 2691 "glsl_parser.cpp"
+ yylsp[0] = yylloc;
+
+ goto yysetstate;
+
+/*------------------------------------------------------------.
+| yynewstate -- Push a new state, which is found in yystate. |
+`------------------------------------------------------------*/
+ yynewstate:
+ /* In all cases, when you get here, the value and location stacks
+ have just been pushed. So pushing a state here evens the stacks. */
+ yyssp++;
+
+ yysetstate:
+ *yyssp = yystate;
+
+ if (yyss + yystacksize - 1 <= yyssp)
+ {
+ /* Get the current used size of the three stacks, in elements. */
+ YYSIZE_T yysize = yyssp - yyss + 1;
+
+#ifdef yyoverflow
+ {
+ /* Give user a chance to reallocate the stack. Use copies of
+ these so that the &'s don't force the real ones into
+ memory. */
+ YYSTYPE *yyvs1 = yyvs;
+ yytype_int16 *yyss1 = yyss;
+ YYLTYPE *yyls1 = yyls;
+
+ /* Each stack pointer address is followed by the size of the
+ data in use in that stack, in bytes. This used to be a
+ conditional around just the two extra args, but that might
+ be undefined if yyoverflow is a macro. */
+ yyoverflow (YY_("memory exhausted"),
+ &yyss1, yysize * sizeof (*yyssp),
+ &yyvs1, yysize * sizeof (*yyvsp),
+ &yyls1, yysize * sizeof (*yylsp),
+ &yystacksize);
+
+ yyls = yyls1;
+ yyss = yyss1;
+ yyvs = yyvs1;
+ }
+#else /* no yyoverflow */
+# ifndef YYSTACK_RELOCATE
+ goto yyexhaustedlab;
+# else
+ /* Extend the stack our own way. */
+ if (YYMAXDEPTH <= yystacksize)
+ goto yyexhaustedlab;
+ yystacksize *= 2;
+ if (YYMAXDEPTH < yystacksize)
+ yystacksize = YYMAXDEPTH;
+
+ {
+ yytype_int16 *yyss1 = yyss;
+ union yyalloc *yyptr =
+ (union yyalloc *) YYSTACK_ALLOC (YYSTACK_BYTES (yystacksize));
+ if (! yyptr)
+ goto yyexhaustedlab;
+ YYSTACK_RELOCATE (yyss_alloc, yyss);
+ YYSTACK_RELOCATE (yyvs_alloc, yyvs);
+ YYSTACK_RELOCATE (yyls_alloc, yyls);
+# undef YYSTACK_RELOCATE
+ if (yyss1 != yyssa)
+ YYSTACK_FREE (yyss1);
+ }
+# endif
+#endif /* no yyoverflow */
+
+ yyssp = yyss + yysize - 1;
+ yyvsp = yyvs + yysize - 1;
+ yylsp = yyls + yysize - 1;
+
+ YYDPRINTF ((stderr, "Stack size increased to %lu\n",
+ (unsigned long int) yystacksize));
+
+ if (yyss + yystacksize - 1 <= yyssp)
+ YYABORT;
+ }
+
+ YYDPRINTF ((stderr, "Entering state %d\n", yystate));
+
+ if (yystate == YYFINAL)
+ YYACCEPT;
+
+ goto yybackup;
+
+/*-----------.
+| yybackup. |
+`-----------*/
+yybackup:
+
+ /* Do appropriate processing given the current state. Read a
+ lookahead token if we need one and don't already have one. */
+
+ /* First try to decide what to do without reference to lookahead token. */
+ yyn = yypact[yystate];
+ if (yyn == YYPACT_NINF)
+ goto yydefault;
+
+ /* Not known => get a lookahead token if don't already have one. */
+
+ /* YYCHAR is either YYEMPTY or YYEOF or a valid lookahead symbol. */
+ if (yychar == YYEMPTY)
+ {
+ YYDPRINTF ((stderr, "Reading a token: "));
+ yychar = YYLEX;
+ }
+
+ if (yychar <= YYEOF)
+ {
+ yychar = yytoken = YYEOF;
+ YYDPRINTF ((stderr, "Now at end of input.\n"));
+ }
+ else
+ {
+ yytoken = YYTRANSLATE (yychar);
+ YY_SYMBOL_PRINT ("Next token is", yytoken, &yylval, &yylloc);
+ }
+
+ /* If the proper action on seeing token YYTOKEN is to reduce or to
+ detect an error, take that action. */
+ yyn += yytoken;
+ if (yyn < 0 || YYLAST < yyn || yycheck[yyn] != yytoken)
+ goto yydefault;
+ yyn = yytable[yyn];
+ if (yyn <= 0)
+ {
+ if (yyn == 0 || yyn == YYTABLE_NINF)
+ goto yyerrlab;
+ yyn = -yyn;
+ goto yyreduce;
+ }
+
+ /* Count tokens shifted since error; after three, turn off error
+ status. */
+ if (yyerrstatus)
+ yyerrstatus--;
+
+ /* Shift the lookahead token. */
+ YY_SYMBOL_PRINT ("Shifting", yytoken, &yylval, &yylloc);
+
+ /* Discard the shifted token. */
+ yychar = YYEMPTY;
+
+ yystate = yyn;
+ *++yyvsp = yylval;
+ *++yylsp = yylloc;
+ goto yynewstate;
+
+
+/*-----------------------------------------------------------.
+| yydefault -- do the default action for the current state. |
+`-----------------------------------------------------------*/
+yydefault:
+ yyn = yydefact[yystate];
+ if (yyn == 0)
+ goto yyerrlab;
+ goto yyreduce;
+
+
+/*-----------------------------.
+| yyreduce -- Do a reduction. |
+`-----------------------------*/
+yyreduce:
+ /* yyn is the number of a rule to reduce with. */
+ yylen = yyr2[yyn];
+
+ /* If YYLEN is nonzero, implement the default value of the action:
+ `$$ = $1'.
+
+ Otherwise, the following line sets YYVAL to garbage.
+ This behavior is undocumented and Bison
+ users should not rely upon it. Assigning to YYVAL
+ unconditionally makes the parser a bit smaller, and it avoids a
+ GCC warning that YYVAL may be used uninitialized. */
+ yyval = yyvsp[1-yylen];
+
+ /* Default location. */
+ YYLLOC_DEFAULT (yyloc, (yylsp - yylen), yylen);
+ YY_REDUCE_PRINT (yyn);
+ switch (yyn)
+ {
+ case 2:
+
+/* Line 1455 of yacc.c */
+#line 209 "glsl_parser.ypp"
+ {
+ _mesa_glsl_initialize_types(state);
+ ;}
+ break;
+
+ case 4:
+
+/* Line 1455 of yacc.c */
+#line 217 "glsl_parser.ypp"
+ {
+ state->language_version = 110;
+ ;}
+ break;
+
+ case 5:
+
+/* Line 1455 of yacc.c */
+#line 221 "glsl_parser.ypp"
+ {
+ switch ((yyvsp[(2) - (3)].n)) {
+ case 110:
+ case 120:
+ case 130:
+ /* FINISHME: Check against implementation support versions. */
+ state->language_version = (yyvsp[(2) - (3)].n);
+ break;
+ default:
+ _mesa_glsl_error(& (yylsp[(2) - (3)]), state, "Shading language version"
+ "%u is not supported\n", (yyvsp[(2) - (3)].n));
+ break;
+ }
+ ;}
+ break;
+
+ case 8:
+
+/* Line 1455 of yacc.c */
+#line 244 "glsl_parser.ypp"
+ {
+ if (!_mesa_glsl_process_extension((yyvsp[(2) - (5)].identifier), & (yylsp[(2) - (5)]), (yyvsp[(4) - (5)].identifier), & (yylsp[(4) - (5)]), state)) {
+ YYERROR;
+ }
+ ;}
+ break;
+
+ case 9:
+
+/* Line 1455 of yacc.c */
+#line 253 "glsl_parser.ypp"
+ {
+ /* FINISHME: The NULL test is only required because 'precision'
+ * FINISHME: statements are not yet supported.
+ */
+ if ((yyvsp[(1) - (1)].node) != NULL)
+ state->translation_unit.push_tail(& (yyvsp[(1) - (1)].node)->link);
+ ;}
+ break;
+
+ case 10:
+
+/* Line 1455 of yacc.c */
+#line 261 "glsl_parser.ypp"
+ {
+ /* FINISHME: The NULL test is only required because 'precision'
+ * FINISHME: statements are not yet supported.
+ */
+ if ((yyvsp[(2) - (2)].node) != NULL)
+ state->translation_unit.push_tail(& (yyvsp[(2) - (2)].node)->link);
+ ;}
+ break;
+
+ case 12:
+
+/* Line 1455 of yacc.c */
+#line 276 "glsl_parser.ypp"
+ {
+ void *ctx = state;
+ (yyval.expression) = new(ctx) ast_expression(ast_identifier, NULL, NULL, NULL);
+ (yyval.expression)->set_location(yylloc);
+ (yyval.expression)->primary_expression.identifier = (yyvsp[(1) - (1)].identifier);
+ ;}
+ break;
+
+ case 13:
+
+/* Line 1455 of yacc.c */
+#line 283 "glsl_parser.ypp"
+ {
+ void *ctx = state;
+ (yyval.expression) = new(ctx) ast_expression(ast_int_constant, NULL, NULL, NULL);
+ (yyval.expression)->set_location(yylloc);
+ (yyval.expression)->primary_expression.int_constant = (yyvsp[(1) - (1)].n);
+ ;}
+ break;
+
+ case 14:
+
+/* Line 1455 of yacc.c */
+#line 290 "glsl_parser.ypp"
+ {
+ void *ctx = state;
+ (yyval.expression) = new(ctx) ast_expression(ast_uint_constant, NULL, NULL, NULL);
+ (yyval.expression)->set_location(yylloc);
+ (yyval.expression)->primary_expression.uint_constant = (yyvsp[(1) - (1)].n);
+ ;}
+ break;
+
+ case 15:
+
+/* Line 1455 of yacc.c */
+#line 297 "glsl_parser.ypp"
+ {
+ void *ctx = state;
+ (yyval.expression) = new(ctx) ast_expression(ast_float_constant, NULL, NULL, NULL);
+ (yyval.expression)->set_location(yylloc);
+ (yyval.expression)->primary_expression.float_constant = (yyvsp[(1) - (1)].real);
+ ;}
+ break;
+
+ case 16:
+
+/* Line 1455 of yacc.c */
+#line 304 "glsl_parser.ypp"
+ {
+ void *ctx = state;
+ (yyval.expression) = new(ctx) ast_expression(ast_bool_constant, NULL, NULL, NULL);
+ (yyval.expression)->set_location(yylloc);
+ (yyval.expression)->primary_expression.bool_constant = (yyvsp[(1) - (1)].n);
+ ;}
+ break;
+
+ case 17:
+
+/* Line 1455 of yacc.c */
+#line 311 "glsl_parser.ypp"
+ {
+ (yyval.expression) = (yyvsp[(2) - (3)].expression);
+ ;}
+ break;
+
+ case 19:
+
+/* Line 1455 of yacc.c */
+#line 319 "glsl_parser.ypp"
+ {
+ void *ctx = state;
+ (yyval.expression) = new(ctx) ast_expression(ast_array_index, (yyvsp[(1) - (4)].expression), (yyvsp[(3) - (4)].expression), NULL);
+ (yyval.expression)->set_location(yylloc);
+ ;}
+ break;
+
+ case 20:
+
+/* Line 1455 of yacc.c */
+#line 325 "glsl_parser.ypp"
+ {
+ (yyval.expression) = (yyvsp[(1) - (1)].expression);
+ ;}
+ break;
+
+ case 21:
+
+/* Line 1455 of yacc.c */
+#line 329 "glsl_parser.ypp"
+ {
+ void *ctx = state;
+ (yyval.expression) = new(ctx) ast_expression(ast_field_selection, (yyvsp[(1) - (3)].expression), NULL, NULL);
+ (yyval.expression)->set_location(yylloc);
+ (yyval.expression)->primary_expression.identifier = (yyvsp[(3) - (3)].identifier);
+ ;}
+ break;
+
+ case 22:
+
+/* Line 1455 of yacc.c */
+#line 336 "glsl_parser.ypp"
+ {
+ void *ctx = state;
+ (yyval.expression) = new(ctx) ast_expression(ast_post_inc, (yyvsp[(1) - (2)].expression), NULL, NULL);
+ (yyval.expression)->set_location(yylloc);
+ ;}
+ break;
+
+ case 23:
+
+/* Line 1455 of yacc.c */
+#line 342 "glsl_parser.ypp"
+ {
+ void *ctx = state;
+ (yyval.expression) = new(ctx) ast_expression(ast_post_dec, (yyvsp[(1) - (2)].expression), NULL, NULL);
+ (yyval.expression)->set_location(yylloc);
+ ;}
+ break;
+
+ case 27:
+
+/* Line 1455 of yacc.c */
+#line 360 "glsl_parser.ypp"
+ {
+ void *ctx = state;
+ (yyval.expression) = new(ctx) ast_expression(ast_field_selection, (yyvsp[(1) - (3)].expression), (yyvsp[(3) - (3)].expression), NULL);
+ (yyval.expression)->set_location(yylloc);
+ ;}
+ break;
+
+ case 32:
+
+/* Line 1455 of yacc.c */
+#line 379 "glsl_parser.ypp"
+ {
+ (yyval.expression) = (yyvsp[(1) - (2)].expression);
+ (yyval.expression)->set_location(yylloc);
+ (yyval.expression)->expressions.push_tail(& (yyvsp[(2) - (2)].expression)->link);
+ ;}
+ break;
+
+ case 33:
+
+/* Line 1455 of yacc.c */
+#line 385 "glsl_parser.ypp"
+ {
+ (yyval.expression) = (yyvsp[(1) - (3)].expression);
+ (yyval.expression)->set_location(yylloc);
+ (yyval.expression)->expressions.push_tail(& (yyvsp[(3) - (3)].expression)->link);
+ ;}
+ break;
+
+ case 35:
+
+/* Line 1455 of yacc.c */
+#line 401 "glsl_parser.ypp"
+ {
+ void *ctx = state;
+ (yyval.expression) = new(ctx) ast_function_expression((yyvsp[(1) - (1)].type_specifier));
+ (yyval.expression)->set_location(yylloc);
+ ;}
+ break;
+
+ case 36:
+
+/* Line 1455 of yacc.c */
+#line 407 "glsl_parser.ypp"
+ {
+ void *ctx = state;
+ ast_expression *callee = new(ctx) ast_expression((yyvsp[(1) - (1)].identifier));
+ (yyval.expression) = new(ctx) ast_function_expression(callee);
+ (yyval.expression)->set_location(yylloc);
+ ;}
+ break;
+
+ case 37:
+
+/* Line 1455 of yacc.c */
+#line 414 "glsl_parser.ypp"
+ {
+ void *ctx = state;
+ ast_expression *callee = new(ctx) ast_expression((yyvsp[(1) - (1)].identifier));
+ (yyval.expression) = new(ctx) ast_function_expression(callee);
+ (yyval.expression)->set_location(yylloc);
+ ;}
+ break;
+
+ case 39:
+
+/* Line 1455 of yacc.c */
+#line 426 "glsl_parser.ypp"
+ {
+ void *ctx = state;
+ (yyval.expression) = new(ctx) ast_expression(ast_pre_inc, (yyvsp[(2) - (2)].expression), NULL, NULL);
+ (yyval.expression)->set_location(yylloc);
+ ;}
+ break;
+
+ case 40:
+
+/* Line 1455 of yacc.c */
+#line 432 "glsl_parser.ypp"
+ {
+ void *ctx = state;
+ (yyval.expression) = new(ctx) ast_expression(ast_pre_dec, (yyvsp[(2) - (2)].expression), NULL, NULL);
+ (yyval.expression)->set_location(yylloc);
+ ;}
+ break;
+
+ case 41:
+
+/* Line 1455 of yacc.c */
+#line 438 "glsl_parser.ypp"
+ {
+ void *ctx = state;
+ (yyval.expression) = new(ctx) ast_expression((yyvsp[(1) - (2)].n), (yyvsp[(2) - (2)].expression), NULL, NULL);
+ (yyval.expression)->set_location(yylloc);
+ ;}
+ break;
+
+ case 42:
+
+/* Line 1455 of yacc.c */
+#line 447 "glsl_parser.ypp"
+ { (yyval.n) = ast_plus; ;}
+ break;
+
+ case 43:
+
+/* Line 1455 of yacc.c */
+#line 448 "glsl_parser.ypp"
+ { (yyval.n) = ast_neg; ;}
+ break;
+
+ case 44:
+
+/* Line 1455 of yacc.c */
+#line 449 "glsl_parser.ypp"
+ { (yyval.n) = ast_logic_not; ;}
+ break;
+
+ case 45:
+
+/* Line 1455 of yacc.c */
+#line 450 "glsl_parser.ypp"
+ { (yyval.n) = ast_bit_not; ;}
+ break;
+
+ case 47:
+
+/* Line 1455 of yacc.c */
+#line 456 "glsl_parser.ypp"
+ {
+ void *ctx = state;
+ (yyval.expression) = new(ctx) ast_expression_bin(ast_mul, (yyvsp[(1) - (3)].expression), (yyvsp[(3) - (3)].expression));
+ (yyval.expression)->set_location(yylloc);
+ ;}
+ break;
+
+ case 48:
+
+/* Line 1455 of yacc.c */
+#line 462 "glsl_parser.ypp"
+ {
+ void *ctx = state;
+ (yyval.expression) = new(ctx) ast_expression_bin(ast_div, (yyvsp[(1) - (3)].expression), (yyvsp[(3) - (3)].expression));
+ (yyval.expression)->set_location(yylloc);
+ ;}
+ break;
+
+ case 49:
+
+/* Line 1455 of yacc.c */
+#line 468 "glsl_parser.ypp"
+ {
+ void *ctx = state;
+ (yyval.expression) = new(ctx) ast_expression_bin(ast_mod, (yyvsp[(1) - (3)].expression), (yyvsp[(3) - (3)].expression));
+ (yyval.expression)->set_location(yylloc);
+ ;}
+ break;
+
+ case 51:
+
+/* Line 1455 of yacc.c */
+#line 478 "glsl_parser.ypp"
+ {
+ void *ctx = state;
+ (yyval.expression) = new(ctx) ast_expression_bin(ast_add, (yyvsp[(1) - (3)].expression), (yyvsp[(3) - (3)].expression));
+ (yyval.expression)->set_location(yylloc);
+ ;}
+ break;
+
+ case 52:
+
+/* Line 1455 of yacc.c */
+#line 484 "glsl_parser.ypp"
+ {
+ void *ctx = state;
+ (yyval.expression) = new(ctx) ast_expression_bin(ast_sub, (yyvsp[(1) - (3)].expression), (yyvsp[(3) - (3)].expression));
+ (yyval.expression)->set_location(yylloc);
+ ;}
+ break;
+
+ case 54:
+
+/* Line 1455 of yacc.c */
+#line 494 "glsl_parser.ypp"
+ {
+ void *ctx = state;
+ (yyval.expression) = new(ctx) ast_expression_bin(ast_lshift, (yyvsp[(1) - (3)].expression), (yyvsp[(3) - (3)].expression));
+ (yyval.expression)->set_location(yylloc);
+ ;}
+ break;
+
+ case 55:
+
+/* Line 1455 of yacc.c */
+#line 500 "glsl_parser.ypp"
+ {
+ void *ctx = state;
+ (yyval.expression) = new(ctx) ast_expression_bin(ast_rshift, (yyvsp[(1) - (3)].expression), (yyvsp[(3) - (3)].expression));
+ (yyval.expression)->set_location(yylloc);
+ ;}
+ break;
+
+ case 57:
+
+/* Line 1455 of yacc.c */
+#line 510 "glsl_parser.ypp"
+ {
+ void *ctx = state;
+ (yyval.expression) = new(ctx) ast_expression_bin(ast_less, (yyvsp[(1) - (3)].expression), (yyvsp[(3) - (3)].expression));
+ (yyval.expression)->set_location(yylloc);
+ ;}
+ break;
+
+ case 58:
+
+/* Line 1455 of yacc.c */
+#line 516 "glsl_parser.ypp"
+ {
+ void *ctx = state;
+ (yyval.expression) = new(ctx) ast_expression_bin(ast_greater, (yyvsp[(1) - (3)].expression), (yyvsp[(3) - (3)].expression));
+ (yyval.expression)->set_location(yylloc);
+ ;}
+ break;
+
+ case 59:
+
+/* Line 1455 of yacc.c */
+#line 522 "glsl_parser.ypp"
+ {
+ void *ctx = state;
+ (yyval.expression) = new(ctx) ast_expression_bin(ast_lequal, (yyvsp[(1) - (3)].expression), (yyvsp[(3) - (3)].expression));
+ (yyval.expression)->set_location(yylloc);
+ ;}
+ break;
+
+ case 60:
+
+/* Line 1455 of yacc.c */
+#line 528 "glsl_parser.ypp"
+ {
+ void *ctx = state;
+ (yyval.expression) = new(ctx) ast_expression_bin(ast_gequal, (yyvsp[(1) - (3)].expression), (yyvsp[(3) - (3)].expression));
+ (yyval.expression)->set_location(yylloc);
+ ;}
+ break;
+
+ case 62:
+
+/* Line 1455 of yacc.c */
+#line 538 "glsl_parser.ypp"
+ {
+ void *ctx = state;
+ (yyval.expression) = new(ctx) ast_expression_bin(ast_equal, (yyvsp[(1) - (3)].expression), (yyvsp[(3) - (3)].expression));
+ (yyval.expression)->set_location(yylloc);
+ ;}
+ break;
+
+ case 63:
+
+/* Line 1455 of yacc.c */
+#line 544 "glsl_parser.ypp"
+ {
+ void *ctx = state;
+ (yyval.expression) = new(ctx) ast_expression_bin(ast_nequal, (yyvsp[(1) - (3)].expression), (yyvsp[(3) - (3)].expression));
+ (yyval.expression)->set_location(yylloc);
+ ;}
+ break;
+
+ case 65:
+
+/* Line 1455 of yacc.c */
+#line 554 "glsl_parser.ypp"
+ {
+ void *ctx = state;
+ (yyval.expression) = new(ctx) ast_expression_bin(ast_bit_or, (yyvsp[(1) - (3)].expression), (yyvsp[(3) - (3)].expression));
+ (yyval.expression)->set_location(yylloc);
+ ;}
+ break;
+
+ case 67:
+
+/* Line 1455 of yacc.c */
+#line 564 "glsl_parser.ypp"
+ {
+ void *ctx = state;
+ (yyval.expression) = new(ctx) ast_expression_bin(ast_bit_xor, (yyvsp[(1) - (3)].expression), (yyvsp[(3) - (3)].expression));
+ (yyval.expression)->set_location(yylloc);
+ ;}
+ break;
+
+ case 69:
+
+/* Line 1455 of yacc.c */
+#line 574 "glsl_parser.ypp"
+ {
+ void *ctx = state;
+ (yyval.expression) = new(ctx) ast_expression_bin(ast_bit_or, (yyvsp[(1) - (3)].expression), (yyvsp[(3) - (3)].expression));
+ (yyval.expression)->set_location(yylloc);
+ ;}
+ break;
+
+ case 71:
+
+/* Line 1455 of yacc.c */
+#line 584 "glsl_parser.ypp"
+ {
+ void *ctx = state;
+ (yyval.expression) = new(ctx) ast_expression_bin(ast_logic_and, (yyvsp[(1) - (3)].expression), (yyvsp[(3) - (3)].expression));
+ (yyval.expression)->set_location(yylloc);
+ ;}
+ break;
+
+ case 73:
+
+/* Line 1455 of yacc.c */
+#line 594 "glsl_parser.ypp"
+ {
+ void *ctx = state;
+ (yyval.expression) = new(ctx) ast_expression_bin(ast_logic_xor, (yyvsp[(1) - (3)].expression), (yyvsp[(3) - (3)].expression));
+ (yyval.expression)->set_location(yylloc);
+ ;}
+ break;
+
+ case 75:
+
+/* Line 1455 of yacc.c */
+#line 604 "glsl_parser.ypp"
+ {
+ void *ctx = state;
+ (yyval.expression) = new(ctx) ast_expression_bin(ast_logic_or, (yyvsp[(1) - (3)].expression), (yyvsp[(3) - (3)].expression));
+ (yyval.expression)->set_location(yylloc);
+ ;}
+ break;
+
+ case 77:
+
+/* Line 1455 of yacc.c */
+#line 614 "glsl_parser.ypp"
+ {
+ void *ctx = state;
+ (yyval.expression) = new(ctx) ast_expression(ast_conditional, (yyvsp[(1) - (5)].expression), (yyvsp[(3) - (5)].expression), (yyvsp[(5) - (5)].expression));
+ (yyval.expression)->set_location(yylloc);
+ ;}
+ break;
+
+ case 79:
+
+/* Line 1455 of yacc.c */
+#line 624 "glsl_parser.ypp"
+ {
+ void *ctx = state;
+ (yyval.expression) = new(ctx) ast_expression((yyvsp[(2) - (3)].n), (yyvsp[(1) - (3)].expression), (yyvsp[(3) - (3)].expression), NULL);
+ (yyval.expression)->set_location(yylloc);
+ ;}
+ break;
+
+ case 80:
+
+/* Line 1455 of yacc.c */
+#line 632 "glsl_parser.ypp"
+ { (yyval.n) = ast_assign; ;}
+ break;
+
+ case 81:
+
+/* Line 1455 of yacc.c */
+#line 633 "glsl_parser.ypp"
+ { (yyval.n) = ast_mul_assign; ;}
+ break;
+
+ case 82:
+
+/* Line 1455 of yacc.c */
+#line 634 "glsl_parser.ypp"
+ { (yyval.n) = ast_div_assign; ;}
+ break;
+
+ case 83:
+
+/* Line 1455 of yacc.c */
+#line 635 "glsl_parser.ypp"
+ { (yyval.n) = ast_mod_assign; ;}
+ break;
+
+ case 84:
+
+/* Line 1455 of yacc.c */
+#line 636 "glsl_parser.ypp"
+ { (yyval.n) = ast_add_assign; ;}
+ break;
+
+ case 85:
+
+/* Line 1455 of yacc.c */
+#line 637 "glsl_parser.ypp"
+ { (yyval.n) = ast_sub_assign; ;}
+ break;
+
+ case 86:
+
+/* Line 1455 of yacc.c */
+#line 638 "glsl_parser.ypp"
+ { (yyval.n) = ast_ls_assign; ;}
+ break;
+
+ case 87:
+
+/* Line 1455 of yacc.c */
+#line 639 "glsl_parser.ypp"
+ { (yyval.n) = ast_rs_assign; ;}
+ break;
+
+ case 88:
+
+/* Line 1455 of yacc.c */
+#line 640 "glsl_parser.ypp"
+ { (yyval.n) = ast_and_assign; ;}
+ break;
+
+ case 89:
+
+/* Line 1455 of yacc.c */
+#line 641 "glsl_parser.ypp"
+ { (yyval.n) = ast_xor_assign; ;}
+ break;
+
+ case 90:
+
+/* Line 1455 of yacc.c */
+#line 642 "glsl_parser.ypp"
+ { (yyval.n) = ast_or_assign; ;}
+ break;
+
+ case 91:
+
+/* Line 1455 of yacc.c */
+#line 647 "glsl_parser.ypp"
+ {
+ (yyval.expression) = (yyvsp[(1) - (1)].expression);
+ ;}
+ break;
+
+ case 92:
+
+/* Line 1455 of yacc.c */
+#line 651 "glsl_parser.ypp"
+ {
+ void *ctx = state;
+ if ((yyvsp[(1) - (3)].expression)->oper != ast_sequence) {
+ (yyval.expression) = new(ctx) ast_expression(ast_sequence, NULL, NULL, NULL);
+ (yyval.expression)->set_location(yylloc);
+ (yyval.expression)->expressions.push_tail(& (yyvsp[(1) - (3)].expression)->link);
+ } else {
+ (yyval.expression) = (yyvsp[(1) - (3)].expression);
+ }
+
+ (yyval.expression)->expressions.push_tail(& (yyvsp[(3) - (3)].expression)->link);
+ ;}
+ break;
+
+ case 94:
+
+/* Line 1455 of yacc.c */
+#line 671 "glsl_parser.ypp"
+ {
+ (yyval.node) = (yyvsp[(1) - (2)].function);
+ ;}
+ break;
+
+ case 95:
+
+/* Line 1455 of yacc.c */
+#line 675 "glsl_parser.ypp"
+ {
+ (yyval.node) = (yyvsp[(1) - (2)].declarator_list);
+ ;}
+ break;
+
+ case 96:
+
+/* Line 1455 of yacc.c */
+#line 679 "glsl_parser.ypp"
+ {
+ if (((yyvsp[(3) - (4)].type_specifier)->type_specifier != ast_float)
+ && ((yyvsp[(3) - (4)].type_specifier)->type_specifier != ast_int)) {
+ _mesa_glsl_error(& (yylsp[(3) - (4)]), state, "global precision qualifier can "
+ "only be applied to `int' or `float'\n");
+ YYERROR;
+ }
+
+ (yyval.node) = NULL; /* FINISHME */
+ ;}
+ break;
+
+ case 100:
+
+/* Line 1455 of yacc.c */
+#line 702 "glsl_parser.ypp"
+ {
+ (yyval.function) = (yyvsp[(1) - (2)].function);
+ (yyval.function)->parameters.push_tail(& (yyvsp[(2) - (2)].parameter_declarator)->link);
+ ;}
+ break;
+
+ case 101:
+
+/* Line 1455 of yacc.c */
+#line 707 "glsl_parser.ypp"
+ {
+ (yyval.function) = (yyvsp[(1) - (3)].function);
+ (yyval.function)->parameters.push_tail(& (yyvsp[(3) - (3)].parameter_declarator)->link);
+ ;}
+ break;
+
+ case 102:
+
+/* Line 1455 of yacc.c */
+#line 715 "glsl_parser.ypp"
+ {
+ void *ctx = state;
+ (yyval.function) = new(ctx) ast_function();
+ (yyval.function)->set_location(yylloc);
+ (yyval.function)->return_type = (yyvsp[(1) - (3)].fully_specified_type);
+ (yyval.function)->identifier = (yyvsp[(2) - (3)].identifier);
+ ;}
+ break;
+
+ case 103:
+
+/* Line 1455 of yacc.c */
+#line 726 "glsl_parser.ypp"
+ {
+ void *ctx = state;
+ (yyval.parameter_declarator) = new(ctx) ast_parameter_declarator();
+ (yyval.parameter_declarator)->set_location(yylloc);
+ (yyval.parameter_declarator)->type = new(ctx) ast_fully_specified_type();
+ (yyval.parameter_declarator)->type->set_location(yylloc);
+ (yyval.parameter_declarator)->type->specifier = (yyvsp[(1) - (2)].type_specifier);
+ (yyval.parameter_declarator)->identifier = (yyvsp[(2) - (2)].identifier);
+ ;}
+ break;
+
+ case 104:
+
+/* Line 1455 of yacc.c */
+#line 736 "glsl_parser.ypp"
+ {
+ void *ctx = state;
+ (yyval.parameter_declarator) = new(ctx) ast_parameter_declarator();
+ (yyval.parameter_declarator)->set_location(yylloc);
+ (yyval.parameter_declarator)->type = new(ctx) ast_fully_specified_type();
+ (yyval.parameter_declarator)->type->set_location(yylloc);
+ (yyval.parameter_declarator)->type->specifier = (yyvsp[(1) - (5)].type_specifier);
+ (yyval.parameter_declarator)->identifier = (yyvsp[(2) - (5)].identifier);
+ (yyval.parameter_declarator)->is_array = true;
+ (yyval.parameter_declarator)->array_size = (yyvsp[(4) - (5)].expression);
+ ;}
+ break;
+
+ case 105:
+
+/* Line 1455 of yacc.c */
+#line 751 "glsl_parser.ypp"
+ {
+ (yyvsp[(1) - (3)].type_qualifier).i |= (yyvsp[(2) - (3)].type_qualifier).i;
+
+ (yyval.parameter_declarator) = (yyvsp[(3) - (3)].parameter_declarator);
+ (yyval.parameter_declarator)->type->qualifier = (yyvsp[(1) - (3)].type_qualifier).q;
+ ;}
+ break;
+
+ case 106:
+
+/* Line 1455 of yacc.c */
+#line 758 "glsl_parser.ypp"
+ {
+ (yyval.parameter_declarator) = (yyvsp[(2) - (2)].parameter_declarator);
+ (yyval.parameter_declarator)->type->qualifier = (yyvsp[(1) - (2)].type_qualifier).q;
+ ;}
+ break;
+
+ case 107:
+
+/* Line 1455 of yacc.c */
+#line 763 "glsl_parser.ypp"
+ {
+ void *ctx = state;
+ (yyvsp[(1) - (3)].type_qualifier).i |= (yyvsp[(2) - (3)].type_qualifier).i;
+
+ (yyval.parameter_declarator) = new(ctx) ast_parameter_declarator();
+ (yyval.parameter_declarator)->set_location(yylloc);
+ (yyval.parameter_declarator)->type = new(ctx) ast_fully_specified_type();
+ (yyval.parameter_declarator)->type->qualifier = (yyvsp[(1) - (3)].type_qualifier).q;
+ (yyval.parameter_declarator)->type->specifier = (yyvsp[(3) - (3)].type_specifier);
+ ;}
+ break;
+
+ case 108:
+
+/* Line 1455 of yacc.c */
+#line 774 "glsl_parser.ypp"
+ {
+ void *ctx = state;
+ (yyval.parameter_declarator) = new(ctx) ast_parameter_declarator();
+ (yyval.parameter_declarator)->set_location(yylloc);
+ (yyval.parameter_declarator)->type = new(ctx) ast_fully_specified_type();
+ (yyval.parameter_declarator)->type->qualifier = (yyvsp[(1) - (2)].type_qualifier).q;
+ (yyval.parameter_declarator)->type->specifier = (yyvsp[(2) - (2)].type_specifier);
+ ;}
+ break;
+
+ case 109:
+
+/* Line 1455 of yacc.c */
+#line 785 "glsl_parser.ypp"
+ { (yyval.type_qualifier).i = 0; ;}
+ break;
+
+ case 110:
+
+/* Line 1455 of yacc.c */
+#line 786 "glsl_parser.ypp"
+ { (yyval.type_qualifier).i = 0; (yyval.type_qualifier).q.in = 1; ;}
+ break;
+
+ case 111:
+
+/* Line 1455 of yacc.c */
+#line 787 "glsl_parser.ypp"
+ { (yyval.type_qualifier).i = 0; (yyval.type_qualifier).q.out = 1; ;}
+ break;
+
+ case 112:
+
+/* Line 1455 of yacc.c */
+#line 788 "glsl_parser.ypp"
+ { (yyval.type_qualifier).i = 0; (yyval.type_qualifier).q.in = 1; (yyval.type_qualifier).q.out = 1; ;}
+ break;
+
+ case 115:
+
+/* Line 1455 of yacc.c */
+#line 798 "glsl_parser.ypp"
+ {
+ void *ctx = state;
+ ast_declaration *decl = new(ctx) ast_declaration((yyvsp[(3) - (3)].identifier), false, NULL, NULL);
+ decl->set_location(yylloc);
+
+ (yyval.declarator_list) = (yyvsp[(1) - (3)].declarator_list);
+ (yyval.declarator_list)->declarations.push_tail(&decl->link);
+ ;}
+ break;
+
+ case 116:
+
+/* Line 1455 of yacc.c */
+#line 807 "glsl_parser.ypp"
+ {
+ void *ctx = state;
+ ast_declaration *decl = new(ctx) ast_declaration((yyvsp[(3) - (5)].identifier), true, NULL, NULL);
+ decl->set_location(yylloc);
+
+ (yyval.declarator_list) = (yyvsp[(1) - (5)].declarator_list);
+ (yyval.declarator_list)->declarations.push_tail(&decl->link);
+ ;}
+ break;
+
+ case 117:
+
+/* Line 1455 of yacc.c */
+#line 816 "glsl_parser.ypp"
+ {
+ void *ctx = state;
+ ast_declaration *decl = new(ctx) ast_declaration((yyvsp[(3) - (6)].identifier), true, (yyvsp[(5) - (6)].expression), NULL);
+ decl->set_location(yylloc);
+
+ (yyval.declarator_list) = (yyvsp[(1) - (6)].declarator_list);
+ (yyval.declarator_list)->declarations.push_tail(&decl->link);
+ ;}
+ break;
+
+ case 118:
+
+/* Line 1455 of yacc.c */
+#line 825 "glsl_parser.ypp"
+ {
+ void *ctx = state;
+ ast_declaration *decl = new(ctx) ast_declaration((yyvsp[(3) - (7)].identifier), true, NULL, (yyvsp[(7) - (7)].expression));
+ decl->set_location(yylloc);
+
+ (yyval.declarator_list) = (yyvsp[(1) - (7)].declarator_list);
+ (yyval.declarator_list)->declarations.push_tail(&decl->link);
+ ;}
+ break;
+
+ case 119:
+
+/* Line 1455 of yacc.c */
+#line 834 "glsl_parser.ypp"
+ {
+ void *ctx = state;
+ ast_declaration *decl = new(ctx) ast_declaration((yyvsp[(3) - (8)].identifier), true, (yyvsp[(5) - (8)].expression), (yyvsp[(8) - (8)].expression));
+ decl->set_location(yylloc);
+
+ (yyval.declarator_list) = (yyvsp[(1) - (8)].declarator_list);
+ (yyval.declarator_list)->declarations.push_tail(&decl->link);
+ ;}
+ break;
+
+ case 120:
+
+/* Line 1455 of yacc.c */
+#line 843 "glsl_parser.ypp"
+ {
+ void *ctx = state;
+ ast_declaration *decl = new(ctx) ast_declaration((yyvsp[(3) - (5)].identifier), false, NULL, (yyvsp[(5) - (5)].expression));
+ decl->set_location(yylloc);
+
+ (yyval.declarator_list) = (yyvsp[(1) - (5)].declarator_list);
+ (yyval.declarator_list)->declarations.push_tail(&decl->link);
+ ;}
+ break;
+
+ case 121:
+
+/* Line 1455 of yacc.c */
+#line 856 "glsl_parser.ypp"
+ {
+ void *ctx = state;
+ if ((yyvsp[(1) - (1)].fully_specified_type)->specifier->type_specifier != ast_struct) {
+ _mesa_glsl_error(& (yylsp[(1) - (1)]), state, "empty declaration list\n");
+ YYERROR;
+ } else {
+ (yyval.declarator_list) = new(ctx) ast_declarator_list((yyvsp[(1) - (1)].fully_specified_type));
+ (yyval.declarator_list)->set_location(yylloc);
+ }
+ ;}
+ break;
+
+ case 122:
+
+/* Line 1455 of yacc.c */
+#line 867 "glsl_parser.ypp"
+ {
+ void *ctx = state;
+ ast_declaration *decl = new(ctx) ast_declaration((yyvsp[(2) - (2)].identifier), false, NULL, NULL);
+
+ (yyval.declarator_list) = new(ctx) ast_declarator_list((yyvsp[(1) - (2)].fully_specified_type));
+ (yyval.declarator_list)->set_location(yylloc);
+ (yyval.declarator_list)->declarations.push_tail(&decl->link);
+ ;}
+ break;
+
+ case 123:
+
+/* Line 1455 of yacc.c */
+#line 876 "glsl_parser.ypp"
+ {
+ void *ctx = state;
+ ast_declaration *decl = new(ctx) ast_declaration((yyvsp[(2) - (4)].identifier), true, NULL, NULL);
+
+ (yyval.declarator_list) = new(ctx) ast_declarator_list((yyvsp[(1) - (4)].fully_specified_type));
+ (yyval.declarator_list)->set_location(yylloc);
+ (yyval.declarator_list)->declarations.push_tail(&decl->link);
+ ;}
+ break;
+
+ case 124:
+
+/* Line 1455 of yacc.c */
+#line 885 "glsl_parser.ypp"
+ {
+ void *ctx = state;
+ ast_declaration *decl = new(ctx) ast_declaration((yyvsp[(2) - (5)].identifier), true, (yyvsp[(4) - (5)].expression), NULL);
+
+ (yyval.declarator_list) = new(ctx) ast_declarator_list((yyvsp[(1) - (5)].fully_specified_type));
+ (yyval.declarator_list)->set_location(yylloc);
+ (yyval.declarator_list)->declarations.push_tail(&decl->link);
+ ;}
+ break;
+
+ case 125:
+
+/* Line 1455 of yacc.c */
+#line 894 "glsl_parser.ypp"
+ {
+ void *ctx = state;
+ ast_declaration *decl = new(ctx) ast_declaration((yyvsp[(2) - (6)].identifier), true, NULL, (yyvsp[(6) - (6)].expression));
+
+ (yyval.declarator_list) = new(ctx) ast_declarator_list((yyvsp[(1) - (6)].fully_specified_type));
+ (yyval.declarator_list)->set_location(yylloc);
+ (yyval.declarator_list)->declarations.push_tail(&decl->link);
+ ;}
+ break;
+
+ case 126:
+
+/* Line 1455 of yacc.c */
+#line 903 "glsl_parser.ypp"
+ {
+ void *ctx = state;
+ ast_declaration *decl = new(ctx) ast_declaration((yyvsp[(2) - (7)].identifier), true, (yyvsp[(4) - (7)].expression), (yyvsp[(7) - (7)].expression));
+
+ (yyval.declarator_list) = new(ctx) ast_declarator_list((yyvsp[(1) - (7)].fully_specified_type));
+ (yyval.declarator_list)->set_location(yylloc);
+ (yyval.declarator_list)->declarations.push_tail(&decl->link);
+ ;}
+ break;
+
+ case 127:
+
+/* Line 1455 of yacc.c */
+#line 912 "glsl_parser.ypp"
+ {
+ void *ctx = state;
+ ast_declaration *decl = new(ctx) ast_declaration((yyvsp[(2) - (4)].identifier), false, NULL, (yyvsp[(4) - (4)].expression));
+
+ (yyval.declarator_list) = new(ctx) ast_declarator_list((yyvsp[(1) - (4)].fully_specified_type));
+ (yyval.declarator_list)->set_location(yylloc);
+ (yyval.declarator_list)->declarations.push_tail(&decl->link);
+ ;}
+ break;
+
+ case 128:
+
+/* Line 1455 of yacc.c */
+#line 921 "glsl_parser.ypp"
+ {
+ void *ctx = state;
+ ast_declaration *decl = new(ctx) ast_declaration((yyvsp[(2) - (2)].identifier), false, NULL, NULL);
+
+ (yyval.declarator_list) = new(ctx) ast_declarator_list(NULL);
+ (yyval.declarator_list)->set_location(yylloc);
+ (yyval.declarator_list)->invariant = true;
+
+ (yyval.declarator_list)->declarations.push_tail(&decl->link);
+ ;}
+ break;
+
+ case 129:
+
+/* Line 1455 of yacc.c */
+#line 935 "glsl_parser.ypp"
+ {
+ void *ctx = state;
+ (yyval.fully_specified_type) = new(ctx) ast_fully_specified_type();
+ (yyval.fully_specified_type)->set_location(yylloc);
+ (yyval.fully_specified_type)->specifier = (yyvsp[(1) - (1)].type_specifier);
+ ;}
+ break;
+
+ case 130:
+
+/* Line 1455 of yacc.c */
+#line 942 "glsl_parser.ypp"
+ {
+ void *ctx = state;
+ (yyval.fully_specified_type) = new(ctx) ast_fully_specified_type();
+ (yyval.fully_specified_type)->set_location(yylloc);
+ (yyval.fully_specified_type)->qualifier = (yyvsp[(1) - (2)].type_qualifier).q;
+ (yyval.fully_specified_type)->specifier = (yyvsp[(2) - (2)].type_specifier);
+ ;}
+ break;
+
+ case 131:
+
+/* Line 1455 of yacc.c */
+#line 952 "glsl_parser.ypp"
+ { (yyval.type_qualifier).i = 0; ;}
+ break;
+
+ case 133:
+
+/* Line 1455 of yacc.c */
+#line 958 "glsl_parser.ypp"
+ {
+ (yyval.type_qualifier) = (yyvsp[(3) - (4)].type_qualifier);
+ ;}
+ break;
+
+ case 135:
+
+/* Line 1455 of yacc.c */
+#line 966 "glsl_parser.ypp"
+ {
+ (yyval.type_qualifier).i = (yyvsp[(1) - (3)].type_qualifier).i | (yyvsp[(3) - (3)].type_qualifier).i;
+ ;}
+ break;
+
+ case 136:
+
+/* Line 1455 of yacc.c */
+#line 973 "glsl_parser.ypp"
+ {
+ (yyval.type_qualifier).i = 0;
+
+ if (state->ARB_fragment_coord_conventions_enable) {
+ bool got_one = false;
+
+ if (strcmp((yyvsp[(1) - (1)].identifier), "origin_upper_left") == 0) {
+ got_one = true;
+ (yyval.type_qualifier).q.origin_upper_left = 1;
+ } else if (strcmp((yyvsp[(1) - (1)].identifier), "pixel_center_integer") == 0) {
+ got_one = true;
+ (yyval.type_qualifier).q.pixel_center_integer = 1;
+ }
+
+ if (state->ARB_fragment_coord_conventions_warn && got_one) {
+ _mesa_glsl_warning(& (yylsp[(1) - (1)]), state,
+ "GL_ARB_fragment_coord_conventions layout "
+ "identifier `%s' used\n", (yyvsp[(1) - (1)].identifier));
+ }
+ }
+
+ /* If the identifier didn't match any known layout identifiers,
+ * emit an error.
+ */
+ if ((yyval.type_qualifier).i == 0) {
+ _mesa_glsl_error(& (yylsp[(1) - (1)]), state, "unrecognized layout identifier "
+ "`%s'\n", (yyvsp[(1) - (1)].identifier));
+ YYERROR;
+ }
+ ;}
+ break;
+
+ case 137:
+
+/* Line 1455 of yacc.c */
+#line 1006 "glsl_parser.ypp"
+ { (yyval.type_qualifier).i = 0; (yyval.type_qualifier).q.smooth = 1; ;}
+ break;
+
+ case 138:
+
+/* Line 1455 of yacc.c */
+#line 1007 "glsl_parser.ypp"
+ { (yyval.type_qualifier).i = 0; (yyval.type_qualifier).q.flat = 1; ;}
+ break;
+
+ case 139:
+
+/* Line 1455 of yacc.c */
+#line 1008 "glsl_parser.ypp"
+ { (yyval.type_qualifier).i = 0; (yyval.type_qualifier).q.noperspective = 1; ;}
+ break;
+
+ case 140:
+
+/* Line 1455 of yacc.c */
+#line 1012 "glsl_parser.ypp"
+ { (yyval.type_qualifier).i = 0; (yyval.type_qualifier).q.constant = 1; ;}
+ break;
+
+ case 142:
+
+/* Line 1455 of yacc.c */
+#line 1018 "glsl_parser.ypp"
+ {
+ (yyval.type_qualifier).i = (yyvsp[(1) - (2)].type_qualifier).i | (yyvsp[(2) - (2)].type_qualifier).i;
+ ;}
+ break;
+
+ case 143:
+
+/* Line 1455 of yacc.c */
+#line 1022 "glsl_parser.ypp"
+ {
+ (yyval.type_qualifier) = (yyvsp[(2) - (2)].type_qualifier);
+ (yyval.type_qualifier).q.invariant = 1;
+ ;}
+ break;
+
+ case 144:
+
+/* Line 1455 of yacc.c */
+#line 1029 "glsl_parser.ypp"
+ { (yyval.type_qualifier).i = 0; (yyval.type_qualifier).q.constant = 1; ;}
+ break;
+
+ case 145:
+
+/* Line 1455 of yacc.c */
+#line 1030 "glsl_parser.ypp"
+ { (yyval.type_qualifier).i = 0; (yyval.type_qualifier).q.attribute = 1; ;}
+ break;
+
+ case 146:
+
+/* Line 1455 of yacc.c */
+#line 1031 "glsl_parser.ypp"
+ { (yyval.type_qualifier).i = (yyvsp[(1) - (2)].type_qualifier).i; (yyval.type_qualifier).q.varying = 1; ;}
+ break;
+
+ case 147:
+
+/* Line 1455 of yacc.c */
+#line 1032 "glsl_parser.ypp"
+ { (yyval.type_qualifier).i = 0; (yyval.type_qualifier).q.centroid = 1; (yyval.type_qualifier).q.varying = 1; ;}
+ break;
+
+ case 148:
+
+/* Line 1455 of yacc.c */
+#line 1033 "glsl_parser.ypp"
+ { (yyval.type_qualifier).i = 0; (yyval.type_qualifier).q.in = 1; ;}
+ break;
+
+ case 149:
+
+/* Line 1455 of yacc.c */
+#line 1034 "glsl_parser.ypp"
+ { (yyval.type_qualifier).i = 0; (yyval.type_qualifier).q.out = 1; ;}
+ break;
+
+ case 150:
+
+/* Line 1455 of yacc.c */
+#line 1035 "glsl_parser.ypp"
+ { (yyval.type_qualifier).i = 0; (yyval.type_qualifier).q.centroid = 1; (yyval.type_qualifier).q.in = 1; ;}
+ break;
+
+ case 151:
+
+/* Line 1455 of yacc.c */
+#line 1036 "glsl_parser.ypp"
+ { (yyval.type_qualifier).i = 0; (yyval.type_qualifier).q.centroid = 1; (yyval.type_qualifier).q.out = 1; ;}
+ break;
+
+ case 152:
+
+/* Line 1455 of yacc.c */
+#line 1037 "glsl_parser.ypp"
+ { (yyval.type_qualifier).i = 0; (yyval.type_qualifier).q.uniform = 1; ;}
+ break;
+
+ case 154:
+
+/* Line 1455 of yacc.c */
+#line 1043 "glsl_parser.ypp"
+ {
+ (yyval.type_specifier) = (yyvsp[(2) - (2)].type_specifier);
+ (yyval.type_specifier)->precision = (yyvsp[(1) - (2)].n);
+ ;}
+ break;
+
+ case 156:
+
+/* Line 1455 of yacc.c */
+#line 1052 "glsl_parser.ypp"
+ {
+ (yyval.type_specifier) = (yyvsp[(1) - (3)].type_specifier);
+ (yyval.type_specifier)->is_array = true;
+ (yyval.type_specifier)->array_size = NULL;
+ ;}
+ break;
+
+ case 157:
+
+/* Line 1455 of yacc.c */
+#line 1058 "glsl_parser.ypp"
+ {
+ (yyval.type_specifier) = (yyvsp[(1) - (4)].type_specifier);
+ (yyval.type_specifier)->is_array = true;
+ (yyval.type_specifier)->array_size = (yyvsp[(3) - (4)].expression);
+ ;}
+ break;
+
+ case 158:
+
+/* Line 1455 of yacc.c */
+#line 1067 "glsl_parser.ypp"
+ {
+ void *ctx = state;
+ (yyval.type_specifier) = new(ctx) ast_type_specifier((yyvsp[(1) - (1)].n));
+ (yyval.type_specifier)->set_location(yylloc);
+ ;}
+ break;
+
+ case 159:
+
+/* Line 1455 of yacc.c */
+#line 1073 "glsl_parser.ypp"
+ {
+ void *ctx = state;
+ (yyval.type_specifier) = new(ctx) ast_type_specifier((yyvsp[(1) - (1)].struct_specifier));
+ (yyval.type_specifier)->set_location(yylloc);
+ ;}
+ break;
+
+ case 160:
+
+/* Line 1455 of yacc.c */
+#line 1079 "glsl_parser.ypp"
+ {
+ void *ctx = state;
+ (yyval.type_specifier) = new(ctx) ast_type_specifier((yyvsp[(1) - (1)].identifier));
+ (yyval.type_specifier)->set_location(yylloc);
+ ;}
+ break;
+
+ case 161:
+
+/* Line 1455 of yacc.c */
+#line 1087 "glsl_parser.ypp"
+ { (yyval.n) = ast_void; ;}
+ break;
+
+ case 162:
+
+/* Line 1455 of yacc.c */
+#line 1088 "glsl_parser.ypp"
+ { (yyval.n) = ast_float; ;}
+ break;
+
+ case 163:
+
+/* Line 1455 of yacc.c */
+#line 1089 "glsl_parser.ypp"
+ { (yyval.n) = ast_int; ;}
+ break;
+
+ case 164:
+
+/* Line 1455 of yacc.c */
+#line 1090 "glsl_parser.ypp"
+ { (yyval.n) = ast_uint; ;}
+ break;
+
+ case 165:
+
+/* Line 1455 of yacc.c */
+#line 1091 "glsl_parser.ypp"
+ { (yyval.n) = ast_bool; ;}
+ break;
+
+ case 166:
+
+/* Line 1455 of yacc.c */
+#line 1092 "glsl_parser.ypp"
+ { (yyval.n) = ast_vec2; ;}
+ break;
+
+ case 167:
+
+/* Line 1455 of yacc.c */
+#line 1093 "glsl_parser.ypp"
+ { (yyval.n) = ast_vec3; ;}
+ break;
+
+ case 168:
+
+/* Line 1455 of yacc.c */
+#line 1094 "glsl_parser.ypp"
+ { (yyval.n) = ast_vec4; ;}
+ break;
+
+ case 169:
+
+/* Line 1455 of yacc.c */
+#line 1095 "glsl_parser.ypp"
+ { (yyval.n) = ast_bvec2; ;}
+ break;
+
+ case 170:
+
+/* Line 1455 of yacc.c */
+#line 1096 "glsl_parser.ypp"
+ { (yyval.n) = ast_bvec3; ;}
+ break;
+
+ case 171:
+
+/* Line 1455 of yacc.c */
+#line 1097 "glsl_parser.ypp"
+ { (yyval.n) = ast_bvec4; ;}
+ break;
+
+ case 172:
+
+/* Line 1455 of yacc.c */
+#line 1098 "glsl_parser.ypp"
+ { (yyval.n) = ast_ivec2; ;}
+ break;
+
+ case 173:
+
+/* Line 1455 of yacc.c */
+#line 1099 "glsl_parser.ypp"
+ { (yyval.n) = ast_ivec3; ;}
+ break;
+
+ case 174:
+
+/* Line 1455 of yacc.c */
+#line 1100 "glsl_parser.ypp"
+ { (yyval.n) = ast_ivec4; ;}
+ break;
+
+ case 175:
+
+/* Line 1455 of yacc.c */
+#line 1101 "glsl_parser.ypp"
+ { (yyval.n) = ast_uvec2; ;}
+ break;
+
+ case 176:
+
+/* Line 1455 of yacc.c */
+#line 1102 "glsl_parser.ypp"
+ { (yyval.n) = ast_uvec3; ;}
+ break;
+
+ case 177:
+
+/* Line 1455 of yacc.c */
+#line 1103 "glsl_parser.ypp"
+ { (yyval.n) = ast_uvec4; ;}
+ break;
+
+ case 178:
+
+/* Line 1455 of yacc.c */
+#line 1104 "glsl_parser.ypp"
+ { (yyval.n) = ast_mat2; ;}
+ break;
+
+ case 179:
+
+/* Line 1455 of yacc.c */
+#line 1105 "glsl_parser.ypp"
+ { (yyval.n) = ast_mat2x3; ;}
+ break;
+
+ case 180:
+
+/* Line 1455 of yacc.c */
+#line 1106 "glsl_parser.ypp"
+ { (yyval.n) = ast_mat2x4; ;}
+ break;
+
+ case 181:
+
+/* Line 1455 of yacc.c */
+#line 1107 "glsl_parser.ypp"
+ { (yyval.n) = ast_mat3x2; ;}
+ break;
+
+ case 182:
+
+/* Line 1455 of yacc.c */
+#line 1108 "glsl_parser.ypp"
+ { (yyval.n) = ast_mat3; ;}
+ break;
+
+ case 183:
+
+/* Line 1455 of yacc.c */
+#line 1109 "glsl_parser.ypp"
+ { (yyval.n) = ast_mat3x4; ;}
+ break;
+
+ case 184:
+
+/* Line 1455 of yacc.c */
+#line 1110 "glsl_parser.ypp"
+ { (yyval.n) = ast_mat4x2; ;}
+ break;
+
+ case 185:
+
+/* Line 1455 of yacc.c */
+#line 1111 "glsl_parser.ypp"
+ { (yyval.n) = ast_mat4x3; ;}
+ break;
+
+ case 186:
+
+/* Line 1455 of yacc.c */
+#line 1112 "glsl_parser.ypp"
+ { (yyval.n) = ast_mat4; ;}
+ break;
+
+ case 187:
+
+/* Line 1455 of yacc.c */
+#line 1113 "glsl_parser.ypp"
+ { (yyval.n) = ast_sampler1d; ;}
+ break;
+
+ case 188:
+
+/* Line 1455 of yacc.c */
+#line 1114 "glsl_parser.ypp"
+ { (yyval.n) = ast_sampler2d; ;}
+ break;
+
+ case 189:
+
+/* Line 1455 of yacc.c */
+#line 1115 "glsl_parser.ypp"
+ { (yyval.n) = ast_sampler2drect; ;}
+ break;
+
+ case 190:
+
+/* Line 1455 of yacc.c */
+#line 1116 "glsl_parser.ypp"
+ { (yyval.n) = ast_sampler3d; ;}
+ break;
+
+ case 191:
+
+/* Line 1455 of yacc.c */
+#line 1117 "glsl_parser.ypp"
+ { (yyval.n) = ast_samplercube; ;}
+ break;
+
+ case 192:
+
+/* Line 1455 of yacc.c */
+#line 1118 "glsl_parser.ypp"
+ { (yyval.n) = ast_sampler1dshadow; ;}
+ break;
+
+ case 193:
+
+/* Line 1455 of yacc.c */
+#line 1119 "glsl_parser.ypp"
+ { (yyval.n) = ast_sampler2dshadow; ;}
+ break;
+
+ case 194:
+
+/* Line 1455 of yacc.c */
+#line 1120 "glsl_parser.ypp"
+ { (yyval.n) = ast_sampler2drectshadow; ;}
+ break;
+
+ case 195:
+
+/* Line 1455 of yacc.c */
+#line 1121 "glsl_parser.ypp"
+ { (yyval.n) = ast_samplercubeshadow; ;}
+ break;
+
+ case 196:
+
+/* Line 1455 of yacc.c */
+#line 1122 "glsl_parser.ypp"
+ { (yyval.n) = ast_sampler1darray; ;}
+ break;
+
+ case 197:
+
+/* Line 1455 of yacc.c */
+#line 1123 "glsl_parser.ypp"
+ { (yyval.n) = ast_sampler2darray; ;}
+ break;
+
+ case 198:
+
+/* Line 1455 of yacc.c */
+#line 1124 "glsl_parser.ypp"
+ { (yyval.n) = ast_sampler1darrayshadow; ;}
+ break;
+
+ case 199:
+
+/* Line 1455 of yacc.c */
+#line 1125 "glsl_parser.ypp"
+ { (yyval.n) = ast_sampler2darrayshadow; ;}
+ break;
+
+ case 200:
+
+/* Line 1455 of yacc.c */
+#line 1126 "glsl_parser.ypp"
+ { (yyval.n) = ast_isampler1d; ;}
+ break;
+
+ case 201:
+
+/* Line 1455 of yacc.c */
+#line 1127 "glsl_parser.ypp"
+ { (yyval.n) = ast_isampler2d; ;}
+ break;
+
+ case 202:
+
+/* Line 1455 of yacc.c */
+#line 1128 "glsl_parser.ypp"
+ { (yyval.n) = ast_isampler3d; ;}
+ break;
+
+ case 203:
+
+/* Line 1455 of yacc.c */
+#line 1129 "glsl_parser.ypp"
+ { (yyval.n) = ast_isamplercube; ;}
+ break;
+
+ case 204:
+
+/* Line 1455 of yacc.c */
+#line 1130 "glsl_parser.ypp"
+ { (yyval.n) = ast_isampler1darray; ;}
+ break;
+
+ case 205:
+
+/* Line 1455 of yacc.c */
+#line 1131 "glsl_parser.ypp"
+ { (yyval.n) = ast_isampler2darray; ;}
+ break;
+
+ case 206:
+
+/* Line 1455 of yacc.c */
+#line 1132 "glsl_parser.ypp"
+ { (yyval.n) = ast_usampler1d; ;}
+ break;
+
+ case 207:
+
+/* Line 1455 of yacc.c */
+#line 1133 "glsl_parser.ypp"
+ { (yyval.n) = ast_usampler2d; ;}
+ break;
+
+ case 208:
+
+/* Line 1455 of yacc.c */
+#line 1134 "glsl_parser.ypp"
+ { (yyval.n) = ast_usampler3d; ;}
+ break;
+
+ case 209:
+
+/* Line 1455 of yacc.c */
+#line 1135 "glsl_parser.ypp"
+ { (yyval.n) = ast_usamplercube; ;}
+ break;
+
+ case 210:
+
+/* Line 1455 of yacc.c */
+#line 1136 "glsl_parser.ypp"
+ { (yyval.n) = ast_usampler1darray; ;}
+ break;
+
+ case 211:
+
+/* Line 1455 of yacc.c */
+#line 1137 "glsl_parser.ypp"
+ { (yyval.n) = ast_usampler2darray; ;}
+ break;
+
+ case 212:
+
+/* Line 1455 of yacc.c */
+#line 1141 "glsl_parser.ypp"
+ {
+ if (state->language_version < 130)
+ _mesa_glsl_error(& (yylsp[(1) - (1)]), state,
+ "precision qualifier forbidden "
+ "in GLSL %d.%d (1.30 or later "
+ "required)\n",
+ state->language_version / 100,
+ state->language_version % 100);
+
+ (yyval.n) = ast_precision_high;
+ ;}
+ break;
+
+ case 213:
+
+/* Line 1455 of yacc.c */
+#line 1152 "glsl_parser.ypp"
+ {
+ if (state->language_version < 130)
+ _mesa_glsl_error(& (yylsp[(1) - (1)]), state,
+ "precision qualifier forbidden "
+ "in GLSL %d.%d (1.30 or later "
+ "required)\n",
+ state->language_version / 100,
+ state->language_version % 100);
+
+ (yyval.n) = ast_precision_medium;
+ ;}
+ break;
+
+ case 214:
+
+/* Line 1455 of yacc.c */
+#line 1163 "glsl_parser.ypp"
+ {
+ if (state->language_version < 130)
+ _mesa_glsl_error(& (yylsp[(1) - (1)]), state,
+ "precision qualifier forbidden "
+ "in GLSL %d.%d (1.30 or later "
+ "required)\n",
+ state->language_version / 100,
+ state->language_version % 100);
+
+ (yyval.n) = ast_precision_low;
+ ;}
+ break;
+
+ case 215:
+
+/* Line 1455 of yacc.c */
+#line 1178 "glsl_parser.ypp"
+ {
+ void *ctx = state;
+ (yyval.struct_specifier) = new(ctx) ast_struct_specifier((yyvsp[(2) - (5)].identifier), (yyvsp[(4) - (5)].node));
+ (yyval.struct_specifier)->set_location(yylloc);
+ ;}
+ break;
+
+ case 216:
+
+/* Line 1455 of yacc.c */
+#line 1184 "glsl_parser.ypp"
+ {
+ void *ctx = state;
+ (yyval.struct_specifier) = new(ctx) ast_struct_specifier(NULL, (yyvsp[(3) - (4)].node));
+ (yyval.struct_specifier)->set_location(yylloc);
+ ;}
+ break;
+
+ case 217:
+
+/* Line 1455 of yacc.c */
+#line 1193 "glsl_parser.ypp"
+ {
+ (yyval.node) = (ast_node *) (yyvsp[(1) - (1)].declarator_list);
+ (yyvsp[(1) - (1)].declarator_list)->link.self_link();
+ ;}
+ break;
+
+ case 218:
+
+/* Line 1455 of yacc.c */
+#line 1198 "glsl_parser.ypp"
+ {
+ (yyval.node) = (ast_node *) (yyvsp[(1) - (2)].node);
+ (yyval.node)->link.insert_before(& (yyvsp[(2) - (2)].declarator_list)->link);
+ ;}
+ break;
+
+ case 219:
+
+/* Line 1455 of yacc.c */
+#line 1206 "glsl_parser.ypp"
+ {
+ void *ctx = state;
+ ast_fully_specified_type *type = new(ctx) ast_fully_specified_type();
+ type->set_location(yylloc);
+
+ type->specifier = (yyvsp[(1) - (3)].type_specifier);
+ (yyval.declarator_list) = new(ctx) ast_declarator_list(type);
+ (yyval.declarator_list)->set_location(yylloc);
+
+ (yyval.declarator_list)->declarations.push_degenerate_list_at_head(& (yyvsp[(2) - (3)].declaration)->link);
+ ;}
+ break;
+
+ case 220:
+
+/* Line 1455 of yacc.c */
+#line 1221 "glsl_parser.ypp"
+ {
+ (yyval.declaration) = (yyvsp[(1) - (1)].declaration);
+ (yyvsp[(1) - (1)].declaration)->link.self_link();
+ ;}
+ break;
+
+ case 221:
+
+/* Line 1455 of yacc.c */
+#line 1226 "glsl_parser.ypp"
+ {
+ (yyval.declaration) = (yyvsp[(1) - (3)].declaration);
+ (yyval.declaration)->link.insert_before(& (yyvsp[(3) - (3)].declaration)->link);
+ ;}
+ break;
+
+ case 222:
+
+/* Line 1455 of yacc.c */
+#line 1234 "glsl_parser.ypp"
+ {
+ void *ctx = state;
+ (yyval.declaration) = new(ctx) ast_declaration((yyvsp[(1) - (1)].identifier), false, NULL, NULL);
+ (yyval.declaration)->set_location(yylloc);
+ ;}
+ break;
+
+ case 223:
+
+/* Line 1455 of yacc.c */
+#line 1240 "glsl_parser.ypp"
+ {
+ void *ctx = state;
+ (yyval.declaration) = new(ctx) ast_declaration((yyvsp[(1) - (4)].identifier), true, (yyvsp[(3) - (4)].expression), NULL);
+ (yyval.declaration)->set_location(yylloc);
+ ;}
+ break;
+
+ case 228:
+
+/* Line 1455 of yacc.c */
+#line 1263 "glsl_parser.ypp"
+ { (yyval.node) = (ast_node *) (yyvsp[(1) - (1)].compound_statement); ;}
+ break;
+
+ case 234:
+
+/* Line 1455 of yacc.c */
+#line 1275 "glsl_parser.ypp"
+ { (yyval.node) = NULL; ;}
+ break;
+
+ case 235:
+
+/* Line 1455 of yacc.c */
+#line 1276 "glsl_parser.ypp"
+ { (yyval.node) = NULL; ;}
+ break;
+
+ case 238:
+
+/* Line 1455 of yacc.c */
+#line 1283 "glsl_parser.ypp"
+ {
+ void *ctx = state;
+ (yyval.compound_statement) = new(ctx) ast_compound_statement(true, NULL);
+ (yyval.compound_statement)->set_location(yylloc);
+ ;}
+ break;
+
+ case 239:
+
+/* Line 1455 of yacc.c */
+#line 1289 "glsl_parser.ypp"
+ {
+ void *ctx = state;
+ (yyval.compound_statement) = new(ctx) ast_compound_statement(true, (yyvsp[(2) - (3)].node));
+ (yyval.compound_statement)->set_location(yylloc);
+ ;}
+ break;
+
+ case 240:
+
+/* Line 1455 of yacc.c */
+#line 1297 "glsl_parser.ypp"
+ { (yyval.node) = (ast_node *) (yyvsp[(1) - (1)].compound_statement); ;}
+ break;
+
+ case 242:
+
+/* Line 1455 of yacc.c */
+#line 1303 "glsl_parser.ypp"
+ {
+ void *ctx = state;
+ (yyval.compound_statement) = new(ctx) ast_compound_statement(false, NULL);
+ (yyval.compound_statement)->set_location(yylloc);
+ ;}
+ break;
+
+ case 243:
+
+/* Line 1455 of yacc.c */
+#line 1309 "glsl_parser.ypp"
+ {
+ void *ctx = state;
+ (yyval.compound_statement) = new(ctx) ast_compound_statement(false, (yyvsp[(2) - (3)].node));
+ (yyval.compound_statement)->set_location(yylloc);
+ ;}
+ break;
+
+ case 244:
+
+/* Line 1455 of yacc.c */
+#line 1318 "glsl_parser.ypp"
+ {
+ if ((yyvsp[(1) - (1)].node) == NULL) {
+ _mesa_glsl_error(& (yylsp[(1) - (1)]), state, "<nil> statement\n");
+ assert((yyvsp[(1) - (1)].node) != NULL);
+ }
+
+ (yyval.node) = (yyvsp[(1) - (1)].node);
+ (yyval.node)->link.self_link();
+ ;}
+ break;
+
+ case 245:
+
+/* Line 1455 of yacc.c */
+#line 1328 "glsl_parser.ypp"
+ {
+ if ((yyvsp[(2) - (2)].node) == NULL) {
+ _mesa_glsl_error(& (yylsp[(2) - (2)]), state, "<nil> statement\n");
+ assert((yyvsp[(2) - (2)].node) != NULL);
+ }
+ (yyval.node) = (yyvsp[(1) - (2)].node);
+ (yyval.node)->link.insert_before(& (yyvsp[(2) - (2)].node)->link);
+ ;}
+ break;
+
+ case 246:
+
+/* Line 1455 of yacc.c */
+#line 1340 "glsl_parser.ypp"
+ {
+ void *ctx = state;
+ (yyval.node) = new(ctx) ast_expression_statement(NULL);
+ (yyval.node)->set_location(yylloc);
+ ;}
+ break;
+
+ case 247:
+
+/* Line 1455 of yacc.c */
+#line 1346 "glsl_parser.ypp"
+ {
+ void *ctx = state;
+ (yyval.node) = new(ctx) ast_expression_statement((yyvsp[(1) - (2)].expression));
+ (yyval.node)->set_location(yylloc);
+ ;}
+ break;
+
+ case 248:
+
+/* Line 1455 of yacc.c */
+#line 1355 "glsl_parser.ypp"
+ {
+ void *ctx = state;
+ (yyval.node) = new(ctx) ast_selection_statement((yyvsp[(3) - (7)].expression), (yyvsp[(5) - (7)].node), (yyvsp[(7) - (7)].node));
+ (yyval.node)->set_location(yylloc);
+ ;}
+ break;
+
+ case 249:
+
+/* Line 1455 of yacc.c */
+#line 1364 "glsl_parser.ypp"
+ {
+ void *ctx = state;
+ (yyval.node) = new(ctx) ast_selection_statement((yyvsp[(3) - (5)].expression), (yyvsp[(5) - (5)].node), NULL);
+ (yyval.node)->set_location(yylloc);
+ ;}
+ break;
+
+ case 250:
+
+/* Line 1455 of yacc.c */
+#line 1370 "glsl_parser.ypp"
+ {
+ void *ctx = state;
+ (yyval.node) = new(ctx) ast_selection_statement((yyvsp[(3) - (5)].expression), (yyvsp[(5) - (5)].node), NULL);
+ (yyval.node)->set_location(yylloc);
+ ;}
+ break;
+
+ case 251:
+
+/* Line 1455 of yacc.c */
+#line 1376 "glsl_parser.ypp"
+ {
+ void *ctx = state;
+ (yyval.node) = new(ctx) ast_selection_statement((yyvsp[(3) - (7)].expression), (yyvsp[(5) - (7)].node), (yyvsp[(7) - (7)].node));
+ (yyval.node)->set_location(yylloc);
+ ;}
+ break;
+
+ case 252:
+
+/* Line 1455 of yacc.c */
+#line 1385 "glsl_parser.ypp"
+ {
+ (yyval.node) = (ast_node *) (yyvsp[(1) - (1)].expression);
+ ;}
+ break;
+
+ case 253:
+
+/* Line 1455 of yacc.c */
+#line 1389 "glsl_parser.ypp"
+ {
+ void *ctx = state;
+ ast_declaration *decl = new(ctx) ast_declaration((yyvsp[(2) - (4)].identifier), false, NULL, (yyvsp[(4) - (4)].expression));
+ ast_declarator_list *declarator = new(ctx) ast_declarator_list((yyvsp[(1) - (4)].fully_specified_type));
+ decl->set_location(yylloc);
+ declarator->set_location(yylloc);
+
+ declarator->declarations.push_tail(&decl->link);
+ (yyval.node) = declarator;
+ ;}
+ break;
+
+ case 257:
+
+/* Line 1455 of yacc.c */
+#line 1412 "glsl_parser.ypp"
+ {
+ void *ctx = state;
+ (yyval.node) = new(ctx) ast_iteration_statement(ast_iteration_statement::ast_while,
+ NULL, (yyvsp[(3) - (5)].node), NULL, (yyvsp[(5) - (5)].node));
+ (yyval.node)->set_location(yylloc);
+ ;}
+ break;
+
+ case 258:
+
+/* Line 1455 of yacc.c */
+#line 1419 "glsl_parser.ypp"
+ {
+ void *ctx = state;
+ (yyval.node) = new(ctx) ast_iteration_statement(ast_iteration_statement::ast_do_while,
+ NULL, (yyvsp[(5) - (7)].expression), NULL, (yyvsp[(2) - (7)].node));
+ (yyval.node)->set_location(yylloc);
+ ;}
+ break;
+
+ case 259:
+
+/* Line 1455 of yacc.c */
+#line 1426 "glsl_parser.ypp"
+ {
+ void *ctx = state;
+ (yyval.node) = new(ctx) ast_iteration_statement(ast_iteration_statement::ast_for,
+ (yyvsp[(3) - (6)].node), (yyvsp[(4) - (6)].for_rest_statement).cond, (yyvsp[(4) - (6)].for_rest_statement).rest, (yyvsp[(6) - (6)].node));
+ (yyval.node)->set_location(yylloc);
+ ;}
+ break;
+
+ case 263:
+
+/* Line 1455 of yacc.c */
+#line 1442 "glsl_parser.ypp"
+ {
+ (yyval.node) = NULL;
+ ;}
+ break;
+
+ case 264:
+
+/* Line 1455 of yacc.c */
+#line 1449 "glsl_parser.ypp"
+ {
+ (yyval.for_rest_statement).cond = (yyvsp[(1) - (2)].node);
+ (yyval.for_rest_statement).rest = NULL;
+ ;}
+ break;
+
+ case 265:
+
+/* Line 1455 of yacc.c */
+#line 1454 "glsl_parser.ypp"
+ {
+ (yyval.for_rest_statement).cond = (yyvsp[(1) - (3)].node);
+ (yyval.for_rest_statement).rest = (yyvsp[(3) - (3)].expression);
+ ;}
+ break;
+
+ case 266:
+
+/* Line 1455 of yacc.c */
+#line 1463 "glsl_parser.ypp"
+ {
+ void *ctx = state;
+ (yyval.node) = new(ctx) ast_jump_statement(ast_jump_statement::ast_continue, NULL);
+ (yyval.node)->set_location(yylloc);
+ ;}
+ break;
+
+ case 267:
+
+/* Line 1455 of yacc.c */
+#line 1469 "glsl_parser.ypp"
+ {
+ void *ctx = state;
+ (yyval.node) = new(ctx) ast_jump_statement(ast_jump_statement::ast_break, NULL);
+ (yyval.node)->set_location(yylloc);
+ ;}
+ break;
+
+ case 268:
+
+/* Line 1455 of yacc.c */
+#line 1475 "glsl_parser.ypp"
+ {
+ void *ctx = state;
+ (yyval.node) = new(ctx) ast_jump_statement(ast_jump_statement::ast_return, NULL);
+ (yyval.node)->set_location(yylloc);
+ ;}
+ break;
+
+ case 269:
+
+/* Line 1455 of yacc.c */
+#line 1481 "glsl_parser.ypp"
+ {
+ void *ctx = state;
+ (yyval.node) = new(ctx) ast_jump_statement(ast_jump_statement::ast_return, (yyvsp[(2) - (3)].expression));
+ (yyval.node)->set_location(yylloc);
+ ;}
+ break;
+
+ case 270:
+
+/* Line 1455 of yacc.c */
+#line 1487 "glsl_parser.ypp"
+ {
+ void *ctx = state;
+ (yyval.node) = new(ctx) ast_jump_statement(ast_jump_statement::ast_discard, NULL);
+ (yyval.node)->set_location(yylloc);
+ ;}
+ break;
+
+ case 271:
+
+/* Line 1455 of yacc.c */
+#line 1495 "glsl_parser.ypp"
+ { (yyval.node) = (yyvsp[(1) - (1)].function_definition); ;}
+ break;
+
+ case 272:
+
+/* Line 1455 of yacc.c */
+#line 1496 "glsl_parser.ypp"
+ { (yyval.node) = (yyvsp[(1) - (1)].node); ;}
+ break;
+
+ case 273:
+
+/* Line 1455 of yacc.c */
+#line 1501 "glsl_parser.ypp"
+ {
+ void *ctx = state;
+ (yyval.function_definition) = new(ctx) ast_function_definition();
+ (yyval.function_definition)->set_location(yylloc);
+ (yyval.function_definition)->prototype = (yyvsp[(1) - (2)].function);
+ (yyval.function_definition)->body = (yyvsp[(2) - (2)].compound_statement);
+ ;}
+ break;
+
+
+
+/* Line 1455 of yacc.c */
+#line 5029 "glsl_parser.cpp"
+ default: break;
+ }
+ YY_SYMBOL_PRINT ("-> $$ =", yyr1[yyn], &yyval, &yyloc);
+
+ YYPOPSTACK (yylen);
+ yylen = 0;
+ YY_STACK_PRINT (yyss, yyssp);
+
+ *++yyvsp = yyval;
+ *++yylsp = yyloc;
+
+ /* Now `shift' the result of the reduction. Determine what state
+ that goes to, based on the state we popped back to and the rule
+ number reduced by. */
+
+ yyn = yyr1[yyn];
+
+ yystate = yypgoto[yyn - YYNTOKENS] + *yyssp;
+ if (0 <= yystate && yystate <= YYLAST && yycheck[yystate] == *yyssp)
+ yystate = yytable[yystate];
+ else
+ yystate = yydefgoto[yyn - YYNTOKENS];
+
+ goto yynewstate;
+
+
+/*------------------------------------.
+| yyerrlab -- here on detecting error |
+`------------------------------------*/
+yyerrlab:
+ /* If not already recovering from an error, report this error. */
+ if (!yyerrstatus)
+ {
+ ++yynerrs;
+#if ! YYERROR_VERBOSE
+ yyerror (&yylloc, state, YY_("syntax error"));
+#else
+ {
+ YYSIZE_T yysize = yysyntax_error (0, yystate, yychar);
+ if (yymsg_alloc < yysize && yymsg_alloc < YYSTACK_ALLOC_MAXIMUM)
+ {
+ YYSIZE_T yyalloc = 2 * yysize;
+ if (! (yysize <= yyalloc && yyalloc <= YYSTACK_ALLOC_MAXIMUM))
+ yyalloc = YYSTACK_ALLOC_MAXIMUM;
+ if (yymsg != yymsgbuf)
+ YYSTACK_FREE (yymsg);
+ yymsg = (char *) YYSTACK_ALLOC (yyalloc);
+ if (yymsg)
+ yymsg_alloc = yyalloc;
+ else
+ {
+ yymsg = yymsgbuf;
+ yymsg_alloc = sizeof yymsgbuf;
+ }
+ }
+
+ if (0 < yysize && yysize <= yymsg_alloc)
+ {
+ (void) yysyntax_error (yymsg, yystate, yychar);
+ yyerror (&yylloc, state, yymsg);
+ }
+ else
+ {
+ yyerror (&yylloc, state, YY_("syntax error"));
+ if (yysize != 0)
+ goto yyexhaustedlab;
+ }
+ }
+#endif
+ }
+
+ yyerror_range[0] = yylloc;
+
+ if (yyerrstatus == 3)
+ {
+ /* If just tried and failed to reuse lookahead token after an
+ error, discard it. */
+
+ if (yychar <= YYEOF)
+ {
+ /* Return failure if at end of input. */
+ if (yychar == YYEOF)
+ YYABORT;
+ }
+ else
+ {
+ yydestruct ("Error: discarding",
+ yytoken, &yylval, &yylloc, state);
+ yychar = YYEMPTY;
+ }
+ }
+
+ /* Else will try to reuse lookahead token after shifting the error
+ token. */
+ goto yyerrlab1;
+
+
+/*---------------------------------------------------.
+| yyerrorlab -- error raised explicitly by YYERROR. |
+`---------------------------------------------------*/
+yyerrorlab:
+
+ /* Pacify compilers like GCC when the user code never invokes
+ YYERROR and the label yyerrorlab therefore never appears in user
+ code. */
+ if (/*CONSTCOND*/ 0)
+ goto yyerrorlab;
+
+ yyerror_range[0] = yylsp[1-yylen];
+ /* Do not reclaim the symbols of the rule which action triggered
+ this YYERROR. */
+ YYPOPSTACK (yylen);
+ yylen = 0;
+ YY_STACK_PRINT (yyss, yyssp);
+ yystate = *yyssp;
+ goto yyerrlab1;
+
+
+/*-------------------------------------------------------------.
+| yyerrlab1 -- common code for both syntax error and YYERROR. |
+`-------------------------------------------------------------*/
+yyerrlab1:
+ yyerrstatus = 3; /* Each real token shifted decrements this. */
+
+ for (;;)
+ {
+ yyn = yypact[yystate];
+ if (yyn != YYPACT_NINF)
+ {
+ yyn += YYTERROR;
+ if (0 <= yyn && yyn <= YYLAST && yycheck[yyn] == YYTERROR)
+ {
+ yyn = yytable[yyn];
+ if (0 < yyn)
+ break;
+ }
+ }
+
+ /* Pop the current state because it cannot handle the error token. */
+ if (yyssp == yyss)
+ YYABORT;
+
+ yyerror_range[0] = *yylsp;
+ yydestruct ("Error: popping",
+ yystos[yystate], yyvsp, yylsp, state);
+ YYPOPSTACK (1);
+ yystate = *yyssp;
+ YY_STACK_PRINT (yyss, yyssp);
+ }
+
+ *++yyvsp = yylval;
+
+ yyerror_range[1] = yylloc;
+ /* Using YYLLOC is tempting, but would change the location of
+ the lookahead. YYLOC is available though. */
+ YYLLOC_DEFAULT (yyloc, (yyerror_range - 1), 2);
+ *++yylsp = yyloc;
+
+ /* Shift the error token. */
+ YY_SYMBOL_PRINT ("Shifting", yystos[yyn], yyvsp, yylsp);
+
+ yystate = yyn;
+ goto yynewstate;
+
+
+/*-------------------------------------.
+| yyacceptlab -- YYACCEPT comes here. |
+`-------------------------------------*/
+yyacceptlab:
+ yyresult = 0;
+ goto yyreturn;
+
+/*-----------------------------------.
+| yyabortlab -- YYABORT comes here. |
+`-----------------------------------*/
+yyabortlab:
+ yyresult = 1;
+ goto yyreturn;
+
+#if !defined(yyoverflow) || YYERROR_VERBOSE
+/*-------------------------------------------------.
+| yyexhaustedlab -- memory exhaustion comes here. |
+`-------------------------------------------------*/
+yyexhaustedlab:
+ yyerror (&yylloc, state, YY_("memory exhausted"));
+ yyresult = 2;
+ /* Fall through. */
+#endif
+
+yyreturn:
+ if (yychar != YYEMPTY)
+ yydestruct ("Cleanup: discarding lookahead",
+ yytoken, &yylval, &yylloc, state);
+ /* Do not reclaim the symbols of the rule which action triggered
+ this YYABORT or YYACCEPT. */
+ YYPOPSTACK (yylen);
+ YY_STACK_PRINT (yyss, yyssp);
+ while (yyssp != yyss)
+ {
+ yydestruct ("Cleanup: popping",
+ yystos[*yyssp], yyvsp, yylsp, state);
+ YYPOPSTACK (1);
+ }
+#ifndef yyoverflow
+ if (yyss != yyssa)
+ YYSTACK_FREE (yyss);
+#endif
+#if YYERROR_VERBOSE
+ if (yymsg != yymsgbuf)
+ YYSTACK_FREE (yymsg);
+#endif
+ /* Make sure YYID is used. */
+ return YYID (yyresult);
+}
+
+
+
diff --git a/src/glsl/glsl_parser.h b/src/glsl/glsl_parser.h
new file mode 100644
index 00000000000..48a0a5fb3a3
--- /dev/null
+++ b/src/glsl/glsl_parser.h
@@ -0,0 +1,291 @@
+
+/* A Bison parser, made by GNU Bison 2.4.1. */
+
+/* Skeleton interface for Bison's Yacc-like parsers in C
+
+ Copyright (C) 1984, 1989, 1990, 2000, 2001, 2002, 2003, 2004, 2005, 2006
+ Free Software Foundation, Inc.
+
+ This program is free software: you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program. If not, see <http://www.gnu.org/licenses/>. */
+
+/* As a special exception, you may create a larger work that contains
+ part or all of the Bison parser skeleton and distribute that work
+ under terms of your choice, so long as that work isn't itself a
+ parser generator using the skeleton or a modified version thereof
+ as a parser skeleton. Alternatively, if you modify or redistribute
+ the parser skeleton itself, you may (at your option) remove this
+ special exception, which will cause the skeleton and the resulting
+ Bison output files to be licensed under the GNU General Public
+ License without this special exception.
+
+ This special exception was added by the Free Software Foundation in
+ version 2.2 of Bison. */
+
+
+/* Tokens. */
+#ifndef YYTOKENTYPE
+# define YYTOKENTYPE
+ /* Put the tokens into the symbol table, so that GDB and other debuggers
+ know about them. */
+ enum yytokentype {
+ ATTRIBUTE = 258,
+ CONST_TOK = 259,
+ BOOL_TOK = 260,
+ FLOAT_TOK = 261,
+ INT_TOK = 262,
+ UINT_TOK = 263,
+ BREAK = 264,
+ CONTINUE = 265,
+ DO = 266,
+ ELSE = 267,
+ FOR = 268,
+ IF = 269,
+ DISCARD = 270,
+ RETURN = 271,
+ SWITCH = 272,
+ CASE = 273,
+ DEFAULT = 274,
+ BVEC2 = 275,
+ BVEC3 = 276,
+ BVEC4 = 277,
+ IVEC2 = 278,
+ IVEC3 = 279,
+ IVEC4 = 280,
+ UVEC2 = 281,
+ UVEC3 = 282,
+ UVEC4 = 283,
+ VEC2 = 284,
+ VEC3 = 285,
+ VEC4 = 286,
+ CENTROID = 287,
+ IN_TOK = 288,
+ OUT_TOK = 289,
+ INOUT_TOK = 290,
+ UNIFORM = 291,
+ VARYING = 292,
+ NOPERSPECTIVE = 293,
+ FLAT = 294,
+ SMOOTH = 295,
+ MAT2X2 = 296,
+ MAT2X3 = 297,
+ MAT2X4 = 298,
+ MAT3X2 = 299,
+ MAT3X3 = 300,
+ MAT3X4 = 301,
+ MAT4X2 = 302,
+ MAT4X3 = 303,
+ MAT4X4 = 304,
+ SAMPLER1D = 305,
+ SAMPLER2D = 306,
+ SAMPLER3D = 307,
+ SAMPLERCUBE = 308,
+ SAMPLER1DSHADOW = 309,
+ SAMPLER2DSHADOW = 310,
+ SAMPLERCUBESHADOW = 311,
+ SAMPLER1DARRAY = 312,
+ SAMPLER2DARRAY = 313,
+ SAMPLER1DARRAYSHADOW = 314,
+ SAMPLER2DARRAYSHADOW = 315,
+ ISAMPLER1D = 316,
+ ISAMPLER2D = 317,
+ ISAMPLER3D = 318,
+ ISAMPLERCUBE = 319,
+ ISAMPLER1DARRAY = 320,
+ ISAMPLER2DARRAY = 321,
+ USAMPLER1D = 322,
+ USAMPLER2D = 323,
+ USAMPLER3D = 324,
+ USAMPLERCUBE = 325,
+ USAMPLER1DARRAY = 326,
+ USAMPLER2DARRAY = 327,
+ STRUCT = 328,
+ VOID_TOK = 329,
+ WHILE = 330,
+ IDENTIFIER = 331,
+ FLOATCONSTANT = 332,
+ INTCONSTANT = 333,
+ UINTCONSTANT = 334,
+ BOOLCONSTANT = 335,
+ FIELD_SELECTION = 336,
+ LEFT_OP = 337,
+ RIGHT_OP = 338,
+ INC_OP = 339,
+ DEC_OP = 340,
+ LE_OP = 341,
+ GE_OP = 342,
+ EQ_OP = 343,
+ NE_OP = 344,
+ AND_OP = 345,
+ OR_OP = 346,
+ XOR_OP = 347,
+ MUL_ASSIGN = 348,
+ DIV_ASSIGN = 349,
+ ADD_ASSIGN = 350,
+ MOD_ASSIGN = 351,
+ LEFT_ASSIGN = 352,
+ RIGHT_ASSIGN = 353,
+ AND_ASSIGN = 354,
+ XOR_ASSIGN = 355,
+ OR_ASSIGN = 356,
+ SUB_ASSIGN = 357,
+ INVARIANT = 358,
+ LOWP = 359,
+ MEDIUMP = 360,
+ HIGHP = 361,
+ SUPERP = 362,
+ PRECISION = 363,
+ VERSION = 364,
+ EXTENSION = 365,
+ LINE = 366,
+ PRAGMA = 367,
+ COLON = 368,
+ EOL = 369,
+ INTERFACE = 370,
+ OUTPUT = 371,
+ LAYOUT_TOK = 372,
+ ASM = 373,
+ CLASS = 374,
+ UNION = 375,
+ ENUM = 376,
+ TYPEDEF = 377,
+ TEMPLATE = 378,
+ THIS = 379,
+ PACKED_TOK = 380,
+ GOTO = 381,
+ INLINE_TOK = 382,
+ NOINLINE = 383,
+ VOLATILE = 384,
+ PUBLIC_TOK = 385,
+ STATIC = 386,
+ EXTERN = 387,
+ EXTERNAL = 388,
+ LONG_TOK = 389,
+ SHORT_TOK = 390,
+ DOUBLE_TOK = 391,
+ HALF = 392,
+ FIXED_TOK = 393,
+ UNSIGNED = 394,
+ INPUT_TOK = 395,
+ OUPTUT = 396,
+ HVEC2 = 397,
+ HVEC3 = 398,
+ HVEC4 = 399,
+ DVEC2 = 400,
+ DVEC3 = 401,
+ DVEC4 = 402,
+ FVEC2 = 403,
+ FVEC3 = 404,
+ FVEC4 = 405,
+ SAMPLER2DRECT = 406,
+ SAMPLER3DRECT = 407,
+ SAMPLER2DRECTSHADOW = 408,
+ SIZEOF = 409,
+ CAST = 410,
+ NAMESPACE = 411,
+ USING = 412,
+ ERROR_TOK = 413,
+ COMMON = 414,
+ PARTITION = 415,
+ ACTIVE = 416,
+ SAMPLERBUFFER = 417,
+ FILTER = 418,
+ IMAGE1D = 419,
+ IMAGE2D = 420,
+ IMAGE3D = 421,
+ IMAGECUBE = 422,
+ IMAGE1DARRAY = 423,
+ IMAGE2DARRAY = 424,
+ IIMAGE1D = 425,
+ IIMAGE2D = 426,
+ IIMAGE3D = 427,
+ IIMAGECUBE = 428,
+ IIMAGE1DARRAY = 429,
+ IIMAGE2DARRAY = 430,
+ UIMAGE1D = 431,
+ UIMAGE2D = 432,
+ UIMAGE3D = 433,
+ UIMAGECUBE = 434,
+ UIMAGE1DARRAY = 435,
+ UIMAGE2DARRAY = 436,
+ IMAGE1DSHADOW = 437,
+ IMAGE2DSHADOW = 438,
+ IMAGEBUFFER = 439,
+ IIMAGEBUFFER = 440,
+ UIMAGEBUFFER = 441,
+ ROW_MAJOR = 442
+ };
+#endif
+
+
+
+#if ! defined YYSTYPE && ! defined YYSTYPE_IS_DECLARED
+typedef union YYSTYPE
+{
+
+/* Line 1676 of yacc.c */
+#line 52 "glsl_parser.ypp"
+
+ int n;
+ float real;
+ char *identifier;
+
+ union {
+ struct ast_type_qualifier q;
+ unsigned i;
+ } type_qualifier;
+
+ ast_node *node;
+ ast_type_specifier *type_specifier;
+ ast_fully_specified_type *fully_specified_type;
+ ast_function *function;
+ ast_parameter_declarator *parameter_declarator;
+ ast_function_definition *function_definition;
+ ast_compound_statement *compound_statement;
+ ast_expression *expression;
+ ast_declarator_list *declarator_list;
+ ast_struct_specifier *struct_specifier;
+ ast_declaration *declaration;
+
+ struct {
+ ast_node *cond;
+ ast_expression *rest;
+ } for_rest_statement;
+
+
+
+/* Line 1676 of yacc.c */
+#line 269 "glsl_parser.h"
+} YYSTYPE;
+# define YYSTYPE_IS_TRIVIAL 1
+# define yystype YYSTYPE /* obsolescent; will be withdrawn */
+# define YYSTYPE_IS_DECLARED 1
+#endif
+
+
+
+#if ! defined YYLTYPE && ! defined YYLTYPE_IS_DECLARED
+typedef struct YYLTYPE
+{
+ int first_line;
+ int first_column;
+ int last_line;
+ int last_column;
+} YYLTYPE;
+# define yyltype YYLTYPE /* obsolescent; will be withdrawn */
+# define YYLTYPE_IS_DECLARED 1
+# define YYLTYPE_IS_TRIVIAL 1
+#endif
+
+
+
diff --git a/src/glsl/glsl_parser.ypp b/src/glsl/glsl_parser.ypp
new file mode 100644
index 00000000000..e0b1d285046
--- /dev/null
+++ b/src/glsl/glsl_parser.ypp
@@ -0,0 +1,1508 @@
+%{
+/*
+ * Copyright © 2008, 2009 Intel Corporation
+ *
+ * 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 (including the next
+ * paragraph) 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
+ * THE AUTHORS OR COPYRIGHT HOLDERS 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.
+ */
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <assert.h>
+
+#include "ast.h"
+#include "glsl_parser_extras.h"
+#include "glsl_types.h"
+
+#define YYLEX_PARAM state->scanner
+
+%}
+
+%pure-parser
+%error-verbose
+
+%locations
+%initial-action {
+ @$.first_line = 1;
+ @$.first_column = 1;
+ @$.last_line = 1;
+ @$.last_column = 1;
+ @$.source = 0;
+}
+
+%lex-param {void *scanner}
+%parse-param {struct _mesa_glsl_parse_state *state}
+
+%union {
+ int n;
+ float real;
+ char *identifier;
+
+ union {
+ struct ast_type_qualifier q;
+ unsigned i;
+ } type_qualifier;
+
+ ast_node *node;
+ ast_type_specifier *type_specifier;
+ ast_fully_specified_type *fully_specified_type;
+ ast_function *function;
+ ast_parameter_declarator *parameter_declarator;
+ ast_function_definition *function_definition;
+ ast_compound_statement *compound_statement;
+ ast_expression *expression;
+ ast_declarator_list *declarator_list;
+ ast_struct_specifier *struct_specifier;
+ ast_declaration *declaration;
+
+ struct {
+ ast_node *cond;
+ ast_expression *rest;
+ } for_rest_statement;
+}
+
+%token ATTRIBUTE CONST_TOK BOOL_TOK FLOAT_TOK INT_TOK UINT_TOK
+%token BREAK CONTINUE DO ELSE FOR IF DISCARD RETURN SWITCH CASE DEFAULT
+%token BVEC2 BVEC3 BVEC4 IVEC2 IVEC3 IVEC4 UVEC2 UVEC3 UVEC4 VEC2 VEC3 VEC4
+%token CENTROID IN_TOK OUT_TOK INOUT_TOK UNIFORM VARYING
+%token NOPERSPECTIVE FLAT SMOOTH
+%token MAT2X2 MAT2X3 MAT2X4
+%token MAT3X2 MAT3X3 MAT3X4
+%token MAT4X2 MAT4X3 MAT4X4
+%token SAMPLER1D SAMPLER2D SAMPLER3D SAMPLERCUBE SAMPLER1DSHADOW SAMPLER2DSHADOW
+%token SAMPLERCUBESHADOW SAMPLER1DARRAY SAMPLER2DARRAY SAMPLER1DARRAYSHADOW
+%token SAMPLER2DARRAYSHADOW ISAMPLER1D ISAMPLER2D ISAMPLER3D ISAMPLERCUBE
+%token ISAMPLER1DARRAY ISAMPLER2DARRAY USAMPLER1D USAMPLER2D USAMPLER3D
+%token USAMPLERCUBE USAMPLER1DARRAY USAMPLER2DARRAY
+%token STRUCT VOID_TOK WHILE
+%token <identifier> IDENTIFIER
+%token <real> FLOATCONSTANT
+%token <n> INTCONSTANT UINTCONSTANT BOOLCONSTANT
+%token <identifier> FIELD_SELECTION
+%token LEFT_OP RIGHT_OP
+%token INC_OP DEC_OP LE_OP GE_OP EQ_OP NE_OP
+%token AND_OP OR_OP XOR_OP MUL_ASSIGN DIV_ASSIGN ADD_ASSIGN
+%token MOD_ASSIGN LEFT_ASSIGN RIGHT_ASSIGN AND_ASSIGN XOR_ASSIGN OR_ASSIGN
+%token SUB_ASSIGN
+%token INVARIANT
+%token LOWP MEDIUMP HIGHP SUPERP PRECISION
+
+%token VERSION EXTENSION LINE PRAGMA COLON EOL INTERFACE OUTPUT
+%token LAYOUT_TOK
+
+ /* Reserved words that are not actually used in the grammar.
+ */
+%token ASM CLASS UNION ENUM TYPEDEF TEMPLATE THIS PACKED_TOK GOTO
+%token INLINE_TOK NOINLINE VOLATILE PUBLIC_TOK STATIC EXTERN EXTERNAL
+%token LONG_TOK SHORT_TOK DOUBLE_TOK HALF FIXED_TOK UNSIGNED INPUT_TOK OUPTUT
+%token HVEC2 HVEC3 HVEC4 DVEC2 DVEC3 DVEC4 FVEC2 FVEC3 FVEC4
+%token SAMPLER2DRECT SAMPLER3DRECT SAMPLER2DRECTSHADOW
+%token SIZEOF CAST NAMESPACE USING
+
+%token ERROR_TOK
+
+%token COMMON PARTITION ACTIVE SAMPLERBUFFER FILTER
+%token IMAGE1D IMAGE2D IMAGE3D IMAGECUBE IMAGE1DARRAY IMAGE2DARRAY
+%token IIMAGE1D IIMAGE2D IIMAGE3D IIMAGECUBE IIMAGE1DARRAY IIMAGE2DARRAY
+%token UIMAGE1D UIMAGE2D UIMAGE3D UIMAGECUBE UIMAGE1DARRAY UIMAGE2DARRAY
+%token IMAGE1DSHADOW IMAGE2DSHADOW IMAGEBUFFER IIMAGEBUFFER UIMAGEBUFFER
+%token ROW_MAJOR
+
+%type <identifier> variable_identifier
+%type <node> statement
+%type <node> statement_list
+%type <node> simple_statement
+%type <node> statement_matched
+%type <node> statement_unmatched
+%type <n> precision_qualifier
+%type <type_qualifier> type_qualifier
+%type <type_qualifier> storage_qualifier
+%type <type_qualifier> interpolation_qualifier
+%type <type_qualifier> opt_layout_qualifier layout_qualifier
+%type <type_qualifier> layout_qualifier_id_list layout_qualifier_id
+%type <type_specifier> type_specifier
+%type <type_specifier> type_specifier_no_prec
+%type <type_specifier> type_specifier_nonarray
+%type <n> basic_type_specifier_nonarray
+%type <fully_specified_type> fully_specified_type
+%type <function> function_prototype
+%type <function> function_header
+%type <function> function_header_with_parameters
+%type <function> function_declarator
+%type <parameter_declarator> parameter_declarator
+%type <parameter_declarator> parameter_declaration
+%type <type_qualifier> parameter_qualifier
+%type <type_qualifier> parameter_type_qualifier
+%type <type_specifier> parameter_type_specifier
+%type <function_definition> function_definition
+%type <compound_statement> compound_statement_no_new_scope
+%type <compound_statement> compound_statement
+%type <node> statement_no_new_scope
+%type <node> expression_statement
+%type <expression> expression
+%type <expression> primary_expression
+%type <expression> assignment_expression
+%type <expression> conditional_expression
+%type <expression> logical_or_expression
+%type <expression> logical_xor_expression
+%type <expression> logical_and_expression
+%type <expression> inclusive_or_expression
+%type <expression> exclusive_or_expression
+%type <expression> and_expression
+%type <expression> equality_expression
+%type <expression> relational_expression
+%type <expression> shift_expression
+%type <expression> additive_expression
+%type <expression> multiplicative_expression
+%type <expression> unary_expression
+%type <expression> constant_expression
+%type <expression> integer_expression
+%type <expression> postfix_expression
+%type <expression> function_call_header_with_parameters
+%type <expression> function_call_header_no_parameters
+%type <expression> function_call_header
+%type <expression> function_call_generic
+%type <expression> function_call_or_method
+%type <expression> function_call
+%type <n> assignment_operator
+%type <n> unary_operator
+%type <expression> function_identifier
+%type <node> external_declaration
+%type <declarator_list> init_declarator_list
+%type <declarator_list> single_declaration
+%type <expression> initializer
+%type <node> declaration
+%type <node> declaration_statement
+%type <node> jump_statement
+%type <struct_specifier> struct_specifier
+%type <node> struct_declaration_list
+%type <declarator_list> struct_declaration
+%type <declaration> struct_declarator
+%type <declaration> struct_declarator_list
+%type <node> selection_statement_matched
+%type <node> selection_statement_unmatched
+%type <node> iteration_statement
+%type <node> condition
+%type <node> conditionopt
+%type <node> for_init_statement
+%type <for_rest_statement> for_rest_statement
+%%
+
+translation_unit:
+ version_statement extension_statement_list
+ {
+ _mesa_glsl_initialize_types(state);
+ }
+ external_declaration_list
+ ;
+
+version_statement:
+ /* blank - no #version specified */
+ {
+ state->language_version = 110;
+ }
+ | VERSION INTCONSTANT EOL
+ {
+ switch ($2) {
+ case 110:
+ case 120:
+ case 130:
+ /* FINISHME: Check against implementation support versions. */
+ state->language_version = $2;
+ break;
+ default:
+ _mesa_glsl_error(& @2, state, "Shading language version"
+ "%u is not supported\n", $2);
+ break;
+ }
+ }
+ ;
+
+extension_statement_list:
+
+ | extension_statement_list extension_statement
+ ;
+
+extension_statement:
+ EXTENSION IDENTIFIER COLON IDENTIFIER EOL
+ {
+ if (!_mesa_glsl_process_extension($2, & @2, $4, & @4, state)) {
+ YYERROR;
+ }
+ }
+ ;
+
+external_declaration_list:
+ external_declaration
+ {
+ /* FINISHME: The NULL test is only required because 'precision'
+ * FINISHME: statements are not yet supported.
+ */
+ if ($1 != NULL)
+ state->translation_unit.push_tail(& $1->link);
+ }
+ | external_declaration_list external_declaration
+ {
+ /* FINISHME: The NULL test is only required because 'precision'
+ * FINISHME: statements are not yet supported.
+ */
+ if ($2 != NULL)
+ state->translation_unit.push_tail(& $2->link);
+ }
+ ;
+
+variable_identifier:
+ IDENTIFIER
+ ;
+
+primary_expression:
+ variable_identifier
+ {
+ void *ctx = state;
+ $$ = new(ctx) ast_expression(ast_identifier, NULL, NULL, NULL);
+ $$->set_location(yylloc);
+ $$->primary_expression.identifier = $1;
+ }
+ | INTCONSTANT
+ {
+ void *ctx = state;
+ $$ = new(ctx) ast_expression(ast_int_constant, NULL, NULL, NULL);
+ $$->set_location(yylloc);
+ $$->primary_expression.int_constant = $1;
+ }
+ | UINTCONSTANT
+ {
+ void *ctx = state;
+ $$ = new(ctx) ast_expression(ast_uint_constant, NULL, NULL, NULL);
+ $$->set_location(yylloc);
+ $$->primary_expression.uint_constant = $1;
+ }
+ | FLOATCONSTANT
+ {
+ void *ctx = state;
+ $$ = new(ctx) ast_expression(ast_float_constant, NULL, NULL, NULL);
+ $$->set_location(yylloc);
+ $$->primary_expression.float_constant = $1;
+ }
+ | BOOLCONSTANT
+ {
+ void *ctx = state;
+ $$ = new(ctx) ast_expression(ast_bool_constant, NULL, NULL, NULL);
+ $$->set_location(yylloc);
+ $$->primary_expression.bool_constant = $1;
+ }
+ | '(' expression ')'
+ {
+ $$ = $2;
+ }
+ ;
+
+postfix_expression:
+ primary_expression
+ | postfix_expression '[' integer_expression ']'
+ {
+ void *ctx = state;
+ $$ = new(ctx) ast_expression(ast_array_index, $1, $3, NULL);
+ $$->set_location(yylloc);
+ }
+ | function_call
+ {
+ $$ = $1;
+ }
+ | postfix_expression '.' IDENTIFIER
+ {
+ void *ctx = state;
+ $$ = new(ctx) ast_expression(ast_field_selection, $1, NULL, NULL);
+ $$->set_location(yylloc);
+ $$->primary_expression.identifier = $3;
+ }
+ | postfix_expression INC_OP
+ {
+ void *ctx = state;
+ $$ = new(ctx) ast_expression(ast_post_inc, $1, NULL, NULL);
+ $$->set_location(yylloc);
+ }
+ | postfix_expression DEC_OP
+ {
+ void *ctx = state;
+ $$ = new(ctx) ast_expression(ast_post_dec, $1, NULL, NULL);
+ $$->set_location(yylloc);
+ }
+ ;
+
+integer_expression:
+ expression
+ ;
+
+function_call:
+ function_call_or_method
+ ;
+
+function_call_or_method:
+ function_call_generic
+ | postfix_expression '.' function_call_generic
+ {
+ void *ctx = state;
+ $$ = new(ctx) ast_expression(ast_field_selection, $1, $3, NULL);
+ $$->set_location(yylloc);
+ }
+ ;
+
+function_call_generic:
+ function_call_header_with_parameters ')'
+ | function_call_header_no_parameters ')'
+ ;
+
+function_call_header_no_parameters:
+ function_call_header VOID_TOK
+ | function_call_header
+ ;
+
+function_call_header_with_parameters:
+ function_call_header assignment_expression
+ {
+ $$ = $1;
+ $$->set_location(yylloc);
+ $$->expressions.push_tail(& $2->link);
+ }
+ | function_call_header_with_parameters ',' assignment_expression
+ {
+ $$ = $1;
+ $$->set_location(yylloc);
+ $$->expressions.push_tail(& $3->link);
+ }
+ ;
+
+ // Grammar Note: Constructors look like functions, but lexical
+ // analysis recognized most of them as keywords. They are now
+ // recognized through "type_specifier".
+function_call_header:
+ function_identifier '('
+ ;
+
+function_identifier:
+ type_specifier
+ {
+ void *ctx = state;
+ $$ = new(ctx) ast_function_expression($1);
+ $$->set_location(yylloc);
+ }
+ | IDENTIFIER
+ {
+ void *ctx = state;
+ ast_expression *callee = new(ctx) ast_expression($1);
+ $$ = new(ctx) ast_function_expression(callee);
+ $$->set_location(yylloc);
+ }
+ | FIELD_SELECTION
+ {
+ void *ctx = state;
+ ast_expression *callee = new(ctx) ast_expression($1);
+ $$ = new(ctx) ast_function_expression(callee);
+ $$->set_location(yylloc);
+ }
+ ;
+
+ // Grammar Note: No traditional style type casts.
+unary_expression:
+ postfix_expression
+ | INC_OP unary_expression
+ {
+ void *ctx = state;
+ $$ = new(ctx) ast_expression(ast_pre_inc, $2, NULL, NULL);
+ $$->set_location(yylloc);
+ }
+ | DEC_OP unary_expression
+ {
+ void *ctx = state;
+ $$ = new(ctx) ast_expression(ast_pre_dec, $2, NULL, NULL);
+ $$->set_location(yylloc);
+ }
+ | unary_operator unary_expression
+ {
+ void *ctx = state;
+ $$ = new(ctx) ast_expression($1, $2, NULL, NULL);
+ $$->set_location(yylloc);
+ }
+ ;
+
+ // Grammar Note: No '*' or '&' unary ops. Pointers are not supported.
+unary_operator:
+ '+' { $$ = ast_plus; }
+ | '-' { $$ = ast_neg; }
+ | '!' { $$ = ast_logic_not; }
+ | '~' { $$ = ast_bit_not; }
+ ;
+
+multiplicative_expression:
+ unary_expression
+ | multiplicative_expression '*' unary_expression
+ {
+ void *ctx = state;
+ $$ = new(ctx) ast_expression_bin(ast_mul, $1, $3);
+ $$->set_location(yylloc);
+ }
+ | multiplicative_expression '/' unary_expression
+ {
+ void *ctx = state;
+ $$ = new(ctx) ast_expression_bin(ast_div, $1, $3);
+ $$->set_location(yylloc);
+ }
+ | multiplicative_expression '%' unary_expression
+ {
+ void *ctx = state;
+ $$ = new(ctx) ast_expression_bin(ast_mod, $1, $3);
+ $$->set_location(yylloc);
+ }
+ ;
+
+additive_expression:
+ multiplicative_expression
+ | additive_expression '+' multiplicative_expression
+ {
+ void *ctx = state;
+ $$ = new(ctx) ast_expression_bin(ast_add, $1, $3);
+ $$->set_location(yylloc);
+ }
+ | additive_expression '-' multiplicative_expression
+ {
+ void *ctx = state;
+ $$ = new(ctx) ast_expression_bin(ast_sub, $1, $3);
+ $$->set_location(yylloc);
+ }
+ ;
+
+shift_expression:
+ additive_expression
+ | shift_expression LEFT_OP additive_expression
+ {
+ void *ctx = state;
+ $$ = new(ctx) ast_expression_bin(ast_lshift, $1, $3);
+ $$->set_location(yylloc);
+ }
+ | shift_expression RIGHT_OP additive_expression
+ {
+ void *ctx = state;
+ $$ = new(ctx) ast_expression_bin(ast_rshift, $1, $3);
+ $$->set_location(yylloc);
+ }
+ ;
+
+relational_expression:
+ shift_expression
+ | relational_expression '<' shift_expression
+ {
+ void *ctx = state;
+ $$ = new(ctx) ast_expression_bin(ast_less, $1, $3);
+ $$->set_location(yylloc);
+ }
+ | relational_expression '>' shift_expression
+ {
+ void *ctx = state;
+ $$ = new(ctx) ast_expression_bin(ast_greater, $1, $3);
+ $$->set_location(yylloc);
+ }
+ | relational_expression LE_OP shift_expression
+ {
+ void *ctx = state;
+ $$ = new(ctx) ast_expression_bin(ast_lequal, $1, $3);
+ $$->set_location(yylloc);
+ }
+ | relational_expression GE_OP shift_expression
+ {
+ void *ctx = state;
+ $$ = new(ctx) ast_expression_bin(ast_gequal, $1, $3);
+ $$->set_location(yylloc);
+ }
+ ;
+
+equality_expression:
+ relational_expression
+ | equality_expression EQ_OP relational_expression
+ {
+ void *ctx = state;
+ $$ = new(ctx) ast_expression_bin(ast_equal, $1, $3);
+ $$->set_location(yylloc);
+ }
+ | equality_expression NE_OP relational_expression
+ {
+ void *ctx = state;
+ $$ = new(ctx) ast_expression_bin(ast_nequal, $1, $3);
+ $$->set_location(yylloc);
+ }
+ ;
+
+and_expression:
+ equality_expression
+ | and_expression '&' equality_expression
+ {
+ void *ctx = state;
+ $$ = new(ctx) ast_expression_bin(ast_bit_or, $1, $3);
+ $$->set_location(yylloc);
+ }
+ ;
+
+exclusive_or_expression:
+ and_expression
+ | exclusive_or_expression '^' and_expression
+ {
+ void *ctx = state;
+ $$ = new(ctx) ast_expression_bin(ast_bit_xor, $1, $3);
+ $$->set_location(yylloc);
+ }
+ ;
+
+inclusive_or_expression:
+ exclusive_or_expression
+ | inclusive_or_expression '|' exclusive_or_expression
+ {
+ void *ctx = state;
+ $$ = new(ctx) ast_expression_bin(ast_bit_or, $1, $3);
+ $$->set_location(yylloc);
+ }
+ ;
+
+logical_and_expression:
+ inclusive_or_expression
+ | logical_and_expression AND_OP inclusive_or_expression
+ {
+ void *ctx = state;
+ $$ = new(ctx) ast_expression_bin(ast_logic_and, $1, $3);
+ $$->set_location(yylloc);
+ }
+ ;
+
+logical_xor_expression:
+ logical_and_expression
+ | logical_xor_expression XOR_OP logical_and_expression
+ {
+ void *ctx = state;
+ $$ = new(ctx) ast_expression_bin(ast_logic_xor, $1, $3);
+ $$->set_location(yylloc);
+ }
+ ;
+
+logical_or_expression:
+ logical_xor_expression
+ | logical_or_expression OR_OP logical_xor_expression
+ {
+ void *ctx = state;
+ $$ = new(ctx) ast_expression_bin(ast_logic_or, $1, $3);
+ $$->set_location(yylloc);
+ }
+ ;
+
+conditional_expression:
+ logical_or_expression
+ | logical_or_expression '?' expression ':' assignment_expression
+ {
+ void *ctx = state;
+ $$ = new(ctx) ast_expression(ast_conditional, $1, $3, $5);
+ $$->set_location(yylloc);
+ }
+ ;
+
+assignment_expression:
+ conditional_expression
+ | unary_expression assignment_operator assignment_expression
+ {
+ void *ctx = state;
+ $$ = new(ctx) ast_expression($2, $1, $3, NULL);
+ $$->set_location(yylloc);
+ }
+ ;
+
+assignment_operator:
+ '=' { $$ = ast_assign; }
+ | MUL_ASSIGN { $$ = ast_mul_assign; }
+ | DIV_ASSIGN { $$ = ast_div_assign; }
+ | MOD_ASSIGN { $$ = ast_mod_assign; }
+ | ADD_ASSIGN { $$ = ast_add_assign; }
+ | SUB_ASSIGN { $$ = ast_sub_assign; }
+ | LEFT_ASSIGN { $$ = ast_ls_assign; }
+ | RIGHT_ASSIGN { $$ = ast_rs_assign; }
+ | AND_ASSIGN { $$ = ast_and_assign; }
+ | XOR_ASSIGN { $$ = ast_xor_assign; }
+ | OR_ASSIGN { $$ = ast_or_assign; }
+ ;
+
+expression:
+ assignment_expression
+ {
+ $$ = $1;
+ }
+ | expression ',' assignment_expression
+ {
+ void *ctx = state;
+ if ($1->oper != ast_sequence) {
+ $$ = new(ctx) ast_expression(ast_sequence, NULL, NULL, NULL);
+ $$->set_location(yylloc);
+ $$->expressions.push_tail(& $1->link);
+ } else {
+ $$ = $1;
+ }
+
+ $$->expressions.push_tail(& $3->link);
+ }
+ ;
+
+constant_expression:
+ conditional_expression
+ ;
+
+declaration:
+ function_prototype ';'
+ {
+ $$ = $1;
+ }
+ | init_declarator_list ';'
+ {
+ $$ = $1;
+ }
+ | PRECISION precision_qualifier type_specifier_no_prec ';'
+ {
+ if (($3->type_specifier != ast_float)
+ && ($3->type_specifier != ast_int)) {
+ _mesa_glsl_error(& @3, state, "global precision qualifier can "
+ "only be applied to `int' or `float'\n");
+ YYERROR;
+ }
+
+ $$ = NULL; /* FINISHME */
+ }
+ ;
+
+function_prototype:
+ function_declarator ')'
+ ;
+
+function_declarator:
+ function_header
+ | function_header_with_parameters
+ ;
+
+function_header_with_parameters:
+ function_header parameter_declaration
+ {
+ $$ = $1;
+ $$->parameters.push_tail(& $2->link);
+ }
+ | function_header_with_parameters ',' parameter_declaration
+ {
+ $$ = $1;
+ $$->parameters.push_tail(& $3->link);
+ }
+ ;
+
+function_header:
+ fully_specified_type IDENTIFIER '('
+ {
+ void *ctx = state;
+ $$ = new(ctx) ast_function();
+ $$->set_location(yylloc);
+ $$->return_type = $1;
+ $$->identifier = $2;
+ }
+ ;
+
+parameter_declarator:
+ type_specifier IDENTIFIER
+ {
+ void *ctx = state;
+ $$ = new(ctx) ast_parameter_declarator();
+ $$->set_location(yylloc);
+ $$->type = new(ctx) ast_fully_specified_type();
+ $$->type->set_location(yylloc);
+ $$->type->specifier = $1;
+ $$->identifier = $2;
+ }
+ | type_specifier IDENTIFIER '[' constant_expression ']'
+ {
+ void *ctx = state;
+ $$ = new(ctx) ast_parameter_declarator();
+ $$->set_location(yylloc);
+ $$->type = new(ctx) ast_fully_specified_type();
+ $$->type->set_location(yylloc);
+ $$->type->specifier = $1;
+ $$->identifier = $2;
+ $$->is_array = true;
+ $$->array_size = $4;
+ }
+ ;
+
+parameter_declaration:
+ parameter_type_qualifier parameter_qualifier parameter_declarator
+ {
+ $1.i |= $2.i;
+
+ $$ = $3;
+ $$->type->qualifier = $1.q;
+ }
+ | parameter_qualifier parameter_declarator
+ {
+ $$ = $2;
+ $$->type->qualifier = $1.q;
+ }
+ | parameter_type_qualifier parameter_qualifier parameter_type_specifier
+ {
+ void *ctx = state;
+ $1.i |= $2.i;
+
+ $$ = new(ctx) ast_parameter_declarator();
+ $$->set_location(yylloc);
+ $$->type = new(ctx) ast_fully_specified_type();
+ $$->type->qualifier = $1.q;
+ $$->type->specifier = $3;
+ }
+ | parameter_qualifier parameter_type_specifier
+ {
+ void *ctx = state;
+ $$ = new(ctx) ast_parameter_declarator();
+ $$->set_location(yylloc);
+ $$->type = new(ctx) ast_fully_specified_type();
+ $$->type->qualifier = $1.q;
+ $$->type->specifier = $2;
+ }
+ ;
+
+parameter_qualifier:
+ /* empty */ { $$.i = 0; }
+ | IN_TOK { $$.i = 0; $$.q.in = 1; }
+ | OUT_TOK { $$.i = 0; $$.q.out = 1; }
+ | INOUT_TOK { $$.i = 0; $$.q.in = 1; $$.q.out = 1; }
+ ;
+
+parameter_type_specifier:
+ type_specifier
+ ;
+
+init_declarator_list:
+ single_declaration
+ | init_declarator_list ',' IDENTIFIER
+ {
+ void *ctx = state;
+ ast_declaration *decl = new(ctx) ast_declaration($3, false, NULL, NULL);
+ decl->set_location(yylloc);
+
+ $$ = $1;
+ $$->declarations.push_tail(&decl->link);
+ }
+ | init_declarator_list ',' IDENTIFIER '[' ']'
+ {
+ void *ctx = state;
+ ast_declaration *decl = new(ctx) ast_declaration($3, true, NULL, NULL);
+ decl->set_location(yylloc);
+
+ $$ = $1;
+ $$->declarations.push_tail(&decl->link);
+ }
+ | init_declarator_list ',' IDENTIFIER '[' constant_expression ']'
+ {
+ void *ctx = state;
+ ast_declaration *decl = new(ctx) ast_declaration($3, true, $5, NULL);
+ decl->set_location(yylloc);
+
+ $$ = $1;
+ $$->declarations.push_tail(&decl->link);
+ }
+ | init_declarator_list ',' IDENTIFIER '[' ']' '=' initializer
+ {
+ void *ctx = state;
+ ast_declaration *decl = new(ctx) ast_declaration($3, true, NULL, $7);
+ decl->set_location(yylloc);
+
+ $$ = $1;
+ $$->declarations.push_tail(&decl->link);
+ }
+ | init_declarator_list ',' IDENTIFIER '[' constant_expression ']' '=' initializer
+ {
+ void *ctx = state;
+ ast_declaration *decl = new(ctx) ast_declaration($3, true, $5, $8);
+ decl->set_location(yylloc);
+
+ $$ = $1;
+ $$->declarations.push_tail(&decl->link);
+ }
+ | init_declarator_list ',' IDENTIFIER '=' initializer
+ {
+ void *ctx = state;
+ ast_declaration *decl = new(ctx) ast_declaration($3, false, NULL, $5);
+ decl->set_location(yylloc);
+
+ $$ = $1;
+ $$->declarations.push_tail(&decl->link);
+ }
+ ;
+
+ // Grammar Note: No 'enum', or 'typedef'.
+single_declaration:
+ fully_specified_type
+ {
+ void *ctx = state;
+ if ($1->specifier->type_specifier != ast_struct) {
+ _mesa_glsl_error(& @1, state, "empty declaration list\n");
+ YYERROR;
+ } else {
+ $$ = new(ctx) ast_declarator_list($1);
+ $$->set_location(yylloc);
+ }
+ }
+ | fully_specified_type IDENTIFIER
+ {
+ void *ctx = state;
+ ast_declaration *decl = new(ctx) ast_declaration($2, false, NULL, NULL);
+
+ $$ = new(ctx) ast_declarator_list($1);
+ $$->set_location(yylloc);
+ $$->declarations.push_tail(&decl->link);
+ }
+ | fully_specified_type IDENTIFIER '[' ']'
+ {
+ void *ctx = state;
+ ast_declaration *decl = new(ctx) ast_declaration($2, true, NULL, NULL);
+
+ $$ = new(ctx) ast_declarator_list($1);
+ $$->set_location(yylloc);
+ $$->declarations.push_tail(&decl->link);
+ }
+ | fully_specified_type IDENTIFIER '[' constant_expression ']'
+ {
+ void *ctx = state;
+ ast_declaration *decl = new(ctx) ast_declaration($2, true, $4, NULL);
+
+ $$ = new(ctx) ast_declarator_list($1);
+ $$->set_location(yylloc);
+ $$->declarations.push_tail(&decl->link);
+ }
+ | fully_specified_type IDENTIFIER '[' ']' '=' initializer
+ {
+ void *ctx = state;
+ ast_declaration *decl = new(ctx) ast_declaration($2, true, NULL, $6);
+
+ $$ = new(ctx) ast_declarator_list($1);
+ $$->set_location(yylloc);
+ $$->declarations.push_tail(&decl->link);
+ }
+ | fully_specified_type IDENTIFIER '[' constant_expression ']' '=' initializer
+ {
+ void *ctx = state;
+ ast_declaration *decl = new(ctx) ast_declaration($2, true, $4, $7);
+
+ $$ = new(ctx) ast_declarator_list($1);
+ $$->set_location(yylloc);
+ $$->declarations.push_tail(&decl->link);
+ }
+ | fully_specified_type IDENTIFIER '=' initializer
+ {
+ void *ctx = state;
+ ast_declaration *decl = new(ctx) ast_declaration($2, false, NULL, $4);
+
+ $$ = new(ctx) ast_declarator_list($1);
+ $$->set_location(yylloc);
+ $$->declarations.push_tail(&decl->link);
+ }
+ | INVARIANT IDENTIFIER // Vertex only.
+ {
+ void *ctx = state;
+ ast_declaration *decl = new(ctx) ast_declaration($2, false, NULL, NULL);
+
+ $$ = new(ctx) ast_declarator_list(NULL);
+ $$->set_location(yylloc);
+ $$->invariant = true;
+
+ $$->declarations.push_tail(&decl->link);
+ }
+ ;
+
+fully_specified_type:
+ type_specifier
+ {
+ void *ctx = state;
+ $$ = new(ctx) ast_fully_specified_type();
+ $$->set_location(yylloc);
+ $$->specifier = $1;
+ }
+ | type_qualifier type_specifier
+ {
+ void *ctx = state;
+ $$ = new(ctx) ast_fully_specified_type();
+ $$->set_location(yylloc);
+ $$->qualifier = $1.q;
+ $$->specifier = $2;
+ }
+ ;
+
+opt_layout_qualifier:
+ { $$.i = 0; }
+ | layout_qualifier
+ ;
+
+layout_qualifier:
+ LAYOUT_TOK '(' layout_qualifier_id_list ')'
+ {
+ $$ = $3;
+ }
+ ;
+
+layout_qualifier_id_list:
+ layout_qualifier_id
+ | layout_qualifier_id_list ',' layout_qualifier_id
+ {
+ $$.i = $1.i | $3.i;
+ }
+ ;
+
+layout_qualifier_id:
+ IDENTIFIER
+ {
+ $$.i = 0;
+
+ if (state->ARB_fragment_coord_conventions_enable) {
+ bool got_one = false;
+
+ if (strcmp($1, "origin_upper_left") == 0) {
+ got_one = true;
+ $$.q.origin_upper_left = 1;
+ } else if (strcmp($1, "pixel_center_integer") == 0) {
+ got_one = true;
+ $$.q.pixel_center_integer = 1;
+ }
+
+ if (state->ARB_fragment_coord_conventions_warn && got_one) {
+ _mesa_glsl_warning(& @1, state,
+ "GL_ARB_fragment_coord_conventions layout "
+ "identifier `%s' used\n", $1);
+ }
+ }
+
+ /* If the identifier didn't match any known layout identifiers,
+ * emit an error.
+ */
+ if ($$.i == 0) {
+ _mesa_glsl_error(& @1, state, "unrecognized layout identifier "
+ "`%s'\n", $1);
+ YYERROR;
+ }
+ }
+ ;
+
+interpolation_qualifier:
+ SMOOTH { $$.i = 0; $$.q.smooth = 1; }
+ | FLAT { $$.i = 0; $$.q.flat = 1; }
+ | NOPERSPECTIVE { $$.i = 0; $$.q.noperspective = 1; }
+ ;
+
+parameter_type_qualifier:
+ CONST_TOK { $$.i = 0; $$.q.constant = 1; }
+ ;
+
+type_qualifier:
+ storage_qualifier
+ | interpolation_qualifier type_qualifier
+ {
+ $$.i = $1.i | $2.i;
+ }
+ | INVARIANT type_qualifier
+ {
+ $$ = $2;
+ $$.q.invariant = 1;
+ }
+ ;
+
+storage_qualifier:
+ CONST_TOK { $$.i = 0; $$.q.constant = 1; }
+ | ATTRIBUTE { $$.i = 0; $$.q.attribute = 1; }
+ | opt_layout_qualifier VARYING { $$.i = $1.i; $$.q.varying = 1; }
+ | CENTROID VARYING { $$.i = 0; $$.q.centroid = 1; $$.q.varying = 1; }
+ | opt_layout_qualifier IN_TOK { $$.i = 0; $$.q.in = 1; }
+ | OUT_TOK { $$.i = 0; $$.q.out = 1; }
+ | CENTROID IN_TOK { $$.i = 0; $$.q.centroid = 1; $$.q.in = 1; }
+ | CENTROID OUT_TOK { $$.i = 0; $$.q.centroid = 1; $$.q.out = 1; }
+ | UNIFORM { $$.i = 0; $$.q.uniform = 1; }
+ ;
+
+type_specifier:
+ type_specifier_no_prec
+ | precision_qualifier type_specifier_no_prec
+ {
+ $$ = $2;
+ $$->precision = $1;
+ }
+ ;
+
+type_specifier_no_prec:
+ type_specifier_nonarray
+ | type_specifier_nonarray '[' ']'
+ {
+ $$ = $1;
+ $$->is_array = true;
+ $$->array_size = NULL;
+ }
+ | type_specifier_nonarray '[' constant_expression ']'
+ {
+ $$ = $1;
+ $$->is_array = true;
+ $$->array_size = $3;
+ }
+ ;
+
+type_specifier_nonarray:
+ basic_type_specifier_nonarray
+ {
+ void *ctx = state;
+ $$ = new(ctx) ast_type_specifier($1);
+ $$->set_location(yylloc);
+ }
+ | struct_specifier
+ {
+ void *ctx = state;
+ $$ = new(ctx) ast_type_specifier($1);
+ $$->set_location(yylloc);
+ }
+ | IDENTIFIER
+ {
+ void *ctx = state;
+ $$ = new(ctx) ast_type_specifier($1);
+ $$->set_location(yylloc);
+ }
+ ;
+
+basic_type_specifier_nonarray:
+ VOID_TOK { $$ = ast_void; }
+ | FLOAT_TOK { $$ = ast_float; }
+ | INT_TOK { $$ = ast_int; }
+ | UINT_TOK { $$ = ast_uint; }
+ | BOOL_TOK { $$ = ast_bool; }
+ | VEC2 { $$ = ast_vec2; }
+ | VEC3 { $$ = ast_vec3; }
+ | VEC4 { $$ = ast_vec4; }
+ | BVEC2 { $$ = ast_bvec2; }
+ | BVEC3 { $$ = ast_bvec3; }
+ | BVEC4 { $$ = ast_bvec4; }
+ | IVEC2 { $$ = ast_ivec2; }
+ | IVEC3 { $$ = ast_ivec3; }
+ | IVEC4 { $$ = ast_ivec4; }
+ | UVEC2 { $$ = ast_uvec2; }
+ | UVEC3 { $$ = ast_uvec3; }
+ | UVEC4 { $$ = ast_uvec4; }
+ | MAT2X2 { $$ = ast_mat2; }
+ | MAT2X3 { $$ = ast_mat2x3; }
+ | MAT2X4 { $$ = ast_mat2x4; }
+ | MAT3X2 { $$ = ast_mat3x2; }
+ | MAT3X3 { $$ = ast_mat3; }
+ | MAT3X4 { $$ = ast_mat3x4; }
+ | MAT4X2 { $$ = ast_mat4x2; }
+ | MAT4X3 { $$ = ast_mat4x3; }
+ | MAT4X4 { $$ = ast_mat4; }
+ | SAMPLER1D { $$ = ast_sampler1d; }
+ | SAMPLER2D { $$ = ast_sampler2d; }
+ | SAMPLER2DRECT { $$ = ast_sampler2drect; }
+ | SAMPLER3D { $$ = ast_sampler3d; }
+ | SAMPLERCUBE { $$ = ast_samplercube; }
+ | SAMPLER1DSHADOW { $$ = ast_sampler1dshadow; }
+ | SAMPLER2DSHADOW { $$ = ast_sampler2dshadow; }
+ | SAMPLER2DRECTSHADOW { $$ = ast_sampler2drectshadow; }
+ | SAMPLERCUBESHADOW { $$ = ast_samplercubeshadow; }
+ | SAMPLER1DARRAY { $$ = ast_sampler1darray; }
+ | SAMPLER2DARRAY { $$ = ast_sampler2darray; }
+ | SAMPLER1DARRAYSHADOW { $$ = ast_sampler1darrayshadow; }
+ | SAMPLER2DARRAYSHADOW { $$ = ast_sampler2darrayshadow; }
+ | ISAMPLER1D { $$ = ast_isampler1d; }
+ | ISAMPLER2D { $$ = ast_isampler2d; }
+ | ISAMPLER3D { $$ = ast_isampler3d; }
+ | ISAMPLERCUBE { $$ = ast_isamplercube; }
+ | ISAMPLER1DARRAY { $$ = ast_isampler1darray; }
+ | ISAMPLER2DARRAY { $$ = ast_isampler2darray; }
+ | USAMPLER1D { $$ = ast_usampler1d; }
+ | USAMPLER2D { $$ = ast_usampler2d; }
+ | USAMPLER3D { $$ = ast_usampler3d; }
+ | USAMPLERCUBE { $$ = ast_usamplercube; }
+ | USAMPLER1DARRAY { $$ = ast_usampler1darray; }
+ | USAMPLER2DARRAY { $$ = ast_usampler2darray; }
+ ;
+
+precision_qualifier:
+ HIGHP {
+ if (state->language_version < 130)
+ _mesa_glsl_error(& @1, state,
+ "precision qualifier forbidden "
+ "in GLSL %d.%d (1.30 or later "
+ "required)\n",
+ state->language_version / 100,
+ state->language_version % 100);
+
+ $$ = ast_precision_high;
+ }
+ | MEDIUMP {
+ if (state->language_version < 130)
+ _mesa_glsl_error(& @1, state,
+ "precision qualifier forbidden "
+ "in GLSL %d.%d (1.30 or later "
+ "required)\n",
+ state->language_version / 100,
+ state->language_version % 100);
+
+ $$ = ast_precision_medium;
+ }
+ | LOWP {
+ if (state->language_version < 130)
+ _mesa_glsl_error(& @1, state,
+ "precision qualifier forbidden "
+ "in GLSL %d.%d (1.30 or later "
+ "required)\n",
+ state->language_version / 100,
+ state->language_version % 100);
+
+ $$ = ast_precision_low;
+ }
+ ;
+
+struct_specifier:
+ STRUCT IDENTIFIER '{' struct_declaration_list '}'
+ {
+ void *ctx = state;
+ $$ = new(ctx) ast_struct_specifier($2, $4);
+ $$->set_location(yylloc);
+ }
+ | STRUCT '{' struct_declaration_list '}'
+ {
+ void *ctx = state;
+ $$ = new(ctx) ast_struct_specifier(NULL, $3);
+ $$->set_location(yylloc);
+ }
+ ;
+
+struct_declaration_list:
+ struct_declaration
+ {
+ $$ = (ast_node *) $1;
+ $1->link.self_link();
+ }
+ | struct_declaration_list struct_declaration
+ {
+ $$ = (ast_node *) $1;
+ $$->link.insert_before(& $2->link);
+ }
+ ;
+
+struct_declaration:
+ type_specifier struct_declarator_list ';'
+ {
+ void *ctx = state;
+ ast_fully_specified_type *type = new(ctx) ast_fully_specified_type();
+ type->set_location(yylloc);
+
+ type->specifier = $1;
+ $$ = new(ctx) ast_declarator_list(type);
+ $$->set_location(yylloc);
+
+ $$->declarations.push_degenerate_list_at_head(& $2->link);
+ }
+ ;
+
+struct_declarator_list:
+ struct_declarator
+ {
+ $$ = $1;
+ $1->link.self_link();
+ }
+ | struct_declarator_list ',' struct_declarator
+ {
+ $$ = $1;
+ $$->link.insert_before(& $3->link);
+ }
+ ;
+
+struct_declarator:
+ IDENTIFIER
+ {
+ void *ctx = state;
+ $$ = new(ctx) ast_declaration($1, false, NULL, NULL);
+ $$->set_location(yylloc);
+ }
+ | IDENTIFIER '[' constant_expression ']'
+ {
+ void *ctx = state;
+ $$ = new(ctx) ast_declaration($1, true, $3, NULL);
+ $$->set_location(yylloc);
+ }
+ ;
+
+initializer:
+ assignment_expression
+ ;
+
+declaration_statement:
+ declaration
+ ;
+
+ // Grammar Note: labeled statements for SWITCH only; 'goto' is not
+ // supported.
+statement:
+ statement_matched
+ | statement_unmatched
+ ;
+
+statement_matched:
+ compound_statement { $$ = (ast_node *) $1; }
+ | simple_statement
+ ;
+
+statement_unmatched:
+ selection_statement_unmatched
+ ;
+
+simple_statement:
+ declaration_statement
+ | expression_statement
+ | selection_statement_matched
+ | switch_statement { $$ = NULL; }
+ | case_label { $$ = NULL; }
+ | iteration_statement
+ | jump_statement
+ ;
+
+compound_statement:
+ '{' '}'
+ {
+ void *ctx = state;
+ $$ = new(ctx) ast_compound_statement(true, NULL);
+ $$->set_location(yylloc);
+ }
+ | '{' statement_list '}'
+ {
+ void *ctx = state;
+ $$ = new(ctx) ast_compound_statement(true, $2);
+ $$->set_location(yylloc);
+ }
+ ;
+
+statement_no_new_scope:
+ compound_statement_no_new_scope { $$ = (ast_node *) $1; }
+ | simple_statement
+ ;
+
+compound_statement_no_new_scope:
+ '{' '}'
+ {
+ void *ctx = state;
+ $$ = new(ctx) ast_compound_statement(false, NULL);
+ $$->set_location(yylloc);
+ }
+ | '{' statement_list '}'
+ {
+ void *ctx = state;
+ $$ = new(ctx) ast_compound_statement(false, $2);
+ $$->set_location(yylloc);
+ }
+ ;
+
+statement_list:
+ statement
+ {
+ if ($1 == NULL) {
+ _mesa_glsl_error(& @1, state, "<nil> statement\n");
+ assert($1 != NULL);
+ }
+
+ $$ = $1;
+ $$->link.self_link();
+ }
+ | statement_list statement
+ {
+ if ($2 == NULL) {
+ _mesa_glsl_error(& @2, state, "<nil> statement\n");
+ assert($2 != NULL);
+ }
+ $$ = $1;
+ $$->link.insert_before(& $2->link);
+ }
+ ;
+
+expression_statement:
+ ';'
+ {
+ void *ctx = state;
+ $$ = new(ctx) ast_expression_statement(NULL);
+ $$->set_location(yylloc);
+ }
+ | expression ';'
+ {
+ void *ctx = state;
+ $$ = new(ctx) ast_expression_statement($1);
+ $$->set_location(yylloc);
+ }
+ ;
+
+selection_statement_matched:
+ IF '(' expression ')' statement_matched ELSE statement_matched
+ {
+ void *ctx = state;
+ $$ = new(ctx) ast_selection_statement($3, $5, $7);
+ $$->set_location(yylloc);
+ }
+ ;
+
+selection_statement_unmatched:
+ IF '(' expression ')' statement_matched
+ {
+ void *ctx = state;
+ $$ = new(ctx) ast_selection_statement($3, $5, NULL);
+ $$->set_location(yylloc);
+ }
+ | IF '(' expression ')' statement_unmatched
+ {
+ void *ctx = state;
+ $$ = new(ctx) ast_selection_statement($3, $5, NULL);
+ $$->set_location(yylloc);
+ }
+ | IF '(' expression ')' statement_matched ELSE statement_unmatched
+ {
+ void *ctx = state;
+ $$ = new(ctx) ast_selection_statement($3, $5, $7);
+ $$->set_location(yylloc);
+ }
+ ;
+
+condition:
+ expression
+ {
+ $$ = (ast_node *) $1;
+ }
+ | fully_specified_type IDENTIFIER '=' initializer
+ {
+ void *ctx = state;
+ ast_declaration *decl = new(ctx) ast_declaration($2, false, NULL, $4);
+ ast_declarator_list *declarator = new(ctx) ast_declarator_list($1);
+ decl->set_location(yylloc);
+ declarator->set_location(yylloc);
+
+ declarator->declarations.push_tail(&decl->link);
+ $$ = declarator;
+ }
+ ;
+
+switch_statement:
+ SWITCH '(' expression ')' compound_statement
+ ;
+
+case_label:
+ CASE expression ':'
+ | DEFAULT ':'
+ ;
+
+iteration_statement:
+ WHILE '(' condition ')' statement_no_new_scope
+ {
+ void *ctx = state;
+ $$ = new(ctx) ast_iteration_statement(ast_iteration_statement::ast_while,
+ NULL, $3, NULL, $5);
+ $$->set_location(yylloc);
+ }
+ | DO statement WHILE '(' expression ')' ';'
+ {
+ void *ctx = state;
+ $$ = new(ctx) ast_iteration_statement(ast_iteration_statement::ast_do_while,
+ NULL, $5, NULL, $2);
+ $$->set_location(yylloc);
+ }
+ | FOR '(' for_init_statement for_rest_statement ')' statement_no_new_scope
+ {
+ void *ctx = state;
+ $$ = new(ctx) ast_iteration_statement(ast_iteration_statement::ast_for,
+ $3, $4.cond, $4.rest, $6);
+ $$->set_location(yylloc);
+ }
+ ;
+
+for_init_statement:
+ expression_statement
+ | declaration_statement
+ ;
+
+conditionopt:
+ condition
+ | /* empty */
+ {
+ $$ = NULL;
+ }
+ ;
+
+for_rest_statement:
+ conditionopt ';'
+ {
+ $$.cond = $1;
+ $$.rest = NULL;
+ }
+ | conditionopt ';' expression
+ {
+ $$.cond = $1;
+ $$.rest = $3;
+ }
+ ;
+
+ // Grammar Note: No 'goto'. Gotos are not supported.
+jump_statement:
+ CONTINUE ';'
+ {
+ void *ctx = state;
+ $$ = new(ctx) ast_jump_statement(ast_jump_statement::ast_continue, NULL);
+ $$->set_location(yylloc);
+ }
+ | BREAK ';'
+ {
+ void *ctx = state;
+ $$ = new(ctx) ast_jump_statement(ast_jump_statement::ast_break, NULL);
+ $$->set_location(yylloc);
+ }
+ | RETURN ';'
+ {
+ void *ctx = state;
+ $$ = new(ctx) ast_jump_statement(ast_jump_statement::ast_return, NULL);
+ $$->set_location(yylloc);
+ }
+ | RETURN expression ';'
+ {
+ void *ctx = state;
+ $$ = new(ctx) ast_jump_statement(ast_jump_statement::ast_return, $2);
+ $$->set_location(yylloc);
+ }
+ | DISCARD ';' // Fragment shader only.
+ {
+ void *ctx = state;
+ $$ = new(ctx) ast_jump_statement(ast_jump_statement::ast_discard, NULL);
+ $$->set_location(yylloc);
+ }
+ ;
+
+external_declaration:
+ function_definition { $$ = $1; }
+ | declaration { $$ = $1; }
+ ;
+
+function_definition:
+ function_prototype compound_statement_no_new_scope
+ {
+ void *ctx = state;
+ $$ = new(ctx) ast_function_definition();
+ $$->set_location(yylloc);
+ $$->prototype = $1;
+ $$->body = $2;
+ }
+ ;
diff --git a/src/glsl/glsl_parser_extras.cpp b/src/glsl/glsl_parser_extras.cpp
new file mode 100644
index 00000000000..d1bb1ae5ecc
--- /dev/null
+++ b/src/glsl/glsl_parser_extras.cpp
@@ -0,0 +1,743 @@
+/*
+ * Copyright © 2008, 2009 Intel Corporation
+ *
+ * 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 (including the next
+ * paragraph) 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
+ * THE AUTHORS OR COPYRIGHT HOLDERS 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.
+ */
+#include <stdio.h>
+#include <stdarg.h>
+#include <string.h>
+#include <assert.h>
+
+extern "C" {
+#include <talloc.h>
+#include "main/mtypes.h"
+}
+
+#include "ast.h"
+#include "glsl_parser_extras.h"
+#include "glsl_parser.h"
+#include "ir_optimization.h"
+
+_mesa_glsl_parse_state::_mesa_glsl_parse_state(struct __GLcontextRec *ctx,
+ GLenum target, void *mem_ctx)
+{
+ switch (target) {
+ case GL_VERTEX_SHADER: this->target = vertex_shader; break;
+ case GL_FRAGMENT_SHADER: this->target = fragment_shader; break;
+ case GL_GEOMETRY_SHADER: this->target = geometry_shader; break;
+ }
+
+ this->scanner = NULL;
+ this->translation_unit.make_empty();
+ this->symbols = new(mem_ctx) glsl_symbol_table;
+ this->info_log = talloc_strdup(mem_ctx, "");
+ this->error = false;
+ this->loop_or_switch_nesting = NULL;
+ this->ARB_texture_rectangle_enable = true;
+
+ if (ctx != NULL) {
+ this->extensions = &ctx->Extensions;
+
+ this->Const.MaxLights = ctx->Const.MaxLights;
+ this->Const.MaxClipPlanes = ctx->Const.MaxClipPlanes;
+ this->Const.MaxTextureUnits = ctx->Const.MaxTextureUnits;
+ this->Const.MaxTextureCoords = ctx->Const.MaxTextureCoordUnits;
+ this->Const.MaxVertexAttribs = ctx->Const.VertexProgram.MaxAttribs;
+ this->Const.MaxVertexUniformComponents = ctx->Const.VertexProgram.MaxUniformComponents;
+ this->Const.MaxVaryingFloats = ctx->Const.MaxVarying * 4;
+ this->Const.MaxVertexTextureImageUnits = ctx->Const.MaxVertexTextureImageUnits;
+ this->Const.MaxCombinedTextureImageUnits = ctx->Const.MaxCombinedTextureImageUnits;
+ this->Const.MaxTextureImageUnits = ctx->Const.MaxTextureImageUnits;
+ this->Const.MaxFragmentUniformComponents = ctx->Const.FragmentProgram.MaxUniformComponents;
+
+ this->Const.MaxDrawBuffers = ctx->Const.MaxDrawBuffers;
+ } else {
+ /* If there is no GL context (standalone compiler), fill in constants
+ * with the minimum required values.
+ */
+ static struct gl_extensions null_extensions;
+
+ memset(&null_extensions, 0, sizeof(null_extensions));
+ null_extensions.ARB_draw_buffers = GL_TRUE;
+ null_extensions.ARB_fragment_coord_conventions = GL_TRUE;
+ null_extensions.EXT_texture_array = GL_TRUE;
+ null_extensions.NV_texture_rectangle = GL_TRUE;
+
+ this->extensions = &null_extensions;
+
+ /* 1.10 minimums. */
+ this->Const.MaxLights = 8;
+ this->Const.MaxClipPlanes = 8;
+ this->Const.MaxTextureUnits = 2;
+
+ /* More than the 1.10 minimum to appease parser tests taken from
+ * apps that (hopefully) already checked the number of coords.
+ */
+ this->Const.MaxTextureCoords = 4;
+
+ this->Const.MaxVertexAttribs = 16;
+ this->Const.MaxVertexUniformComponents = 512;
+ this->Const.MaxVaryingFloats = 32;
+ this->Const.MaxVertexTextureImageUnits = 0;
+ this->Const.MaxCombinedTextureImageUnits = 2;
+ this->Const.MaxTextureImageUnits = 2;
+ this->Const.MaxFragmentUniformComponents = 64;
+
+ this->Const.MaxDrawBuffers = 2;
+ }
+}
+
+const char *
+_mesa_glsl_shader_target_name(enum _mesa_glsl_parser_targets target)
+{
+ switch (target) {
+ case vertex_shader: return "vertex";
+ case fragment_shader: return "fragment";
+ case geometry_shader: return "geometry";
+ case ir_shader: break;
+ }
+
+ assert(!"Should not get here.");
+ return "unknown";
+}
+
+
+void
+_mesa_glsl_error(YYLTYPE *locp, _mesa_glsl_parse_state *state,
+ const char *fmt, ...)
+{
+ va_list ap;
+
+ state->error = true;
+
+ assert(state->info_log != NULL);
+ state->info_log = talloc_asprintf_append(state->info_log,
+ "%u:%u(%u): error: ",
+ locp->source,
+ locp->first_line,
+ locp->first_column);
+ va_start(ap, fmt);
+ state->info_log = talloc_vasprintf_append(state->info_log, fmt, ap);
+ va_end(ap);
+ state->info_log = talloc_strdup_append(state->info_log, "\n");
+}
+
+
+void
+_mesa_glsl_warning(const YYLTYPE *locp, _mesa_glsl_parse_state *state,
+ const char *fmt, ...)
+{
+ va_list ap;
+
+ assert(state->info_log != NULL);
+ state->info_log = talloc_asprintf_append(state->info_log,
+ "%u:%u(%u): warning: ",
+ locp->source,
+ locp->first_line,
+ locp->first_column);
+ va_start(ap, fmt);
+ state->info_log = talloc_vasprintf_append(state->info_log, fmt, ap);
+ va_end(ap);
+ state->info_log = talloc_strdup_append(state->info_log, "\n");
+}
+
+
+bool
+_mesa_glsl_process_extension(const char *name, YYLTYPE *name_locp,
+ const char *behavior, YYLTYPE *behavior_locp,
+ _mesa_glsl_parse_state *state)
+{
+ enum {
+ extension_disable,
+ extension_enable,
+ extension_require,
+ extension_warn
+ } ext_mode;
+
+ if (strcmp(behavior, "warn") == 0) {
+ ext_mode = extension_warn;
+ } else if (strcmp(behavior, "require") == 0) {
+ ext_mode = extension_require;
+ } else if (strcmp(behavior, "enable") == 0) {
+ ext_mode = extension_enable;
+ } else if (strcmp(behavior, "disable") == 0) {
+ ext_mode = extension_disable;
+ } else {
+ _mesa_glsl_error(behavior_locp, state,
+ "Unknown extension behavior `%s'",
+ behavior);
+ return false;
+ }
+
+ bool unsupported = false;
+
+ if (strcmp(name, "all") == 0) {
+ if ((ext_mode == extension_enable) || (ext_mode == extension_require)) {
+ _mesa_glsl_error(name_locp, state, "Cannot %s all extensions",
+ (ext_mode == extension_enable)
+ ? "enable" : "require");
+ return false;
+ }
+ } else if (strcmp(name, "GL_ARB_draw_buffers") == 0) {
+ /* This extension is only supported in fragment shaders.
+ */
+ if (state->target != fragment_shader) {
+ unsupported = true;
+ } else {
+ state->ARB_draw_buffers_enable = (ext_mode != extension_disable);
+ state->ARB_draw_buffers_warn = (ext_mode == extension_warn);
+ }
+ } else if (strcmp(name, "GL_ARB_fragment_coord_conventions") == 0) {
+ state->ARB_fragment_coord_conventions_enable =
+ (ext_mode != extension_disable);
+ state->ARB_fragment_coord_conventions_warn =
+ (ext_mode == extension_warn);
+
+ unsupported = !state->extensions->ARB_fragment_coord_conventions;
+ } else if (strcmp(name, "GL_ARB_texture_rectangle") == 0) {
+ state->ARB_texture_rectangle_enable = (ext_mode != extension_disable);
+ state->ARB_texture_rectangle_warn = (ext_mode == extension_warn);
+ } else if (strcmp(name, "GL_EXT_texture_array") == 0) {
+ state->EXT_texture_array_enable = (ext_mode != extension_disable);
+ state->EXT_texture_array_warn = (ext_mode == extension_warn);
+
+ unsupported = !state->extensions->EXT_texture_array;
+ } else {
+ unsupported = true;
+ }
+
+ if (unsupported) {
+ static const char *const fmt = "extension `%s' unsupported in %s shader";
+
+ if (ext_mode == extension_require) {
+ _mesa_glsl_error(name_locp, state, fmt,
+ name, _mesa_glsl_shader_target_name(state->target));
+ return false;
+ } else {
+ _mesa_glsl_warning(name_locp, state, fmt,
+ name, _mesa_glsl_shader_target_name(state->target));
+ }
+ }
+
+ return true;
+}
+
+void
+_mesa_ast_type_qualifier_print(const struct ast_type_qualifier *q)
+{
+ if (q->constant)
+ printf("const ");
+
+ if (q->invariant)
+ printf("invariant ");
+
+ if (q->attribute)
+ printf("attribute ");
+
+ if (q->varying)
+ printf("varying ");
+
+ if (q->in && q->out)
+ printf("inout ");
+ else {
+ if (q->in)
+ printf("in ");
+
+ if (q->out)
+ printf("out ");
+ }
+
+ if (q->centroid)
+ printf("centroid ");
+ if (q->uniform)
+ printf("uniform ");
+ if (q->smooth)
+ printf("smooth ");
+ if (q->flat)
+ printf("flat ");
+ if (q->noperspective)
+ printf("noperspective ");
+}
+
+
+void
+ast_node::print(void) const
+{
+ printf("unhandled node ");
+}
+
+
+ast_node::ast_node(void)
+{
+ this->location.source = 0;
+ this->location.line = 0;
+ this->location.column = 0;
+}
+
+
+static void
+ast_opt_array_size_print(bool is_array, const ast_expression *array_size)
+{
+ if (is_array) {
+ printf("[ ");
+
+ if (array_size)
+ array_size->print();
+
+ printf("] ");
+ }
+}
+
+
+void
+ast_compound_statement::print(void) const
+{
+ printf("{\n");
+
+ foreach_list_const(n, &this->statements) {
+ ast_node *ast = exec_node_data(ast_node, n, link);
+ ast->print();
+ }
+
+ printf("}\n");
+}
+
+
+ast_compound_statement::ast_compound_statement(int new_scope,
+ ast_node *statements)
+{
+ this->new_scope = new_scope;
+
+ if (statements != NULL) {
+ this->statements.push_degenerate_list_at_head(&statements->link);
+ }
+}
+
+
+void
+ast_expression::print(void) const
+{
+ switch (oper) {
+ case ast_assign:
+ case ast_mul_assign:
+ case ast_div_assign:
+ case ast_mod_assign:
+ case ast_add_assign:
+ case ast_sub_assign:
+ case ast_ls_assign:
+ case ast_rs_assign:
+ case ast_and_assign:
+ case ast_xor_assign:
+ case ast_or_assign:
+ subexpressions[0]->print();
+ printf("%s ", operator_string(oper));
+ subexpressions[1]->print();
+ break;
+
+ case ast_field_selection:
+ subexpressions[0]->print();
+ printf(". %s ", primary_expression.identifier);
+ break;
+
+ case ast_plus:
+ case ast_neg:
+ case ast_bit_not:
+ case ast_logic_not:
+ case ast_pre_inc:
+ case ast_pre_dec:
+ printf("%s ", operator_string(oper));
+ subexpressions[0]->print();
+ break;
+
+ case ast_post_inc:
+ case ast_post_dec:
+ subexpressions[0]->print();
+ printf("%s ", operator_string(oper));
+ break;
+
+ case ast_conditional:
+ subexpressions[0]->print();
+ printf("? ");
+ subexpressions[1]->print();
+ printf(": ");
+ subexpressions[1]->print();
+ break;
+
+ case ast_array_index:
+ subexpressions[0]->print();
+ printf("[ ");
+ subexpressions[1]->print();
+ printf("] ");
+ break;
+
+ case ast_function_call: {
+ subexpressions[0]->print();
+ printf("( ");
+
+ foreach_list_const (n, &this->expressions) {
+ if (n != this->expressions.get_head())
+ printf(", ");
+
+ ast_node *ast = exec_node_data(ast_node, n, link);
+ ast->print();
+ }
+
+ printf(") ");
+ break;
+ }
+
+ case ast_identifier:
+ printf("%s ", primary_expression.identifier);
+ break;
+
+ case ast_int_constant:
+ printf("%d ", primary_expression.int_constant);
+ break;
+
+ case ast_uint_constant:
+ printf("%u ", primary_expression.uint_constant);
+ break;
+
+ case ast_float_constant:
+ printf("%f ", primary_expression.float_constant);
+ break;
+
+ case ast_bool_constant:
+ printf("%s ",
+ primary_expression.bool_constant
+ ? "true" : "false");
+ break;
+
+ case ast_sequence: {
+ printf("( ");
+ foreach_list_const(n, & this->expressions) {
+ if (n != this->expressions.get_head())
+ printf(", ");
+
+ ast_node *ast = exec_node_data(ast_node, n, link);
+ ast->print();
+ }
+ printf(") ");
+ break;
+ }
+
+ default:
+ assert(0);
+ break;
+ }
+}
+
+ast_expression::ast_expression(int oper,
+ ast_expression *ex0,
+ ast_expression *ex1,
+ ast_expression *ex2)
+{
+ this->oper = ast_operators(oper);
+ this->subexpressions[0] = ex0;
+ this->subexpressions[1] = ex1;
+ this->subexpressions[2] = ex2;
+}
+
+
+void
+ast_expression_statement::print(void) const
+{
+ if (expression)
+ expression->print();
+
+ printf("; ");
+}
+
+
+ast_expression_statement::ast_expression_statement(ast_expression *ex) :
+ expression(ex)
+{
+ /* empty */
+}
+
+
+void
+ast_function::print(void) const
+{
+ return_type->print();
+ printf(" %s (", identifier);
+
+ foreach_list_const(n, & this->parameters) {
+ ast_node *ast = exec_node_data(ast_node, n, link);
+ ast->print();
+ }
+
+ printf(")");
+}
+
+
+ast_function::ast_function(void)
+ : is_definition(false), signature(NULL)
+{
+ /* empty */
+}
+
+
+void
+ast_fully_specified_type::print(void) const
+{
+ _mesa_ast_type_qualifier_print(& qualifier);
+ specifier->print();
+}
+
+
+void
+ast_parameter_declarator::print(void) const
+{
+ type->print();
+ if (identifier)
+ printf("%s ", identifier);
+ ast_opt_array_size_print(is_array, array_size);
+}
+
+
+void
+ast_function_definition::print(void) const
+{
+ prototype->print();
+ body->print();
+}
+
+
+void
+ast_declaration::print(void) const
+{
+ printf("%s ", identifier);
+ ast_opt_array_size_print(is_array, array_size);
+
+ if (initializer) {
+ printf("= ");
+ initializer->print();
+ }
+}
+
+
+ast_declaration::ast_declaration(char *identifier, int is_array,
+ ast_expression *array_size,
+ ast_expression *initializer)
+{
+ this->identifier = identifier;
+ this->is_array = is_array;
+ this->array_size = array_size;
+ this->initializer = initializer;
+}
+
+
+void
+ast_declarator_list::print(void) const
+{
+ assert(type || invariant);
+
+ if (type)
+ type->print();
+ else
+ printf("invariant ");
+
+ foreach_list_const (ptr, & this->declarations) {
+ if (ptr != this->declarations.get_head())
+ printf(", ");
+
+ ast_node *ast = exec_node_data(ast_node, ptr, link);
+ ast->print();
+ }
+
+ printf("; ");
+}
+
+
+ast_declarator_list::ast_declarator_list(ast_fully_specified_type *type)
+{
+ this->type = type;
+ this->invariant = false;
+}
+
+void
+ast_jump_statement::print(void) const
+{
+ switch (mode) {
+ case ast_continue:
+ printf("continue; ");
+ break;
+ case ast_break:
+ printf("break; ");
+ break;
+ case ast_return:
+ printf("return ");
+ if (opt_return_value)
+ opt_return_value->print();
+
+ printf("; ");
+ break;
+ case ast_discard:
+ printf("discard; ");
+ break;
+ }
+}
+
+
+ast_jump_statement::ast_jump_statement(int mode, ast_expression *return_value)
+{
+ this->mode = ast_jump_modes(mode);
+
+ if (mode == ast_return)
+ opt_return_value = return_value;
+}
+
+
+void
+ast_selection_statement::print(void) const
+{
+ printf("if ( ");
+ condition->print();
+ printf(") ");
+
+ then_statement->print();
+
+ if (else_statement) {
+ printf("else ");
+ else_statement->print();
+ }
+
+}
+
+
+ast_selection_statement::ast_selection_statement(ast_expression *condition,
+ ast_node *then_statement,
+ ast_node *else_statement)
+{
+ this->condition = condition;
+ this->then_statement = then_statement;
+ this->else_statement = else_statement;
+}
+
+
+void
+ast_iteration_statement::print(void) const
+{
+ switch (mode) {
+ case ast_for:
+ printf("for( ");
+ if (init_statement)
+ init_statement->print();
+ printf("; ");
+
+ if (condition)
+ condition->print();
+ printf("; ");
+
+ if (rest_expression)
+ rest_expression->print();
+ printf(") ");
+
+ body->print();
+ break;
+
+ case ast_while:
+ printf("while ( ");
+ if (condition)
+ condition->print();
+ printf(") ");
+ body->print();
+ break;
+
+ case ast_do_while:
+ printf("do ");
+ body->print();
+ printf("while ( ");
+ if (condition)
+ condition->print();
+ printf("); ");
+ break;
+ }
+}
+
+
+ast_iteration_statement::ast_iteration_statement(int mode,
+ ast_node *init,
+ ast_node *condition,
+ ast_expression *rest_expression,
+ ast_node *body)
+{
+ this->mode = ast_iteration_modes(mode);
+ this->init_statement = init;
+ this->condition = condition;
+ this->rest_expression = rest_expression;
+ this->body = body;
+}
+
+
+void
+ast_struct_specifier::print(void) const
+{
+ printf("struct %s { ", name);
+ foreach_list_const(n, &this->declarations) {
+ ast_node *ast = exec_node_data(ast_node, n, link);
+ ast->print();
+ }
+ printf("} ");
+}
+
+
+ast_struct_specifier::ast_struct_specifier(char *identifier,
+ ast_node *declarator_list)
+{
+ name = identifier;
+ this->declarations.push_degenerate_list_at_head(&declarator_list->link);
+}
+
+bool
+do_common_optimization(exec_list *ir, bool linked)
+{
+ GLboolean progress = GL_FALSE;
+
+ progress = do_sub_to_add_neg(ir) || progress;
+
+ if (linked) {
+ progress = do_function_inlining(ir) || progress;
+ progress = do_dead_functions(ir) || progress;
+ }
+ progress = do_structure_splitting(ir) || progress;
+ progress = do_if_simplification(ir) || progress;
+ progress = do_copy_propagation(ir) || progress;
+ if (linked)
+ progress = do_dead_code(ir) || progress;
+ else
+ progress = do_dead_code_unlinked(ir) || progress;
+ progress = do_dead_code_local(ir) || progress;
+ progress = do_tree_grafting(ir) || progress;
+ progress = do_constant_propagation(ir) || progress;
+ if (linked)
+ progress = do_constant_variable(ir) || progress;
+ else
+ progress = do_constant_variable_unlinked(ir) || progress;
+ progress = do_constant_folding(ir) || progress;
+ progress = do_algebraic(ir) || progress;
+ progress = do_if_return(ir) || progress;
+ progress = do_vec_index_to_swizzle(ir) || progress;
+ progress = do_swizzle_swizzle(ir) || progress;
+ progress = do_noop_swizzle(ir) || progress;
+
+ return progress;
+}
diff --git a/src/glsl/glsl_parser_extras.h b/src/glsl/glsl_parser_extras.h
new file mode 100644
index 00000000000..3b53ba07f68
--- /dev/null
+++ b/src/glsl/glsl_parser_extras.h
@@ -0,0 +1,214 @@
+/*
+ * Copyright © 2010 Intel Corporation
+ *
+ * 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 (including the next
+ * paragraph) 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
+ * THE AUTHORS OR COPYRIGHT HOLDERS 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.
+ */
+
+#pragma once
+#ifndef GLSL_PARSER_EXTRAS_H
+#define GLSL_PARSER_EXTRAS_H
+
+#include <cstdlib>
+#include "glsl_symbol_table.h"
+
+enum _mesa_glsl_parser_targets {
+ vertex_shader,
+ geometry_shader,
+ fragment_shader,
+ ir_shader
+};
+
+struct __GLcontextRec;
+
+struct _mesa_glsl_parse_state {
+ _mesa_glsl_parse_state(struct __GLcontextRec *ctx, GLenum target,
+ void *mem_ctx);
+
+ /* Callers of this talloc-based new need not call delete. It's
+ * easier to just talloc_free 'ctx' (or any of its ancestors). */
+ static void* operator new(size_t size, void *ctx)
+ {
+ void *mem = talloc_zero_size(ctx, size);
+ assert(mem != NULL);
+
+ return mem;
+ }
+
+ /* If the user *does* call delete, that's OK, we will just
+ * talloc_free in that case. */
+ static void operator delete(void *mem)
+ {
+ talloc_free(mem);
+ }
+
+ void *scanner;
+ exec_list translation_unit;
+ glsl_symbol_table *symbols;
+
+ unsigned language_version;
+ enum _mesa_glsl_parser_targets target;
+
+ /**
+ * Implementation defined limits that affect built-in variables, etc.
+ *
+ * \sa struct gl_constants (in mtypes.h)
+ */
+ struct {
+ /* 1.10 */
+ unsigned MaxLights;
+ unsigned MaxClipPlanes;
+ unsigned MaxTextureUnits;
+ unsigned MaxTextureCoords;
+ unsigned MaxVertexAttribs;
+ unsigned MaxVertexUniformComponents;
+ unsigned MaxVaryingFloats;
+ unsigned MaxVertexTextureImageUnits;
+ unsigned MaxCombinedTextureImageUnits;
+ unsigned MaxTextureImageUnits;
+ unsigned MaxFragmentUniformComponents;
+
+ /* ARB_draw_buffers */
+ unsigned MaxDrawBuffers;
+ } Const;
+
+ /**
+ * During AST to IR conversion, pointer to current IR function
+ *
+ * Will be \c NULL whenever the AST to IR conversion is not inside a
+ * function definition.
+ */
+ class ir_function_signature *current_function;
+
+ /** Have we found a return statement in this function? */
+ bool found_return;
+
+ /** Was there an error during compilation? */
+ bool error;
+
+ /** Loop or switch statement containing the current instructions. */
+ class ir_instruction *loop_or_switch_nesting;
+ class ast_iteration_statement *loop_or_switch_nesting_ast;
+
+ /** List of structures defined in user code. */
+ const glsl_type **user_structures;
+ unsigned num_user_structures;
+
+ char *info_log;
+
+ /**
+ * \name Enable bits for GLSL extensions
+ */
+ /*@{*/
+ unsigned ARB_draw_buffers_enable:1;
+ unsigned ARB_draw_buffers_warn:1;
+ unsigned ARB_fragment_coord_conventions_enable:1;
+ unsigned ARB_fragment_coord_conventions_warn:1;
+ unsigned ARB_texture_rectangle_enable:1;
+ unsigned ARB_texture_rectangle_warn:1;
+ unsigned EXT_texture_array_enable:1;
+ unsigned EXT_texture_array_warn:1;
+ /*@}*/
+
+ /** Extensions supported by the OpenGL implementation. */
+ const struct gl_extensions *extensions;
+
+ /** Shaders containing built-in functions that are used for linking. */
+ struct gl_shader *builtins_to_link[16];
+ unsigned num_builtins_to_link;
+};
+
+typedef struct YYLTYPE {
+ int first_line;
+ int first_column;
+ int last_line;
+ int last_column;
+ unsigned source;
+} YYLTYPE;
+# define YYLTYPE_IS_DECLARED 1
+# define YYLTYPE_IS_TRIVIAL 1
+
+# define YYLLOC_DEFAULT(Current, Rhs, N) \
+do { \
+ if (N) \
+ { \
+ (Current).first_line = YYRHSLOC(Rhs, 1).first_line; \
+ (Current).first_column = YYRHSLOC(Rhs, 1).first_column; \
+ (Current).last_line = YYRHSLOC(Rhs, N).last_line; \
+ (Current).last_column = YYRHSLOC(Rhs, N).last_column; \
+ } \
+ else \
+ { \
+ (Current).first_line = (Current).last_line = \
+ YYRHSLOC(Rhs, 0).last_line; \
+ (Current).first_column = (Current).last_column = \
+ YYRHSLOC(Rhs, 0).last_column; \
+ } \
+ (Current).source = 0; \
+} while (0)
+
+extern void _mesa_glsl_error(YYLTYPE *locp, _mesa_glsl_parse_state *state,
+ const char *fmt, ...);
+
+/**
+ * Emit a warning to the shader log
+ *
+ * \sa _mesa_glsl_error
+ */
+extern void _mesa_glsl_warning(const YYLTYPE *locp,
+ _mesa_glsl_parse_state *state,
+ const char *fmt, ...);
+
+extern "C" {
+extern int preprocess(void *ctx, const char **shader, char **info_log,
+ const struct gl_extensions *extensions);
+}
+
+extern void _mesa_glsl_lexer_ctor(struct _mesa_glsl_parse_state *state,
+ const char *string);
+
+extern void _mesa_glsl_lexer_dtor(struct _mesa_glsl_parse_state *state);
+
+union YYSTYPE;
+extern int _mesa_glsl_lex(union YYSTYPE *yylval, YYLTYPE *yylloc,
+ void *scanner);
+
+extern int _mesa_glsl_parse(struct _mesa_glsl_parse_state *);
+
+/**
+ * Process elements of the #extension directive
+ *
+ * \return
+ * If \c name and \c behavior are valid, \c true is returned. Otherwise
+ * \c false is returned.
+ */
+extern bool _mesa_glsl_process_extension(const char *name, YYLTYPE *name_locp,
+ const char *behavior,
+ YYLTYPE *behavior_locp,
+ _mesa_glsl_parse_state *state);
+
+/**
+ * Get the textual name of the specified shader target
+ */
+extern const char *
+_mesa_glsl_shader_target_name(enum _mesa_glsl_parser_targets target);
+
+void do_ir_to_mesa(exec_list *instructions);
+
+#endif /* GLSL_PARSER_EXTRAS_H */
diff --git a/src/glsl/glsl_symbol_table.h b/src/glsl/glsl_symbol_table.h
new file mode 100644
index 00000000000..02e4542cf3d
--- /dev/null
+++ b/src/glsl/glsl_symbol_table.h
@@ -0,0 +1,171 @@
+/* -*- c++ -*- */
+/*
+ * Copyright © 2010 Intel Corporation
+ *
+ * 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 (including the next
+ * paragraph) 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
+ * THE AUTHORS OR COPYRIGHT HOLDERS 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.
+ */
+
+#pragma once
+#ifndef GLSL_SYMBOL_TABLE
+#define GLSL_SYMBOL_TABLE
+
+#include <new>
+
+extern "C" {
+#include "program/symbol_table.h"
+}
+#include "ir.h"
+#include "glsl_types.h"
+
+/**
+ * Facade class for _mesa_symbol_table
+ *
+ * Wraps the existing \c _mesa_symbol_table data structure to enforce some
+ * type safe and some symbol table invariants.
+ */
+class glsl_symbol_table {
+private:
+ enum glsl_symbol_name_space {
+ glsl_variable_name_space = 0,
+ glsl_type_name_space = 1,
+ glsl_function_name_space = 2
+ };
+
+ static int
+ _glsl_symbol_table_destructor (glsl_symbol_table *table)
+ {
+ table->~glsl_symbol_table();
+
+ return 0;
+ }
+
+public:
+ /* Callers of this talloc-based new need not call delete. It's
+ * easier to just talloc_free 'ctx' (or any of its ancestors). */
+ static void* operator new(size_t size, void *ctx)
+ {
+ void *table;
+
+ table = talloc_size(ctx, size);
+ assert(table != NULL);
+
+ talloc_set_destructor(table, (int (*)(void*)) _glsl_symbol_table_destructor);
+
+ return table;
+ }
+
+ /* If the user *does* call delete, that's OK, we will just
+ * talloc_free in that case. Here, C++ will have already called the
+ * destructor so tell talloc not to do that again. */
+ static void operator delete(void *table)
+ {
+ talloc_set_destructor(table, NULL);
+ talloc_free(table);
+ }
+
+ glsl_symbol_table()
+ {
+ table = _mesa_symbol_table_ctor();
+ }
+
+ ~glsl_symbol_table()
+ {
+ _mesa_symbol_table_dtor(table);
+ }
+
+ void push_scope()
+ {
+ _mesa_symbol_table_push_scope(table);
+ }
+
+ void pop_scope()
+ {
+ _mesa_symbol_table_pop_scope(table);
+ }
+
+ /**
+ * Determine whether a name was declared at the current scope
+ */
+ bool name_declared_this_scope(const char *name)
+ {
+ return _mesa_symbol_table_symbol_scope(table, -1, name) == 0;
+ }
+
+ /**
+ * \name Methods to add symbols to the table
+ *
+ * There is some temptation to rename all these functions to \c add_symbol
+ * or similar. However, this breaks symmetry with the getter functions and
+ * reduces the clarity of the intention of code that uses these methods.
+ */
+ /*@{*/
+ bool add_variable(const char *name, ir_variable *v)
+ {
+ return _mesa_symbol_table_add_symbol(table, glsl_variable_name_space,
+ name, v) == 0;
+ }
+
+ bool add_type(const char *name, const glsl_type *t)
+ {
+ return _mesa_symbol_table_add_symbol(table, glsl_type_name_space,
+ name, (void *) t) == 0;
+ }
+
+ bool add_function(const char *name, ir_function *f)
+ {
+ return _mesa_symbol_table_add_symbol(table, glsl_function_name_space,
+ name, f) == 0;
+ }
+
+ bool remove_function(const char *name, ir_function *f)
+ {
+ return _mesa_symbol_table_add_symbol(table, glsl_function_name_space,
+ name, f) == 0;
+ }
+ /*@}*/
+
+ /**
+ * \name Methods to get symbols from the table
+ */
+ /*@{*/
+ ir_variable *get_variable(const char *name)
+ {
+ return (ir_variable *)
+ _mesa_symbol_table_find_symbol(table, glsl_variable_name_space, name);
+ }
+
+ glsl_type *get_type(const char *name)
+ {
+ return (glsl_type *)
+ _mesa_symbol_table_find_symbol(table, glsl_type_name_space, name);
+ }
+
+ ir_function *get_function(const char *name)
+ {
+ return (ir_function *)
+ _mesa_symbol_table_find_symbol(table, glsl_function_name_space, name);
+ }
+ /*@}*/
+
+private:
+ struct _mesa_symbol_table *table;
+};
+
+#endif /* GLSL_SYMBOL_TABLE */
diff --git a/src/glsl/glsl_types.cpp b/src/glsl/glsl_types.cpp
new file mode 100644
index 00000000000..8e80cf99e96
--- /dev/null
+++ b/src/glsl/glsl_types.cpp
@@ -0,0 +1,550 @@
+/*
+ * Copyright © 2009 Intel Corporation
+ *
+ * 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 (including the next
+ * paragraph) 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
+ * THE AUTHORS OR COPYRIGHT HOLDERS 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.
+ */
+
+#include <cstdio>
+#include <stdlib.h>
+#include "main/compiler.h"
+#include "glsl_symbol_table.h"
+#include "glsl_parser_extras.h"
+#include "glsl_types.h"
+#include "builtin_types.h"
+extern "C" {
+#include "program/hash_table.h"
+}
+
+hash_table *glsl_type::array_types = NULL;
+hash_table *glsl_type::record_types = NULL;
+void *glsl_type::mem_ctx = NULL;
+
+void
+glsl_type::init_talloc_type_ctx(void)
+{
+ if (glsl_type::mem_ctx == NULL) {
+ glsl_type::mem_ctx = talloc_init("glsl_type");
+ assert(glsl_type::mem_ctx != NULL);
+ }
+}
+
+glsl_type::glsl_type(GLenum gl_type,
+ unsigned base_type, unsigned vector_elements,
+ unsigned matrix_columns, const char *name) :
+ gl_type(gl_type),
+ base_type(base_type),
+ sampler_dimensionality(0), sampler_shadow(0), sampler_array(0),
+ sampler_type(0),
+ vector_elements(vector_elements), matrix_columns(matrix_columns),
+ length(0)
+{
+ init_talloc_type_ctx();
+ this->name = talloc_strdup(this->mem_ctx, name);
+ /* Neither dimension is zero or both dimensions are zero.
+ */
+ assert((vector_elements == 0) == (matrix_columns == 0));
+ memset(& fields, 0, sizeof(fields));
+}
+
+glsl_type::glsl_type(GLenum gl_type,
+ enum glsl_sampler_dim dim, bool shadow, bool array,
+ unsigned type, const char *name) :
+ gl_type(gl_type),
+ base_type(GLSL_TYPE_SAMPLER),
+ sampler_dimensionality(dim), sampler_shadow(shadow),
+ sampler_array(array), sampler_type(type),
+ vector_elements(0), matrix_columns(0),
+ length(0)
+{
+ init_talloc_type_ctx();
+ this->name = talloc_strdup(this->mem_ctx, name);
+ memset(& fields, 0, sizeof(fields));
+}
+
+glsl_type::glsl_type(const glsl_struct_field *fields, unsigned num_fields,
+ const char *name) :
+ base_type(GLSL_TYPE_STRUCT),
+ sampler_dimensionality(0), sampler_shadow(0), sampler_array(0),
+ sampler_type(0),
+ vector_elements(0), matrix_columns(0),
+ length(num_fields)
+{
+ unsigned int i;
+
+ init_talloc_type_ctx();
+ this->name = talloc_strdup(this->mem_ctx, name);
+ this->fields.structure = talloc_array(this->mem_ctx,
+ glsl_struct_field, length);
+ for (i = 0; i < length; i++) {
+ this->fields.structure[i].type = fields[i].type;
+ this->fields.structure[i].name = talloc_strdup(this->fields.structure,
+ fields[i].name);
+ }
+}
+
+static void
+add_types_to_symbol_table(glsl_symbol_table *symtab,
+ const struct glsl_type *types,
+ unsigned num_types, bool warn)
+{
+ (void) warn;
+
+ for (unsigned i = 0; i < num_types; i++) {
+ symtab->add_type(types[i].name, & types[i]);
+ }
+}
+
+
+void
+glsl_type::generate_110_types(glsl_symbol_table *symtab)
+{
+ add_types_to_symbol_table(symtab, builtin_core_types,
+ Elements(builtin_core_types),
+ false);
+ add_types_to_symbol_table(symtab, builtin_structure_types,
+ Elements(builtin_structure_types),
+ false);
+ add_types_to_symbol_table(symtab, builtin_110_deprecated_structure_types,
+ Elements(builtin_110_deprecated_structure_types),
+ false);
+ add_types_to_symbol_table(symtab, & void_type, 1, false);
+}
+
+
+void
+glsl_type::generate_120_types(glsl_symbol_table *symtab)
+{
+ generate_110_types(symtab);
+
+ add_types_to_symbol_table(symtab, builtin_120_types,
+ Elements(builtin_120_types), false);
+}
+
+
+void
+glsl_type::generate_130_types(glsl_symbol_table *symtab)
+{
+ generate_120_types(symtab);
+
+ add_types_to_symbol_table(symtab, builtin_130_types,
+ Elements(builtin_130_types), false);
+ generate_EXT_texture_array_types(symtab, false);
+}
+
+
+void
+glsl_type::generate_ARB_texture_rectangle_types(glsl_symbol_table *symtab,
+ bool warn)
+{
+ add_types_to_symbol_table(symtab, builtin_ARB_texture_rectangle_types,
+ Elements(builtin_ARB_texture_rectangle_types),
+ warn);
+}
+
+
+void
+glsl_type::generate_EXT_texture_array_types(glsl_symbol_table *symtab,
+ bool warn)
+{
+ add_types_to_symbol_table(symtab, builtin_EXT_texture_array_types,
+ Elements(builtin_EXT_texture_array_types),
+ warn);
+}
+
+
+void
+_mesa_glsl_initialize_types(struct _mesa_glsl_parse_state *state)
+{
+ switch (state->language_version) {
+ case 110:
+ glsl_type::generate_110_types(state->symbols);
+ break;
+ case 120:
+ glsl_type::generate_120_types(state->symbols);
+ break;
+ case 130:
+ glsl_type::generate_130_types(state->symbols);
+ break;
+ default:
+ /* error */
+ break;
+ }
+
+ if (state->ARB_texture_rectangle_enable) {
+ glsl_type::generate_ARB_texture_rectangle_types(state->symbols,
+ state->ARB_texture_rectangle_warn);
+ }
+
+ if (state->EXT_texture_array_enable && state->language_version < 130) {
+ // These are already included in 130; don't create twice.
+ glsl_type::generate_EXT_texture_array_types(state->symbols,
+ state->EXT_texture_array_warn);
+ }
+}
+
+
+const glsl_type *glsl_type::get_base_type() const
+{
+ switch (base_type) {
+ case GLSL_TYPE_UINT:
+ return uint_type;
+ case GLSL_TYPE_INT:
+ return int_type;
+ case GLSL_TYPE_FLOAT:
+ return float_type;
+ case GLSL_TYPE_BOOL:
+ return bool_type;
+ default:
+ return error_type;
+ }
+}
+
+
+void
+_mesa_glsl_release_types(void)
+{
+ if (glsl_type::array_types != NULL) {
+ hash_table_dtor(glsl_type::array_types);
+ glsl_type::array_types = NULL;
+ }
+
+ if (glsl_type::record_types != NULL) {
+ hash_table_dtor(glsl_type::record_types);
+ glsl_type::record_types = NULL;
+ }
+
+ if (glsl_type::mem_ctx != NULL) {
+ talloc_free(glsl_type::mem_ctx);
+ glsl_type::mem_ctx = NULL;
+ }
+}
+
+
+ir_function *
+glsl_type::generate_constructor(glsl_symbol_table *symtab) const
+{
+ void *ctx = symtab;
+
+ /* Generate the function name and add it to the symbol table.
+ */
+ ir_function *const f = new(ctx) ir_function(name);
+
+ bool added = symtab->add_function(name, f);
+ assert(added);
+
+ ir_function_signature *const sig = new(ctx) ir_function_signature(this);
+ f->add_signature(sig);
+
+ ir_variable **declarations =
+ (ir_variable **) malloc(sizeof(ir_variable *) * this->length);
+ for (unsigned i = 0; i < length; i++) {
+ char *const param_name = (char *) malloc(10);
+
+ snprintf(param_name, 10, "p%08X", i);
+
+ ir_variable *var = (this->base_type == GLSL_TYPE_ARRAY)
+ ? new(ctx) ir_variable(fields.array, param_name, ir_var_in)
+ : new(ctx) ir_variable(fields.structure[i].type, param_name, ir_var_in);
+
+ declarations[i] = var;
+ sig->parameters.push_tail(var);
+ }
+
+ /* Generate the body of the constructor. The body assigns each of the
+ * parameters to a portion of a local variable called _ret_val that has
+ * the same type as the constructor. After initializing _ret_val,
+ * _ret_val is returned.
+ */
+ ir_variable *retval = new(ctx) ir_variable(this, "_ret_val", ir_var_auto);
+ sig->body.push_tail(retval);
+
+ for (unsigned i = 0; i < length; i++) {
+ ir_dereference *const lhs = (this->base_type == GLSL_TYPE_ARRAY)
+ ? (ir_dereference *) new(ctx) ir_dereference_array(retval,
+ new(ctx) ir_constant(i))
+ : (ir_dereference *) new(ctx) ir_dereference_record(retval,
+ fields.structure[i].name);
+
+ ir_dereference *const rhs = new(ctx) ir_dereference_variable(declarations[i]);
+ ir_instruction *const assign = new(ctx) ir_assignment(lhs, rhs, NULL);
+
+ sig->body.push_tail(assign);
+ }
+
+ free(declarations);
+
+ ir_dereference *const retref = new(ctx) ir_dereference_variable(retval);
+ ir_instruction *const inst = new(ctx) ir_return(retref);
+ sig->body.push_tail(inst);
+
+ return f;
+}
+
+
+glsl_type::glsl_type(const glsl_type *array, unsigned length) :
+ base_type(GLSL_TYPE_ARRAY),
+ sampler_dimensionality(0), sampler_shadow(0), sampler_array(0),
+ sampler_type(0),
+ vector_elements(0), matrix_columns(0),
+ name(NULL), length(length)
+{
+ this->fields.array = array;
+ /* Inherit the gl type of the base. The GL type is used for
+ * uniform/statevar handling in Mesa and the arrayness of the type
+ * is represented by the size rather than the type.
+ */
+ this->gl_type = array->gl_type;
+
+ /* Allow a maximum of 10 characters for the array size. This is enough
+ * for 32-bits of ~0. The extra 3 are for the '[', ']', and terminating
+ * NUL.
+ */
+ const unsigned name_length = strlen(array->name) + 10 + 3;
+ char *const n = (char *) talloc_size(this->mem_ctx, name_length);
+
+ if (length == 0)
+ snprintf(n, name_length, "%s[]", array->name);
+ else
+ snprintf(n, name_length, "%s[%u]", array->name, length);
+
+ this->name = n;
+}
+
+
+const glsl_type *
+glsl_type::get_instance(unsigned base_type, unsigned rows, unsigned columns)
+{
+ if (base_type == GLSL_TYPE_VOID)
+ return &void_type;
+
+ if ((rows < 1) || (rows > 4) || (columns < 1) || (columns > 4))
+ return error_type;
+
+ /* Treat GLSL vectors as Nx1 matrices.
+ */
+ if (columns == 1) {
+ switch (base_type) {
+ case GLSL_TYPE_UINT:
+ return uint_type + (rows - 1);
+ case GLSL_TYPE_INT:
+ return int_type + (rows - 1);
+ case GLSL_TYPE_FLOAT:
+ return float_type + (rows - 1);
+ case GLSL_TYPE_BOOL:
+ return bool_type + (rows - 1);
+ default:
+ return error_type;
+ }
+ } else {
+ if ((base_type != GLSL_TYPE_FLOAT) || (rows == 1))
+ return error_type;
+
+ /* GLSL matrix types are named mat{COLUMNS}x{ROWS}. Only the following
+ * combinations are valid:
+ *
+ * 1 2 3 4
+ * 1
+ * 2 x x x
+ * 3 x x x
+ * 4 x x x
+ */
+#define IDX(c,r) (((c-1)*3) + (r-1))
+
+ switch (IDX(columns, rows)) {
+ case IDX(2,2): return mat2_type;
+ case IDX(2,3): return mat2x3_type;
+ case IDX(2,4): return mat2x4_type;
+ case IDX(3,2): return mat3x2_type;
+ case IDX(3,3): return mat3_type;
+ case IDX(3,4): return mat3x4_type;
+ case IDX(4,2): return mat4x2_type;
+ case IDX(4,3): return mat4x3_type;
+ case IDX(4,4): return mat4_type;
+ default: return error_type;
+ }
+ }
+
+ assert(!"Should not get here.");
+ return error_type;
+}
+
+
+const glsl_type *
+glsl_type::get_array_instance(const glsl_type *base, unsigned array_size)
+{
+
+ if (array_types == NULL) {
+ array_types = hash_table_ctor(64, hash_table_string_hash,
+ hash_table_string_compare);
+ }
+
+ /* Generate a name using the base type pointer in the key. This is
+ * done because the name of the base type may not be unique across
+ * shaders. For example, two shaders may have different record types
+ * named 'foo'.
+ */
+ char key[128];
+ snprintf(key, sizeof(key), "%p[%u]", (void *) base, array_size);
+
+ const glsl_type *t = (glsl_type *) hash_table_find(array_types, key);
+ if (t == NULL) {
+ t = new glsl_type(base, array_size);
+
+ hash_table_insert(array_types, (void *) t, talloc_strdup(mem_ctx, key));
+ }
+
+ assert(t->base_type == GLSL_TYPE_ARRAY);
+ assert(t->length == array_size);
+ assert(t->fields.array == base);
+
+ return t;
+}
+
+
+int
+glsl_type::record_key_compare(const void *a, const void *b)
+{
+ const glsl_type *const key1 = (glsl_type *) a;
+ const glsl_type *const key2 = (glsl_type *) b;
+
+ /* Return zero is the types match (there is zero difference) or non-zero
+ * otherwise.
+ */
+ if (strcmp(key1->name, key2->name) != 0)
+ return 1;
+
+ if (key1->length != key2->length)
+ return 1;
+
+ for (unsigned i = 0; i < key1->length; i++) {
+ if (key1->fields.structure[i].type != key2->fields.structure[i].type)
+ return 1;
+ if (strcmp(key1->fields.structure[i].name,
+ key2->fields.structure[i].name) != 0)
+ return 1;
+ }
+
+ return 0;
+}
+
+
+unsigned
+glsl_type::record_key_hash(const void *a)
+{
+ const glsl_type *const key = (glsl_type *) a;
+ char hash_key[128];
+ unsigned size = 0;
+
+ size = snprintf(hash_key, sizeof(hash_key), "%08x", key->length);
+
+ for (unsigned i = 0; i < key->length; i++) {
+ if (size >= sizeof(hash_key))
+ break;
+
+ size += snprintf(& hash_key[size], sizeof(hash_key) - size,
+ "%p", (void *) key->fields.structure[i].type);
+ }
+
+ return hash_table_string_hash(& hash_key);
+}
+
+
+const glsl_type *
+glsl_type::get_record_instance(const glsl_struct_field *fields,
+ unsigned num_fields,
+ const char *name)
+{
+ const glsl_type key(fields, num_fields, name);
+
+ if (record_types == NULL) {
+ record_types = hash_table_ctor(64, record_key_hash, record_key_compare);
+ }
+
+ const glsl_type *t = (glsl_type *) hash_table_find(record_types, & key);
+ if (t == NULL) {
+ t = new glsl_type(fields, num_fields, name);
+
+ hash_table_insert(record_types, (void *) t, t);
+ }
+
+ assert(t->base_type == GLSL_TYPE_STRUCT);
+ assert(t->length == num_fields);
+ assert(strcmp(t->name, name) == 0);
+
+ return t;
+}
+
+
+const glsl_type *
+glsl_type::field_type(const char *name) const
+{
+ if (this->base_type != GLSL_TYPE_STRUCT)
+ return error_type;
+
+ for (unsigned i = 0; i < this->length; i++) {
+ if (strcmp(name, this->fields.structure[i].name) == 0)
+ return this->fields.structure[i].type;
+ }
+
+ return error_type;
+}
+
+
+int
+glsl_type::field_index(const char *name) const
+{
+ if (this->base_type != GLSL_TYPE_STRUCT)
+ return -1;
+
+ for (unsigned i = 0; i < this->length; i++) {
+ if (strcmp(name, this->fields.structure[i].name) == 0)
+ return i;
+ }
+
+ return -1;
+}
+
+
+unsigned
+glsl_type::component_slots() const
+{
+ switch (this->base_type) {
+ case GLSL_TYPE_UINT:
+ case GLSL_TYPE_INT:
+ case GLSL_TYPE_FLOAT:
+ case GLSL_TYPE_BOOL:
+ return this->components();
+
+ case GLSL_TYPE_STRUCT: {
+ unsigned size = 0;
+
+ for (unsigned i = 0; i < this->length; i++)
+ size += this->fields.structure[i].type->component_slots();
+
+ return size;
+ }
+
+ case GLSL_TYPE_ARRAY:
+ return this->length * this->fields.array->component_slots();
+
+ default:
+ return 0;
+ }
+}
diff --git a/src/glsl/glsl_types.h b/src/glsl/glsl_types.h
new file mode 100644
index 00000000000..97d0d98c624
--- /dev/null
+++ b/src/glsl/glsl_types.h
@@ -0,0 +1,479 @@
+/* -*- c++ -*- */
+/*
+ * Copyright © 2009 Intel Corporation
+ *
+ * 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 (including the next
+ * paragraph) 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
+ * THE AUTHORS OR COPYRIGHT HOLDERS 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.
+ */
+
+#pragma once
+#ifndef GLSL_TYPES_H
+#define GLSL_TYPES_H
+
+#include <cstring>
+#include <cassert>
+
+extern "C" {
+#include "GL/gl.h"
+#include <talloc.h>
+}
+
+struct _mesa_glsl_parse_state;
+
+extern "C" void
+_mesa_glsl_initialize_types(struct _mesa_glsl_parse_state *state);
+
+extern "C" void
+_mesa_glsl_release_types(void);
+
+#define GLSL_TYPE_UINT 0
+#define GLSL_TYPE_INT 1
+#define GLSL_TYPE_FLOAT 2
+#define GLSL_TYPE_BOOL 3
+#define GLSL_TYPE_SAMPLER 4
+#define GLSL_TYPE_STRUCT 5
+#define GLSL_TYPE_ARRAY 6
+#define GLSL_TYPE_FUNCTION 7
+#define GLSL_TYPE_VOID 8
+#define GLSL_TYPE_ERROR 9
+
+enum glsl_sampler_dim {
+ GLSL_SAMPLER_DIM_1D = 0,
+ GLSL_SAMPLER_DIM_2D,
+ GLSL_SAMPLER_DIM_3D,
+ GLSL_SAMPLER_DIM_CUBE,
+ GLSL_SAMPLER_DIM_RECT,
+ GLSL_SAMPLER_DIM_BUF
+};
+
+
+struct glsl_type {
+ GLenum gl_type;
+ unsigned base_type:4;
+
+ unsigned sampler_dimensionality:3;
+ unsigned sampler_shadow:1;
+ unsigned sampler_array:1;
+ unsigned sampler_type:2; /**< Type of data returned using this sampler.
+ * only \c GLSL_TYPE_FLOAT, \c GLSL_TYPE_INT,
+ * and \c GLSL_TYPE_UINT are valid.
+ */
+
+ /* Callers of this talloc-based new need not call delete. It's
+ * easier to just talloc_free 'mem_ctx' (or any of its ancestors). */
+ static void* operator new(size_t size)
+ {
+ if (glsl_type::mem_ctx == NULL) {
+ glsl_type::mem_ctx = talloc_init("glsl_type");
+ assert(glsl_type::mem_ctx != NULL);
+ }
+
+ void *type;
+
+ type = talloc_size(glsl_type::mem_ctx, size);
+ assert(type != NULL);
+
+ return type;
+ }
+
+ /* If the user *does* call delete, that's OK, we will just
+ * talloc_free in that case. */
+ static void operator delete(void *type)
+ {
+ talloc_free(type);
+ }
+
+ /**
+ * \name Vector and matrix element counts
+ *
+ * For scalars, each of these values will be 1. For non-numeric types
+ * these will be 0.
+ */
+ /*@{*/
+ unsigned vector_elements:3; /**< 1, 2, 3, or 4 vector elements. */
+ unsigned matrix_columns:3; /**< 1, 2, 3, or 4 matrix columns. */
+ /*@}*/
+
+ /**
+ * Name of the data type
+ *
+ * This may be \c NULL for anonymous structures, for arrays, or for
+ * function types.
+ */
+ const char *name;
+
+ /**
+ * For \c GLSL_TYPE_ARRAY, this is the length of the array. For
+ * \c GLSL_TYPE_STRUCT, it is the number of elements in the structure and
+ * the number of values pointed to by \c fields.structure (below).
+ *
+ * For \c GLSL_TYPE_FUNCTION, it is the number of parameters to the
+ * function. The return value from a function is implicitly the first
+ * parameter. The types of the parameters are stored in
+ * \c fields.parameters (below).
+ */
+ unsigned length;
+
+ /**
+ * Subtype of composite data types.
+ */
+ union {
+ const struct glsl_type *array; /**< Type of array elements. */
+ const struct glsl_type *parameters; /**< Parameters to function. */
+ struct glsl_struct_field *structure; /**< List of struct fields. */
+ } fields;
+
+
+ /**
+ * \name Pointers to various public type singletons
+ */
+ /*@{*/
+ static const glsl_type *const error_type;
+ static const glsl_type *const int_type;
+ static const glsl_type *const ivec4_type;
+ static const glsl_type *const uint_type;
+ static const glsl_type *const uvec4_type;
+ static const glsl_type *const float_type;
+ static const glsl_type *const vec2_type;
+ static const glsl_type *const vec3_type;
+ static const glsl_type *const vec4_type;
+ static const glsl_type *const bool_type;
+ static const glsl_type *const mat2_type;
+ static const glsl_type *const mat2x3_type;
+ static const glsl_type *const mat2x4_type;
+ static const glsl_type *const mat3x2_type;
+ static const glsl_type *const mat3_type;
+ static const glsl_type *const mat3x4_type;
+ static const glsl_type *const mat4x2_type;
+ static const glsl_type *const mat4x3_type;
+ static const glsl_type *const mat4_type;
+ /*@}*/
+
+
+ /**
+ * For numeric and boolean derrived types returns the basic scalar type
+ *
+ * If the type is a numeric or boolean scalar, vector, or matrix type,
+ * this function gets the scalar type of the individual components. For
+ * all other types, including arrays of numeric or boolean types, the
+ * error type is returned.
+ */
+ const glsl_type *get_base_type() const;
+
+ /**
+ * Query the type of elements in an array
+ *
+ * \return
+ * Pointer to the type of elements in the array for array types, or \c NULL
+ * for non-array types.
+ */
+ const glsl_type *element_type() const
+ {
+ return is_array() ? fields.array : NULL;
+ }
+
+ /**
+ * Get the instance of a built-in scalar, vector, or matrix type
+ */
+ static const glsl_type *get_instance(unsigned base_type, unsigned rows,
+ unsigned columns);
+
+ /**
+ * Get the instance of an array type
+ */
+ static const glsl_type *get_array_instance(const glsl_type *base,
+ unsigned elements);
+
+ /**
+ * Get the instance of a record type
+ */
+ static const glsl_type *get_record_instance(const glsl_struct_field *fields,
+ unsigned num_fields,
+ const char *name);
+ /**
+ * Generate the constructor for this type and add it to the symbol table
+ */
+ class ir_function *generate_constructor(class glsl_symbol_table *) const;
+
+ /**
+ * Query the total number of scalars that make up a scalar, vector or matrix
+ */
+ unsigned components() const
+ {
+ return vector_elements * matrix_columns;
+ }
+
+ /**
+ * Calculate the number of components slots required to hold this type
+ *
+ * This is used to determine how many uniform or varying locations a type
+ * might occupy.
+ */
+ unsigned component_slots() const;
+
+
+ /**
+ * Query whether or not a type is a scalar (non-vector and non-matrix).
+ */
+ bool is_scalar() const
+ {
+ return (vector_elements == 1)
+ && (base_type >= GLSL_TYPE_UINT)
+ && (base_type <= GLSL_TYPE_BOOL);
+ }
+
+ /**
+ * Query whether or not a type is a vector
+ */
+ bool is_vector() const
+ {
+ return (vector_elements > 1)
+ && (matrix_columns == 1)
+ && (base_type >= GLSL_TYPE_UINT)
+ && (base_type <= GLSL_TYPE_BOOL);
+ }
+
+ /**
+ * Query whether or not a type is a matrix
+ */
+ bool is_matrix() const
+ {
+ /* GLSL only has float matrices. */
+ return (matrix_columns > 1) && (base_type == GLSL_TYPE_FLOAT);
+ }
+
+ /**
+ * Query whether or not a type is a non-array numeric type
+ */
+ bool is_numeric() const
+ {
+ return (base_type >= GLSL_TYPE_UINT) && (base_type <= GLSL_TYPE_FLOAT);
+ }
+
+ /**
+ * Query whether or not a type is an integral type
+ */
+ bool is_integer() const
+ {
+ return (base_type == GLSL_TYPE_UINT) || (base_type == GLSL_TYPE_INT);
+ }
+
+ /**
+ * Query whether or not a type is a float type
+ */
+ bool is_float() const
+ {
+ return base_type == GLSL_TYPE_FLOAT;
+ }
+
+ /**
+ * Query whether or not a type is a non-array boolean type
+ */
+ bool is_boolean() const
+ {
+ return base_type == GLSL_TYPE_BOOL;
+ }
+
+ /**
+ * Query whether or not a type is a sampler
+ */
+ bool is_sampler() const
+ {
+ return base_type == GLSL_TYPE_SAMPLER;
+ }
+
+ /**
+ * Query whether or not a type is an array
+ */
+ bool is_array() const
+ {
+ return base_type == GLSL_TYPE_ARRAY;
+ }
+
+ /**
+ * Query whether or not a type is a record
+ */
+ bool is_record() const
+ {
+ return base_type == GLSL_TYPE_STRUCT;
+ }
+
+ /**
+ * Query whether or not a type is the void type singleton.
+ */
+ bool is_void() const
+ {
+ return base_type == GLSL_TYPE_VOID;
+ }
+
+ /**
+ * Query whether or not a type is the error type singleton.
+ */
+ bool is_error() const
+ {
+ return base_type == GLSL_TYPE_ERROR;
+ }
+
+ /**
+ * Query the full type of a matrix row
+ *
+ * \return
+ * If the type is not a matrix, \c glsl_type::error_type is returned.
+ * Otherwise a type matching the rows of the matrix is returned.
+ */
+ const glsl_type *row_type() const
+ {
+ return is_matrix()
+ ? get_instance(base_type, matrix_columns, 1)
+ : error_type;
+ }
+
+ /**
+ * Query the full type of a matrix column
+ *
+ * \return
+ * If the type is not a matrix, \c glsl_type::error_type is returned.
+ * Otherwise a type matching the columns of the matrix is returned.
+ */
+ const glsl_type *column_type() const
+ {
+ return is_matrix()
+ ? get_instance(base_type, vector_elements, 1)
+ : error_type;
+ }
+
+
+ /**
+ * Get the type of a structure field
+ *
+ * \return
+ * Pointer to the type of the named field. If the type is not a structure
+ * or the named field does not exist, \c glsl_type::error_type is returned.
+ */
+ const glsl_type *field_type(const char *name) const;
+
+
+ /**
+ * Get the location of a filed within a record type
+ */
+ int field_index(const char *name) const;
+
+
+ /**
+ * Query the number of elements in an array type
+ *
+ * \return
+ * The number of elements in the array for array types or -1 for non-array
+ * types. If the number of elements in the array has not yet been declared,
+ * zero is returned.
+ */
+ int array_size() const
+ {
+ return is_array() ? length : -1;
+ }
+
+private:
+ /**
+ * talloc context for all glsl_type allocations
+ *
+ * Set on the first call to \c glsl_type::new.
+ */
+ static void *mem_ctx;
+
+ void init_talloc_type_ctx(void);
+
+ /** Constructor for vector and matrix types */
+ glsl_type(GLenum gl_type,
+ unsigned base_type, unsigned vector_elements,
+ unsigned matrix_columns, const char *name);
+
+ /** Constructor for sampler types */
+ glsl_type(GLenum gl_type,
+ enum glsl_sampler_dim dim, bool shadow, bool array,
+ unsigned type, const char *name);
+
+ /** Constructor for record types */
+ glsl_type(const glsl_struct_field *fields, unsigned num_fields,
+ const char *name);
+
+ /** Constructor for array types */
+ glsl_type(const glsl_type *array, unsigned length);
+
+ /** Hash table containing the known array types. */
+ static struct hash_table *array_types;
+
+ /** Hash table containing the known record types. */
+ static struct hash_table *record_types;
+
+ static int record_key_compare(const void *a, const void *b);
+ static unsigned record_key_hash(const void *key);
+
+ /**
+ * \name Pointers to various type singletons
+ */
+ /*@{*/
+ static const glsl_type _error_type;
+ static const glsl_type void_type;
+ static const glsl_type builtin_core_types[];
+ static const glsl_type builtin_structure_types[];
+ static const glsl_type builtin_110_deprecated_structure_types[];
+ static const glsl_type builtin_120_types[];
+ static const glsl_type builtin_130_types[];
+ static const glsl_type builtin_ARB_texture_rectangle_types[];
+ static const glsl_type builtin_EXT_texture_array_types[];
+ static const glsl_type builtin_EXT_texture_buffer_object_types[];
+ /*@}*/
+
+ /**
+ * \name Methods to populate a symbol table with built-in types.
+ *
+ * \internal
+ * This is one of the truely annoying things about C++. Methods that are
+ * completely internal and private to a type still have to be advertised to
+ * the world in a public header file.
+ */
+ /*@{*/
+ static void generate_110_types(class glsl_symbol_table *);
+ static void generate_120_types(class glsl_symbol_table *);
+ static void generate_130_types(class glsl_symbol_table *);
+ static void generate_ARB_texture_rectangle_types(class glsl_symbol_table *,
+ bool);
+ static void generate_EXT_texture_array_types(class glsl_symbol_table *,
+ bool);
+ /*@}*/
+
+ /**
+ * \name Friend functions.
+ *
+ * These functions are friends because they must have C linkage and the
+ * need to call various private methods or access various private static
+ * data.
+ */
+ /*@{*/
+ friend void _mesa_glsl_initialize_types(struct _mesa_glsl_parse_state *);
+ friend void _mesa_glsl_release_types(void);
+ /*@}*/
+};
+
+struct glsl_struct_field {
+ const struct glsl_type *type;
+ const char *name;
+};
+
+#endif /* GLSL_TYPES_H */
diff --git a/src/glsl/hir_field_selection.cpp b/src/glsl/hir_field_selection.cpp
new file mode 100644
index 00000000000..23045ff1827
--- /dev/null
+++ b/src/glsl/hir_field_selection.cpp
@@ -0,0 +1,103 @@
+/*
+ * Copyright © 2010 Intel Corporation
+ *
+ * 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 (including the next
+ * paragraph) 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
+ * THE AUTHORS OR COPYRIGHT HOLDERS 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.
+ */
+
+#include "ir.h"
+#include "main/imports.h"
+#include "program/symbol_table.h"
+#include "glsl_parser_extras.h"
+#include "ast.h"
+#include "glsl_types.h"
+
+ir_rvalue *
+_mesa_ast_field_selection_to_hir(const ast_expression *expr,
+ exec_list *instructions,
+ struct _mesa_glsl_parse_state *state)
+{
+ void *ctx = state;
+ ir_rvalue *result = NULL;
+ ir_rvalue *op;
+
+ op = expr->subexpressions[0]->hir(instructions, state);
+
+ /* There are two kinds of field selection. There is the selection of a
+ * specific field from a structure, and there is the selection of a
+ * swizzle / mask from a vector. Which is which is determined entirely
+ * by the base type of the thing to which the field selection operator is
+ * being applied.
+ */
+ YYLTYPE loc = expr->get_location();
+ if (op->type->is_error()) {
+ /* silently propagate the error */
+ } else if (op->type->is_vector()) {
+ ir_swizzle *swiz = ir_swizzle::create(op,
+ expr->primary_expression.identifier,
+ op->type->vector_elements);
+ if (swiz != NULL) {
+ result = swiz;
+ } else {
+ /* FINISHME: Logging of error messages should be moved into
+ * FINISHME: ir_swizzle::create. This allows the generation of more
+ * FINISHME: specific error messages.
+ */
+ _mesa_glsl_error(& loc, state, "Invalid swizzle / mask `%s'",
+ expr->primary_expression.identifier);
+ }
+ } else if (op->type->base_type == GLSL_TYPE_STRUCT) {
+ result = new(ctx) ir_dereference_record(op,
+ expr->primary_expression.identifier);
+
+ if (result->type->is_error()) {
+ _mesa_glsl_error(& loc, state, "Cannot access field `%s' of "
+ "structure",
+ expr->primary_expression.identifier);
+ }
+ } else if (expr->subexpressions[1] != NULL) {
+ /* Handle "method calls" in GLSL 1.20 - namely, array.length() */
+ if (state->language_version < 120)
+ _mesa_glsl_error(&loc, state, "Methods not supported in GLSL 1.10.");
+
+ ast_expression *call = expr->subexpressions[1];
+ assert(call->oper == ast_function_call);
+
+ const char *method;
+ method = call->subexpressions[0]->primary_expression.identifier;
+
+ if (op->type->is_array() && strcmp(method, "length") == 0) {
+ if (!call->expressions.is_empty())
+ _mesa_glsl_error(&loc, state, "length method takes no arguments.");
+
+ if (op->type->array_size() == 0)
+ _mesa_glsl_error(&loc, state, "length called on unsized array.");
+
+ result = new(ctx) ir_constant(op->type->array_size());
+ } else {
+ _mesa_glsl_error(&loc, state, "Unknown method: `%s'.", method);
+ }
+ } else {
+ _mesa_glsl_error(& loc, state, "Cannot access field `%s' of "
+ "non-structure / non-vector.",
+ expr->primary_expression.identifier);
+ }
+
+ return result ? result : ir_call::get_error_instruction(ctx);
+}
diff --git a/src/glsl/ir.cpp b/src/glsl/ir.cpp
new file mode 100644
index 00000000000..dd059e470d5
--- /dev/null
+++ b/src/glsl/ir.cpp
@@ -0,0 +1,1062 @@
+/*
+ * Copyright © 2010 Intel Corporation
+ *
+ * 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 (including the next
+ * paragraph) 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
+ * THE AUTHORS OR COPYRIGHT HOLDERS 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.
+ */
+#include <string.h>
+#include "main/imports.h"
+#include "main/macros.h"
+#include "ir.h"
+#include "ir_visitor.h"
+#include "glsl_types.h"
+
+ir_rvalue::ir_rvalue()
+{
+ this->type = glsl_type::error_type;
+}
+
+/**
+ * Modify the swizzle make to move one component to another
+ *
+ * \param m IR swizzle to be modified
+ * \param from Component in the RHS that is to be swizzled
+ * \param to Desired swizzle location of \c from
+ */
+static void
+update_rhs_swizzle(ir_swizzle_mask &m, unsigned from, unsigned to)
+{
+ switch (to) {
+ case 0: m.x = from; break;
+ case 1: m.y = from; break;
+ case 2: m.z = from; break;
+ case 3: m.w = from; break;
+ default: assert(!"Should not get here.");
+ }
+
+ m.num_components = MAX2(m.num_components, (to + 1));
+}
+
+void
+ir_assignment::set_lhs(ir_rvalue *lhs)
+{
+ while (lhs != NULL) {
+ ir_swizzle *swiz = lhs->as_swizzle();
+
+ if (swiz == NULL)
+ break;
+
+ unsigned write_mask = 0;
+ ir_swizzle_mask rhs_swiz = { 0, 0, 0, 0, 0, 0 };
+
+ for (unsigned i = 0; i < swiz->mask.num_components; i++) {
+ unsigned c = 0;
+
+ switch (i) {
+ case 0: c = swiz->mask.x; break;
+ case 1: c = swiz->mask.y; break;
+ case 2: c = swiz->mask.z; break;
+ case 3: c = swiz->mask.w; break;
+ default: assert(!"Should not get here.");
+ }
+
+ write_mask |= (((this->write_mask >> i) & 1) << c);
+ update_rhs_swizzle(rhs_swiz, i, c);
+ }
+
+ this->write_mask = write_mask;
+ lhs = swiz->val;
+
+ this->rhs = new(this) ir_swizzle(this->rhs, rhs_swiz);
+ }
+
+ assert((lhs == NULL) || lhs->as_dereference());
+
+ this->lhs = (ir_dereference *) lhs;
+}
+
+ir_variable *
+ir_assignment::whole_variable_written()
+{
+ ir_variable *v = this->lhs->whole_variable_referenced();
+
+ if (v == NULL)
+ return NULL;
+
+ if (v->type->is_scalar())
+ return v;
+
+ if (v->type->is_vector()) {
+ const unsigned mask = (1U << v->type->vector_elements) - 1;
+
+ if (mask != this->write_mask)
+ return NULL;
+ }
+
+ /* Either all the vector components are assigned or the variable is some
+ * composite type (and the whole thing is assigned.
+ */
+ return v;
+}
+
+ir_assignment::ir_assignment(ir_dereference *lhs, ir_rvalue *rhs,
+ ir_rvalue *condition, unsigned write_mask)
+{
+ this->ir_type = ir_type_assignment;
+ this->condition = condition;
+ this->rhs = rhs;
+ this->lhs = lhs;
+ this->write_mask = write_mask;
+}
+
+ir_assignment::ir_assignment(ir_rvalue *lhs, ir_rvalue *rhs,
+ ir_rvalue *condition)
+{
+ this->ir_type = ir_type_assignment;
+ this->condition = condition;
+ this->rhs = rhs;
+
+ /* If the RHS is a vector type, assume that all components of the vector
+ * type are being written to the LHS. The write mask comes from the RHS
+ * because we can have a case where the LHS is a vec4 and the RHS is a
+ * vec3. In that case, the assignment is:
+ *
+ * (assign (...) (xyz) (var_ref lhs) (var_ref rhs))
+ */
+ if (rhs->type->is_vector())
+ this->write_mask = (1U << rhs->type->vector_elements) - 1;
+ else if (rhs->type->is_scalar())
+ this->write_mask = 1;
+ else
+ this->write_mask = 0;
+
+ this->set_lhs(lhs);
+}
+
+
+ir_expression::ir_expression(int op, const struct glsl_type *type,
+ ir_rvalue *op0, ir_rvalue *op1)
+{
+ this->ir_type = ir_type_expression;
+ this->type = type;
+ this->operation = ir_expression_operation(op);
+ this->operands[0] = op0;
+ this->operands[1] = op1;
+}
+
+unsigned int
+ir_expression::get_num_operands(ir_expression_operation op)
+{
+/* Update ir_print_visitor.cpp when updating this list. */
+ const int num_operands[] = {
+ 1, /* ir_unop_bit_not */
+ 1, /* ir_unop_logic_not */
+ 1, /* ir_unop_neg */
+ 1, /* ir_unop_abs */
+ 1, /* ir_unop_sign */
+ 1, /* ir_unop_rcp */
+ 1, /* ir_unop_rsq */
+ 1, /* ir_unop_sqrt */
+ 1, /* ir_unop_exp */
+ 1, /* ir_unop_log */
+ 1, /* ir_unop_exp2 */
+ 1, /* ir_unop_log2 */
+ 1, /* ir_unop_f2i */
+ 1, /* ir_unop_i2f */
+ 1, /* ir_unop_f2b */
+ 1, /* ir_unop_b2f */
+ 1, /* ir_unop_i2b */
+ 1, /* ir_unop_b2i */
+ 1, /* ir_unop_u2f */
+
+ 1, /* ir_unop_trunc */
+ 1, /* ir_unop_ceil */
+ 1, /* ir_unop_floor */
+ 1, /* ir_unop_fract */
+
+ 1, /* ir_unop_sin */
+ 1, /* ir_unop_cos */
+
+ 1, /* ir_unop_dFdx */
+ 1, /* ir_unop_dFdy */
+
+ 2, /* ir_binop_add */
+ 2, /* ir_binop_sub */
+ 2, /* ir_binop_mul */
+ 2, /* ir_binop_div */
+ 2, /* ir_binop_mod */
+
+ 2, /* ir_binop_less */
+ 2, /* ir_binop_greater */
+ 2, /* ir_binop_lequal */
+ 2, /* ir_binop_gequal */
+ 2, /* ir_binop_equal */
+ 2, /* ir_binop_nequal */
+
+ 2, /* ir_binop_lshift */
+ 2, /* ir_binop_rshift */
+ 2, /* ir_binop_bit_and */
+ 2, /* ir_binop_bit_xor */
+ 2, /* ir_binop_bit_or */
+
+ 2, /* ir_binop_logic_and */
+ 2, /* ir_binop_logic_xor */
+ 2, /* ir_binop_logic_or */
+
+ 2, /* ir_binop_dot */
+ 2, /* ir_binop_cross */
+ 2, /* ir_binop_min */
+ 2, /* ir_binop_max */
+
+ 2, /* ir_binop_pow */
+ };
+
+ assert(sizeof(num_operands) / sizeof(num_operands[0]) == ir_binop_pow + 1);
+
+ return num_operands[op];
+}
+
+static const char *const operator_strs[] = {
+ "~",
+ "!",
+ "neg",
+ "abs",
+ "sign",
+ "rcp",
+ "rsq",
+ "sqrt",
+ "exp",
+ "log",
+ "exp2",
+ "log2",
+ "f2i",
+ "i2f",
+ "f2b",
+ "b2f",
+ "i2b",
+ "b2i",
+ "u2f",
+ "trunc",
+ "ceil",
+ "floor",
+ "fract",
+ "sin",
+ "cos",
+ "dFdx",
+ "dFdy",
+ "+",
+ "-",
+ "*",
+ "/",
+ "%",
+ "<",
+ ">",
+ "<=",
+ ">=",
+ "==",
+ "!=",
+ "<<",
+ ">>",
+ "&",
+ "^",
+ "|",
+ "&&",
+ "^^",
+ "||",
+ "dot",
+ "cross",
+ "min",
+ "max",
+ "pow",
+};
+
+const char *ir_expression::operator_string()
+{
+ assert((unsigned int) operation <=
+ sizeof(operator_strs) / sizeof(operator_strs[0]));
+ return operator_strs[operation];
+}
+
+ir_expression_operation
+ir_expression::get_operator(const char *str)
+{
+ const int operator_count = sizeof(operator_strs) / sizeof(operator_strs[0]);
+ for (int op = 0; op < operator_count; op++) {
+ if (strcmp(str, operator_strs[op]) == 0)
+ return (ir_expression_operation) op;
+ }
+ return (ir_expression_operation) -1;
+}
+
+ir_constant::ir_constant()
+{
+ this->ir_type = ir_type_constant;
+}
+
+ir_constant::ir_constant(const struct glsl_type *type,
+ const ir_constant_data *data)
+{
+ assert((type->base_type >= GLSL_TYPE_UINT)
+ && (type->base_type <= GLSL_TYPE_BOOL));
+
+ this->ir_type = ir_type_constant;
+ this->type = type;
+ memcpy(& this->value, data, sizeof(this->value));
+}
+
+ir_constant::ir_constant(float f)
+{
+ this->ir_type = ir_type_constant;
+ this->type = glsl_type::float_type;
+ this->value.f[0] = f;
+}
+
+ir_constant::ir_constant(unsigned int u)
+{
+ this->ir_type = ir_type_constant;
+ this->type = glsl_type::uint_type;
+ this->value.u[0] = u;
+}
+
+ir_constant::ir_constant(int i)
+{
+ this->ir_type = ir_type_constant;
+ this->type = glsl_type::int_type;
+ this->value.i[0] = i;
+}
+
+ir_constant::ir_constant(bool b)
+{
+ this->ir_type = ir_type_constant;
+ this->type = glsl_type::bool_type;
+ this->value.b[0] = b;
+}
+
+ir_constant::ir_constant(const ir_constant *c, unsigned i)
+{
+ this->ir_type = ir_type_constant;
+ this->type = c->type->get_base_type();
+
+ switch (this->type->base_type) {
+ case GLSL_TYPE_UINT: this->value.u[0] = c->value.u[i]; break;
+ case GLSL_TYPE_INT: this->value.i[0] = c->value.i[i]; break;
+ case GLSL_TYPE_FLOAT: this->value.f[0] = c->value.f[i]; break;
+ case GLSL_TYPE_BOOL: this->value.b[0] = c->value.b[i]; break;
+ default: assert(!"Should not get here."); break;
+ }
+}
+
+ir_constant::ir_constant(const struct glsl_type *type, exec_list *value_list)
+{
+ this->ir_type = ir_type_constant;
+ this->type = type;
+
+ assert(type->is_scalar() || type->is_vector() || type->is_matrix()
+ || type->is_record() || type->is_array());
+
+ if (type->is_array()) {
+ this->array_elements = talloc_array(this, ir_constant *, type->length);
+ unsigned i = 0;
+ foreach_list(node, value_list) {
+ ir_constant *value = (ir_constant *) node;
+ assert(value->as_constant() != NULL);
+
+ this->array_elements[i++] = value;
+ }
+ return;
+ }
+
+ /* If the constant is a record, the types of each of the entries in
+ * value_list must be a 1-for-1 match with the structure components. Each
+ * entry must also be a constant. Just move the nodes from the value_list
+ * to the list in the ir_constant.
+ */
+ /* FINISHME: Should there be some type checking and / or assertions here? */
+ /* FINISHME: Should the new constant take ownership of the nodes from
+ * FINISHME: value_list, or should it make copies?
+ */
+ if (type->is_record()) {
+ value_list->move_nodes_to(& this->components);
+ return;
+ }
+
+
+ ir_constant *value = (ir_constant *) (value_list->head);
+
+ /* Use each component from each entry in the value_list to initialize one
+ * component of the constant being constructed.
+ */
+ for (unsigned i = 0; i < type->components(); /* empty */) {
+ assert(value->as_constant() != NULL);
+ assert(!value->is_tail_sentinel());
+
+ for (unsigned j = 0; j < value->type->components(); j++) {
+ switch (type->base_type) {
+ case GLSL_TYPE_UINT:
+ this->value.u[i] = value->get_uint_component(j);
+ break;
+ case GLSL_TYPE_INT:
+ this->value.i[i] = value->get_int_component(j);
+ break;
+ case GLSL_TYPE_FLOAT:
+ this->value.f[i] = value->get_float_component(j);
+ break;
+ case GLSL_TYPE_BOOL:
+ this->value.b[i] = value->get_bool_component(j);
+ break;
+ default:
+ /* FINISHME: What to do? Exceptions are not the answer.
+ */
+ break;
+ }
+
+ i++;
+ if (i >= type->components())
+ break;
+ }
+
+ value = (ir_constant *) value->next;
+ }
+}
+
+ir_constant *
+ir_constant::zero(void *mem_ctx, const glsl_type *type)
+{
+ assert(type->is_numeric());
+
+ ir_constant *c = new(mem_ctx) ir_constant;
+ c->type = type;
+ memset(&c->value, 0, sizeof(c->value));
+
+ return c;
+}
+
+bool
+ir_constant::get_bool_component(unsigned i) const
+{
+ switch (this->type->base_type) {
+ case GLSL_TYPE_UINT: return this->value.u[i] != 0;
+ case GLSL_TYPE_INT: return this->value.i[i] != 0;
+ case GLSL_TYPE_FLOAT: return ((int)this->value.f[i]) != 0;
+ case GLSL_TYPE_BOOL: return this->value.b[i];
+ default: assert(!"Should not get here."); break;
+ }
+
+ /* Must return something to make the compiler happy. This is clearly an
+ * error case.
+ */
+ return false;
+}
+
+float
+ir_constant::get_float_component(unsigned i) const
+{
+ switch (this->type->base_type) {
+ case GLSL_TYPE_UINT: return (float) this->value.u[i];
+ case GLSL_TYPE_INT: return (float) this->value.i[i];
+ case GLSL_TYPE_FLOAT: return this->value.f[i];
+ case GLSL_TYPE_BOOL: return this->value.b[i] ? 1.0 : 0.0;
+ default: assert(!"Should not get here."); break;
+ }
+
+ /* Must return something to make the compiler happy. This is clearly an
+ * error case.
+ */
+ return 0.0;
+}
+
+int
+ir_constant::get_int_component(unsigned i) const
+{
+ switch (this->type->base_type) {
+ case GLSL_TYPE_UINT: return this->value.u[i];
+ case GLSL_TYPE_INT: return this->value.i[i];
+ case GLSL_TYPE_FLOAT: return (int) this->value.f[i];
+ case GLSL_TYPE_BOOL: return this->value.b[i] ? 1 : 0;
+ default: assert(!"Should not get here."); break;
+ }
+
+ /* Must return something to make the compiler happy. This is clearly an
+ * error case.
+ */
+ return 0;
+}
+
+unsigned
+ir_constant::get_uint_component(unsigned i) const
+{
+ switch (this->type->base_type) {
+ case GLSL_TYPE_UINT: return this->value.u[i];
+ case GLSL_TYPE_INT: return this->value.i[i];
+ case GLSL_TYPE_FLOAT: return (unsigned) this->value.f[i];
+ case GLSL_TYPE_BOOL: return this->value.b[i] ? 1 : 0;
+ default: assert(!"Should not get here."); break;
+ }
+
+ /* Must return something to make the compiler happy. This is clearly an
+ * error case.
+ */
+ return 0;
+}
+
+ir_constant *
+ir_constant::get_array_element(unsigned i) const
+{
+ assert(this->type->is_array());
+ assert(i < this->type->length);
+
+ return array_elements[i];
+}
+
+ir_constant *
+ir_constant::get_record_field(const char *name)
+{
+ int idx = this->type->field_index(name);
+
+ if (idx < 0)
+ return NULL;
+
+ if (this->components.is_empty())
+ return NULL;
+
+ exec_node *node = this->components.head;
+ for (int i = 0; i < idx; i++) {
+ node = node->next;
+
+ /* If the end of the list is encountered before the element matching the
+ * requested field is found, return NULL.
+ */
+ if (node->is_tail_sentinel())
+ return NULL;
+ }
+
+ return (ir_constant *) node;
+}
+
+
+bool
+ir_constant::has_value(const ir_constant *c) const
+{
+ if (this->type != c->type)
+ return false;
+
+ if (this->type->is_array()) {
+ for (unsigned i = 0; i < this->type->length; i++) {
+ if (this->array_elements[i]->has_value(c->array_elements[i]))
+ return false;
+ }
+ return true;
+ }
+
+ if (this->type->base_type == GLSL_TYPE_STRUCT) {
+ const exec_node *a_node = this->components.head;
+ const exec_node *b_node = c->components.head;
+
+ while (!a_node->is_tail_sentinel()) {
+ assert(!b_node->is_tail_sentinel());
+
+ const ir_constant *const a_field = (ir_constant *) a_node;
+ const ir_constant *const b_field = (ir_constant *) b_node;
+
+ if (!a_field->has_value(b_field))
+ return false;
+
+ a_node = a_node->next;
+ b_node = b_node->next;
+ }
+
+ return true;
+ }
+
+ for (unsigned i = 0; i < this->type->components(); i++) {
+ switch (this->type->base_type) {
+ case GLSL_TYPE_UINT:
+ if (this->value.u[i] != c->value.u[i])
+ return false;
+ break;
+ case GLSL_TYPE_INT:
+ if (this->value.i[i] != c->value.i[i])
+ return false;
+ break;
+ case GLSL_TYPE_FLOAT:
+ if (this->value.f[i] != c->value.f[i])
+ return false;
+ break;
+ case GLSL_TYPE_BOOL:
+ if (this->value.b[i] != c->value.b[i])
+ return false;
+ break;
+ default:
+ assert(!"Should not get here.");
+ return false;
+ }
+ }
+
+ return true;
+}
+
+ir_dereference_variable::ir_dereference_variable(ir_variable *var)
+{
+ this->ir_type = ir_type_dereference_variable;
+ this->var = var;
+ this->type = (var != NULL) ? var->type : glsl_type::error_type;
+}
+
+
+ir_dereference_array::ir_dereference_array(ir_rvalue *value,
+ ir_rvalue *array_index)
+{
+ this->ir_type = ir_type_dereference_array;
+ this->array_index = array_index;
+ this->set_array(value);
+}
+
+
+ir_dereference_array::ir_dereference_array(ir_variable *var,
+ ir_rvalue *array_index)
+{
+ void *ctx = talloc_parent(var);
+
+ this->ir_type = ir_type_dereference_array;
+ this->array_index = array_index;
+ this->set_array(new(ctx) ir_dereference_variable(var));
+}
+
+
+void
+ir_dereference_array::set_array(ir_rvalue *value)
+{
+ this->array = value;
+ this->type = glsl_type::error_type;
+
+ if (this->array != NULL) {
+ const glsl_type *const vt = this->array->type;
+
+ if (vt->is_array()) {
+ type = vt->element_type();
+ } else if (vt->is_matrix()) {
+ type = vt->column_type();
+ } else if (vt->is_vector()) {
+ type = vt->get_base_type();
+ }
+ }
+}
+
+
+ir_dereference_record::ir_dereference_record(ir_rvalue *value,
+ const char *field)
+{
+ this->ir_type = ir_type_dereference_record;
+ this->record = value;
+ this->field = talloc_strdup(this, field);
+ this->type = (this->record != NULL)
+ ? this->record->type->field_type(field) : glsl_type::error_type;
+}
+
+
+ir_dereference_record::ir_dereference_record(ir_variable *var,
+ const char *field)
+{
+ void *ctx = talloc_parent(var);
+
+ this->ir_type = ir_type_dereference_record;
+ this->record = new(ctx) ir_dereference_variable(var);
+ this->field = talloc_strdup(this, field);
+ this->type = (this->record != NULL)
+ ? this->record->type->field_type(field) : glsl_type::error_type;
+}
+
+
+bool
+ir_dereference::is_lvalue()
+{
+ ir_variable *var = this->variable_referenced();
+
+ /* Every l-value derference chain eventually ends in a variable.
+ */
+ if ((var == NULL) || var->read_only)
+ return false;
+
+ if (this->type->is_array() && !var->array_lvalue)
+ return false;
+
+ return true;
+}
+
+
+const char *tex_opcode_strs[] = { "tex", "txb", "txl", "txd", "txf" };
+
+const char *ir_texture::opcode_string()
+{
+ assert((unsigned int) op <=
+ sizeof(tex_opcode_strs) / sizeof(tex_opcode_strs[0]));
+ return tex_opcode_strs[op];
+}
+
+ir_texture_opcode
+ir_texture::get_opcode(const char *str)
+{
+ const int count = sizeof(tex_opcode_strs) / sizeof(tex_opcode_strs[0]);
+ for (int op = 0; op < count; op++) {
+ if (strcmp(str, tex_opcode_strs[op]) == 0)
+ return (ir_texture_opcode) op;
+ }
+ return (ir_texture_opcode) -1;
+}
+
+
+void
+ir_texture::set_sampler(ir_dereference *sampler)
+{
+ assert(sampler != NULL);
+ this->sampler = sampler;
+
+ switch (sampler->type->sampler_type) {
+ case GLSL_TYPE_FLOAT:
+ this->type = glsl_type::vec4_type;
+ break;
+ case GLSL_TYPE_INT:
+ this->type = glsl_type::ivec4_type;
+ break;
+ case GLSL_TYPE_UINT:
+ this->type = glsl_type::uvec4_type;
+ break;
+ }
+}
+
+
+void
+ir_swizzle::init_mask(const unsigned *comp, unsigned count)
+{
+ assert((count >= 1) && (count <= 4));
+
+ memset(&this->mask, 0, sizeof(this->mask));
+ this->mask.num_components = count;
+
+ unsigned dup_mask = 0;
+ switch (count) {
+ case 4:
+ assert(comp[3] <= 3);
+ dup_mask |= (1U << comp[3])
+ & ((1U << comp[0]) | (1U << comp[1]) | (1U << comp[2]));
+ this->mask.w = comp[3];
+
+ case 3:
+ assert(comp[2] <= 3);
+ dup_mask |= (1U << comp[2])
+ & ((1U << comp[0]) | (1U << comp[1]));
+ this->mask.z = comp[2];
+
+ case 2:
+ assert(comp[1] <= 3);
+ dup_mask |= (1U << comp[1])
+ & ((1U << comp[0]));
+ this->mask.y = comp[1];
+
+ case 1:
+ assert(comp[0] <= 3);
+ this->mask.x = comp[0];
+ }
+
+ this->mask.has_duplicates = dup_mask != 0;
+
+ /* Based on the number of elements in the swizzle and the base type
+ * (i.e., float, int, unsigned, or bool) of the vector being swizzled,
+ * generate the type of the resulting value.
+ */
+ type = glsl_type::get_instance(val->type->base_type, mask.num_components, 1);
+}
+
+ir_swizzle::ir_swizzle(ir_rvalue *val, unsigned x, unsigned y, unsigned z,
+ unsigned w, unsigned count)
+ : val(val)
+{
+ const unsigned components[4] = { x, y, z, w };
+ this->ir_type = ir_type_swizzle;
+ this->init_mask(components, count);
+}
+
+ir_swizzle::ir_swizzle(ir_rvalue *val, const unsigned *comp,
+ unsigned count)
+ : val(val)
+{
+ this->ir_type = ir_type_swizzle;
+ this->init_mask(comp, count);
+}
+
+ir_swizzle::ir_swizzle(ir_rvalue *val, ir_swizzle_mask mask)
+{
+ this->ir_type = ir_type_swizzle;
+ this->val = val;
+ this->mask = mask;
+ this->type = glsl_type::get_instance(val->type->base_type,
+ mask.num_components, 1);
+}
+
+#define X 1
+#define R 5
+#define S 9
+#define I 13
+
+ir_swizzle *
+ir_swizzle::create(ir_rvalue *val, const char *str, unsigned vector_length)
+{
+ void *ctx = talloc_parent(val);
+
+ /* For each possible swizzle character, this table encodes the value in
+ * \c idx_map that represents the 0th element of the vector. For invalid
+ * swizzle characters (e.g., 'k'), a special value is used that will allow
+ * detection of errors.
+ */
+ static const unsigned char base_idx[26] = {
+ /* a b c d e f g h i j k l m */
+ R, R, I, I, I, I, R, I, I, I, I, I, I,
+ /* n o p q r s t u v w x y z */
+ I, I, S, S, R, S, S, I, I, X, X, X, X
+ };
+
+ /* Each valid swizzle character has an entry in the previous table. This
+ * table encodes the base index encoded in the previous table plus the actual
+ * index of the swizzle character. When processing swizzles, the first
+ * character in the string is indexed in the previous table. Each character
+ * in the string is indexed in this table, and the value found there has the
+ * value form the first table subtracted. The result must be on the range
+ * [0,3].
+ *
+ * For example, the string "wzyx" will get X from the first table. Each of
+ * the charcaters will get X+3, X+2, X+1, and X+0 from this table. After
+ * subtraction, the swizzle values are { 3, 2, 1, 0 }.
+ *
+ * The string "wzrg" will get X from the first table. Each of the characters
+ * will get X+3, X+2, R+0, and R+1 from this table. After subtraction, the
+ * swizzle values are { 3, 2, 4, 5 }. Since 4 and 5 are outside the range
+ * [0,3], the error is detected.
+ */
+ static const unsigned char idx_map[26] = {
+ /* a b c d e f g h i j k l m */
+ R+3, R+2, 0, 0, 0, 0, R+1, 0, 0, 0, 0, 0, 0,
+ /* n o p q r s t u v w x y z */
+ 0, 0, S+2, S+3, R+0, S+0, S+1, 0, 0, X+3, X+0, X+1, X+2
+ };
+
+ int swiz_idx[4] = { 0, 0, 0, 0 };
+ unsigned i;
+
+
+ /* Validate the first character in the swizzle string and look up the base
+ * index value as described above.
+ */
+ if ((str[0] < 'a') || (str[0] > 'z'))
+ return NULL;
+
+ const unsigned base = base_idx[str[0] - 'a'];
+
+
+ for (i = 0; (i < 4) && (str[i] != '\0'); i++) {
+ /* Validate the next character, and, as described above, convert it to a
+ * swizzle index.
+ */
+ if ((str[i] < 'a') || (str[i] > 'z'))
+ return NULL;
+
+ swiz_idx[i] = idx_map[str[i] - 'a'] - base;
+ if ((swiz_idx[i] < 0) || (swiz_idx[i] >= (int) vector_length))
+ return NULL;
+ }
+
+ if (str[i] != '\0')
+ return NULL;
+
+ return new(ctx) ir_swizzle(val, swiz_idx[0], swiz_idx[1], swiz_idx[2],
+ swiz_idx[3], i);
+}
+
+#undef X
+#undef R
+#undef S
+#undef I
+
+ir_variable *
+ir_swizzle::variable_referenced()
+{
+ return this->val->variable_referenced();
+}
+
+
+ir_variable::ir_variable(const struct glsl_type *type, const char *name,
+ ir_variable_mode mode)
+ : max_array_access(0), read_only(false), centroid(false), invariant(false),
+ mode(mode), interpolation(ir_var_smooth), array_lvalue(false)
+{
+ this->ir_type = ir_type_variable;
+ this->type = type;
+ this->name = talloc_strdup(this, name);
+ this->location = -1;
+ this->warn_extension = NULL;
+ this->constant_value = NULL;
+ this->origin_upper_left = false;
+ this->pixel_center_integer = false;
+
+ if (type && type->base_type == GLSL_TYPE_SAMPLER)
+ this->read_only = true;
+}
+
+
+const char *
+ir_variable::interpolation_string() const
+{
+ switch (this->interpolation) {
+ case ir_var_smooth: return "smooth";
+ case ir_var_flat: return "flat";
+ case ir_var_noperspective: return "noperspective";
+ }
+
+ assert(!"Should not get here.");
+ return "";
+}
+
+
+unsigned
+ir_variable::component_slots() const
+{
+ /* FINISHME: Sparsely accessed arrays require fewer slots. */
+ return this->type->component_slots();
+}
+
+
+ir_function_signature::ir_function_signature(const glsl_type *return_type)
+ : return_type(return_type), is_defined(false), _function(NULL)
+{
+ this->ir_type = ir_type_function_signature;
+ this->is_built_in = false;
+}
+
+
+const char *
+ir_function_signature::qualifiers_match(exec_list *params)
+{
+ exec_list_iterator iter_a = parameters.iterator();
+ exec_list_iterator iter_b = params->iterator();
+
+ /* check that the qualifiers match. */
+ while (iter_a.has_next()) {
+ ir_variable *a = (ir_variable *)iter_a.get();
+ ir_variable *b = (ir_variable *)iter_b.get();
+
+ if (a->read_only != b->read_only ||
+ a->mode != b->mode ||
+ a->interpolation != b->interpolation ||
+ a->centroid != b->centroid) {
+
+ /* parameter a's qualifiers don't match */
+ return a->name;
+ }
+
+ iter_a.next();
+ iter_b.next();
+ }
+ return NULL;
+}
+
+
+void
+ir_function_signature::replace_parameters(exec_list *new_params)
+{
+ /* Destroy all of the previous parameter information. If the previous
+ * parameter information comes from the function prototype, it may either
+ * specify incorrect parameter names or not have names at all.
+ */
+ foreach_iter(exec_list_iterator, iter, parameters) {
+ assert(((ir_instruction *) iter.get())->as_variable() != NULL);
+
+ iter.remove();
+ }
+
+ new_params->move_nodes_to(&parameters);
+}
+
+
+ir_function::ir_function(const char *name)
+{
+ this->ir_type = ir_type_function;
+ this->name = talloc_strdup(this, name);
+}
+
+
+ir_call *
+ir_call::get_error_instruction(void *ctx)
+{
+ ir_call *call = new(ctx) ir_call;
+
+ call->type = glsl_type::error_type;
+ return call;
+}
+
+void
+ir_call::set_callee(ir_function_signature *sig)
+{
+ assert((this->type == NULL) || (this->type == sig->return_type));
+
+ this->callee = sig;
+}
+
+void
+visit_exec_list(exec_list *list, ir_visitor *visitor)
+{
+ foreach_iter(exec_list_iterator, iter, *list) {
+ ((ir_instruction *)iter.get())->accept(visitor);
+ }
+}
+
+
+static void
+steal_memory(ir_instruction *ir, void *new_ctx)
+{
+ ir_variable *var = ir->as_variable();
+ ir_constant *constant = ir->as_constant();
+ if (var != NULL && var->constant_value != NULL)
+ steal_memory(var->constant_value, ir);
+
+ /* The components of aggregate constants are not visited by the normal
+ * visitor, so steal their values by hand.
+ */
+ if (constant != NULL) {
+ if (constant->type->is_record()) {
+ foreach_iter(exec_list_iterator, iter, constant->components) {
+ ir_constant *field = (ir_constant *)iter.get();
+ steal_memory(field, ir);
+ }
+ } else if (constant->type->is_array()) {
+ for (unsigned int i = 0; i < constant->type->length; i++) {
+ steal_memory(constant->array_elements[i], ir);
+ }
+ }
+ }
+
+ talloc_steal(new_ctx, ir);
+}
+
+
+void
+reparent_ir(exec_list *list, void *mem_ctx)
+{
+ foreach_list(node, list) {
+ visit_tree((ir_instruction *) node, steal_memory, mem_ctx);
+ }
+}
diff --git a/src/glsl/ir.h b/src/glsl/ir.h
new file mode 100644
index 00000000000..eb9e6cdf0e2
--- /dev/null
+++ b/src/glsl/ir.h
@@ -0,0 +1,1398 @@
+/* -*- c++ -*- */
+/*
+ * Copyright © 2010 Intel Corporation
+ *
+ * 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 (including the next
+ * paragraph) 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
+ * THE AUTHORS OR COPYRIGHT HOLDERS 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.
+ */
+
+#pragma once
+#ifndef IR_H
+#define IR_H
+
+#include <cstdio>
+#include <cstdlib>
+
+extern "C" {
+#include <talloc.h>
+}
+
+#include "list.h"
+#include "ir_visitor.h"
+#include "ir_hierarchical_visitor.h"
+
+#ifndef ARRAY_SIZE
+#define ARRAY_SIZE(x) (sizeof(x) / sizeof(x[0]))
+#endif
+
+enum ir_node_type {
+ ir_type_unset,
+ ir_type_variable,
+ ir_type_assignment,
+ ir_type_call,
+ ir_type_constant,
+ ir_type_dereference_array,
+ ir_type_dereference_record,
+ ir_type_dereference_variable,
+ ir_type_discard,
+ ir_type_expression,
+ ir_type_function,
+ ir_type_function_signature,
+ ir_type_if,
+ ir_type_loop,
+ ir_type_loop_jump,
+ ir_type_return,
+ ir_type_swizzle,
+ ir_type_texture,
+ ir_type_max /**< maximum ir_type enum number, for validation */
+};
+
+/**
+ * Base class of all IR instructions
+ */
+class ir_instruction : public exec_node {
+public:
+ enum ir_node_type ir_type;
+ const struct glsl_type *type;
+
+ /** ir_print_visitor helper for debugging. */
+ void print(void) const;
+
+ virtual void accept(ir_visitor *) = 0;
+ virtual ir_visitor_status accept(ir_hierarchical_visitor *) = 0;
+ virtual ir_instruction *clone(void *mem_ctx,
+ struct hash_table *ht) const = 0;
+
+ /**
+ * \name IR instruction downcast functions
+ *
+ * These functions either cast the object to a derived class or return
+ * \c NULL if the object's type does not match the specified derived class.
+ * Additional downcast functions will be added as needed.
+ */
+ /*@{*/
+ virtual class ir_variable * as_variable() { return NULL; }
+ virtual class ir_function * as_function() { return NULL; }
+ virtual class ir_dereference * as_dereference() { return NULL; }
+ virtual class ir_dereference_array * as_dereference_array() { return NULL; }
+ virtual class ir_dereference_variable *as_dereference_variable() { return NULL; }
+ virtual class ir_expression * as_expression() { return NULL; }
+ virtual class ir_rvalue * as_rvalue() { return NULL; }
+ virtual class ir_loop * as_loop() { return NULL; }
+ virtual class ir_assignment * as_assignment() { return NULL; }
+ virtual class ir_call * as_call() { return NULL; }
+ virtual class ir_return * as_return() { return NULL; }
+ virtual class ir_if * as_if() { return NULL; }
+ virtual class ir_swizzle * as_swizzle() { return NULL; }
+ virtual class ir_constant * as_constant() { return NULL; }
+ /*@}*/
+
+protected:
+ ir_instruction()
+ {
+ ir_type = ir_type_unset;
+ type = NULL;
+ }
+};
+
+
+class ir_rvalue : public ir_instruction {
+public:
+ virtual ir_rvalue *clone(void *mem_ctx, struct hash_table *) const = 0;
+
+ virtual ir_constant *constant_expression_value() = 0;
+
+ virtual ir_rvalue * as_rvalue()
+ {
+ return this;
+ }
+
+ virtual bool is_lvalue()
+ {
+ return false;
+ }
+
+ /**
+ * Get the variable that is ultimately referenced by an r-value
+ */
+ virtual ir_variable *variable_referenced()
+ {
+ return NULL;
+ }
+
+
+ /**
+ * If an r-value is a reference to a whole variable, get that variable
+ *
+ * \return
+ * Pointer to a variable that is completely dereferenced by the r-value. If
+ * the r-value is not a dereference or the dereference does not access the
+ * entire variable (i.e., it's just one array element, struct field), \c NULL
+ * is returned.
+ */
+ virtual ir_variable *whole_variable_referenced()
+ {
+ return NULL;
+ }
+
+protected:
+ ir_rvalue();
+};
+
+
+enum ir_variable_mode {
+ ir_var_auto = 0,
+ ir_var_uniform,
+ ir_var_in,
+ ir_var_out,
+ ir_var_inout,
+ ir_var_temporary /**< Temporary variable generated during compilation. */
+};
+
+enum ir_variable_interpolation {
+ ir_var_smooth = 0,
+ ir_var_flat,
+ ir_var_noperspective
+};
+
+
+class ir_variable : public ir_instruction {
+public:
+ ir_variable(const struct glsl_type *, const char *, ir_variable_mode);
+
+ virtual ir_variable *clone(void *mem_ctx, struct hash_table *ht) const;
+
+ virtual ir_variable *as_variable()
+ {
+ return this;
+ }
+
+ virtual void accept(ir_visitor *v)
+ {
+ v->visit(this);
+ }
+
+ virtual ir_visitor_status accept(ir_hierarchical_visitor *);
+
+
+ /**
+ * Get the string value for the interpolation qualifier
+ *
+ * \return The string that would be used in a shader to specify \c
+ * mode will be returned.
+ *
+ * This function should only be used on a shader input or output variable.
+ */
+ const char *interpolation_string() const;
+
+ /**
+ * Calculate the number of slots required to hold this variable
+ *
+ * This is used to determine how many uniform or varying locations a variable
+ * occupies. The count is in units of floating point components.
+ */
+ unsigned component_slots() const;
+
+ const char *name;
+
+ /**
+ * Highest element accessed with a constant expression array index
+ *
+ * Not used for non-array variables.
+ */
+ unsigned max_array_access;
+
+ unsigned read_only:1;
+ unsigned centroid:1;
+ unsigned invariant:1;
+
+ unsigned mode:3;
+ unsigned interpolation:2;
+
+ /**
+ * Flag that the whole array is assignable
+ *
+ * In GLSL 1.20 and later whole arrays are assignable (and comparable for
+ * equality). This flag enables this behavior.
+ */
+ unsigned array_lvalue:1;
+
+ /* ARB_fragment_coord_conventions */
+ unsigned origin_upper_left:1;
+ unsigned pixel_center_integer:1;
+
+ /**
+ * Storage location of the base of this variable
+ *
+ * The precise meaning of this field depends on the nature of the variable.
+ *
+ * - Vertex shader input: one of the values from \c gl_vert_attrib.
+ * - Vertex shader output: one of the values from \c gl_vert_result.
+ * - Fragment shader input: one of the values from \c gl_frag_attrib.
+ * - Fragment shader output: one of the values from \c gl_frag_result.
+ * - Uniforms: Per-stage uniform slot number.
+ * - Other: This field is not currently used.
+ *
+ * If the variable is a uniform, shader input, or shader output, and the
+ * slot has not been assigned, the value will be -1.
+ */
+ int location;
+
+ /**
+ * Emit a warning if this variable is accessed.
+ */
+ const char *warn_extension;
+
+ /**
+ * Value assigned in the initializer of a variable declared "const"
+ */
+ ir_constant *constant_value;
+};
+
+
+/*@{*/
+/**
+ * The representation of a function instance; may be the full definition or
+ * simply a prototype.
+ */
+class ir_function_signature : public ir_instruction {
+ /* An ir_function_signature will be part of the list of signatures in
+ * an ir_function.
+ */
+public:
+ ir_function_signature(const glsl_type *return_type);
+
+ virtual ir_function_signature *clone(void *mem_ctx,
+ struct hash_table *ht) const;
+
+ virtual void accept(ir_visitor *v)
+ {
+ v->visit(this);
+ }
+
+ virtual ir_visitor_status accept(ir_hierarchical_visitor *);
+
+ /**
+ * Get the name of the function for which this is a signature
+ */
+ const char *function_name() const;
+
+ /**
+ * Get a handle to the function for which this is a signature
+ *
+ * There is no setter function, this function returns a \c const pointer,
+ * and \c ir_function_signature::_function is private for a reason. The
+ * only way to make a connection between a function and function signature
+ * is via \c ir_function::add_signature. This helps ensure that certain
+ * invariants (i.e., a function signature is in the list of signatures for
+ * its \c _function) are met.
+ *
+ * \sa ir_function::add_signature
+ */
+ inline const class ir_function *function() const
+ {
+ return this->_function;
+ }
+
+ /**
+ * Check whether the qualifiers match between this signature's parameters
+ * and the supplied parameter list. If not, returns the name of the first
+ * parameter with mismatched qualifiers (for use in error messages).
+ */
+ const char *qualifiers_match(exec_list *params);
+
+ /**
+ * Replace the current parameter list with the given one. This is useful
+ * if the current information came from a prototype, and either has invalid
+ * or missing parameter names.
+ */
+ void replace_parameters(exec_list *new_params);
+
+ /**
+ * Function return type.
+ *
+ * \note This discards the optional precision qualifier.
+ */
+ const struct glsl_type *return_type;
+
+ /**
+ * List of ir_variable of function parameters.
+ *
+ * This represents the storage. The paramaters passed in a particular
+ * call will be in ir_call::actual_paramaters.
+ */
+ struct exec_list parameters;
+
+ /** Whether or not this function has a body (which may be empty). */
+ unsigned is_defined:1;
+
+ /** Whether or not this function signature is a built-in. */
+ unsigned is_built_in:1;
+
+ /** Body of instructions in the function. */
+ struct exec_list body;
+
+private:
+ /** Function of which this signature is one overload. */
+ class ir_function *_function;
+
+ friend class ir_function;
+};
+
+
+/**
+ * Header for tracking multiple overloaded functions with the same name.
+ * Contains a list of ir_function_signatures representing each of the
+ * actual functions.
+ */
+class ir_function : public ir_instruction {
+public:
+ ir_function(const char *name);
+
+ virtual ir_function *clone(void *mem_ctx, struct hash_table *ht) const;
+
+ virtual ir_function *as_function()
+ {
+ return this;
+ }
+
+ virtual void accept(ir_visitor *v)
+ {
+ v->visit(this);
+ }
+
+ virtual ir_visitor_status accept(ir_hierarchical_visitor *);
+
+ void add_signature(ir_function_signature *sig)
+ {
+ sig->_function = this;
+ this->signatures.push_tail(sig);
+ }
+
+ /**
+ * Get an iterator for the set of function signatures
+ */
+ exec_list_iterator iterator()
+ {
+ return signatures.iterator();
+ }
+
+ /**
+ * Find a signature that matches a set of actual parameters, taking implicit
+ * conversions into account.
+ */
+ ir_function_signature *matching_signature(const exec_list *actual_param);
+
+ /**
+ * Find a signature that exactly matches a set of actual parameters without
+ * any implicit type conversions.
+ */
+ ir_function_signature *exact_matching_signature(const exec_list *actual_ps);
+
+ /**
+ * Name of the function.
+ */
+ const char *name;
+
+ /**
+ * List of ir_function_signature for each overloaded function with this name.
+ */
+ struct exec_list signatures;
+};
+
+inline const char *ir_function_signature::function_name() const
+{
+ return this->_function->name;
+}
+/*@}*/
+
+
+/**
+ * IR instruction representing high-level if-statements
+ */
+class ir_if : public ir_instruction {
+public:
+ ir_if(ir_rvalue *condition)
+ : condition(condition)
+ {
+ ir_type = ir_type_if;
+ }
+
+ virtual ir_if *clone(void *mem_ctx, struct hash_table *ht) const;
+
+ virtual ir_if *as_if()
+ {
+ return this;
+ }
+
+ virtual void accept(ir_visitor *v)
+ {
+ v->visit(this);
+ }
+
+ virtual ir_visitor_status accept(ir_hierarchical_visitor *);
+
+ ir_rvalue *condition;
+ /** List of ir_instruction for the body of the then branch */
+ exec_list then_instructions;
+ /** List of ir_instruction for the body of the else branch */
+ exec_list else_instructions;
+};
+
+
+/**
+ * IR instruction representing a high-level loop structure.
+ */
+class ir_loop : public ir_instruction {
+public:
+ ir_loop() : from(NULL), to(NULL), increment(NULL), counter(NULL)
+ {
+ ir_type = ir_type_loop;
+ }
+
+ virtual ir_loop *clone(void *mem_ctx, struct hash_table *ht) const;
+
+ virtual void accept(ir_visitor *v)
+ {
+ v->visit(this);
+ }
+
+ virtual ir_visitor_status accept(ir_hierarchical_visitor *);
+
+ virtual ir_loop *as_loop()
+ {
+ return this;
+ }
+
+ /**
+ * Get an iterator for the instructions of the loop body
+ */
+ exec_list_iterator iterator()
+ {
+ return body_instructions.iterator();
+ }
+
+ /** List of ir_instruction that make up the body of the loop. */
+ exec_list body_instructions;
+
+ /**
+ * \name Loop counter and controls
+ */
+ /*@{*/
+ ir_rvalue *from;
+ ir_rvalue *to;
+ ir_rvalue *increment;
+ ir_variable *counter;
+ /*@}*/
+};
+
+
+class ir_assignment : public ir_instruction {
+public:
+ ir_assignment(ir_rvalue *lhs, ir_rvalue *rhs, ir_rvalue *condition);
+
+ /**
+ * Construct an assignment with an explicit write mask
+ *
+ * \note
+ * Since a write mask is supplied, the LHS must already be a bare
+ * \c ir_dereference. The cannot be any swizzles in the LHS.
+ */
+ ir_assignment(ir_dereference *lhs, ir_rvalue *rhs, ir_rvalue *condition,
+ unsigned write_mask);
+
+ virtual ir_assignment *clone(void *mem_ctx, struct hash_table *ht) const;
+
+ virtual ir_constant *constant_expression_value();
+
+ virtual void accept(ir_visitor *v)
+ {
+ v->visit(this);
+ }
+
+ virtual ir_visitor_status accept(ir_hierarchical_visitor *);
+
+ virtual ir_assignment * as_assignment()
+ {
+ return this;
+ }
+
+ /**
+ * Get a whole variable written by an assignment
+ *
+ * If the LHS of the assignment writes a whole variable, the variable is
+ * returned. Otherwise \c NULL is returned. Examples of whole-variable
+ * assignment are:
+ *
+ * - Assigning to a scalar
+ * - Assigning to all components of a vector
+ * - Whole array (or matrix) assignment
+ * - Whole structure assignment
+ */
+ ir_variable *whole_variable_written();
+
+ /**
+ * Set the LHS of an assignment
+ */
+ void set_lhs(ir_rvalue *lhs);
+
+ /**
+ * Left-hand side of the assignment.
+ *
+ * This should be treated as read only. If you need to set the LHS of an
+ * assignment, use \c ir_assignment::set_lhs.
+ */
+ ir_dereference *lhs;
+
+ /**
+ * Value being assigned
+ */
+ ir_rvalue *rhs;
+
+ /**
+ * Optional condition for the assignment.
+ */
+ ir_rvalue *condition;
+
+
+ /**
+ * Component mask written
+ *
+ * For non-vector types in the LHS, this field will be zero. For vector
+ * types, a bit will be set for each component that is written. Note that
+ * for \c vec2 and \c vec3 types only the lower bits will ever be set.
+ */
+ unsigned write_mask:4;
+};
+
+/* Update ir_expression::num_operands() and operator_strs when
+ * updating this list.
+ */
+enum ir_expression_operation {
+ ir_unop_bit_not,
+ ir_unop_logic_not,
+ ir_unop_neg,
+ ir_unop_abs,
+ ir_unop_sign,
+ ir_unop_rcp,
+ ir_unop_rsq,
+ ir_unop_sqrt,
+ ir_unop_exp, /**< Log base e on gentype */
+ ir_unop_log, /**< Natural log on gentype */
+ ir_unop_exp2,
+ ir_unop_log2,
+ ir_unop_f2i, /**< Float-to-integer conversion. */
+ ir_unop_i2f, /**< Integer-to-float conversion. */
+ ir_unop_f2b, /**< Float-to-boolean conversion */
+ ir_unop_b2f, /**< Boolean-to-float conversion */
+ ir_unop_i2b, /**< int-to-boolean conversion */
+ ir_unop_b2i, /**< Boolean-to-int conversion */
+ ir_unop_u2f, /**< Unsigned-to-float conversion. */
+
+ /**
+ * \name Unary floating-point rounding operations.
+ */
+ /*@{*/
+ ir_unop_trunc,
+ ir_unop_ceil,
+ ir_unop_floor,
+ ir_unop_fract,
+ /*@}*/
+
+ /**
+ * \name Trigonometric operations.
+ */
+ /*@{*/
+ ir_unop_sin,
+ ir_unop_cos,
+ /*@}*/
+
+ /**
+ * \name Partial derivatives.
+ */
+ /*@{*/
+ ir_unop_dFdx,
+ ir_unop_dFdy,
+ /*@}*/
+
+ ir_binop_add,
+ ir_binop_sub,
+ ir_binop_mul,
+ ir_binop_div,
+
+ /**
+ * Takes one of two combinations of arguments:
+ *
+ * - mod(vecN, vecN)
+ * - mod(vecN, float)
+ *
+ * Does not take integer types.
+ */
+ ir_binop_mod,
+
+ /**
+ * \name Binary comparison operators
+ */
+ /*@{*/
+ ir_binop_less,
+ ir_binop_greater,
+ ir_binop_lequal,
+ ir_binop_gequal,
+ /**
+ * Returns single boolean for whether all components of operands[0]
+ * equal the components of operands[1].
+ */
+ ir_binop_equal,
+ /**
+ * Returns single boolean for whether any component of operands[0]
+ * is not equal to the corresponding component of operands[1].
+ */
+ ir_binop_nequal,
+ /*@}*/
+
+ /**
+ * \name Bit-wise binary operations.
+ */
+ /*@{*/
+ ir_binop_lshift,
+ ir_binop_rshift,
+ ir_binop_bit_and,
+ ir_binop_bit_xor,
+ ir_binop_bit_or,
+ /*@}*/
+
+ ir_binop_logic_and,
+ ir_binop_logic_xor,
+ ir_binop_logic_or,
+
+ ir_binop_dot,
+ ir_binop_cross,
+ ir_binop_min,
+ ir_binop_max,
+
+ ir_binop_pow
+};
+
+class ir_expression : public ir_rvalue {
+public:
+ ir_expression(int op, const struct glsl_type *type,
+ ir_rvalue *, ir_rvalue *);
+
+ virtual ir_expression *as_expression()
+ {
+ return this;
+ }
+
+ virtual ir_expression *clone(void *mem_ctx, struct hash_table *ht) const;
+
+ virtual ir_constant *constant_expression_value();
+
+ static unsigned int get_num_operands(ir_expression_operation);
+ unsigned int get_num_operands() const
+ {
+ return get_num_operands(operation);
+ }
+
+ /**
+ * Return a string representing this expression's operator.
+ */
+ const char *operator_string();
+
+ /**
+ * Do a reverse-lookup to translate the given string into an operator.
+ */
+ static ir_expression_operation get_operator(const char *);
+
+ virtual void accept(ir_visitor *v)
+ {
+ v->visit(this);
+ }
+
+ virtual ir_visitor_status accept(ir_hierarchical_visitor *);
+
+ ir_expression_operation operation;
+ ir_rvalue *operands[2];
+};
+
+
+/**
+ * IR instruction representing a function call
+ */
+class ir_call : public ir_rvalue {
+public:
+ ir_call(ir_function_signature *callee, exec_list *actual_parameters)
+ : callee(callee)
+ {
+ ir_type = ir_type_call;
+ assert(callee->return_type != NULL);
+ type = callee->return_type;
+ actual_parameters->move_nodes_to(& this->actual_parameters);
+ }
+
+ virtual ir_call *clone(void *mem_ctx, struct hash_table *ht) const;
+
+ virtual ir_constant *constant_expression_value();
+
+ virtual ir_call *as_call()
+ {
+ return this;
+ }
+
+ virtual void accept(ir_visitor *v)
+ {
+ v->visit(this);
+ }
+
+ virtual ir_visitor_status accept(ir_hierarchical_visitor *);
+
+ /**
+ * Get a generic ir_call object when an error occurs
+ *
+ * Any allocation will be performed with 'ctx' as talloc owner.
+ */
+ static ir_call *get_error_instruction(void *ctx);
+
+ /**
+ * Get an iterator for the set of acutal parameters
+ */
+ exec_list_iterator iterator()
+ {
+ return actual_parameters.iterator();
+ }
+
+ /**
+ * Get the name of the function being called.
+ */
+ const char *callee_name() const
+ {
+ return callee->function_name();
+ }
+
+ ir_function_signature *get_callee()
+ {
+ return callee;
+ }
+
+ /**
+ * Set the function call target
+ */
+ void set_callee(ir_function_signature *sig);
+
+ /**
+ * Generates an inline version of the function before @ir,
+ * returning the return value of the function.
+ */
+ ir_rvalue *generate_inline(ir_instruction *ir);
+
+ /* List of ir_rvalue of paramaters passed in this call. */
+ exec_list actual_parameters;
+
+private:
+ ir_call()
+ : callee(NULL)
+ {
+ this->ir_type = ir_type_call;
+ }
+
+ ir_function_signature *callee;
+};
+
+
+/**
+ * \name Jump-like IR instructions.
+ *
+ * These include \c break, \c continue, \c return, and \c discard.
+ */
+/*@{*/
+class ir_jump : public ir_instruction {
+protected:
+ ir_jump()
+ {
+ ir_type = ir_type_unset;
+ }
+};
+
+class ir_return : public ir_jump {
+public:
+ ir_return()
+ : value(NULL)
+ {
+ this->ir_type = ir_type_return;
+ }
+
+ ir_return(ir_rvalue *value)
+ : value(value)
+ {
+ this->ir_type = ir_type_return;
+ }
+
+ virtual ir_return *clone(void *mem_ctx, struct hash_table *) const;
+
+ virtual ir_return *as_return()
+ {
+ return this;
+ }
+
+ ir_rvalue *get_value() const
+ {
+ return value;
+ }
+
+ virtual void accept(ir_visitor *v)
+ {
+ v->visit(this);
+ }
+
+ virtual ir_visitor_status accept(ir_hierarchical_visitor *);
+
+ ir_rvalue *value;
+};
+
+
+/**
+ * Jump instructions used inside loops
+ *
+ * These include \c break and \c continue. The \c break within a loop is
+ * different from the \c break within a switch-statement.
+ *
+ * \sa ir_switch_jump
+ */
+class ir_loop_jump : public ir_jump {
+public:
+ enum jump_mode {
+ jump_break,
+ jump_continue
+ };
+
+ ir_loop_jump(jump_mode mode)
+ {
+ this->ir_type = ir_type_loop_jump;
+ this->mode = mode;
+ this->loop = loop;
+ }
+
+ virtual ir_loop_jump *clone(void *mem_ctx, struct hash_table *) const;
+
+ virtual void accept(ir_visitor *v)
+ {
+ v->visit(this);
+ }
+
+ virtual ir_visitor_status accept(ir_hierarchical_visitor *);
+
+ bool is_break() const
+ {
+ return mode == jump_break;
+ }
+
+ bool is_continue() const
+ {
+ return mode == jump_continue;
+ }
+
+ /** Mode selector for the jump instruction. */
+ enum jump_mode mode;
+private:
+ /** Loop containing this break instruction. */
+ ir_loop *loop;
+};
+
+/**
+ * IR instruction representing discard statements.
+ */
+class ir_discard : public ir_jump {
+public:
+ ir_discard()
+ {
+ this->ir_type = ir_type_discard;
+ this->condition = NULL;
+ }
+
+ ir_discard(ir_rvalue *cond)
+ {
+ this->ir_type = ir_type_discard;
+ this->condition = cond;
+ }
+
+ virtual ir_discard *clone(void *mem_ctx, struct hash_table *ht) const;
+
+ virtual void accept(ir_visitor *v)
+ {
+ v->visit(this);
+ }
+
+ virtual ir_visitor_status accept(ir_hierarchical_visitor *);
+
+ ir_rvalue *condition;
+};
+/*@}*/
+
+
+/**
+ * Texture sampling opcodes used in ir_texture
+ */
+enum ir_texture_opcode {
+ ir_tex, /* Regular texture look-up */
+ ir_txb, /* Texture look-up with LOD bias */
+ ir_txl, /* Texture look-up with explicit LOD */
+ ir_txd, /* Texture look-up with partial derivatvies */
+ ir_txf /* Texel fetch with explicit LOD */
+};
+
+
+/**
+ * IR instruction to sample a texture
+ *
+ * The specific form of the IR instruction depends on the \c mode value
+ * selected from \c ir_texture_opcodes. In the printed IR, these will
+ * appear as:
+ *
+ * Texel offset
+ * | Projection divisor
+ * | | Shadow comparitor
+ * | | |
+ * v v v
+ * (tex (sampler) (coordinate) (0 0 0) (1) ( ))
+ * (txb (sampler) (coordinate) (0 0 0) (1) ( ) (bias))
+ * (txl (sampler) (coordinate) (0 0 0) (1) ( ) (lod))
+ * (txd (sampler) (coordinate) (0 0 0) (1) ( ) (dPdx dPdy))
+ * (txf (sampler) (coordinate) (0 0 0) (lod))
+ */
+class ir_texture : public ir_rvalue {
+public:
+ ir_texture(enum ir_texture_opcode op)
+ : op(op), projector(NULL), shadow_comparitor(NULL)
+ {
+ this->ir_type = ir_type_texture;
+ }
+
+ virtual ir_texture *clone(void *mem_ctx, struct hash_table *) const;
+
+ virtual ir_constant *constant_expression_value();
+
+ virtual void accept(ir_visitor *v)
+ {
+ v->visit(this);
+ }
+
+ virtual ir_visitor_status accept(ir_hierarchical_visitor *);
+
+ /**
+ * Return a string representing the ir_texture_opcode.
+ */
+ const char *opcode_string();
+
+ /** Set the sampler and infer the type. */
+ void set_sampler(ir_dereference *sampler);
+
+ /**
+ * Do a reverse-lookup to translate a string into an ir_texture_opcode.
+ */
+ static ir_texture_opcode get_opcode(const char *);
+
+ enum ir_texture_opcode op;
+
+ /** Sampler to use for the texture access. */
+ ir_dereference *sampler;
+
+ /** Texture coordinate to sample */
+ ir_rvalue *coordinate;
+
+ /**
+ * Value used for projective divide.
+ *
+ * If there is no projective divide (the common case), this will be
+ * \c NULL. Optimization passes should check for this to point to a constant
+ * of 1.0 and replace that with \c NULL.
+ */
+ ir_rvalue *projector;
+
+ /**
+ * Coordinate used for comparison on shadow look-ups.
+ *
+ * If there is no shadow comparison, this will be \c NULL. For the
+ * \c ir_txf opcode, this *must* be \c NULL.
+ */
+ ir_rvalue *shadow_comparitor;
+
+ /** Explicit texel offsets. */
+ signed char offsets[3];
+
+ union {
+ ir_rvalue *lod; /**< Floating point LOD */
+ ir_rvalue *bias; /**< Floating point LOD bias */
+ struct {
+ ir_rvalue *dPdx; /**< Partial derivative of coordinate wrt X */
+ ir_rvalue *dPdy; /**< Partial derivative of coordinate wrt Y */
+ } grad;
+ } lod_info;
+};
+
+
+struct ir_swizzle_mask {
+ unsigned x:2;
+ unsigned y:2;
+ unsigned z:2;
+ unsigned w:2;
+
+ /**
+ * Number of components in the swizzle.
+ */
+ unsigned num_components:3;
+
+ /**
+ * Does the swizzle contain duplicate components?
+ *
+ * L-value swizzles cannot contain duplicate components.
+ */
+ unsigned has_duplicates:1;
+};
+
+
+class ir_swizzle : public ir_rvalue {
+public:
+ ir_swizzle(ir_rvalue *, unsigned x, unsigned y, unsigned z, unsigned w,
+ unsigned count);
+
+ ir_swizzle(ir_rvalue *val, const unsigned *components, unsigned count);
+
+ ir_swizzle(ir_rvalue *val, ir_swizzle_mask mask);
+
+ virtual ir_swizzle *clone(void *mem_ctx, struct hash_table *) const;
+
+ virtual ir_constant *constant_expression_value();
+
+ virtual ir_swizzle *as_swizzle()
+ {
+ return this;
+ }
+
+ /**
+ * Construct an ir_swizzle from the textual representation. Can fail.
+ */
+ static ir_swizzle *create(ir_rvalue *, const char *, unsigned vector_length);
+
+ virtual void accept(ir_visitor *v)
+ {
+ v->visit(this);
+ }
+
+ virtual ir_visitor_status accept(ir_hierarchical_visitor *);
+
+ bool is_lvalue()
+ {
+ return val->is_lvalue() && !mask.has_duplicates;
+ }
+
+ /**
+ * Get the variable that is ultimately referenced by an r-value
+ */
+ virtual ir_variable *variable_referenced();
+
+ ir_rvalue *val;
+ ir_swizzle_mask mask;
+
+private:
+ /**
+ * Initialize the mask component of a swizzle
+ *
+ * This is used by the \c ir_swizzle constructors.
+ */
+ void init_mask(const unsigned *components, unsigned count);
+};
+
+
+class ir_dereference : public ir_rvalue {
+public:
+ virtual ir_dereference *clone(void *mem_ctx, struct hash_table *) const = 0;
+
+ virtual ir_dereference *as_dereference()
+ {
+ return this;
+ }
+
+ bool is_lvalue();
+
+ /**
+ * Get the variable that is ultimately referenced by an r-value
+ */
+ virtual ir_variable *variable_referenced() = 0;
+};
+
+
+class ir_dereference_variable : public ir_dereference {
+public:
+ ir_dereference_variable(ir_variable *var);
+
+ virtual ir_dereference_variable *clone(void *mem_ctx,
+ struct hash_table *) const;
+
+ virtual ir_constant *constant_expression_value();
+
+ virtual ir_dereference_variable *as_dereference_variable()
+ {
+ return this;
+ }
+
+ /**
+ * Get the variable that is ultimately referenced by an r-value
+ */
+ virtual ir_variable *variable_referenced()
+ {
+ return this->var;
+ }
+
+ virtual ir_variable *whole_variable_referenced()
+ {
+ /* ir_dereference_variable objects always dereference the entire
+ * variable. However, if this dereference is dereferenced by anything
+ * else, the complete deferefernce chain is not a whole-variable
+ * dereference. This method should only be called on the top most
+ * ir_rvalue in a dereference chain.
+ */
+ return this->var;
+ }
+
+ virtual void accept(ir_visitor *v)
+ {
+ v->visit(this);
+ }
+
+ virtual ir_visitor_status accept(ir_hierarchical_visitor *);
+
+ /**
+ * Object being dereferenced.
+ */
+ ir_variable *var;
+};
+
+
+class ir_dereference_array : public ir_dereference {
+public:
+ ir_dereference_array(ir_rvalue *value, ir_rvalue *array_index);
+
+ ir_dereference_array(ir_variable *var, ir_rvalue *array_index);
+
+ virtual ir_dereference_array *clone(void *mem_ctx,
+ struct hash_table *) const;
+
+ virtual ir_constant *constant_expression_value();
+
+ virtual ir_dereference_array *as_dereference_array()
+ {
+ return this;
+ }
+
+ /**
+ * Get the variable that is ultimately referenced by an r-value
+ */
+ virtual ir_variable *variable_referenced()
+ {
+ return this->array->variable_referenced();
+ }
+
+ virtual void accept(ir_visitor *v)
+ {
+ v->visit(this);
+ }
+
+ virtual ir_visitor_status accept(ir_hierarchical_visitor *);
+
+ ir_rvalue *array;
+ ir_rvalue *array_index;
+
+private:
+ void set_array(ir_rvalue *value);
+};
+
+
+class ir_dereference_record : public ir_dereference {
+public:
+ ir_dereference_record(ir_rvalue *value, const char *field);
+
+ ir_dereference_record(ir_variable *var, const char *field);
+
+ virtual ir_dereference_record *clone(void *mem_ctx,
+ struct hash_table *) const;
+
+ virtual ir_constant *constant_expression_value();
+
+ /**
+ * Get the variable that is ultimately referenced by an r-value
+ */
+ virtual ir_variable *variable_referenced()
+ {
+ return this->record->variable_referenced();
+ }
+
+ virtual void accept(ir_visitor *v)
+ {
+ v->visit(this);
+ }
+
+ virtual ir_visitor_status accept(ir_hierarchical_visitor *);
+
+ ir_rvalue *record;
+ const char *field;
+};
+
+
+/**
+ * Data stored in an ir_constant
+ */
+union ir_constant_data {
+ unsigned u[16];
+ int i[16];
+ float f[16];
+ bool b[16];
+};
+
+
+class ir_constant : public ir_rvalue {
+public:
+ ir_constant(const struct glsl_type *type, const ir_constant_data *data);
+ ir_constant(bool b);
+ ir_constant(unsigned int u);
+ ir_constant(int i);
+ ir_constant(float f);
+
+ /**
+ * Construct an ir_constant from a list of ir_constant values
+ */
+ ir_constant(const struct glsl_type *type, exec_list *values);
+
+ /**
+ * Construct an ir_constant from a scalar component of another ir_constant
+ *
+ * The new \c ir_constant inherits the type of the component from the
+ * source constant.
+ *
+ * \note
+ * In the case of a matrix constant, the new constant is a scalar, \b not
+ * a vector.
+ */
+ ir_constant(const ir_constant *c, unsigned i);
+
+ /**
+ * Return a new ir_constant of the specified type containing all zeros.
+ */
+ static ir_constant *zero(void *mem_ctx, const glsl_type *type);
+
+ virtual ir_constant *clone(void *mem_ctx, struct hash_table *) const;
+
+ virtual ir_constant *constant_expression_value();
+
+ virtual ir_constant *as_constant()
+ {
+ return this;
+ }
+
+ virtual void accept(ir_visitor *v)
+ {
+ v->visit(this);
+ }
+
+ virtual ir_visitor_status accept(ir_hierarchical_visitor *);
+
+ /**
+ * Get a particular component of a constant as a specific type
+ *
+ * This is useful, for example, to get a value from an integer constant
+ * as a float or bool. This appears frequently when constructors are
+ * called with all constant parameters.
+ */
+ /*@{*/
+ bool get_bool_component(unsigned i) const;
+ float get_float_component(unsigned i) const;
+ int get_int_component(unsigned i) const;
+ unsigned get_uint_component(unsigned i) const;
+ /*@}*/
+
+ ir_constant *get_array_element(unsigned i) const;
+
+ ir_constant *get_record_field(const char *name);
+
+ /**
+ * Determine whether a constant has the same value as another constant
+ */
+ bool has_value(const ir_constant *) const;
+
+ /**
+ * Value of the constant.
+ *
+ * The field used to back the values supplied by the constant is determined
+ * by the type associated with the \c ir_instruction. Constants may be
+ * scalars, vectors, or matrices.
+ */
+ union ir_constant_data value;
+
+ /* Array elements */
+ ir_constant **array_elements;
+
+ /* Structure fields */
+ exec_list components;
+
+private:
+ /**
+ * Parameterless constructor only used by the clone method
+ */
+ ir_constant(void);
+};
+
+void
+visit_exec_list(exec_list *list, ir_visitor *visitor);
+
+void validate_ir_tree(exec_list *instructions);
+
+/**
+ * Make a clone of each IR instruction in a list
+ *
+ * \param in List of IR instructions that are to be cloned
+ * \param out List to hold the cloned instructions
+ */
+void
+clone_ir_list(void *mem_ctx, exec_list *out, const exec_list *in);
+
+extern void
+_mesa_glsl_initialize_variables(exec_list *instructions,
+ struct _mesa_glsl_parse_state *state);
+
+extern void
+_mesa_glsl_initialize_functions(exec_list *instructions,
+ struct _mesa_glsl_parse_state *state);
+
+extern void
+_mesa_glsl_release_functions(void);
+
+extern void
+reparent_ir(exec_list *list, void *mem_ctx);
+
+class glsl_symbol_table;
+
+extern void
+import_prototypes(const exec_list *source, exec_list *dest,
+ class glsl_symbol_table *symbols, void *mem_ctx);
+
+extern bool
+ir_has_call(ir_instruction *ir);
+
+extern void
+do_set_program_inouts(exec_list *instructions, struct gl_program *prog);
+
+#endif /* IR_H */
diff --git a/src/glsl/ir_algebraic.cpp b/src/glsl/ir_algebraic.cpp
new file mode 100644
index 00000000000..a66c820a278
--- /dev/null
+++ b/src/glsl/ir_algebraic.cpp
@@ -0,0 +1,392 @@
+/*
+ * Copyright © 2010 Intel Corporation
+ *
+ * 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 (including the next
+ * paragraph) 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
+ * THE AUTHORS OR COPYRIGHT HOLDERS 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 ir_algebraic.cpp
+ *
+ * Takes advantage of association, commutivity, and other algebraic
+ * properties to simplify expressions.
+ */
+
+#include "ir.h"
+#include "ir_visitor.h"
+#include "ir_rvalue_visitor.h"
+#include "ir_optimization.h"
+#include "glsl_types.h"
+
+/**
+ * Visitor class for replacing expressions with ir_constant values.
+ */
+
+class ir_algebraic_visitor : public ir_rvalue_visitor {
+public:
+ ir_algebraic_visitor()
+ {
+ this->progress = false;
+ }
+
+ virtual ~ir_algebraic_visitor()
+ {
+ }
+
+ ir_rvalue *handle_expression(ir_expression *ir);
+ void handle_rvalue(ir_rvalue **rvalue);
+ bool reassociate_constant(ir_expression *ir1,
+ int const_index,
+ ir_constant *constant,
+ ir_expression *ir2);
+ void reassociate_operands(ir_expression *ir1,
+ int op1,
+ ir_expression *ir2,
+ int op2);
+ bool progress;
+};
+
+static bool
+is_vec_zero(ir_constant *ir)
+{
+ int c;
+
+ if (!ir)
+ return false;
+ if (!ir->type->is_scalar() &&
+ !ir->type->is_vector())
+ return false;
+
+ for (c = 0; c < ir->type->vector_elements; c++) {
+ switch (ir->type->base_type) {
+ case GLSL_TYPE_FLOAT:
+ if (ir->value.f[c] != 0.0)
+ return false;
+ break;
+ case GLSL_TYPE_INT:
+ if (ir->value.i[c] != 0)
+ return false;
+ break;
+ case GLSL_TYPE_UINT:
+ if (ir->value.u[c] != 0)
+ return false;
+ break;
+ case GLSL_TYPE_BOOL:
+ if (ir->value.b[c] != false)
+ return false;
+ break;
+ default:
+ assert(!"bad base type");
+ return false;
+ }
+ }
+
+ return true;
+}
+
+static bool
+is_vec_one(ir_constant *ir)
+{
+ int c;
+
+ if (!ir)
+ return false;
+ if (!ir->type->is_scalar() &&
+ !ir->type->is_vector())
+ return false;
+
+ for (c = 0; c < ir->type->vector_elements; c++) {
+ switch (ir->type->base_type) {
+ case GLSL_TYPE_FLOAT:
+ if (ir->value.f[c] != 1.0)
+ return false;
+ break;
+ case GLSL_TYPE_INT:
+ if (ir->value.i[c] != 1)
+ return false;
+ break;
+ case GLSL_TYPE_UINT:
+ if (ir->value.u[c] != 1)
+ return false;
+ break;
+ case GLSL_TYPE_BOOL:
+ if (ir->value.b[c] != true)
+ return false;
+ break;
+ default:
+ assert(!"bad base type");
+ return false;
+ }
+ }
+
+ return true;
+}
+
+static void
+update_type(ir_expression *ir)
+{
+ if (ir->operands[0]->type->is_vector())
+ ir->type = ir->operands[0]->type;
+ else
+ ir->type = ir->operands[1]->type;
+}
+
+void
+ir_algebraic_visitor::reassociate_operands(ir_expression *ir1,
+ int op1,
+ ir_expression *ir2,
+ int op2)
+{
+ ir_rvalue *temp = ir2->operands[op2];
+ ir2->operands[op2] = ir1->operands[op1];
+ ir1->operands[op1] = temp;
+
+ /* Update the type of ir2. The type of ir1 won't have changed --
+ * base types matched, and at least one of the operands of the 2
+ * binops is still a vector if any of them were.
+ */
+ update_type(ir2);
+
+ this->progress = true;
+}
+
+/**
+ * Reassociates a constant down a tree of adds or multiplies.
+ *
+ * Consider (2 * (a * (b * 0.5))). We want to send up with a * b.
+ */
+bool
+ir_algebraic_visitor::reassociate_constant(ir_expression *ir1, int const_index,
+ ir_constant *constant,
+ ir_expression *ir2)
+{
+ if (!ir2 || ir1->operation != ir2->operation)
+ return false;
+
+ /* Don't want to even think about matrices. */
+ if (ir1->operands[0]->type->is_matrix() ||
+ ir1->operands[0]->type->is_matrix() ||
+ ir2->operands[1]->type->is_matrix() ||
+ ir2->operands[1]->type->is_matrix())
+ return false;
+
+ ir_constant *ir2_const[2];
+ ir2_const[0] = ir2->operands[0]->constant_expression_value();
+ ir2_const[1] = ir2->operands[1]->constant_expression_value();
+
+ if (ir2_const[0] && ir2_const[1])
+ return false;
+
+ if (ir2_const[0]) {
+ reassociate_operands(ir1, const_index, ir2, 1);
+ return true;
+ } else if (ir2_const[1]) {
+ reassociate_operands(ir1, const_index, ir2, 0);
+ return true;
+ }
+
+ if (reassociate_constant(ir1, const_index, constant,
+ ir2->operands[0]->as_expression())) {
+ update_type(ir2);
+ return true;
+ }
+
+ if (reassociate_constant(ir1, const_index, constant,
+ ir2->operands[1]->as_expression())) {
+ update_type(ir2);
+ return true;
+ }
+
+ return false;
+}
+
+ir_rvalue *
+ir_algebraic_visitor::handle_expression(ir_expression *ir)
+{
+ ir_constant *op_const[2] = {NULL, NULL};
+ ir_expression *op_expr[2] = {NULL, NULL};
+ unsigned int i;
+
+ for (i = 0; i < ir->get_num_operands(); i++) {
+ if (ir->operands[i]->type->is_matrix())
+ return ir;
+
+ op_const[i] = ir->operands[i]->constant_expression_value();
+ op_expr[i] = ir->operands[i]->as_expression();
+ }
+
+ switch (ir->operation) {
+ case ir_unop_logic_not: {
+ enum ir_expression_operation new_op = ir_unop_logic_not;
+
+ if (op_expr[0] == NULL)
+ break;
+
+ switch (op_expr[0]->operation) {
+ case ir_binop_less: new_op = ir_binop_gequal; break;
+ case ir_binop_greater: new_op = ir_binop_lequal; break;
+ case ir_binop_lequal: new_op = ir_binop_greater; break;
+ case ir_binop_gequal: new_op = ir_binop_less; break;
+ case ir_binop_equal: new_op = ir_binop_nequal; break;
+ case ir_binop_nequal: new_op = ir_binop_equal; break;
+
+ default:
+ /* The default case handler is here to silence a warning from GCC.
+ */
+ break;
+ }
+
+ if (new_op != ir_unop_logic_not) {
+ this->progress = true;
+ return new(ir) ir_expression(new_op,
+ ir->type,
+ op_expr[0]->operands[0],
+ op_expr[0]->operands[1]);
+ }
+
+ break;
+ }
+
+ case ir_binop_add:
+ if (is_vec_zero(op_const[0])) {
+ this->progress = true;
+ return ir->operands[1];
+ }
+ if (is_vec_zero(op_const[1])) {
+ this->progress = true;
+ return ir->operands[0];
+ }
+
+ /* Reassociate addition of constants so that we can do constant
+ * folding.
+ */
+ if (op_const[0] && !op_const[1])
+ reassociate_constant(ir, 0, op_const[0],
+ ir->operands[1]->as_expression());
+ if (op_const[1] && !op_const[0])
+ reassociate_constant(ir, 1, op_const[1],
+ ir->operands[0]->as_expression());
+ break;
+
+ case ir_binop_sub:
+ if (is_vec_zero(op_const[0])) {
+ this->progress = true;
+ return new(ir) ir_expression(ir_unop_neg,
+ ir->type,
+ ir->operands[1],
+ NULL);
+ }
+ if (is_vec_zero(op_const[1])) {
+ this->progress = true;
+ return ir->operands[0];
+ }
+ break;
+
+ case ir_binop_mul:
+ if (is_vec_one(op_const[0])) {
+ this->progress = true;
+ return ir->operands[1];
+ }
+ if (is_vec_one(op_const[1])) {
+ this->progress = true;
+ return ir->operands[0];
+ }
+
+ if (is_vec_zero(op_const[0]) || is_vec_zero(op_const[1])) {
+ this->progress = true;
+ return ir_constant::zero(ir, ir->type);
+ }
+
+ /* Reassociate multiplication of constants so that we can do
+ * constant folding.
+ */
+ if (op_const[0] && !op_const[1])
+ reassociate_constant(ir, 0, op_const[0],
+ ir->operands[1]->as_expression());
+ if (op_const[1] && !op_const[0])
+ reassociate_constant(ir, 1, op_const[1],
+ ir->operands[0]->as_expression());
+
+ break;
+
+ case ir_binop_div:
+ if (is_vec_one(op_const[0]) && ir->type->base_type == GLSL_TYPE_FLOAT) {
+ this->progress = true;
+ return new(ir) ir_expression(ir_unop_rcp,
+ ir->type,
+ ir->operands[1],
+ NULL);
+ }
+ if (is_vec_one(op_const[1])) {
+ this->progress = true;
+ return ir->operands[0];
+ }
+ break;
+
+ case ir_unop_rcp:
+ if (op_expr[0] && op_expr[0]->operation == ir_unop_rcp) {
+ this->progress = true;
+ return op_expr[0]->operands[0];
+ }
+
+ /* FINISHME: We should do rcp(rsq(x)) -> sqrt(x) for some
+ * backends, except that some backends will have done sqrt ->
+ * rcp(rsq(x)) and we don't want to undo it for them.
+ */
+
+ /* As far as we know, all backends are OK with rsq. */
+ if (op_expr[0] && op_expr[0]->operation == ir_unop_sqrt) {
+ this->progress = true;
+ return new(ir) ir_expression(ir_unop_rsq,
+ ir->type,
+ op_expr[0]->operands[0],
+ NULL);
+ }
+
+ break;
+
+ default:
+ break;
+ }
+
+ return ir;
+}
+
+void
+ir_algebraic_visitor::handle_rvalue(ir_rvalue **rvalue)
+{
+ if (!*rvalue)
+ return;
+
+ ir_expression *expr = (*rvalue)->as_expression();
+ if (!expr)
+ return;
+
+ *rvalue = handle_expression(expr);
+}
+
+bool
+do_algebraic(exec_list *instructions)
+{
+ ir_algebraic_visitor v;
+
+ visit_list_elements(&v, instructions);
+
+ return v.progress;
+}
diff --git a/src/glsl/ir_basic_block.cpp b/src/glsl/ir_basic_block.cpp
new file mode 100644
index 00000000000..a8338259620
--- /dev/null
+++ b/src/glsl/ir_basic_block.cpp
@@ -0,0 +1,149 @@
+/*
+ * Copyright © 2010 Intel Corporation
+ *
+ * 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 (including the next
+ * paragraph) 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
+ * THE AUTHORS OR COPYRIGHT HOLDERS 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 ir_basic_block.cpp
+ *
+ * Basic block analysis of instruction streams.
+ */
+
+#include "ir.h"
+#include "ir_visitor.h"
+#include "ir_basic_block.h"
+#include "glsl_types.h"
+
+class ir_has_call_visitor : public ir_hierarchical_visitor {
+public:
+ ir_has_call_visitor()
+ {
+ has_call = false;
+ }
+
+ virtual ir_visitor_status visit_enter(ir_call *ir)
+ {
+ (void) ir;
+ has_call = true;
+ return visit_stop;
+ }
+
+ bool has_call;
+};
+
+bool
+ir_has_call(ir_instruction *ir)
+{
+ ir_has_call_visitor v;
+ ir->accept(&v);
+ return v.has_call;
+}
+
+/**
+ * Calls a user function for every basic block in the instruction stream.
+ *
+ * Basic block analysis is pretty easy in our IR thanks to the lack of
+ * unstructured control flow. We've got:
+ *
+ * ir_loop (for () {}, while () {}, do {} while ())
+ * ir_loop_jump (
+ * ir_if () {}
+ * ir_return
+ * ir_call()
+ *
+ * Note that the basic blocks returned by this don't encompass all
+ * operations performed by the program -- for example, if conditions
+ * don't get returned, nor do the assignments that will be generated
+ * for ir_call parameters.
+ */
+void call_for_basic_blocks(exec_list *instructions,
+ void (*callback)(ir_instruction *first,
+ ir_instruction *last,
+ void *data),
+ void *data)
+{
+ ir_instruction *leader = NULL;
+ ir_instruction *last = NULL;
+
+ foreach_iter(exec_list_iterator, iter, *instructions) {
+ ir_instruction *ir = (ir_instruction *)iter.get();
+ ir_if *ir_if;
+ ir_loop *ir_loop;
+ ir_function *ir_function;
+
+ if (!leader)
+ leader = ir;
+
+ if ((ir_if = ir->as_if())) {
+ callback(leader, ir, data);
+ leader = NULL;
+
+ call_for_basic_blocks(&ir_if->then_instructions, callback, data);
+ call_for_basic_blocks(&ir_if->else_instructions, callback, data);
+ } else if ((ir_loop = ir->as_loop())) {
+ callback(leader, ir, data);
+ leader = NULL;
+ call_for_basic_blocks(&ir_loop->body_instructions, callback, data);
+ } else if (ir->as_return() || ir->as_call()) {
+ callback(leader, ir, data);
+ leader = NULL;
+ } else if ((ir_function = ir->as_function())) {
+ /* A function definition doesn't interrupt our basic block
+ * since execution doesn't go into it. We should process the
+ * bodies of its signatures for BBs, though.
+ *
+ * Note that we miss an opportunity for producing more
+ * maximal BBs between the instructions that precede main()
+ * and the body of main(). Perhaps those instructions ought
+ * to live inside of main().
+ */
+ foreach_iter(exec_list_iterator, fun_iter, *ir_function) {
+ ir_function_signature *ir_sig;
+
+ ir_sig = (ir_function_signature *)fun_iter.get();
+
+ call_for_basic_blocks(&ir_sig->body, callback, data);
+ }
+ } else if (ir->as_assignment()) {
+ /* If there's a call in the expression tree being assigned,
+ * then that ends the BB too.
+ *
+ * The assumption is that any consumer of the basic block
+ * walker is fine with the fact that the call is somewhere in
+ * the tree even if portions of the tree may be evaluated
+ * after the call.
+ *
+ * A consumer that has an issue with this could not process
+ * the last instruction of the basic block. If doing so,
+ * expression flattener may be useful before using the basic
+ * block finder to get more maximal basic blocks out.
+ */
+ if (ir_has_call(ir)) {
+ callback(leader, ir, data);
+ leader = NULL;
+ }
+ }
+ last = ir;
+ }
+ if (leader) {
+ callback(leader, last, data);
+ }
+}
diff --git a/src/glsl/ir_basic_block.h b/src/glsl/ir_basic_block.h
new file mode 100644
index 00000000000..dbd678b5c4f
--- /dev/null
+++ b/src/glsl/ir_basic_block.h
@@ -0,0 +1,28 @@
+/*
+ * Copyright © 2010 Intel Corporation
+ *
+ * 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 (including the next
+ * paragraph) 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
+ * THE AUTHORS OR COPYRIGHT HOLDERS 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.
+ */
+
+void call_for_basic_blocks(exec_list *instructions,
+ void (*callback)(ir_instruction *first,
+ ir_instruction *last,
+ void *data),
+ void *data);
diff --git a/src/glsl/ir_clone.cpp b/src/glsl/ir_clone.cpp
new file mode 100644
index 00000000000..a72609601ae
--- /dev/null
+++ b/src/glsl/ir_clone.cpp
@@ -0,0 +1,401 @@
+/*
+ * Copyright © 2010 Intel Corporation
+ *
+ * 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 (including the next
+ * paragraph) 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
+ * THE AUTHORS OR COPYRIGHT HOLDERS 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.
+ */
+
+#include <string.h>
+#include "ir.h"
+#include "glsl_types.h"
+extern "C" {
+#include "program/hash_table.h"
+}
+
+/**
+ * Duplicate an IR variable
+ *
+ * \note
+ * This will probably be made \c virtual and moved to the base class
+ * eventually.
+ */
+ir_variable *
+ir_variable::clone(void *mem_ctx, struct hash_table *ht) const
+{
+ ir_variable *var = new(mem_ctx) ir_variable(this->type, this->name,
+ (ir_variable_mode) this->mode);
+
+ var->max_array_access = this->max_array_access;
+ var->read_only = this->read_only;
+ var->centroid = this->centroid;
+ var->invariant = this->invariant;
+ var->interpolation = this->interpolation;
+ var->array_lvalue = this->array_lvalue;
+ var->location = this->location;
+ var->warn_extension = this->warn_extension;
+ var->origin_upper_left = this->origin_upper_left;
+ var->pixel_center_integer = this->pixel_center_integer;
+
+ if (this->constant_value)
+ var->constant_value = this->constant_value->clone(mem_ctx, ht);
+
+ if (ht) {
+ hash_table_insert(ht, var, (void *)const_cast<ir_variable *>(this));
+ }
+
+ return var;
+}
+
+ir_swizzle *
+ir_swizzle::clone(void *mem_ctx, struct hash_table *ht) const
+{
+ return new(mem_ctx) ir_swizzle(this->val->clone(mem_ctx, ht), this->mask);
+}
+
+ir_return *
+ir_return::clone(void *mem_ctx, struct hash_table *ht) const
+{
+ ir_rvalue *new_value = NULL;
+
+ if (this->value)
+ new_value = this->value->clone(mem_ctx, ht);
+
+ return new(mem_ctx) ir_return(new_value);
+}
+
+ir_discard *
+ir_discard::clone(void *mem_ctx, struct hash_table *ht) const
+{
+ ir_rvalue *new_condition = NULL;
+
+ if (this->condition != NULL)
+ new_condition = this->condition->clone(mem_ctx, ht);
+
+ return new(mem_ctx) ir_discard(new_condition);
+}
+
+ir_loop_jump *
+ir_loop_jump::clone(void *mem_ctx, struct hash_table *ht) const
+{
+ (void)ht;
+
+ return new(mem_ctx) ir_loop_jump(this->mode);
+}
+
+ir_if *
+ir_if::clone(void *mem_ctx, struct hash_table *ht) const
+{
+ ir_if *new_if = new(mem_ctx) ir_if(this->condition->clone(mem_ctx, ht));
+
+ foreach_iter(exec_list_iterator, iter, this->then_instructions) {
+ ir_instruction *ir = (ir_instruction *)iter.get();
+ new_if->then_instructions.push_tail(ir->clone(mem_ctx, ht));
+ }
+
+ foreach_iter(exec_list_iterator, iter, this->else_instructions) {
+ ir_instruction *ir = (ir_instruction *)iter.get();
+ new_if->else_instructions.push_tail(ir->clone(mem_ctx, ht));
+ }
+
+ return new_if;
+}
+
+ir_loop *
+ir_loop::clone(void *mem_ctx, struct hash_table *ht) const
+{
+ ir_loop *new_loop = new(mem_ctx) ir_loop();
+
+ if (this->from)
+ new_loop->from = this->from->clone(mem_ctx, ht);
+ if (this->to)
+ new_loop->to = this->to->clone(mem_ctx, ht);
+ if (this->increment)
+ new_loop->increment = this->increment->clone(mem_ctx, ht);
+ new_loop->counter = counter;
+
+ foreach_iter(exec_list_iterator, iter, this->body_instructions) {
+ ir_instruction *ir = (ir_instruction *)iter.get();
+ new_loop->body_instructions.push_tail(ir->clone(mem_ctx, ht));
+ }
+
+ return new_loop;
+}
+
+ir_call *
+ir_call::clone(void *mem_ctx, struct hash_table *ht) const
+{
+ exec_list new_parameters;
+
+ foreach_iter(exec_list_iterator, iter, this->actual_parameters) {
+ ir_instruction *ir = (ir_instruction *)iter.get();
+ new_parameters.push_tail(ir->clone(mem_ctx, ht));
+ }
+
+ return new(mem_ctx) ir_call(this->callee, &new_parameters);
+}
+
+ir_expression *
+ir_expression::clone(void *mem_ctx, struct hash_table *ht) const
+{
+ ir_rvalue *op[2] = {NULL, NULL};
+ unsigned int i;
+
+ for (i = 0; i < get_num_operands(); i++) {
+ op[i] = this->operands[i]->clone(mem_ctx, ht);
+ }
+
+ return new(mem_ctx) ir_expression(this->operation, this->type, op[0], op[1]);
+}
+
+ir_dereference_variable *
+ir_dereference_variable::clone(void *mem_ctx, struct hash_table *ht) const
+{
+ ir_variable *new_var;
+
+ if (ht) {
+ new_var = (ir_variable *)hash_table_find(ht, this->var);
+ if (!new_var)
+ new_var = this->var;
+ } else {
+ new_var = this->var;
+ }
+
+ return new(mem_ctx) ir_dereference_variable(new_var);
+}
+
+ir_dereference_array *
+ir_dereference_array::clone(void *mem_ctx, struct hash_table *ht) const
+{
+ return new(mem_ctx) ir_dereference_array(this->array->clone(mem_ctx, ht),
+ this->array_index->clone(mem_ctx,
+ ht));
+}
+
+ir_dereference_record *
+ir_dereference_record::clone(void *mem_ctx, struct hash_table *ht) const
+{
+ return new(mem_ctx) ir_dereference_record(this->record->clone(mem_ctx, ht),
+ this->field);
+}
+
+ir_texture *
+ir_texture::clone(void *mem_ctx, struct hash_table *ht) const
+{
+ ir_texture *new_tex = new(mem_ctx) ir_texture(this->op);
+ new_tex->type = this->type;
+
+ new_tex->sampler = this->sampler->clone(mem_ctx, ht);
+ new_tex->coordinate = this->coordinate->clone(mem_ctx, ht);
+ if (this->projector)
+ new_tex->projector = this->projector->clone(mem_ctx, ht);
+ if (this->shadow_comparitor) {
+ new_tex->shadow_comparitor = this->shadow_comparitor->clone(mem_ctx, ht);
+ }
+
+ for (int i = 0; i < 3; i++)
+ new_tex->offsets[i] = this->offsets[i];
+
+ switch (this->op) {
+ case ir_tex:
+ break;
+ case ir_txb:
+ new_tex->lod_info.bias = this->lod_info.bias->clone(mem_ctx, ht);
+ break;
+ case ir_txl:
+ case ir_txf:
+ new_tex->lod_info.lod = this->lod_info.lod->clone(mem_ctx, ht);
+ break;
+ case ir_txd:
+ new_tex->lod_info.grad.dPdx = this->lod_info.grad.dPdx->clone(mem_ctx, ht);
+ new_tex->lod_info.grad.dPdy = this->lod_info.grad.dPdy->clone(mem_ctx, ht);
+ break;
+ }
+
+ return new_tex;
+}
+
+ir_assignment *
+ir_assignment::clone(void *mem_ctx, struct hash_table *ht) const
+{
+ ir_rvalue *new_condition = NULL;
+
+ if (this->condition)
+ new_condition = this->condition->clone(mem_ctx, ht);
+
+ return new(mem_ctx) ir_assignment(this->lhs->clone(mem_ctx, ht),
+ this->rhs->clone(mem_ctx, ht),
+ new_condition,
+ this->write_mask);
+}
+
+ir_function *
+ir_function::clone(void *mem_ctx, struct hash_table *ht) const
+{
+ ir_function *copy = new(mem_ctx) ir_function(this->name);
+
+ foreach_list_const(node, &this->signatures) {
+ const ir_function_signature *const sig =
+ (const ir_function_signature *const) node;
+
+ ir_function_signature *sig_copy = sig->clone(mem_ctx, ht);
+ copy->add_signature(sig_copy);
+
+ if (ht != NULL)
+ hash_table_insert(ht, sig_copy,
+ (void *)const_cast<ir_function_signature *>(sig));
+ }
+
+ return copy;
+}
+
+ir_function_signature *
+ir_function_signature::clone(void *mem_ctx, struct hash_table *ht) const
+{
+ ir_function_signature *copy =
+ new(mem_ctx) ir_function_signature(this->return_type);
+
+ copy->is_defined = this->is_defined;
+ copy->is_built_in = this->is_built_in;
+
+ /* Clone the parameter list.
+ */
+ foreach_list_const(node, &this->parameters) {
+ const ir_variable *const param = (const ir_variable *) node;
+
+ assert(const_cast<ir_variable *>(param)->as_variable() != NULL);
+
+ ir_variable *const param_copy = param->clone(mem_ctx, ht);
+ copy->parameters.push_tail(param_copy);
+ }
+
+ /* Clone the instruction list.
+ */
+ foreach_list_const(node, &this->body) {
+ const ir_instruction *const inst = (const ir_instruction *) node;
+
+ ir_instruction *const inst_copy = inst->clone(mem_ctx, ht);
+ copy->body.push_tail(inst_copy);
+ }
+
+ return copy;
+}
+
+ir_constant *
+ir_constant::clone(void *mem_ctx, struct hash_table *ht) const
+{
+ (void)ht;
+
+ switch (this->type->base_type) {
+ case GLSL_TYPE_UINT:
+ case GLSL_TYPE_INT:
+ case GLSL_TYPE_FLOAT:
+ case GLSL_TYPE_BOOL:
+ return new(mem_ctx) ir_constant(this->type, &this->value);
+
+ case GLSL_TYPE_STRUCT: {
+ ir_constant *c = new(mem_ctx) ir_constant;
+
+ c->type = this->type;
+ for (exec_node *node = this->components.head
+ ; !node->is_tail_sentinel()
+ ; node = node->next) {
+ ir_constant *const orig = (ir_constant *) node;
+
+ c->components.push_tail(orig->clone(mem_ctx, NULL));
+ }
+
+ return c;
+ }
+
+ case GLSL_TYPE_ARRAY: {
+ ir_constant *c = new(mem_ctx) ir_constant;
+
+ c->type = this->type;
+ c->array_elements = talloc_array(c, ir_constant *, this->type->length);
+ for (unsigned i = 0; i < this->type->length; i++) {
+ c->array_elements[i] = this->array_elements[i]->clone(mem_ctx, NULL);
+ }
+ return c;
+ }
+
+ default:
+ assert(!"Should not get here."); break;
+ return NULL;
+ }
+}
+
+
+class fixup_ir_call_visitor : public ir_hierarchical_visitor {
+public:
+ fixup_ir_call_visitor(struct hash_table *ht)
+ {
+ this->ht = ht;
+ }
+
+ virtual ir_visitor_status visit_enter(ir_call *ir)
+ {
+ /* Try to find the function signature referenced by the ir_call in the
+ * table. If it is found, replace it with the value from the table.
+ */
+ ir_function_signature *sig =
+ (ir_function_signature *) hash_table_find(this->ht, ir->get_callee());
+ if (sig != NULL)
+ ir->set_callee(sig);
+
+ /* Since this may be used before function call parameters are flattened,
+ * the children also need to be processed.
+ */
+ return visit_continue;
+ }
+
+private:
+ struct hash_table *ht;
+};
+
+
+static void
+fixup_function_calls(struct hash_table *ht, exec_list *instructions)
+{
+ fixup_ir_call_visitor v(ht);
+ v.run(instructions);
+}
+
+
+void
+clone_ir_list(void *mem_ctx, exec_list *out, const exec_list *in)
+{
+ struct hash_table *ht =
+ hash_table_ctor(0, hash_table_pointer_hash, hash_table_pointer_compare);
+
+ foreach_list_const(node, in) {
+ const ir_instruction *const original = (ir_instruction *) node;
+ ir_instruction *copy = original->clone(mem_ctx, ht);
+
+ out->push_tail(copy);
+ }
+
+ /* Make a pass over the cloned tree to fix up ir_call nodes to point to the
+ * cloned ir_function_signature nodes. This cannot be done automatically
+ * during cloning because the ir_call might be a forward reference (i.e.,
+ * the function signature that it references may not have been cloned yet).
+ */
+ fixup_function_calls(ht, out);
+
+ hash_table_dtor(ht);
+}
diff --git a/src/glsl/ir_constant_expression.cpp b/src/glsl/ir_constant_expression.cpp
new file mode 100644
index 00000000000..0a924246da1
--- /dev/null
+++ b/src/glsl/ir_constant_expression.cpp
@@ -0,0 +1,1144 @@
+/*
+ * Copyright © 2010 Intel Corporation
+ *
+ * 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 (including the next
+ * paragraph) 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
+ * THE AUTHORS OR COPYRIGHT HOLDERS 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 ir_constant_expression.cpp
+ * Evaluate and process constant valued expressions
+ *
+ * In GLSL, constant valued expressions are used in several places. These
+ * must be processed and evaluated very early in the compilation process.
+ *
+ * * Sizes of arrays
+ * * Initializers for uniforms
+ * * Initializers for \c const variables
+ */
+
+#include <math.h>
+#include "main/macros.h"
+#include "ir.h"
+#include "ir_visitor.h"
+#include "glsl_types.h"
+
+static float
+dot(ir_constant *op0, ir_constant *op1)
+{
+ assert(op0->type->is_float() && op1->type->is_float());
+
+ float result = 0;
+ for (unsigned c = 0; c < op0->type->components(); c++)
+ result += op0->value.f[c] * op1->value.f[c];
+
+ return result;
+}
+
+ir_constant *
+ir_expression::constant_expression_value()
+{
+ ir_constant *op[2] = { NULL, NULL };
+ ir_constant_data data;
+
+ memset(&data, 0, sizeof(data));
+
+ for (unsigned operand = 0; operand < this->get_num_operands(); operand++) {
+ op[operand] = this->operands[operand]->constant_expression_value();
+ if (!op[operand])
+ return NULL;
+ }
+
+ if (op[1] != NULL)
+ assert(op[0]->type->base_type == op[1]->type->base_type);
+
+ bool op0_scalar = op[0]->type->is_scalar();
+ bool op1_scalar = op[1] != NULL && op[1]->type->is_scalar();
+
+ /* When iterating over a vector or matrix's components, we want to increase
+ * the loop counter. However, for scalars, we want to stay at 0.
+ */
+ unsigned c0_inc = op0_scalar ? 0 : 1;
+ unsigned c1_inc = op1_scalar ? 0 : 1;
+ unsigned components;
+ if (op1_scalar || !op[1]) {
+ components = op[0]->type->components();
+ } else {
+ components = op[1]->type->components();
+ }
+
+ void *ctx = talloc_parent(this);
+
+ /* Handle array operations here, rather than below. */
+ if (op[0]->type->is_array()) {
+ assert(op[1] != NULL && op[1]->type->is_array());
+ switch (this->operation) {
+ case ir_binop_equal:
+ return new(ctx) ir_constant(op[0]->has_value(op[1]));
+ case ir_binop_nequal:
+ return new(ctx) ir_constant(!op[0]->has_value(op[1]));
+ default:
+ break;
+ }
+ return NULL;
+ }
+
+ switch (this->operation) {
+ case ir_unop_logic_not:
+ assert(op[0]->type->base_type == GLSL_TYPE_BOOL);
+ for (unsigned c = 0; c < op[0]->type->components(); c++)
+ data.b[c] = !op[0]->value.b[c];
+ break;
+
+ case ir_unop_f2i:
+ assert(op[0]->type->base_type == GLSL_TYPE_FLOAT);
+ for (unsigned c = 0; c < op[0]->type->components(); c++) {
+ data.i[c] = op[0]->value.f[c];
+ }
+ break;
+ case ir_unop_i2f:
+ assert(op[0]->type->base_type == GLSL_TYPE_INT);
+ for (unsigned c = 0; c < op[0]->type->components(); c++) {
+ data.f[c] = op[0]->value.i[c];
+ }
+ break;
+ case ir_unop_u2f:
+ assert(op[0]->type->base_type == GLSL_TYPE_UINT);
+ for (unsigned c = 0; c < op[0]->type->components(); c++) {
+ data.f[c] = op[0]->value.u[c];
+ }
+ break;
+ case ir_unop_b2f:
+ assert(op[0]->type->base_type == GLSL_TYPE_BOOL);
+ for (unsigned c = 0; c < op[0]->type->components(); c++) {
+ data.f[c] = op[0]->value.b[c] ? 1.0 : 0.0;
+ }
+ break;
+ case ir_unop_f2b:
+ assert(op[0]->type->base_type == GLSL_TYPE_FLOAT);
+ for (unsigned c = 0; c < op[0]->type->components(); c++) {
+ data.b[c] = bool(op[0]->value.f[c]);
+ }
+ break;
+ case ir_unop_b2i:
+ assert(op[0]->type->base_type == GLSL_TYPE_BOOL);
+ for (unsigned c = 0; c < op[0]->type->components(); c++) {
+ data.u[c] = op[0]->value.b[c] ? 1 : 0;
+ }
+ break;
+ case ir_unop_i2b:
+ assert(op[0]->type->is_integer());
+ for (unsigned c = 0; c < op[0]->type->components(); c++) {
+ data.b[c] = bool(op[0]->value.u[c]);
+ }
+ break;
+
+ case ir_unop_trunc:
+ assert(op[0]->type->base_type == GLSL_TYPE_FLOAT);
+ for (unsigned c = 0; c < op[0]->type->components(); c++) {
+ data.f[c] = truncf(op[0]->value.f[c]);
+ }
+ break;
+
+ case ir_unop_ceil:
+ assert(op[0]->type->base_type == GLSL_TYPE_FLOAT);
+ for (unsigned c = 0; c < op[0]->type->components(); c++) {
+ data.f[c] = ceilf(op[0]->value.f[c]);
+ }
+ break;
+
+ case ir_unop_floor:
+ assert(op[0]->type->base_type == GLSL_TYPE_FLOAT);
+ for (unsigned c = 0; c < op[0]->type->components(); c++) {
+ data.f[c] = floorf(op[0]->value.f[c]);
+ }
+ break;
+
+ case ir_unop_fract:
+ for (unsigned c = 0; c < op[0]->type->components(); c++) {
+ switch (this->type->base_type) {
+ case GLSL_TYPE_UINT:
+ data.u[c] = 0;
+ break;
+ case GLSL_TYPE_INT:
+ data.i[c] = 0;
+ break;
+ case GLSL_TYPE_FLOAT:
+ data.f[c] = op[0]->value.f[c] - floor(op[0]->value.f[c]);
+ break;
+ default:
+ assert(0);
+ }
+ }
+ break;
+
+ case ir_unop_sin:
+ assert(op[0]->type->base_type == GLSL_TYPE_FLOAT);
+ for (unsigned c = 0; c < op[0]->type->components(); c++) {
+ data.f[c] = sinf(op[0]->value.f[c]);
+ }
+ break;
+
+ case ir_unop_cos:
+ assert(op[0]->type->base_type == GLSL_TYPE_FLOAT);
+ for (unsigned c = 0; c < op[0]->type->components(); c++) {
+ data.f[c] = cosf(op[0]->value.f[c]);
+ }
+ break;
+
+ case ir_unop_neg:
+ for (unsigned c = 0; c < op[0]->type->components(); c++) {
+ switch (this->type->base_type) {
+ case GLSL_TYPE_UINT:
+ data.u[c] = -op[0]->value.u[c];
+ break;
+ case GLSL_TYPE_INT:
+ data.i[c] = -op[0]->value.i[c];
+ break;
+ case GLSL_TYPE_FLOAT:
+ data.f[c] = -op[0]->value.f[c];
+ break;
+ default:
+ assert(0);
+ }
+ }
+ break;
+
+ case ir_unop_abs:
+ for (unsigned c = 0; c < op[0]->type->components(); c++) {
+ switch (this->type->base_type) {
+ case GLSL_TYPE_UINT:
+ data.u[c] = op[0]->value.u[c];
+ break;
+ case GLSL_TYPE_INT:
+ data.i[c] = op[0]->value.i[c];
+ if (data.i[c] < 0)
+ data.i[c] = -data.i[c];
+ break;
+ case GLSL_TYPE_FLOAT:
+ data.f[c] = fabs(op[0]->value.f[c]);
+ break;
+ default:
+ assert(0);
+ }
+ }
+ break;
+
+ case ir_unop_sign:
+ for (unsigned c = 0; c < op[0]->type->components(); c++) {
+ switch (this->type->base_type) {
+ case GLSL_TYPE_UINT:
+ data.u[c] = op[0]->value.i[c] > 0;
+ break;
+ case GLSL_TYPE_INT:
+ data.i[c] = (op[0]->value.i[c] > 0) - (op[0]->value.i[c] < 0);
+ break;
+ case GLSL_TYPE_FLOAT:
+ data.f[c] = float((op[0]->value.f[c] > 0)-(op[0]->value.f[c] < 0));
+ break;
+ default:
+ assert(0);
+ }
+ }
+ break;
+
+ case ir_unop_rcp:
+ assert(op[0]->type->base_type == GLSL_TYPE_FLOAT);
+ for (unsigned c = 0; c < op[0]->type->components(); c++) {
+ switch (this->type->base_type) {
+ case GLSL_TYPE_UINT:
+ if (op[0]->value.u[c] != 0.0)
+ data.u[c] = 1 / op[0]->value.u[c];
+ break;
+ case GLSL_TYPE_INT:
+ if (op[0]->value.i[c] != 0.0)
+ data.i[c] = 1 / op[0]->value.i[c];
+ break;
+ case GLSL_TYPE_FLOAT:
+ if (op[0]->value.f[c] != 0.0)
+ data.f[c] = 1.0 / op[0]->value.f[c];
+ break;
+ default:
+ assert(0);
+ }
+ }
+ break;
+
+ case ir_unop_rsq:
+ assert(op[0]->type->base_type == GLSL_TYPE_FLOAT);
+ for (unsigned c = 0; c < op[0]->type->components(); c++) {
+ data.f[c] = 1.0 / sqrtf(op[0]->value.f[c]);
+ }
+ break;
+
+ case ir_unop_sqrt:
+ assert(op[0]->type->base_type == GLSL_TYPE_FLOAT);
+ for (unsigned c = 0; c < op[0]->type->components(); c++) {
+ data.f[c] = sqrtf(op[0]->value.f[c]);
+ }
+ break;
+
+ case ir_unop_exp:
+ assert(op[0]->type->base_type == GLSL_TYPE_FLOAT);
+ for (unsigned c = 0; c < op[0]->type->components(); c++) {
+ data.f[c] = expf(op[0]->value.f[c]);
+ }
+ break;
+
+ case ir_unop_exp2:
+ assert(op[0]->type->base_type == GLSL_TYPE_FLOAT);
+ for (unsigned c = 0; c < op[0]->type->components(); c++) {
+ data.f[c] = exp2f(op[0]->value.f[c]);
+ }
+ break;
+
+ case ir_unop_log:
+ assert(op[0]->type->base_type == GLSL_TYPE_FLOAT);
+ for (unsigned c = 0; c < op[0]->type->components(); c++) {
+ data.f[c] = logf(op[0]->value.f[c]);
+ }
+ break;
+
+ case ir_unop_log2:
+ assert(op[0]->type->base_type == GLSL_TYPE_FLOAT);
+ for (unsigned c = 0; c < op[0]->type->components(); c++) {
+ data.f[c] = log2f(op[0]->value.f[c]);
+ }
+ break;
+
+ case ir_unop_dFdx:
+ case ir_unop_dFdy:
+ assert(op[0]->type->base_type == GLSL_TYPE_FLOAT);
+ for (unsigned c = 0; c < op[0]->type->components(); c++) {
+ data.f[c] = 0.0;
+ }
+ break;
+
+ case ir_binop_pow:
+ assert(op[0]->type->base_type == GLSL_TYPE_FLOAT);
+ for (unsigned c = 0; c < op[0]->type->components(); c++) {
+ data.f[c] = powf(op[0]->value.f[c], op[1]->value.f[c]);
+ }
+ break;
+
+ case ir_binop_dot:
+ data.f[0] = dot(op[0], op[1]);
+ break;
+
+ case ir_binop_min:
+ assert(op[0]->type == op[1]->type || op0_scalar || op1_scalar);
+ for (unsigned c = 0, c0 = 0, c1 = 0;
+ c < components;
+ c0 += c0_inc, c1 += c1_inc, c++) {
+
+ switch (op[0]->type->base_type) {
+ case GLSL_TYPE_UINT:
+ data.u[c] = MIN2(op[0]->value.u[c0], op[1]->value.u[c1]);
+ break;
+ case GLSL_TYPE_INT:
+ data.i[c] = MIN2(op[0]->value.i[c0], op[1]->value.i[c1]);
+ break;
+ case GLSL_TYPE_FLOAT:
+ data.f[c] = MIN2(op[0]->value.f[c0], op[1]->value.f[c1]);
+ break;
+ default:
+ assert(0);
+ }
+ }
+
+ break;
+ case ir_binop_max:
+ assert(op[0]->type == op[1]->type || op0_scalar || op1_scalar);
+ for (unsigned c = 0, c0 = 0, c1 = 0;
+ c < components;
+ c0 += c0_inc, c1 += c1_inc, c++) {
+
+ switch (op[0]->type->base_type) {
+ case GLSL_TYPE_UINT:
+ data.u[c] = MAX2(op[0]->value.u[c0], op[1]->value.u[c1]);
+ break;
+ case GLSL_TYPE_INT:
+ data.i[c] = MAX2(op[0]->value.i[c0], op[1]->value.i[c1]);
+ break;
+ case GLSL_TYPE_FLOAT:
+ data.f[c] = MAX2(op[0]->value.f[c0], op[1]->value.f[c1]);
+ break;
+ default:
+ assert(0);
+ }
+ }
+ break;
+
+ case ir_binop_cross:
+ assert(op[0]->type == glsl_type::vec3_type);
+ assert(op[1]->type == glsl_type::vec3_type);
+ data.f[0] = (op[0]->value.f[1] * op[1]->value.f[2] -
+ op[1]->value.f[1] * op[0]->value.f[2]);
+ data.f[1] = (op[0]->value.f[2] * op[1]->value.f[0] -
+ op[1]->value.f[2] * op[0]->value.f[0]);
+ data.f[2] = (op[0]->value.f[0] * op[1]->value.f[1] -
+ op[1]->value.f[0] * op[0]->value.f[1]);
+ break;
+
+ case ir_binop_add:
+ assert(op[0]->type == op[1]->type || op0_scalar || op1_scalar);
+ for (unsigned c = 0, c0 = 0, c1 = 0;
+ c < components;
+ c0 += c0_inc, c1 += c1_inc, c++) {
+
+ switch (op[0]->type->base_type) {
+ case GLSL_TYPE_UINT:
+ data.u[c] = op[0]->value.u[c0] + op[1]->value.u[c1];
+ break;
+ case GLSL_TYPE_INT:
+ data.i[c] = op[0]->value.i[c0] + op[1]->value.i[c1];
+ break;
+ case GLSL_TYPE_FLOAT:
+ data.f[c] = op[0]->value.f[c0] + op[1]->value.f[c1];
+ break;
+ default:
+ assert(0);
+ }
+ }
+
+ break;
+ case ir_binop_sub:
+ assert(op[0]->type == op[1]->type || op0_scalar || op1_scalar);
+ for (unsigned c = 0, c0 = 0, c1 = 0;
+ c < components;
+ c0 += c0_inc, c1 += c1_inc, c++) {
+
+ switch (op[0]->type->base_type) {
+ case GLSL_TYPE_UINT:
+ data.u[c] = op[0]->value.u[c0] - op[1]->value.u[c1];
+ break;
+ case GLSL_TYPE_INT:
+ data.i[c] = op[0]->value.i[c0] - op[1]->value.i[c1];
+ break;
+ case GLSL_TYPE_FLOAT:
+ data.f[c] = op[0]->value.f[c0] - op[1]->value.f[c1];
+ break;
+ default:
+ assert(0);
+ }
+ }
+
+ break;
+ case ir_binop_mul:
+ /* Check for equal types, or unequal types involving scalars */
+ if ((op[0]->type == op[1]->type && !op[0]->type->is_matrix())
+ || op0_scalar || op1_scalar) {
+ for (unsigned c = 0, c0 = 0, c1 = 0;
+ c < components;
+ c0 += c0_inc, c1 += c1_inc, c++) {
+
+ switch (op[0]->type->base_type) {
+ case GLSL_TYPE_UINT:
+ data.u[c] = op[0]->value.u[c0] * op[1]->value.u[c1];
+ break;
+ case GLSL_TYPE_INT:
+ data.i[c] = op[0]->value.i[c0] * op[1]->value.i[c1];
+ break;
+ case GLSL_TYPE_FLOAT:
+ data.f[c] = op[0]->value.f[c0] * op[1]->value.f[c1];
+ break;
+ default:
+ assert(0);
+ }
+ }
+ } else {
+ assert(op[0]->type->is_matrix() || op[1]->type->is_matrix());
+
+ /* Multiply an N-by-M matrix with an M-by-P matrix. Since either
+ * matrix can be a GLSL vector, either N or P can be 1.
+ *
+ * For vec*mat, the vector is treated as a row vector. This
+ * means the vector is a 1-row x M-column matrix.
+ *
+ * For mat*vec, the vector is treated as a column vector. Since
+ * matrix_columns is 1 for vectors, this just works.
+ */
+ const unsigned n = op[0]->type->is_vector()
+ ? 1 : op[0]->type->vector_elements;
+ const unsigned m = op[1]->type->vector_elements;
+ const unsigned p = op[1]->type->matrix_columns;
+ for (unsigned j = 0; j < p; j++) {
+ for (unsigned i = 0; i < n; i++) {
+ for (unsigned k = 0; k < m; k++) {
+ data.f[i+n*j] += op[0]->value.f[i+n*k]*op[1]->value.f[k+m*j];
+ }
+ }
+ }
+ }
+
+ break;
+ case ir_binop_div:
+ assert(op[0]->type == op[1]->type || op0_scalar || op1_scalar);
+ for (unsigned c = 0, c0 = 0, c1 = 0;
+ c < components;
+ c0 += c0_inc, c1 += c1_inc, c++) {
+
+ switch (op[0]->type->base_type) {
+ case GLSL_TYPE_UINT:
+ data.u[c] = op[0]->value.u[c0] / op[1]->value.u[c1];
+ break;
+ case GLSL_TYPE_INT:
+ data.i[c] = op[0]->value.i[c0] / op[1]->value.i[c1];
+ break;
+ case GLSL_TYPE_FLOAT:
+ data.f[c] = op[0]->value.f[c0] / op[1]->value.f[c1];
+ break;
+ default:
+ assert(0);
+ }
+ }
+
+ break;
+ case ir_binop_mod:
+ assert(op[0]->type == op[1]->type || op0_scalar || op1_scalar);
+ for (unsigned c = 0, c0 = 0, c1 = 0;
+ c < components;
+ c0 += c0_inc, c1 += c1_inc, c++) {
+
+ switch (op[0]->type->base_type) {
+ case GLSL_TYPE_UINT:
+ data.u[c] = op[0]->value.u[c0] % op[1]->value.u[c1];
+ break;
+ case GLSL_TYPE_INT:
+ data.i[c] = op[0]->value.i[c0] % op[1]->value.i[c1];
+ break;
+ case GLSL_TYPE_FLOAT:
+ /* We don't use fmod because it rounds toward zero; GLSL specifies
+ * the use of floor.
+ */
+ data.f[c] = op[0]->value.f[c0] - op[1]->value.f[c1]
+ * floorf(op[0]->value.f[c0] / op[1]->value.f[c1]);
+ break;
+ default:
+ assert(0);
+ }
+ }
+
+ break;
+
+ case ir_binop_logic_and:
+ assert(op[0]->type->base_type == GLSL_TYPE_BOOL);
+ for (unsigned c = 0; c < op[0]->type->components(); c++)
+ data.b[c] = op[0]->value.b[c] && op[1]->value.b[c];
+ break;
+ case ir_binop_logic_xor:
+ assert(op[0]->type->base_type == GLSL_TYPE_BOOL);
+ for (unsigned c = 0; c < op[0]->type->components(); c++)
+ data.b[c] = op[0]->value.b[c] ^ op[1]->value.b[c];
+ break;
+ case ir_binop_logic_or:
+ assert(op[0]->type->base_type == GLSL_TYPE_BOOL);
+ for (unsigned c = 0; c < op[0]->type->components(); c++)
+ data.b[c] = op[0]->value.b[c] || op[1]->value.b[c];
+ break;
+
+ case ir_binop_less:
+ switch (op[0]->type->base_type) {
+ case GLSL_TYPE_UINT:
+ data.b[0] = op[0]->value.u[0] < op[1]->value.u[0];
+ break;
+ case GLSL_TYPE_INT:
+ data.b[0] = op[0]->value.i[0] < op[1]->value.i[0];
+ break;
+ case GLSL_TYPE_FLOAT:
+ data.b[0] = op[0]->value.f[0] < op[1]->value.f[0];
+ break;
+ default:
+ assert(0);
+ }
+ break;
+ case ir_binop_greater:
+ switch (op[0]->type->base_type) {
+ case GLSL_TYPE_UINT:
+ data.b[0] = op[0]->value.u[0] > op[1]->value.u[0];
+ break;
+ case GLSL_TYPE_INT:
+ data.b[0] = op[0]->value.i[0] > op[1]->value.i[0];
+ break;
+ case GLSL_TYPE_FLOAT:
+ data.b[0] = op[0]->value.f[0] > op[1]->value.f[0];
+ break;
+ default:
+ assert(0);
+ }
+ break;
+ case ir_binop_lequal:
+ switch (op[0]->type->base_type) {
+ case GLSL_TYPE_UINT:
+ data.b[0] = op[0]->value.u[0] <= op[1]->value.u[0];
+ break;
+ case GLSL_TYPE_INT:
+ data.b[0] = op[0]->value.i[0] <= op[1]->value.i[0];
+ break;
+ case GLSL_TYPE_FLOAT:
+ data.b[0] = op[0]->value.f[0] <= op[1]->value.f[0];
+ break;
+ default:
+ assert(0);
+ }
+ break;
+ case ir_binop_gequal:
+ switch (op[0]->type->base_type) {
+ case GLSL_TYPE_UINT:
+ data.b[0] = op[0]->value.u[0] >= op[1]->value.u[0];
+ break;
+ case GLSL_TYPE_INT:
+ data.b[0] = op[0]->value.i[0] >= op[1]->value.i[0];
+ break;
+ case GLSL_TYPE_FLOAT:
+ data.b[0] = op[0]->value.f[0] >= op[1]->value.f[0];
+ break;
+ default:
+ assert(0);
+ }
+ break;
+
+ case ir_binop_equal:
+ data.b[0] = op[0]->has_value(op[1]);
+ break;
+ case ir_binop_nequal:
+ data.b[0] = !op[0]->has_value(op[1]);
+ break;
+
+ default:
+ /* FINISHME: Should handle all expression types. */
+ return NULL;
+ }
+
+ return new(ctx) ir_constant(this->type, &data);
+}
+
+
+ir_constant *
+ir_texture::constant_expression_value()
+{
+ /* texture lookups aren't constant expressions */
+ return NULL;
+}
+
+
+ir_constant *
+ir_swizzle::constant_expression_value()
+{
+ ir_constant *v = this->val->constant_expression_value();
+
+ if (v != NULL) {
+ ir_constant_data data;
+
+ const unsigned swiz_idx[4] = {
+ this->mask.x, this->mask.y, this->mask.z, this->mask.w
+ };
+
+ for (unsigned i = 0; i < this->mask.num_components; i++) {
+ switch (v->type->base_type) {
+ case GLSL_TYPE_UINT:
+ case GLSL_TYPE_INT: data.u[i] = v->value.u[swiz_idx[i]]; break;
+ case GLSL_TYPE_FLOAT: data.f[i] = v->value.f[swiz_idx[i]]; break;
+ case GLSL_TYPE_BOOL: data.b[i] = v->value.b[swiz_idx[i]]; break;
+ default: assert(!"Should not get here."); break;
+ }
+ }
+
+ void *ctx = talloc_parent(this);
+ return new(ctx) ir_constant(this->type, &data);
+ }
+ return NULL;
+}
+
+
+ir_constant *
+ir_dereference_variable::constant_expression_value()
+{
+ /* This may occur during compile and var->type is glsl_type::error_type */
+ if (!var)
+ return NULL;
+
+ /* The constant_value of a uniform variable is its initializer,
+ * not the lifetime constant value of the uniform.
+ */
+ if (var->mode == ir_var_uniform)
+ return NULL;
+
+ if (!var->constant_value)
+ return NULL;
+
+ return var->constant_value->clone(talloc_parent(var), NULL);
+}
+
+
+ir_constant *
+ir_dereference_array::constant_expression_value()
+{
+ ir_constant *array = this->array->constant_expression_value();
+ ir_constant *idx = this->array_index->constant_expression_value();
+
+ if ((array != NULL) && (idx != NULL)) {
+ void *ctx = talloc_parent(this);
+ if (array->type->is_matrix()) {
+ /* Array access of a matrix results in a vector.
+ */
+ const unsigned column = idx->value.u[0];
+
+ const glsl_type *const column_type = array->type->column_type();
+
+ /* Offset in the constant matrix to the first element of the column
+ * to be extracted.
+ */
+ const unsigned mat_idx = column * column_type->vector_elements;
+
+ ir_constant_data data;
+
+ switch (column_type->base_type) {
+ case GLSL_TYPE_UINT:
+ case GLSL_TYPE_INT:
+ for (unsigned i = 0; i < column_type->vector_elements; i++)
+ data.u[i] = array->value.u[mat_idx + i];
+
+ break;
+
+ case GLSL_TYPE_FLOAT:
+ for (unsigned i = 0; i < column_type->vector_elements; i++)
+ data.f[i] = array->value.f[mat_idx + i];
+
+ break;
+
+ default:
+ assert(!"Should not get here.");
+ break;
+ }
+
+ return new(ctx) ir_constant(column_type, &data);
+ } else if (array->type->is_vector()) {
+ const unsigned component = idx->value.u[0];
+
+ return new(ctx) ir_constant(array, component);
+ } else {
+ const unsigned index = idx->value.u[0];
+ return array->get_array_element(index)->clone(ctx, NULL);
+ }
+ }
+ return NULL;
+}
+
+
+ir_constant *
+ir_dereference_record::constant_expression_value()
+{
+ ir_constant *v = this->record->constant_expression_value();
+
+ return (v != NULL) ? v->get_record_field(this->field) : NULL;
+}
+
+
+ir_constant *
+ir_assignment::constant_expression_value()
+{
+ /* FINISHME: Handle CEs involving assignment (return RHS) */
+ return NULL;
+}
+
+
+ir_constant *
+ir_constant::constant_expression_value()
+{
+ return this;
+}
+
+
+ir_constant *
+ir_call::constant_expression_value()
+{
+ if (this->type == glsl_type::error_type)
+ return NULL;
+
+ /* From the GLSL 1.20 spec, page 23:
+ * "Function calls to user-defined functions (non-built-in functions)
+ * cannot be used to form constant expressions."
+ */
+ if (!this->callee->is_built_in)
+ return NULL;
+
+ unsigned num_parameters = 0;
+
+ /* Check if all parameters are constant */
+ ir_constant *op[3];
+ foreach_list(n, &this->actual_parameters) {
+ ir_constant *constant = ((ir_rvalue *) n)->constant_expression_value();
+ if (constant == NULL)
+ return NULL;
+
+ op[num_parameters] = constant;
+
+ assert(num_parameters < 3);
+ num_parameters++;
+ }
+
+ /* Individual cases below can either:
+ * - Assign "expr" a new ir_expression to evaluate (for basic opcodes)
+ * - Fill "data" with appopriate constant data
+ * - Return an ir_constant directly.
+ */
+ void *mem_ctx = talloc_parent(this);
+ ir_expression *expr = NULL;
+
+ ir_constant_data data;
+ memset(&data, 0, sizeof(data));
+
+ const char *callee = this->callee_name();
+ if (strcmp(callee, "abs") == 0) {
+ expr = new(mem_ctx) ir_expression(ir_unop_abs, type, op[0], NULL);
+ } else if (strcmp(callee, "all") == 0) {
+ assert(op[0]->type->is_boolean());
+ for (unsigned c = 0; c < op[0]->type->components(); c++) {
+ if (!op[0]->value.b[c])
+ return new(mem_ctx) ir_constant(false);
+ }
+ return new(mem_ctx) ir_constant(true);
+ } else if (strcmp(callee, "any") == 0) {
+ assert(op[0]->type->is_boolean());
+ for (unsigned c = 0; c < op[0]->type->components(); c++) {
+ if (op[0]->value.b[c])
+ return new(mem_ctx) ir_constant(true);
+ }
+ return new(mem_ctx) ir_constant(false);
+ } else if (strcmp(callee, "acos") == 0) {
+ assert(op[0]->type->is_float());
+ for (unsigned c = 0; c < op[0]->type->components(); c++)
+ data.f[c] = acosf(op[0]->value.f[c]);
+ } else if (strcmp(callee, "asin") == 0) {
+ assert(op[0]->type->is_float());
+ for (unsigned c = 0; c < op[0]->type->components(); c++)
+ data.f[c] = asinf(op[0]->value.f[c]);
+ } else if (strcmp(callee, "atan") == 0) {
+ assert(op[0]->type->is_float());
+ if (num_parameters == 2) {
+ assert(op[1]->type->is_float());
+ for (unsigned c = 0; c < op[0]->type->components(); c++)
+ data.f[c] = atan2f(op[0]->value.f[c], op[1]->value.f[c]);
+ } else {
+ for (unsigned c = 0; c < op[0]->type->components(); c++)
+ data.f[c] = atanf(op[0]->value.f[c]);
+ }
+ } else if (strcmp(callee, "dFdx") == 0 || strcmp(callee, "dFdy") == 0) {
+ return ir_constant::zero(mem_ctx, this->type);
+ } else if (strcmp(callee, "ceil") == 0) {
+ expr = new(mem_ctx) ir_expression(ir_unop_ceil, type, op[0], NULL);
+ } else if (strcmp(callee, "clamp") == 0) {
+ assert(num_parameters == 3);
+ unsigned c1_inc = op[1]->type->is_scalar() ? 0 : 1;
+ unsigned c2_inc = op[2]->type->is_scalar() ? 0 : 1;
+ for (unsigned c = 0, c1 = 0, c2 = 0;
+ c < op[0]->type->components();
+ c1 += c1_inc, c2 += c2_inc, c++) {
+
+ switch (op[0]->type->base_type) {
+ case GLSL_TYPE_UINT:
+ data.u[c] = CLAMP(op[0]->value.u[c], op[1]->value.u[c1],
+ op[2]->value.u[c2]);
+ break;
+ case GLSL_TYPE_INT:
+ data.i[c] = CLAMP(op[0]->value.i[c], op[1]->value.i[c1],
+ op[2]->value.i[c2]);
+ break;
+ case GLSL_TYPE_FLOAT:
+ data.f[c] = CLAMP(op[0]->value.f[c], op[1]->value.f[c1],
+ op[2]->value.f[c2]);
+ break;
+ default:
+ assert(!"Should not get here.");
+ }
+ }
+ } else if (strcmp(callee, "cos") == 0) {
+ expr = new(mem_ctx) ir_expression(ir_unop_cos, type, op[0], NULL);
+ } else if (strcmp(callee, "cosh") == 0) {
+ assert(op[0]->type->is_float());
+ for (unsigned c = 0; c < op[0]->type->components(); c++)
+ data.f[c] = coshf(op[0]->value.f[c]);
+ } else if (strcmp(callee, "cross") == 0) {
+ expr = new(mem_ctx) ir_expression(ir_binop_cross, type, op[0], op[1]);
+ } else if (strcmp(callee, "degrees") == 0) {
+ assert(op[0]->type->is_float());
+ for (unsigned c = 0; c < op[0]->type->components(); c++)
+ data.f[c] = 180.0/M_PI * op[0]->value.f[c];
+ } else if (strcmp(callee, "distance") == 0) {
+ assert(op[0]->type->is_float() && op[1]->type->is_float());
+ float length_squared = 0.0;
+ for (unsigned c = 0; c < op[0]->type->components(); c++) {
+ float t = op[0]->value.f[c] - op[1]->value.f[c];
+ length_squared += t * t;
+ }
+ return new(mem_ctx) ir_constant(sqrtf(length_squared));
+ } else if (strcmp(callee, "dot") == 0) {
+ return new(mem_ctx) ir_constant(dot(op[0], op[1]));
+ } else if (strcmp(callee, "equal") == 0) {
+ assert(op[0]->type->is_vector() && op[1] && op[1]->type->is_vector());
+ for (unsigned c = 0; c < op[0]->type->components(); c++) {
+ switch (op[0]->type->base_type) {
+ case GLSL_TYPE_UINT:
+ data.b[c] = op[0]->value.u[c] == op[1]->value.u[c];
+ break;
+ case GLSL_TYPE_INT:
+ data.b[c] = op[0]->value.i[c] == op[1]->value.i[c];
+ break;
+ case GLSL_TYPE_FLOAT:
+ data.b[c] = op[0]->value.f[c] == op[1]->value.f[c];
+ break;
+ default:
+ assert(!"Should not get here.");
+ }
+ }
+ } else if (strcmp(callee, "exp") == 0) {
+ expr = new(mem_ctx) ir_expression(ir_unop_exp, type, op[0], NULL);
+ } else if (strcmp(callee, "exp2") == 0) {
+ expr = new(mem_ctx) ir_expression(ir_unop_exp2, type, op[0], NULL);
+ } else if (strcmp(callee, "faceforward") == 0) {
+ if (dot(op[2], op[1]) < 0)
+ return op[0];
+ for (unsigned c = 0; c < op[0]->type->components(); c++)
+ data.f[c] = -op[0]->value.f[c];
+ } else if (strcmp(callee, "floor") == 0) {
+ expr = new(mem_ctx) ir_expression(ir_unop_floor, type, op[0], NULL);
+ } else if (strcmp(callee, "fract") == 0) {
+ expr = new(mem_ctx) ir_expression(ir_unop_fract, type, op[0], NULL);
+ } else if (strcmp(callee, "fwidth") == 0) {
+ return ir_constant::zero(mem_ctx, this->type);
+ } else if (strcmp(callee, "greaterThan") == 0) {
+ assert(op[0]->type->is_vector() && op[1] && op[1]->type->is_vector());
+ for (unsigned c = 0; c < op[0]->type->components(); c++) {
+ switch (op[0]->type->base_type) {
+ case GLSL_TYPE_UINT:
+ data.b[c] = op[0]->value.u[c] > op[1]->value.u[c];
+ break;
+ case GLSL_TYPE_INT:
+ data.b[c] = op[0]->value.i[c] > op[1]->value.i[c];
+ break;
+ case GLSL_TYPE_FLOAT:
+ data.b[c] = op[0]->value.f[c] > op[1]->value.f[c];
+ break;
+ default:
+ assert(!"Should not get here.");
+ }
+ }
+ } else if (strcmp(callee, "greaterThanEqual") == 0) {
+ assert(op[0]->type->is_vector() && op[1] && op[1]->type->is_vector());
+ for (unsigned c = 0; c < op[0]->type->components(); c++) {
+ switch (op[0]->type->base_type) {
+ case GLSL_TYPE_UINT:
+ data.b[c] = op[0]->value.u[c] >= op[1]->value.u[c];
+ break;
+ case GLSL_TYPE_INT:
+ data.b[c] = op[0]->value.i[c] >= op[1]->value.i[c];
+ break;
+ case GLSL_TYPE_FLOAT:
+ data.b[c] = op[0]->value.f[c] >= op[1]->value.f[c];
+ break;
+ default:
+ assert(!"Should not get here.");
+ }
+ }
+ } else if (strcmp(callee, "inversesqrt") == 0) {
+ expr = new(mem_ctx) ir_expression(ir_unop_rsq, type, op[0], NULL);
+ } else if (strcmp(callee, "length") == 0) {
+ return new(mem_ctx) ir_constant(sqrtf(dot(op[0], op[0])));
+ } else if (strcmp(callee, "lessThan") == 0) {
+ assert(op[0]->type->is_vector() && op[1] && op[1]->type->is_vector());
+ for (unsigned c = 0; c < op[0]->type->components(); c++) {
+ switch (op[0]->type->base_type) {
+ case GLSL_TYPE_UINT:
+ data.b[c] = op[0]->value.u[c] < op[1]->value.u[c];
+ break;
+ case GLSL_TYPE_INT:
+ data.b[c] = op[0]->value.i[c] < op[1]->value.i[c];
+ break;
+ case GLSL_TYPE_FLOAT:
+ data.b[c] = op[0]->value.f[c] < op[1]->value.f[c];
+ break;
+ default:
+ assert(!"Should not get here.");
+ }
+ }
+ } else if (strcmp(callee, "lessThanEqual") == 0) {
+ assert(op[0]->type->is_vector() && op[1] && op[1]->type->is_vector());
+ for (unsigned c = 0; c < op[0]->type->components(); c++) {
+ switch (op[0]->type->base_type) {
+ case GLSL_TYPE_UINT:
+ data.b[c] = op[0]->value.u[c] <= op[1]->value.u[c];
+ break;
+ case GLSL_TYPE_INT:
+ data.b[c] = op[0]->value.i[c] <= op[1]->value.i[c];
+ break;
+ case GLSL_TYPE_FLOAT:
+ data.b[c] = op[0]->value.f[c] <= op[1]->value.f[c];
+ break;
+ default:
+ assert(!"Should not get here.");
+ }
+ }
+ } else if (strcmp(callee, "log") == 0) {
+ expr = new(mem_ctx) ir_expression(ir_unop_log, type, op[0], NULL);
+ } else if (strcmp(callee, "log2") == 0) {
+ expr = new(mem_ctx) ir_expression(ir_unop_log2, type, op[0], NULL);
+ } else if (strcmp(callee, "matrixCompMult") == 0) {
+ assert(op[0]->type->is_float() && op[1]->type->is_float());
+ for (unsigned c = 0; c < op[0]->type->components(); c++)
+ data.f[c] = op[0]->value.f[c] * op[1]->value.f[c];
+ } else if (strcmp(callee, "max") == 0) {
+ expr = new(mem_ctx) ir_expression(ir_binop_max, type, op[0], op[1]);
+ } else if (strcmp(callee, "min") == 0) {
+ expr = new(mem_ctx) ir_expression(ir_binop_min, type, op[0], op[1]);
+ } else if (strcmp(callee, "mix") == 0) {
+ assert(op[0]->type->is_float() && op[1]->type->is_float());
+ if (op[2]->type->is_float()) {
+ unsigned c2_inc = op[2]->type->is_scalar() ? 0 : 1;
+ unsigned components = op[0]->type->components();
+ for (unsigned c = 0, c2 = 0; c < components; c2 += c2_inc, c++) {
+ data.f[c] = op[0]->value.f[c] * (1 - op[2]->value.f[c2]) +
+ op[1]->value.f[c] * op[2]->value.f[c2];
+ }
+ } else {
+ assert(op[2]->type->is_boolean());
+ for (unsigned c = 0; c < op[0]->type->components(); c++)
+ data.f[c] = op[op[2]->value.b[c] ? 1 : 0]->value.f[c];
+ }
+ } else if (strcmp(callee, "mod") == 0) {
+ expr = new(mem_ctx) ir_expression(ir_binop_mod, type, op[0], op[1]);
+ } else if (strcmp(callee, "normalize") == 0) {
+ assert(op[0]->type->is_float());
+ float length = sqrtf(dot(op[0], op[0]));
+
+ if (length == 0)
+ return ir_constant::zero(mem_ctx, this->type);
+
+ for (unsigned c = 0; c < op[0]->type->components(); c++)
+ data.f[c] = op[0]->value.f[c] / length;
+ } else if (strcmp(callee, "not") == 0) {
+ expr = new(mem_ctx) ir_expression(ir_unop_logic_not, type, op[0], NULL);
+ } else if (strcmp(callee, "notEqual") == 0) {
+ assert(op[0]->type->is_vector() && op[1] && op[1]->type->is_vector());
+ for (unsigned c = 0; c < op[0]->type->components(); c++) {
+ switch (op[0]->type->base_type) {
+ case GLSL_TYPE_UINT:
+ data.b[c] = op[0]->value.u[c] != op[1]->value.u[c];
+ break;
+ case GLSL_TYPE_INT:
+ data.b[c] = op[0]->value.i[c] != op[1]->value.i[c];
+ break;
+ case GLSL_TYPE_FLOAT:
+ data.b[c] = op[0]->value.f[c] != op[1]->value.f[c];
+ break;
+ default:
+ assert(!"Should not get here.");
+ }
+ }
+ } else if (strcmp(callee, "outerProduct") == 0) {
+ assert(op[0]->type->is_vector() && op[1]->type->is_vector());
+ const unsigned m = op[0]->type->vector_elements;
+ const unsigned n = op[1]->type->vector_elements;
+ for (unsigned j = 0; j < n; j++) {
+ for (unsigned i = 0; i < m; i++) {
+ data.f[i+m*j] = op[0]->value.f[i] * op[1]->value.f[j];
+ }
+ }
+ } else if (strcmp(callee, "pow") == 0) {
+ expr = new(mem_ctx) ir_expression(ir_binop_pow, type, op[0], op[1]);
+ } else if (strcmp(callee, "radians") == 0) {
+ assert(op[0]->type->is_float());
+ for (unsigned c = 0; c < op[0]->type->components(); c++)
+ data.f[c] = M_PI/180.0 * op[0]->value.f[c];
+ } else if (strcmp(callee, "reflect") == 0) {
+ assert(op[0]->type->is_float());
+ float dot_NI = dot(op[1], op[0]);
+ for (unsigned c = 0; c < op[0]->type->components(); c++)
+ data.f[c] = op[0]->value.f[c] - 2 * dot_NI * op[1]->value.f[c];
+ } else if (strcmp(callee, "refract") == 0) {
+ const float eta = op[2]->value.f[0];
+ const float dot_NI = dot(op[1], op[0]);
+ const float k = 1.0 - eta * eta * (1.0 - dot_NI * dot_NI);
+ if (k < 0.0) {
+ return ir_constant::zero(mem_ctx, this->type);
+ } else {
+ for (unsigned c = 0; c < type->components(); c++) {
+ data.f[c] = eta * op[0]->value.f[c] - (eta * dot_NI + sqrtf(k))
+ * op[1]->value.f[c];
+ }
+ }
+ } else if (strcmp(callee, "sign") == 0) {
+ expr = new(mem_ctx) ir_expression(ir_unop_sign, type, op[0], NULL);
+ } else if (strcmp(callee, "sin") == 0) {
+ expr = new(mem_ctx) ir_expression(ir_unop_sin, type, op[0], NULL);
+ } else if (strcmp(callee, "sinh") == 0) {
+ assert(op[0]->type->is_float());
+ for (unsigned c = 0; c < op[0]->type->components(); c++)
+ data.f[c] = sinhf(op[0]->value.f[c]);
+ } else if (strcmp(callee, "smoothstep") == 0) {
+ assert(num_parameters == 3);
+ assert(op[1]->type == op[0]->type);
+ unsigned edge_inc = op[0]->type->is_scalar() ? 0 : 1;
+ for (unsigned c = 0, e = 0; c < type->components(); e += edge_inc, c++) {
+ const float edge0 = op[0]->value.f[e];
+ const float edge1 = op[1]->value.f[e];
+ if (edge0 == edge1) {
+ data.f[c] = 0.0; /* Avoid a crash - results are undefined anyway */
+ } else {
+ const float numerator = op[2]->value.f[c] - edge0;
+ const float denominator = edge1 - edge0;
+ const float t = CLAMP(numerator/denominator, 0, 1);
+ data.f[c] = t * t * (3 - 2 * t);
+ }
+ }
+ } else if (strcmp(callee, "sqrt") == 0) {
+ expr = new(mem_ctx) ir_expression(ir_unop_sqrt, type, op[0], NULL);
+ } else if (strcmp(callee, "step") == 0) {
+ assert(op[0]->type->is_float() && op[1]->type->is_float());
+ /* op[0] (edge) may be either a scalar or a vector */
+ const unsigned c0_inc = op[0]->type->is_scalar() ? 0 : 1;
+ for (unsigned c = 0, c0 = 0; c < type->components(); c0 += c0_inc, c++)
+ data.f[c] = (op[1]->value.f[c] < op[0]->value.f[c0]) ? 0.0 : 1.0;
+ } else if (strcmp(callee, "tan") == 0) {
+ assert(op[0]->type->is_float());
+ for (unsigned c = 0; c < op[0]->type->components(); c++)
+ data.f[c] = tanf(op[0]->value.f[c]);
+ } else if (strcmp(callee, "tanh") == 0) {
+ assert(op[0]->type->is_float());
+ for (unsigned c = 0; c < op[0]->type->components(); c++)
+ data.f[c] = tanhf(op[0]->value.f[c]);
+ } else if (strcmp(callee, "transpose") == 0) {
+ assert(op[0]->type->is_matrix());
+ const unsigned n = op[0]->type->vector_elements;
+ const unsigned m = op[0]->type->matrix_columns;
+ for (unsigned j = 0; j < m; j++) {
+ for (unsigned i = 0; i < n; i++) {
+ data.f[m*i+j] += op[0]->value.f[i+n*j];
+ }
+ }
+ } else {
+ /* Unsupported builtin - some are not allowed in constant expressions. */
+ return NULL;
+ }
+
+ if (expr != NULL)
+ return expr->constant_expression_value();
+
+ return new(mem_ctx) ir_constant(this->type, &data);
+}
diff --git a/src/glsl/ir_constant_folding.cpp b/src/glsl/ir_constant_folding.cpp
new file mode 100644
index 00000000000..11260423d90
--- /dev/null
+++ b/src/glsl/ir_constant_folding.cpp
@@ -0,0 +1,273 @@
+/*
+ * Copyright © 2010 Intel Corporation
+ *
+ * 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 (including the next
+ * paragraph) 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
+ * THE AUTHORS OR COPYRIGHT HOLDERS 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 ir_constant_folding.cpp
+ * Replace constant-valued expressions with references to constant values.
+ */
+
+#include "ir.h"
+#include "ir_visitor.h"
+#include "ir_optimization.h"
+#include "glsl_types.h"
+
+/**
+ * Visitor class for replacing expressions with ir_constant values.
+ */
+
+class ir_constant_folding_visitor : public ir_visitor {
+public:
+ ir_constant_folding_visitor()
+ {
+ this->progress = false;
+ }
+
+ virtual ~ir_constant_folding_visitor()
+ {
+ /* empty */
+ }
+
+ /**
+ * \name Visit methods
+ *
+ * As typical for the visitor pattern, there must be one \c visit method for
+ * each concrete subclass of \c ir_instruction. Virtual base classes within
+ * the hierarchy should not have \c visit methods.
+ */
+ /*@{*/
+ virtual void visit(ir_variable *);
+ virtual void visit(ir_function_signature *);
+ virtual void visit(ir_function *);
+ virtual void visit(ir_expression *);
+ virtual void visit(ir_texture *);
+ virtual void visit(ir_swizzle *);
+ virtual void visit(ir_dereference_variable *);
+ virtual void visit(ir_dereference_array *);
+ virtual void visit(ir_dereference_record *);
+ virtual void visit(ir_assignment *);
+ virtual void visit(ir_constant *);
+ virtual void visit(ir_call *);
+ virtual void visit(ir_return *);
+ virtual void visit(ir_discard *);
+ virtual void visit(ir_if *);
+ virtual void visit(ir_loop *);
+ virtual void visit(ir_loop_jump *);
+ /*@}*/
+
+ void fold_constant(ir_rvalue **rvalue);
+
+ bool progress;
+};
+
+void
+ir_constant_folding_visitor::fold_constant(ir_rvalue **rvalue)
+{
+ if (*rvalue == NULL || (*rvalue)->ir_type == ir_type_constant)
+ return;
+
+ ir_constant *constant = (*rvalue)->constant_expression_value();
+ if (constant) {
+ *rvalue = constant;
+ this->progress = true;
+ } else {
+ (*rvalue)->accept(this);
+ }
+}
+
+void
+ir_constant_folding_visitor::visit(ir_variable *ir)
+{
+ (void) ir;
+}
+
+
+void
+ir_constant_folding_visitor::visit(ir_function_signature *ir)
+{
+ visit_exec_list(&ir->body, this);
+}
+
+
+void
+ir_constant_folding_visitor::visit(ir_function *ir)
+{
+ foreach_iter(exec_list_iterator, iter, *ir) {
+ ir_function_signature *const sig = (ir_function_signature *) iter.get();
+ sig->accept(this);
+ }
+}
+
+void
+ir_constant_folding_visitor::visit(ir_expression *ir)
+{
+ unsigned int operand;
+
+ for (operand = 0; operand < ir->get_num_operands(); operand++) {
+ fold_constant(&ir->operands[operand]);
+ }
+}
+
+
+void
+ir_constant_folding_visitor::visit(ir_texture *ir)
+{
+ fold_constant(&ir->coordinate);
+ fold_constant(&ir->projector);
+ fold_constant(&ir->shadow_comparitor);
+
+ switch (ir->op) {
+ case ir_tex:
+ break;
+ case ir_txb:
+ fold_constant(&ir->lod_info.bias);
+ break;
+ case ir_txf:
+ case ir_txl:
+ fold_constant(&ir->lod_info.lod);
+ break;
+ case ir_txd:
+ fold_constant(&ir->lod_info.grad.dPdx);
+ fold_constant(&ir->lod_info.grad.dPdy);
+ break;
+ }
+}
+
+
+void
+ir_constant_folding_visitor::visit(ir_swizzle *ir)
+{
+ fold_constant(&ir->val);
+}
+
+
+void
+ir_constant_folding_visitor::visit(ir_dereference_variable *ir)
+{
+ (void) ir;
+}
+
+
+void
+ir_constant_folding_visitor::visit(ir_dereference_array *ir)
+{
+ fold_constant(&ir->array_index);
+ ir->array->accept(this);
+}
+
+
+void
+ir_constant_folding_visitor::visit(ir_dereference_record *ir)
+{
+ ir->record->accept(this);
+}
+
+
+void
+ir_constant_folding_visitor::visit(ir_assignment *ir)
+{
+ fold_constant(&ir->rhs);
+
+ if (ir->condition) {
+ /* If the condition is constant, either remove the condition or
+ * remove the never-executed assignment.
+ */
+ ir_constant *const_val = ir->condition->constant_expression_value();
+ if (const_val) {
+ if (const_val->value.b[0])
+ ir->condition = NULL;
+ else
+ ir->remove();
+ this->progress = true;
+ }
+ }
+}
+
+
+void
+ir_constant_folding_visitor::visit(ir_constant *ir)
+{
+ (void) ir;
+}
+
+
+void
+ir_constant_folding_visitor::visit(ir_call *ir)
+{
+ foreach_iter(exec_list_iterator, iter, *ir) {
+ ir_rvalue *param = (ir_rvalue *)iter.get();
+ ir_rvalue *new_param = param;
+ fold_constant(&new_param);
+
+ if (new_param != param) {
+ param->replace_with(new_param);
+ }
+ }
+}
+
+
+void
+ir_constant_folding_visitor::visit(ir_return *ir)
+{
+ fold_constant(&ir->value);
+}
+
+
+void
+ir_constant_folding_visitor::visit(ir_discard *ir)
+{
+ (void) ir;
+}
+
+
+void
+ir_constant_folding_visitor::visit(ir_if *ir)
+{
+ fold_constant(&ir->condition);
+
+ visit_exec_list(&ir->then_instructions, this);
+ visit_exec_list(&ir->else_instructions, this);
+}
+
+
+void
+ir_constant_folding_visitor::visit(ir_loop *ir)
+{
+ (void) ir;
+}
+
+
+void
+ir_constant_folding_visitor::visit(ir_loop_jump *ir)
+{
+ (void) ir;
+}
+
+bool
+do_constant_folding(exec_list *instructions)
+{
+ ir_constant_folding_visitor constant_folding;
+
+ visit_exec_list(instructions, &constant_folding);
+
+ return constant_folding.progress;
+}
diff --git a/src/glsl/ir_constant_propagation.cpp b/src/glsl/ir_constant_propagation.cpp
new file mode 100644
index 00000000000..76c1ce7013f
--- /dev/null
+++ b/src/glsl/ir_constant_propagation.cpp
@@ -0,0 +1,435 @@
+/*
+ * Constantright © 2010 Intel Corporation
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * constant of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, constant, 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 constantright notice and this permission notice (including the next
+ * paragraph) 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
+ * THE AUTHORS OR CONSTANTRIGHT HOLDERS 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 ir_constant_propagation.cpp
+ *
+ * Tracks assignments of constants to channels of variables, and
+ * usage of those constant channels with direct usage of the constants.
+ *
+ * This can lead to constant folding and algebraic optimizations in
+ * those later expressions, while causing no increase in instruction
+ * count (due to constants being generally free to load from a
+ * constant push buffer or as instruction immediate values) and
+ * possibly reducing register pressure.
+ */
+
+#include "ir.h"
+#include "ir_visitor.h"
+#include "ir_rvalue_visitor.h"
+#include "ir_basic_block.h"
+#include "ir_optimization.h"
+#include "glsl_types.h"
+
+class acp_entry : public exec_node
+{
+public:
+ acp_entry(ir_variable *var, unsigned write_mask, ir_constant *constant)
+ {
+ assert(var);
+ assert(constant);
+ this->var = var;
+ this->write_mask = write_mask;
+ this->constant = constant;
+ }
+
+ ir_variable *var;
+ ir_constant *constant;
+ unsigned write_mask;
+};
+
+
+class kill_entry : public exec_node
+{
+public:
+ kill_entry(ir_variable *var, unsigned write_mask)
+ {
+ assert(var);
+ this->var = var;
+ this->write_mask = write_mask;
+ }
+
+ ir_variable *var;
+ unsigned write_mask;
+};
+
+class ir_constant_propagation_visitor : public ir_rvalue_visitor {
+public:
+ ir_constant_propagation_visitor()
+ {
+ progress = false;
+ mem_ctx = talloc_new(0);
+ this->acp = new(mem_ctx) exec_list;
+ this->kills = new(mem_ctx) exec_list;
+ }
+ ~ir_constant_propagation_visitor()
+ {
+ talloc_free(mem_ctx);
+ }
+
+ virtual ir_visitor_status visit_enter(class ir_loop *);
+ virtual ir_visitor_status visit_enter(class ir_function_signature *);
+ virtual ir_visitor_status visit_enter(class ir_function *);
+ virtual ir_visitor_status visit_enter(class ir_assignment *);
+ virtual ir_visitor_status visit_enter(class ir_call *);
+ virtual ir_visitor_status visit_enter(class ir_if *);
+
+ void add_constant(ir_assignment *ir);
+ void kill(ir_variable *ir, unsigned write_mask);
+ void handle_if_block(exec_list *instructions);
+ void handle_rvalue(ir_rvalue **rvalue);
+
+ /** List of acp_entry: The available constants to propagate */
+ exec_list *acp;
+
+ /**
+ * List of kill_entry: The masks of variables whose values were
+ * killed in this block.
+ */
+ exec_list *kills;
+
+ bool progress;
+
+ bool killed_all;
+
+ void *mem_ctx;
+};
+
+
+void
+ir_constant_propagation_visitor::handle_rvalue(ir_rvalue **rvalue)
+{
+ if (!*rvalue)
+ return;
+
+ const glsl_type *type = (*rvalue)->type;
+ if (!type->is_scalar() && !type->is_vector())
+ return;
+
+ ir_swizzle *swiz = NULL;
+ ir_dereference_variable *deref = (*rvalue)->as_dereference_variable();
+ if (!deref) {
+ swiz = (*rvalue)->as_swizzle();
+ if (!swiz)
+ return;
+
+ deref = swiz->val->as_dereference_variable();
+ if (!deref)
+ return;
+ }
+
+ ir_constant_data data;
+ memset(&data, 0, sizeof(data));
+
+ for (unsigned int i = 0; i < type->components(); i++) {
+ int channel;
+ acp_entry *found = NULL;
+
+ if (swiz) {
+ switch (i) {
+ case 0: channel = swiz->mask.x; break;
+ case 1: channel = swiz->mask.y; break;
+ case 2: channel = swiz->mask.z; break;
+ case 3: channel = swiz->mask.w; break;
+ default: assert(!"shouldn't be reached"); channel = 0; break;
+ }
+ } else {
+ channel = i;
+ }
+
+ foreach_iter(exec_list_iterator, iter, *this->acp) {
+ acp_entry *entry = (acp_entry *)iter.get();
+ if (entry->var == deref->var && entry->write_mask & (1 << channel)) {
+ found = entry;
+ break;
+ }
+ }
+
+ if (!found)
+ return;
+
+ switch (type->base_type) {
+ case GLSL_TYPE_FLOAT:
+ data.f[i] = found->constant->value.f[channel];
+ break;
+ case GLSL_TYPE_INT:
+ data.i[i] = found->constant->value.i[channel];
+ break;
+ case GLSL_TYPE_UINT:
+ data.u[i] = found->constant->value.u[channel];
+ break;
+ case GLSL_TYPE_BOOL:
+ data.b[i] = found->constant->value.b[channel];
+ break;
+ default:
+ assert(!"not reached");
+ break;
+ }
+ }
+
+ *rvalue = new(talloc_parent(deref)) ir_constant(type, &data);
+ this->progress = true;
+}
+
+ir_visitor_status
+ir_constant_propagation_visitor::visit_enter(ir_function_signature *ir)
+{
+ /* Treat entry into a function signature as a completely separate
+ * block. Any instructions at global scope will be shuffled into
+ * main() at link time, so they're irrelevant to us.
+ */
+ exec_list *orig_acp = this->acp;
+ exec_list *orig_kills = this->kills;
+ bool orig_killed_all = this->killed_all;
+
+ this->acp = new(mem_ctx) exec_list;
+ this->kills = new(mem_ctx) exec_list;
+ this->killed_all = false;
+
+ visit_list_elements(this, &ir->body);
+
+ this->kills = orig_kills;
+ this->acp = orig_acp;
+ this->killed_all = orig_killed_all;
+
+ return visit_continue_with_parent;
+}
+
+ir_visitor_status
+ir_constant_propagation_visitor::visit_enter(ir_assignment *ir)
+{
+ /* Inline accepting children, skipping the LHS. */
+ ir->rhs->accept(this);
+ handle_rvalue(&ir->rhs);
+
+ if (ir->condition) {
+ ir->condition->accept(this);
+ handle_rvalue(&ir->condition);
+ }
+
+ kill(ir->lhs->variable_referenced(), ir->write_mask);
+
+ add_constant(ir);
+
+ return visit_continue_with_parent;
+}
+
+ir_visitor_status
+ir_constant_propagation_visitor::visit_enter(ir_function *ir)
+{
+ (void) ir;
+ return visit_continue;
+}
+
+ir_visitor_status
+ir_constant_propagation_visitor::visit_enter(ir_call *ir)
+{
+ /* Do constant propagation on call parameters, but skip any out params */
+ exec_list_iterator sig_param_iter = ir->get_callee()->parameters.iterator();
+ foreach_iter(exec_list_iterator, iter, ir->actual_parameters) {
+ ir_variable *sig_param = (ir_variable *)sig_param_iter.get();
+ ir_rvalue *param = (ir_rvalue *)iter.get();
+ if (sig_param->mode != ir_var_out && sig_param->mode != ir_var_inout) {
+ ir_rvalue *new_param = param;
+ handle_rvalue(&new_param);
+ if (new_param != param)
+ param->replace_with(new_param);
+ else
+ param->accept(this);
+ }
+ sig_param_iter.next();
+ }
+
+ /* Since we're unlinked, we don't (necssarily) know the side effects of
+ * this call. So kill all copies.
+ */
+ acp->make_empty();
+ this->killed_all = true;
+
+ return visit_continue_with_parent;
+}
+
+void
+ir_constant_propagation_visitor::handle_if_block(exec_list *instructions)
+{
+ exec_list *orig_acp = this->acp;
+ exec_list *orig_kills = this->kills;
+ bool orig_killed_all = this->killed_all;
+
+ this->acp = new(mem_ctx) exec_list;
+ this->kills = new(mem_ctx) exec_list;
+ this->killed_all = false;
+
+ /* Populate the initial acp with a constant of the original */
+ foreach_iter(exec_list_iterator, iter, *orig_acp) {
+ acp_entry *a = (acp_entry *)iter.get();
+ this->acp->push_tail(new(this->mem_ctx) acp_entry(a->var, a->write_mask,
+ a->constant));
+ }
+
+ visit_list_elements(this, instructions);
+
+ if (this->killed_all) {
+ orig_acp->make_empty();
+ }
+
+ exec_list *new_kills = this->kills;
+ this->kills = orig_kills;
+ this->acp = orig_acp;
+ this->killed_all = this->killed_all || orig_killed_all;
+
+ foreach_iter(exec_list_iterator, iter, *new_kills) {
+ kill_entry *k = (kill_entry *)iter.get();
+ kill(k->var, k->write_mask);
+ }
+}
+
+ir_visitor_status
+ir_constant_propagation_visitor::visit_enter(ir_if *ir)
+{
+ ir->condition->accept(this);
+ handle_rvalue(&ir->condition);
+
+ handle_if_block(&ir->then_instructions);
+ handle_if_block(&ir->else_instructions);
+
+ /* handle_if_block() already descended into the children. */
+ return visit_continue_with_parent;
+}
+
+ir_visitor_status
+ir_constant_propagation_visitor::visit_enter(ir_loop *ir)
+{
+ exec_list *orig_acp = this->acp;
+ exec_list *orig_kills = this->kills;
+ bool orig_killed_all = this->killed_all;
+
+ /* FINISHME: For now, the initial acp for loops is totally empty.
+ * We could go through once, then go through again with the acp
+ * cloned minus the killed entries after the first run through.
+ */
+ this->acp = new(mem_ctx) exec_list;
+ this->kills = new(mem_ctx) exec_list;
+ this->killed_all = false;
+
+ visit_list_elements(this, &ir->body_instructions);
+
+ if (this->killed_all) {
+ orig_acp->make_empty();
+ }
+
+ exec_list *new_kills = this->kills;
+ this->kills = orig_kills;
+ this->acp = orig_acp;
+ this->killed_all = this->killed_all || orig_killed_all;
+
+ foreach_iter(exec_list_iterator, iter, *new_kills) {
+ kill_entry *k = (kill_entry *)iter.get();
+ kill(k->var, k->write_mask);
+ }
+
+ /* already descended into the children. */
+ return visit_continue_with_parent;
+}
+
+void
+ir_constant_propagation_visitor::kill(ir_variable *var, unsigned write_mask)
+{
+ assert(var != NULL);
+
+ /* We don't track non-vectors. */
+ if (!var->type->is_vector() && !var->type->is_scalar())
+ return;
+
+ /* Remove any entries currently in the ACP for this kill. */
+ foreach_iter(exec_list_iterator, iter, *this->acp) {
+ acp_entry *entry = (acp_entry *)iter.get();
+
+ if (entry->var == var) {
+ entry->write_mask &= ~write_mask;
+ if (entry->write_mask == 0)
+ entry->remove();
+ }
+ }
+
+ /* Add this writemask of the variable to the list of killed
+ * variables in this block.
+ */
+ foreach_iter(exec_list_iterator, iter, *this->kills) {
+ kill_entry *entry = (kill_entry *)iter.get();
+
+ if (entry->var == var) {
+ entry->write_mask |= write_mask;
+ return;
+ }
+ }
+ /* Not already in the list. Make new entry. */
+ this->kills->push_tail(new(this->mem_ctx) kill_entry(var, write_mask));
+}
+
+/**
+ * Adds an entry to the available constant list if it's a plain assignment
+ * of a variable to a variable.
+ */
+void
+ir_constant_propagation_visitor::add_constant(ir_assignment *ir)
+{
+ acp_entry *entry;
+
+ if (ir->condition) {
+ ir_constant *condition = ir->condition->as_constant();
+ if (!condition || !condition->value.b[0])
+ return;
+ }
+
+ if (!ir->write_mask)
+ return;
+
+ ir_dereference_variable *deref = ir->lhs->as_dereference_variable();
+ ir_constant *constant = ir->rhs->as_constant();
+
+ if (!deref || !constant)
+ return;
+
+ /* Only do constant propagation on vectors. Constant matrices,
+ * arrays, or structures would require more work elsewhere.
+ */
+ if (!deref->var->type->is_vector() && !deref->var->type->is_scalar())
+ return;
+
+ entry = new(this->mem_ctx) acp_entry(deref->var, ir->write_mask, constant);
+ this->acp->push_tail(entry);
+}
+
+/**
+ * Does a constant propagation pass on the code present in the instruction stream.
+ */
+bool
+do_constant_propagation(exec_list *instructions)
+{
+ ir_constant_propagation_visitor v;
+
+ visit_list_elements(&v, instructions);
+
+ return v.progress;
+}
diff --git a/src/glsl/ir_constant_variable.cpp b/src/glsl/ir_constant_variable.cpp
new file mode 100644
index 00000000000..1fb73e765e1
--- /dev/null
+++ b/src/glsl/ir_constant_variable.cpp
@@ -0,0 +1,198 @@
+/*
+ * Copyright © 2010 Intel Corporation
+ *
+ * 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 (including the next
+ * paragraph) 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
+ * THE AUTHORS OR COPYRIGHT HOLDERS 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 ir_constant_variable.cpp
+ *
+ * Marks variables assigned a single constant value over the course
+ * of the program as constant.
+ *
+ * The goal here is to trigger further constant folding and then dead
+ * code elimination. This is common with vector/matrix constructors
+ * and calls to builtin functions.
+ */
+
+#include "ir.h"
+#include "ir_visitor.h"
+#include "ir_optimization.h"
+#include "glsl_types.h"
+
+struct assignment_entry {
+ exec_node link;
+ int assignment_count;
+ ir_variable *var;
+ ir_constant *constval;
+ bool our_scope;
+};
+
+class ir_constant_variable_visitor : public ir_hierarchical_visitor {
+public:
+ virtual ir_visitor_status visit_enter(ir_dereference_variable *);
+ virtual ir_visitor_status visit(ir_variable *);
+ virtual ir_visitor_status visit_enter(ir_assignment *);
+ virtual ir_visitor_status visit_enter(ir_call *);
+
+ exec_list list;
+};
+
+static struct assignment_entry *
+get_assignment_entry(ir_variable *var, exec_list *list)
+{
+ struct assignment_entry *entry;
+
+ foreach_list_typed(struct assignment_entry, entry, link, list) {
+ if (entry->var == var)
+ return entry;
+ }
+
+ entry = (struct assignment_entry *)calloc(1, sizeof(*entry));
+ entry->var = var;
+ list->push_head(&entry->link);
+ return entry;
+}
+
+ir_visitor_status
+ir_constant_variable_visitor::visit(ir_variable *ir)
+{
+ struct assignment_entry *entry = get_assignment_entry(ir, &this->list);
+ entry->our_scope = true;
+ return visit_continue;
+}
+
+/* Skip derefs of variables so that we can detect declarations. */
+ir_visitor_status
+ir_constant_variable_visitor::visit_enter(ir_dereference_variable *ir)
+{
+ (void)ir;
+ return visit_continue_with_parent;
+}
+
+ir_visitor_status
+ir_constant_variable_visitor::visit_enter(ir_assignment *ir)
+{
+ ir_constant *constval;
+ struct assignment_entry *entry;
+
+ entry = get_assignment_entry(ir->lhs->variable_referenced(), &this->list);
+ assert(entry);
+ entry->assignment_count++;
+
+ /* If it's already constant, don't do the work. */
+ if (entry->var->constant_value)
+ return visit_continue;
+
+ /* OK, now find if we actually have all the right conditions for
+ * this to be a constant value assigned to the var.
+ */
+ if (ir->condition) {
+ constval = ir->condition->constant_expression_value();
+ if (!constval || !constval->value.b[0])
+ return visit_continue;
+ }
+
+ ir_variable *var = ir->whole_variable_written();
+ if (!var)
+ return visit_continue;
+
+ constval = ir->rhs->constant_expression_value();
+ if (!constval)
+ return visit_continue;
+
+ /* Mark this entry as having a constant assignment (if the
+ * assignment count doesn't go >1). do_constant_variable will fix
+ * up the variable with the constant value later.
+ */
+ entry->constval = constval;
+
+ return visit_continue;
+}
+
+ir_visitor_status
+ir_constant_variable_visitor::visit_enter(ir_call *ir)
+{
+ exec_list_iterator sig_iter = ir->get_callee()->parameters.iterator();
+ foreach_iter(exec_list_iterator, iter, *ir) {
+ ir_rvalue *param_rval = (ir_rvalue *)iter.get();
+ ir_variable *param = (ir_variable *)sig_iter.get();
+
+ if (param->mode == ir_var_out ||
+ param->mode == ir_var_inout) {
+ ir_variable *var = param_rval->variable_referenced();
+ struct assignment_entry *entry;
+
+ assert(var);
+ entry = get_assignment_entry(var, &this->list);
+ entry->assignment_count++;
+ }
+ sig_iter.next();
+ }
+ return visit_continue;
+}
+
+/**
+ * Does a copy propagation pass on the code present in the instruction stream.
+ */
+bool
+do_constant_variable(exec_list *instructions)
+{
+ bool progress = false;
+ ir_constant_variable_visitor v;
+
+ v.run(instructions);
+
+ while (!v.list.is_empty()) {
+
+ struct assignment_entry *entry;
+ entry = exec_node_data(struct assignment_entry, v.list.head, link);
+
+ if (entry->assignment_count == 1 && entry->constval && entry->our_scope) {
+ entry->var->constant_value = entry->constval;
+ progress = true;
+ }
+ entry->link.remove();
+ free(entry);
+ }
+
+ return progress;
+}
+
+bool
+do_constant_variable_unlinked(exec_list *instructions)
+{
+ bool progress = false;
+
+ foreach_iter(exec_list_iterator, iter, *instructions) {
+ ir_instruction *ir = (ir_instruction *)iter.get();
+ ir_function *f = ir->as_function();
+ if (f) {
+ foreach_iter(exec_list_iterator, sigiter, *f) {
+ ir_function_signature *sig =
+ (ir_function_signature *) sigiter.get();
+ if (do_constant_variable(&sig->body))
+ progress = true;
+ }
+ }
+ }
+
+ return progress;
+}
diff --git a/src/glsl/ir_copy_propagation.cpp b/src/glsl/ir_copy_propagation.cpp
new file mode 100644
index 00000000000..6c211f0e70a
--- /dev/null
+++ b/src/glsl/ir_copy_propagation.cpp
@@ -0,0 +1,362 @@
+/*
+ * Copyright © 2010 Intel Corporation
+ *
+ * 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 (including the next
+ * paragraph) 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
+ * THE AUTHORS OR COPYRIGHT HOLDERS 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 ir_copy_propagation.cpp
+ *
+ * Moves usage of recently-copied variables to the previous copy of
+ * the variable.
+ *
+ * This should reduce the number of MOV instructions in the generated
+ * programs unless copy propagation is also done on the LIR, and may
+ * help anyway by triggering other optimizations that live in the HIR.
+ */
+
+#include "ir.h"
+#include "ir_visitor.h"
+#include "ir_basic_block.h"
+#include "ir_optimization.h"
+#include "glsl_types.h"
+
+class acp_entry : public exec_node
+{
+public:
+ acp_entry(ir_variable *lhs, ir_variable *rhs)
+ {
+ assert(lhs);
+ assert(rhs);
+ this->lhs = lhs;
+ this->rhs = rhs;
+ }
+
+ ir_variable *lhs;
+ ir_variable *rhs;
+};
+
+
+class kill_entry : public exec_node
+{
+public:
+ kill_entry(ir_variable *var)
+ {
+ assert(var);
+ this->var = var;
+ }
+
+ ir_variable *var;
+};
+
+class ir_copy_propagation_visitor : public ir_hierarchical_visitor {
+public:
+ ir_copy_propagation_visitor()
+ {
+ progress = false;
+ mem_ctx = talloc_new(0);
+ this->acp = new(mem_ctx) exec_list;
+ this->kills = new(mem_ctx) exec_list;
+ }
+ ~ir_copy_propagation_visitor()
+ {
+ talloc_free(mem_ctx);
+ }
+
+ virtual ir_visitor_status visit(class ir_dereference_variable *);
+ virtual ir_visitor_status visit_enter(class ir_loop *);
+ virtual ir_visitor_status visit_enter(class ir_function_signature *);
+ virtual ir_visitor_status visit_enter(class ir_function *);
+ virtual ir_visitor_status visit_enter(class ir_assignment *);
+ virtual ir_visitor_status visit_enter(class ir_call *);
+ virtual ir_visitor_status visit_enter(class ir_if *);
+
+ void add_copy(ir_assignment *ir);
+ void kill(ir_variable *ir);
+ void handle_if_block(exec_list *instructions);
+
+ /** List of acp_entry: The available copies to propagate */
+ exec_list *acp;
+ /**
+ * List of kill_entry: The variables whose values were killed in this
+ * block.
+ */
+ exec_list *kills;
+
+ bool progress;
+
+ bool killed_all;
+
+ void *mem_ctx;
+};
+
+ir_visitor_status
+ir_copy_propagation_visitor::visit_enter(ir_function_signature *ir)
+{
+ /* Treat entry into a function signature as a completely separate
+ * block. Any instructions at global scope will be shuffled into
+ * main() at link time, so they're irrelevant to us.
+ */
+ exec_list *orig_acp = this->acp;
+ exec_list *orig_kills = this->kills;
+ bool orig_killed_all = this->killed_all;
+
+ this->acp = new(mem_ctx) exec_list;
+ this->kills = new(mem_ctx) exec_list;
+ this->killed_all = false;
+
+ visit_list_elements(this, &ir->body);
+
+ this->kills = orig_kills;
+ this->acp = orig_acp;
+ this->killed_all = orig_killed_all;
+
+ return visit_continue_with_parent;
+}
+
+ir_visitor_status
+ir_copy_propagation_visitor::visit_enter(ir_assignment *ir)
+{
+ ir_visitor_status s;
+
+ /* ir_assignment::accept(ir_hv *v), skipping the LHS so that we can
+ * avoid copy propagating into the LHS.
+ *
+ * Note that this means we won't copy propagate into the derefs of
+ * an array index. Oh well.
+ */
+
+ s = ir->rhs->accept(this);
+ assert(s == visit_continue);
+
+ if (ir->condition) {
+ s = ir->condition->accept(this);
+ assert(s == visit_continue);
+ }
+
+ kill(ir->lhs->variable_referenced());
+
+ add_copy(ir);
+
+ return visit_continue_with_parent;
+}
+
+ir_visitor_status
+ir_copy_propagation_visitor::visit_enter(ir_function *ir)
+{
+ (void) ir;
+ return visit_continue;
+}
+
+/**
+ * Replaces dereferences of ACP RHS variables with ACP LHS variables.
+ *
+ * This is where the actual copy propagation occurs. Note that the
+ * rewriting of ir_dereference means that the ir_dereference instance
+ * must not be shared by multiple IR operations!
+ */
+ir_visitor_status
+ir_copy_propagation_visitor::visit(ir_dereference_variable *ir)
+{
+ ir_variable *var = ir->var;
+
+ foreach_iter(exec_list_iterator, iter, *this->acp) {
+ acp_entry *entry = (acp_entry *)iter.get();
+
+ if (var == entry->lhs) {
+ ir->var = entry->rhs;
+ this->progress = true;
+ break;
+ }
+ }
+
+ return visit_continue;
+}
+
+
+ir_visitor_status
+ir_copy_propagation_visitor::visit_enter(ir_call *ir)
+{
+ /* Do copy propagation on call parameters, but skip any out params */
+ exec_list_iterator sig_param_iter = ir->get_callee()->parameters.iterator();
+ foreach_iter(exec_list_iterator, iter, ir->actual_parameters) {
+ ir_variable *sig_param = (ir_variable *)sig_param_iter.get();
+ ir_instruction *ir = (ir_instruction *)iter.get();
+ if (sig_param->mode != ir_var_out && sig_param->mode != ir_var_inout) {
+ ir->accept(this);
+ }
+ sig_param_iter.next();
+ }
+
+ /* Since we're unlinked, we don't (necssarily) know the side effects of
+ * this call. So kill all copies.
+ */
+ acp->make_empty();
+ this->killed_all = true;
+
+ return visit_continue_with_parent;
+}
+
+void
+ir_copy_propagation_visitor::handle_if_block(exec_list *instructions)
+{
+ exec_list *orig_acp = this->acp;
+ exec_list *orig_kills = this->kills;
+ bool orig_killed_all = this->killed_all;
+
+ this->acp = new(mem_ctx) exec_list;
+ this->kills = new(mem_ctx) exec_list;
+ this->killed_all = false;
+
+ /* Populate the initial acp with a copy of the original */
+ foreach_iter(exec_list_iterator, iter, *orig_acp) {
+ acp_entry *a = (acp_entry *)iter.get();
+ this->acp->push_tail(new(this->mem_ctx) acp_entry(a->lhs, a->rhs));
+ }
+
+ visit_list_elements(this, instructions);
+
+ if (this->killed_all) {
+ orig_acp->make_empty();
+ }
+
+ exec_list *new_kills = this->kills;
+ this->kills = orig_kills;
+ this->acp = orig_acp;
+ this->killed_all = this->killed_all || orig_killed_all;
+
+ foreach_iter(exec_list_iterator, iter, *new_kills) {
+ kill_entry *k = (kill_entry *)iter.get();
+ kill(k->var);
+ }
+}
+
+ir_visitor_status
+ir_copy_propagation_visitor::visit_enter(ir_if *ir)
+{
+ ir->condition->accept(this);
+
+ handle_if_block(&ir->then_instructions);
+ handle_if_block(&ir->else_instructions);
+
+ /* handle_if_block() already descended into the children. */
+ return visit_continue_with_parent;
+}
+
+ir_visitor_status
+ir_copy_propagation_visitor::visit_enter(ir_loop *ir)
+{
+ exec_list *orig_acp = this->acp;
+ exec_list *orig_kills = this->kills;
+ bool orig_killed_all = this->killed_all;
+
+ /* FINISHME: For now, the initial acp for loops is totally empty.
+ * We could go through once, then go through again with the acp
+ * cloned minus the killed entries after the first run through.
+ */
+ this->acp = new(mem_ctx) exec_list;
+ this->kills = new(mem_ctx) exec_list;
+ this->killed_all = false;
+
+ visit_list_elements(this, &ir->body_instructions);
+
+ if (this->killed_all) {
+ orig_acp->make_empty();
+ }
+
+ exec_list *new_kills = this->kills;
+ this->kills = orig_kills;
+ this->acp = orig_acp;
+ this->killed_all = this->killed_all || orig_killed_all;
+
+ foreach_iter(exec_list_iterator, iter, *new_kills) {
+ kill_entry *k = (kill_entry *)iter.get();
+ kill(k->var);
+ }
+
+ /* already descended into the children. */
+ return visit_continue_with_parent;
+}
+
+void
+ir_copy_propagation_visitor::kill(ir_variable *var)
+{
+ assert(var != NULL);
+
+ /* Remove any entries currently in the ACP for this kill. */
+ foreach_iter(exec_list_iterator, iter, *acp) {
+ acp_entry *entry = (acp_entry *)iter.get();
+
+ if (entry->lhs == var || entry->rhs == var) {
+ entry->remove();
+ }
+ }
+
+ /* Add the LHS variable to the list of killed variables in this block.
+ */
+ this->kills->push_tail(new(this->mem_ctx) kill_entry(var));
+}
+
+/**
+ * Adds an entry to the available copy list if it's a plain assignment
+ * of a variable to a variable.
+ */
+void
+ir_copy_propagation_visitor::add_copy(ir_assignment *ir)
+{
+ acp_entry *entry;
+
+ if (ir->condition) {
+ ir_constant *condition = ir->condition->as_constant();
+ if (!condition || !condition->value.b[0])
+ return;
+ }
+
+ ir_variable *lhs_var = ir->whole_variable_written();
+ ir_variable *rhs_var = ir->rhs->whole_variable_referenced();
+
+ if ((lhs_var != NULL) && (rhs_var != NULL)) {
+ if (lhs_var == rhs_var) {
+ /* This is a dumb assignment, but we've conveniently noticed
+ * it here. Removing it now would mess up the loop iteration
+ * calling us. Just flag it to not execute, and someone else
+ * will clean up the mess.
+ */
+ ir->condition = new(talloc_parent(ir)) ir_constant(false);
+ this->progress = true;
+ } else {
+ entry = new(this->mem_ctx) acp_entry(lhs_var, rhs_var);
+ this->acp->push_tail(entry);
+ }
+ }
+}
+
+/**
+ * Does a copy propagation pass on the code present in the instruction stream.
+ */
+bool
+do_copy_propagation(exec_list *instructions)
+{
+ ir_copy_propagation_visitor v;
+
+ visit_list_elements(&v, instructions);
+
+ return v.progress;
+}
diff --git a/src/glsl/ir_dead_code.cpp b/src/glsl/ir_dead_code.cpp
new file mode 100644
index 00000000000..fce921262f4
--- /dev/null
+++ b/src/glsl/ir_dead_code.cpp
@@ -0,0 +1,135 @@
+/*
+ * Copyright © 2010 Intel Corporation
+ *
+ * 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 (including the next
+ * paragraph) 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
+ * THE AUTHORS OR COPYRIGHT HOLDERS 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 ir_dead_code.cpp
+ *
+ * Eliminates dead assignments and variable declarations from the code.
+ */
+
+#include "ir.h"
+#include "ir_visitor.h"
+#include "ir_variable_refcount.h"
+#include "glsl_types.h"
+
+static bool debug = false;
+
+/**
+ * Do a dead code pass over instructions and everything that instructions
+ * references.
+ *
+ * Note that this will remove assignments to globals, so it is not suitable
+ * for usage on an unlinked instruction stream.
+ */
+bool
+do_dead_code(exec_list *instructions)
+{
+ ir_variable_refcount_visitor v;
+ bool progress = false;
+
+ v.run(instructions);
+
+ foreach_iter(exec_list_iterator, iter, v.variable_list) {
+ variable_entry *entry = (variable_entry *)iter.get();
+
+ /* Since each assignment is a reference, the refereneced count must be
+ * greater than or equal to the assignment count. If they are equal,
+ * then all of the references are assignments, and the variable is
+ * dead.
+ *
+ * Note that if the variable is neither assigned nor referenced, both
+ * counts will be zero and will be caught by the equality test.
+ */
+ assert(entry->referenced_count >= entry->assigned_count);
+
+ if (debug) {
+ printf("%s@%p: %d refs, %d assigns, %sdeclared in our scope\n",
+ entry->var->name, (void *) entry->var,
+ entry->referenced_count, entry->assigned_count,
+ entry->declaration ? "" : "not ");
+ }
+
+ if ((entry->referenced_count > entry->assigned_count)
+ || !entry->declaration)
+ continue;
+
+ if (entry->assign) {
+ /* Remove a single dead assignment to the variable we found.
+ * Don't do so if it's a shader output, though.
+ */
+ if (entry->var->mode != ir_var_out &&
+ entry->var->mode != ir_var_inout &&
+ !ir_has_call(entry->assign)) {
+ entry->assign->remove();
+ progress = true;
+
+ if (debug) {
+ printf("Removed assignment to %s@%p\n",
+ entry->var->name, (void *) entry->var);
+ }
+ }
+ } else {
+ /* If there are no assignments or references to the variable left,
+ * then we can remove its declaration.
+ */
+ entry->var->remove();
+ progress = true;
+
+ if (debug) {
+ printf("Removed declaration of %s@%p\n",
+ entry->var->name, (void *) entry->var);
+ }
+ }
+ }
+ talloc_free(v.mem_ctx);
+
+ return progress;
+}
+
+/**
+ * Does a dead code pass on the functions present in the instruction stream.
+ *
+ * This is suitable for use while the program is not linked, as it will
+ * ignore variable declarations (and the assignments to them) for variables
+ * with global scope.
+ */
+bool
+do_dead_code_unlinked(exec_list *instructions)
+{
+ bool progress = false;
+
+ foreach_iter(exec_list_iterator, iter, *instructions) {
+ ir_instruction *ir = (ir_instruction *)iter.get();
+ ir_function *f = ir->as_function();
+ if (f) {
+ foreach_iter(exec_list_iterator, sigiter, *f) {
+ ir_function_signature *sig =
+ (ir_function_signature *) sigiter.get();
+ if (do_dead_code(&sig->body))
+ progress = true;
+ }
+ }
+ }
+
+ return progress;
+}
diff --git a/src/glsl/ir_dead_code_local.cpp b/src/glsl/ir_dead_code_local.cpp
new file mode 100644
index 00000000000..4bbedf0ff94
--- /dev/null
+++ b/src/glsl/ir_dead_code_local.cpp
@@ -0,0 +1,229 @@
+/*
+ * Copyright © 2010 Intel Corporation
+ *
+ * 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 (including the next
+ * paragraph) 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
+ * THE AUTHORS OR COPYRIGHT HOLDERS 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 ir_dead_code_local.cpp
+ *
+ * Eliminates local dead assignments from the code.
+ *
+ * This operates on basic blocks, tracking assignments and finding if
+ * they're used before the variable is completely reassigned.
+ *
+ * Compare this to ir_dead_code.cpp, which operates globally looking
+ * for assignments to variables that are never read.
+ */
+
+#include "ir.h"
+#include "ir_basic_block.h"
+#include "ir_optimization.h"
+#include "glsl_types.h"
+
+static bool debug = false;
+
+class assignment_entry : public exec_node
+{
+public:
+ assignment_entry(ir_variable *lhs, ir_instruction *ir)
+ {
+ assert(lhs);
+ assert(ir);
+ this->lhs = lhs;
+ this->ir = ir;
+ }
+
+ ir_variable *lhs;
+ ir_instruction *ir;
+};
+
+class kill_for_derefs_visitor : public ir_hierarchical_visitor {
+public:
+ kill_for_derefs_visitor(exec_list *assignments)
+ {
+ this->assignments = assignments;
+ }
+
+ virtual ir_visitor_status visit(ir_dereference_variable *ir)
+ {
+ ir_variable *const var = ir->variable_referenced();
+
+ foreach_iter(exec_list_iterator, iter, *this->assignments) {
+ assignment_entry *entry = (assignment_entry *)iter.get();
+
+ if (entry->lhs == var) {
+ if (debug)
+ printf("kill %s\n", entry->lhs->name);
+ entry->remove();
+ }
+ }
+
+ return visit_continue;
+ }
+
+private:
+ exec_list *assignments;
+};
+
+class array_index_visit : public ir_hierarchical_visitor {
+public:
+ array_index_visit(ir_hierarchical_visitor *v)
+ {
+ this->visitor = v;
+ }
+
+ virtual ir_visitor_status visit_enter(class ir_dereference_array *ir)
+ {
+ ir->array_index->accept(visitor);
+ return visit_continue;
+ }
+
+ static void run(ir_instruction *ir, ir_hierarchical_visitor *v)
+ {
+ array_index_visit top_visit(v);
+ ir->accept(& top_visit);
+ }
+
+ ir_hierarchical_visitor *visitor;
+};
+
+
+/**
+ * Adds an entry to the available copy list if it's a plain assignment
+ * of a variable to a variable.
+ */
+static bool
+process_assignment(void *ctx, ir_assignment *ir, exec_list *assignments)
+{
+ ir_variable *var = NULL;
+ bool progress = false;
+ kill_for_derefs_visitor v(assignments);
+
+ /* Kill assignment entries for things used to produce this assignment. */
+ ir->rhs->accept(&v);
+ if (ir->condition) {
+ ir->condition->accept(&v);
+ }
+
+ /* Kill assignment enties used as array indices.
+ */
+ array_index_visit::run(ir->lhs, &v);
+ var = ir->lhs->variable_referenced();
+ assert(var);
+
+ bool always_assign = true;
+ if (ir->condition) {
+ ir_constant *condition = ir->condition->as_constant();
+ if (!condition || !condition->value.b[0])
+ always_assign = false;
+ }
+
+ /* Now, check if we did a whole-variable assignment. */
+ if (always_assign && (ir->whole_variable_written() != NULL)) {
+ /* We did a whole-variable assignment. So, any instruction in
+ * the assignment list with the same LHS is dead.
+ */
+ if (debug)
+ printf("looking for %s to remove\n", var->name);
+ foreach_iter(exec_list_iterator, iter, *assignments) {
+ assignment_entry *entry = (assignment_entry *)iter.get();
+
+ if (entry->lhs == var) {
+ if (debug)
+ printf("removing %s\n", var->name);
+ entry->ir->remove();
+ entry->remove();
+ progress = true;
+ }
+ }
+ }
+
+ /* Add this instruction to the assignment list available to be removed.
+ * But not if the assignment has other side effects.
+ */
+ if (ir_has_call(ir))
+ return progress;
+
+ assignment_entry *entry = new(ctx) assignment_entry(var, ir);
+ assignments->push_tail(entry);
+
+ if (debug) {
+ printf("add %s\n", var->name);
+
+ printf("current entries\n");
+ foreach_iter(exec_list_iterator, iter, *assignments) {
+ assignment_entry *entry = (assignment_entry *)iter.get();
+
+ printf(" %s\n", entry->lhs->name);
+ }
+ }
+
+ return progress;
+}
+
+static void
+dead_code_local_basic_block(ir_instruction *first,
+ ir_instruction *last,
+ void *data)
+{
+ ir_instruction *ir, *ir_next;
+ /* List of avaialble_copy */
+ exec_list assignments;
+ bool *out_progress = (bool *)data;
+ bool progress = false;
+
+ void *ctx = talloc_new(NULL);
+ /* Safe looping, since process_assignment */
+ for (ir = first, ir_next = (ir_instruction *)first->next;;
+ ir = ir_next, ir_next = (ir_instruction *)ir->next) {
+ ir_assignment *ir_assign = ir->as_assignment();
+
+ if (debug) {
+ ir->print();
+ printf("\n");
+ }
+
+ if (ir_assign) {
+ progress = process_assignment(ctx, ir_assign, &assignments) || progress;
+ } else {
+ kill_for_derefs_visitor kill(&assignments);
+ ir->accept(&kill);
+ }
+
+ if (ir == last)
+ break;
+ }
+ *out_progress = progress;
+ talloc_free(ctx);
+}
+
+/**
+ * Does a copy propagation pass on the code present in the instruction stream.
+ */
+bool
+do_dead_code_local(exec_list *instructions)
+{
+ bool progress = false;
+
+ call_for_basic_blocks(instructions, dead_code_local_basic_block, &progress);
+
+ return progress;
+}
diff --git a/src/glsl/ir_dead_functions.cpp b/src/glsl/ir_dead_functions.cpp
new file mode 100644
index 00000000000..26554441d3a
--- /dev/null
+++ b/src/glsl/ir_dead_functions.cpp
@@ -0,0 +1,151 @@
+ /*
+ * Copyright © 2010 Intel Corporation
+ *
+ * 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 (including the next
+ * paragraph) 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
+ * THE AUTHORS OR COPYRIGHT HOLDERS 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 ir_dead_functions.cpp
+ *
+ * Eliminates unused functions from the linked program.
+ */
+
+ #include "ir.h"
+ #include "ir_visitor.h"
+ #include "ir_expression_flattening.h"
+ #include "glsl_types.h"
+
+ class signature_entry : public exec_node
+ {
+ public:
+ signature_entry(ir_function_signature *sig)
+ {
+ this->signature = sig;
+ this->used = false;
+ }
+
+ ir_function_signature *signature;
+ bool used;
+ };
+
+ class ir_dead_functions_visitor : public ir_hierarchical_visitor {
+ public:
+ ir_dead_functions_visitor()
+ {
+ this->mem_ctx = talloc_new(NULL);
+ }
+
+ ~ir_dead_functions_visitor()
+ {
+ talloc_free(this->mem_ctx);
+ }
+
+ virtual ir_visitor_status visit_enter(ir_function_signature *);
+ virtual ir_visitor_status visit_enter(ir_call *);
+
+ signature_entry *get_signature_entry(ir_function_signature *var);
+
+ bool (*predicate)(ir_instruction *ir);
+
+ /* List of signature_entry */
+ exec_list signature_list;
+ void *mem_ctx;
+ };
+
+
+ signature_entry *
+ ir_dead_functions_visitor::get_signature_entry(ir_function_signature *sig)
+ {
+ foreach_iter(exec_list_iterator, iter, this->signature_list) {
+ signature_entry *entry = (signature_entry *)iter.get();
+ if (entry->signature == sig)
+ return entry;
+ }
+
+ signature_entry *entry = new(mem_ctx) signature_entry(sig);
+ this->signature_list.push_tail(entry);
+ return entry;
+ }
+
+
+ ir_visitor_status
+ ir_dead_functions_visitor::visit_enter(ir_function_signature *ir)
+ {
+ signature_entry *entry = this->get_signature_entry(ir);
+
+ if (strcmp(ir->function_name(), "main") == 0) {
+ entry->used = true;
+ }
+
+ return visit_continue;
+ }
+
+
+ ir_visitor_status
+ ir_dead_functions_visitor::visit_enter(ir_call *ir)
+ {
+ signature_entry *entry = this->get_signature_entry(ir->get_callee());
+
+ entry->used = true;
+
+ return visit_continue;
+}
+
+bool
+do_dead_functions(exec_list *instructions)
+{
+ ir_dead_functions_visitor v;
+ bool progress = false;
+
+ visit_list_elements(&v, instructions);
+
+ /* Now that we've figured out which function signatures are used, remove
+ * the unused ones, and remove function definitions that have no more
+ * signatures.
+ */
+ foreach_iter(exec_list_iterator, iter, v.signature_list) {
+ signature_entry *entry = (signature_entry *)iter.get();
+
+ if (!entry->used) {
+ entry->signature->remove();
+ progress = true;
+ }
+ delete(entry);
+ }
+
+ /* We don't just do this above when we nuked a signature because of
+ * const pointers.
+ */
+ foreach_iter(exec_list_iterator, iter, *instructions) {
+ ir_instruction *ir = (ir_instruction *)iter.get();
+ ir_function *func = ir->as_function();
+
+ if (func && func->signatures.is_empty()) {
+ /* At this point (post-linking), the symbol table is no
+ * longer in use, so not removing the function from the
+ * symbol table should be OK.
+ */
+ func->remove();
+ progress = true;
+ }
+ }
+
+ return progress;
+}
diff --git a/src/glsl/ir_div_to_mul_rcp.cpp b/src/glsl/ir_div_to_mul_rcp.cpp
new file mode 100644
index 00000000000..640d5d64f98
--- /dev/null
+++ b/src/glsl/ir_div_to_mul_rcp.cpp
@@ -0,0 +1,115 @@
+/*
+ * Copyright © 2010 Intel Corporation
+ *
+ * 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 (including the next
+ * paragraph) 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
+ * THE AUTHORS OR COPYRIGHT HOLDERS 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 ir_div_to_mul_rcp.cpp
+ *
+ * Breaks an ir_unop_div expression down to op0 * (rcp(op1)).
+ *
+ * Many GPUs don't have a divide instruction (945 and 965 included),
+ * but they do have an RCP instruction to compute an approximate
+ * reciprocal. By breaking the operation down, constant reciprocals
+ * can get constant folded.
+ */
+
+#include "ir.h"
+#include "glsl_types.h"
+
+class ir_div_to_mul_rcp_visitor : public ir_hierarchical_visitor {
+public:
+ ir_div_to_mul_rcp_visitor()
+ {
+ this->made_progress = false;
+ }
+
+ ir_visitor_status visit_leave(ir_expression *);
+
+ bool made_progress;
+};
+
+bool
+do_div_to_mul_rcp(exec_list *instructions)
+{
+ ir_div_to_mul_rcp_visitor v;
+
+ visit_list_elements(&v, instructions);
+ return v.made_progress;
+}
+
+ir_visitor_status
+ir_div_to_mul_rcp_visitor::visit_leave(ir_expression *ir)
+{
+ if (ir->operation != ir_binop_div)
+ return visit_continue;
+
+ if (ir->operands[1]->type->base_type != GLSL_TYPE_INT &&
+ ir->operands[1]->type->base_type != GLSL_TYPE_UINT) {
+ /* New expression for the 1.0 / op1 */
+ ir_rvalue *expr;
+ expr = new(ir) ir_expression(ir_unop_rcp,
+ ir->operands[1]->type,
+ ir->operands[1],
+ NULL);
+
+ /* op0 / op1 -> op0 * (1.0 / op1) */
+ ir->operation = ir_binop_mul;
+ ir->operands[1] = expr;
+ } else {
+ /* Be careful with integer division -- we need to do it as a
+ * float and re-truncate, since rcp(n > 1) of an integer would
+ * just be 0.
+ */
+ ir_rvalue *op0, *op1;
+ const struct glsl_type *vec_type;
+
+ vec_type = glsl_type::get_instance(GLSL_TYPE_FLOAT,
+ ir->operands[1]->type->vector_elements,
+ ir->operands[1]->type->matrix_columns);
+
+ if (ir->operands[1]->type->base_type == GLSL_TYPE_INT)
+ op1 = new(ir) ir_expression(ir_unop_i2f, vec_type, ir->operands[1], NULL);
+ else
+ op1 = new(ir) ir_expression(ir_unop_u2f, vec_type, ir->operands[1], NULL);
+
+ op1 = new(ir) ir_expression(ir_unop_rcp, op1->type, op1, NULL);
+
+ vec_type = glsl_type::get_instance(GLSL_TYPE_FLOAT,
+ ir->operands[0]->type->vector_elements,
+ ir->operands[0]->type->matrix_columns);
+
+ if (ir->operands[0]->type->base_type == GLSL_TYPE_INT)
+ op0 = new(ir) ir_expression(ir_unop_i2f, vec_type, ir->operands[0], NULL);
+ else
+ op0 = new(ir) ir_expression(ir_unop_u2f, vec_type, ir->operands[0], NULL);
+
+ op0 = new(ir) ir_expression(ir_binop_mul, vec_type, op0, op1);
+
+ ir->operation = ir_unop_f2i;
+ ir->operands[0] = op0;
+ ir->operands[1] = NULL;
+ }
+
+ this->made_progress = true;
+
+ return visit_continue;
+}
diff --git a/src/glsl/ir_explog_to_explog2.cpp b/src/glsl/ir_explog_to_explog2.cpp
new file mode 100644
index 00000000000..4fe1daaee91
--- /dev/null
+++ b/src/glsl/ir_explog_to_explog2.cpp
@@ -0,0 +1,85 @@
+/*
+ * Copyright © 2010 Intel Corporation
+ *
+ * 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 (including the next
+ * paragraph) 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
+ * THE AUTHORS OR COPYRIGHT HOLDERS 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 ir_explog_to_explog2.cpp
+ *
+ * Many GPUs don't have a base e log or exponent instruction, but they
+ * do have base 2 versions, so this pass converts exp and log to exp2
+ * and log2 operations.
+ */
+
+#include <math.h>
+#include "ir.h"
+#include "glsl_types.h"
+
+class ir_explog_to_explog2_visitor : public ir_hierarchical_visitor {
+public:
+ ir_explog_to_explog2_visitor()
+ {
+ this->progress = false;
+ }
+
+ ir_visitor_status visit_leave(ir_expression *);
+
+ bool progress;
+};
+
+bool
+do_explog_to_explog2(exec_list *instructions)
+{
+ ir_explog_to_explog2_visitor v;
+
+ visit_list_elements(&v, instructions);
+ return v.progress;
+}
+
+ir_visitor_status
+ir_explog_to_explog2_visitor::visit_leave(ir_expression *ir)
+{
+ if (ir->operation == ir_unop_exp) {
+ void *mem_ctx = talloc_parent(ir);
+ ir_constant *log2_e = new(mem_ctx) ir_constant(log2f(M_E));
+
+ ir->operation = ir_unop_exp2;
+ ir->operands[0] = new(mem_ctx) ir_expression(ir_binop_mul,
+ ir->operands[0]->type,
+ ir->operands[0],
+ log2_e);
+ this->progress = true;
+ }
+
+ if (ir->operation == ir_unop_log) {
+ void *mem_ctx = talloc_parent(ir);
+
+ ir->operation = ir_binop_mul;
+ ir->operands[0] = new(mem_ctx) ir_expression(ir_unop_log2,
+ ir->operands[0]->type,
+ ir->operands[0],
+ NULL);
+ ir->operands[1] = new(mem_ctx) ir_constant(1.0f / log2f(M_E));
+ this->progress = true;
+ }
+
+ return visit_continue;
+}
diff --git a/src/glsl/ir_expression_flattening.cpp b/src/glsl/ir_expression_flattening.cpp
new file mode 100644
index 00000000000..ccb2e2bce9e
--- /dev/null
+++ b/src/glsl/ir_expression_flattening.cpp
@@ -0,0 +1,188 @@
+/*
+ * Copyright © 2010 Intel Corporation
+ *
+ * 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 (including the next
+ * paragraph) 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
+ * THE AUTHORS OR COPYRIGHT HOLDERS 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 ir_expression_flattening.cpp
+ *
+ * Takes the leaves of expression trees and makes them dereferences of
+ * assignments of the leaves to temporaries, according to a predicate.
+ *
+ * This is used for automatic function inlining, where we want to take
+ * an expression containing a call and move the call out to its own
+ * assignment so that we can inline it at the appropriate place in the
+ * instruction stream.
+ */
+
+#include "ir.h"
+#include "ir_visitor.h"
+#include "ir_expression_flattening.h"
+#include "glsl_types.h"
+
+class ir_expression_flattening_visitor : public ir_hierarchical_visitor {
+public:
+ ir_expression_flattening_visitor(ir_instruction *base_ir,
+ bool (*predicate)(ir_instruction *ir))
+ {
+ this->base_ir = base_ir;
+ this->predicate = predicate;
+ }
+
+ virtual ~ir_expression_flattening_visitor()
+ {
+ /* empty */
+ }
+
+ virtual ir_visitor_status visit_enter(ir_call *);
+ virtual ir_visitor_status visit_enter(ir_return *);
+ virtual ir_visitor_status visit_enter(ir_function_signature *);
+ virtual ir_visitor_status visit_enter(ir_if *);
+ virtual ir_visitor_status visit_enter(ir_loop *);
+ virtual ir_visitor_status visit_leave(ir_assignment *);
+ virtual ir_visitor_status visit_leave(ir_expression *);
+ virtual ir_visitor_status visit_leave(ir_swizzle *);
+
+ ir_rvalue *operand_to_temp(ir_rvalue *val);
+ bool (*predicate)(ir_instruction *ir);
+ ir_instruction *base_ir;
+};
+
+void
+do_expression_flattening(exec_list *instructions,
+ bool (*predicate)(ir_instruction *ir))
+{
+ foreach_iter(exec_list_iterator, iter, *instructions) {
+ ir_instruction *ir = (ir_instruction *)iter.get();
+
+ ir_expression_flattening_visitor v(ir, predicate);
+ ir->accept(&v);
+ }
+}
+
+
+ir_rvalue *
+ir_expression_flattening_visitor::operand_to_temp(ir_rvalue *ir)
+{
+ void *ctx = base_ir;
+ ir_variable *var;
+ ir_assignment *assign;
+
+ if (!this->predicate(ir))
+ return ir;
+
+ var = new(ctx) ir_variable(ir->type, "flattening_tmp", ir_var_temporary);
+ base_ir->insert_before(var);
+
+ assign = new(ctx) ir_assignment(new(ctx) ir_dereference_variable(var),
+ ir,
+ NULL);
+ base_ir->insert_before(assign);
+
+ return new(ctx) ir_dereference_variable(var);
+}
+
+ir_visitor_status
+ir_expression_flattening_visitor::visit_enter(ir_function_signature *ir)
+{
+ do_expression_flattening(&ir->body, this->predicate);
+
+ return visit_continue_with_parent;
+}
+
+ir_visitor_status
+ir_expression_flattening_visitor::visit_enter(ir_loop *ir)
+{
+ do_expression_flattening(&ir->body_instructions, this->predicate);
+
+ return visit_continue_with_parent;
+}
+
+ir_visitor_status
+ir_expression_flattening_visitor::visit_enter(ir_if *ir)
+{
+ ir->condition->accept(this);
+
+ do_expression_flattening(&ir->then_instructions, this->predicate);
+ do_expression_flattening(&ir->else_instructions, this->predicate);
+
+ return visit_continue_with_parent;
+}
+
+ir_visitor_status
+ir_expression_flattening_visitor::visit_leave(ir_expression *ir)
+{
+ unsigned int operand;
+
+ for (operand = 0; operand < ir->get_num_operands(); operand++) {
+ /* If the operand matches the predicate, then we'll assign its
+ * value to a temporary and deref the temporary as the operand.
+ */
+ ir->operands[operand] = operand_to_temp(ir->operands[operand]);
+ }
+
+ return visit_continue;
+}
+
+ir_visitor_status
+ir_expression_flattening_visitor::visit_leave(ir_assignment *ir)
+{
+ ir->rhs = operand_to_temp(ir->rhs);
+ if (ir->condition)
+ ir->condition = operand_to_temp(ir->condition);
+
+ return visit_continue;
+}
+
+ir_visitor_status
+ir_expression_flattening_visitor::visit_leave(ir_swizzle *ir)
+{
+ if (this->predicate(ir->val)) {
+ ir->val = operand_to_temp(ir->val);
+ }
+
+ return visit_continue;
+}
+
+ir_visitor_status
+ir_expression_flattening_visitor::visit_enter(ir_call *ir)
+{
+ /* Reminder: iterating ir_call iterates its parameters. */
+ foreach_iter(exec_list_iterator, iter, *ir) {
+ ir_rvalue *ir = (ir_rvalue *)iter.get();
+ ir_rvalue *new_ir = operand_to_temp(ir);
+
+ if (new_ir != ir) {
+ ir->replace_with(new_ir);
+ }
+ }
+
+ return visit_continue;
+}
+
+
+ir_visitor_status
+ir_expression_flattening_visitor::visit_enter(ir_return *ir)
+{
+ if (ir->value)
+ ir->value = operand_to_temp(ir->value);
+ return visit_continue;
+}
diff --git a/src/glsl/ir_expression_flattening.h b/src/glsl/ir_expression_flattening.h
new file mode 100644
index 00000000000..2eda1590001
--- /dev/null
+++ b/src/glsl/ir_expression_flattening.h
@@ -0,0 +1,38 @@
+/*
+ * Copyright © 2010 Intel Corporation
+ *
+ * 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 (including the next
+ * paragraph) 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
+ * THE AUTHORS OR COPYRIGHT HOLDERS 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 ir_expression_flattening.h
+ *
+ * Takes the leaves of expression trees and makes them dereferences of
+ * assignments of the leaves to temporaries, according to a predicate.
+ *
+ * This is used for automatic function inlining, where we want to take
+ * an expression containing a call and move the call out to its own
+ * assignment so that we can inline it at the appropriate place in the
+ * instruction stream.
+ */
+
+void do_expression_flattening(exec_list *instructions,
+ bool (*predicate)(ir_instruction *ir));
diff --git a/src/glsl/ir_function.cpp b/src/glsl/ir_function.cpp
new file mode 100644
index 00000000000..0a97e014244
--- /dev/null
+++ b/src/glsl/ir_function.cpp
@@ -0,0 +1,224 @@
+/*
+ * Copyright © 2010 Intel Corporation
+ *
+ * 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 (including the next
+ * paragraph) 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
+ * THE AUTHORS OR COPYRIGHT HOLDERS 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.
+ */
+
+#include "glsl_types.h"
+#include "ir.h"
+
+int
+type_compare(const glsl_type *a, const glsl_type *b)
+{
+ /* If the types are the same, they trivially match.
+ */
+ if (a == b)
+ return 0;
+
+ switch (a->base_type) {
+ case GLSL_TYPE_UINT:
+ case GLSL_TYPE_INT:
+ case GLSL_TYPE_BOOL:
+ /* There is no implicit conversion to or from integer types or bool.
+ */
+ if ((a->is_integer() != b->is_integer())
+ || (a->is_boolean() != b->is_boolean()))
+ return -1;
+
+ /* FALLTHROUGH */
+
+ case GLSL_TYPE_FLOAT:
+ if ((a->vector_elements != b->vector_elements)
+ || (a->matrix_columns != b->matrix_columns))
+ return -1;
+
+ return 1;
+
+ case GLSL_TYPE_SAMPLER:
+ case GLSL_TYPE_STRUCT:
+ /* Samplers and structures must match exactly.
+ */
+ return -1;
+
+ case GLSL_TYPE_ARRAY:
+ if ((b->base_type != GLSL_TYPE_ARRAY)
+ || (a->length != b->length))
+ return -1;
+
+ /* From GLSL 1.50 spec, page 27 (page 33 of the PDF):
+ * "There are no implicit array or structure conversions."
+ *
+ * If the comparison of the array element types detects that a conversion
+ * would be required, the array types do not match.
+ */
+ return (type_compare(a->fields.array, b->fields.array) == 0) ? 0 : -1;
+
+ case GLSL_TYPE_FUNCTION:
+ case GLSL_TYPE_VOID:
+ case GLSL_TYPE_ERROR:
+ default:
+ /* These are all error conditions. It is invalid for a parameter to
+ * a function to be declared as error, void, or a function.
+ */
+ return -1;
+ }
+
+ /* This point should be unreachable.
+ */
+ assert(0);
+}
+
+
+static int
+parameter_lists_match(const exec_list *list_a, const exec_list *list_b)
+{
+ const exec_node *node_a = list_a->head;
+ const exec_node *node_b = list_b->head;
+ int total_score = 0;
+
+ for (/* empty */
+ ; !node_a->is_tail_sentinel()
+ ; node_a = node_a->next, node_b = node_b->next) {
+ /* If all of the parameters from the other parameter list have been
+ * exhausted, the lists have different length and, by definition,
+ * do not match.
+ */
+ if (node_b->is_tail_sentinel())
+ return -1;
+
+
+ const ir_variable *const param = (ir_variable *) node_a;
+ const ir_instruction *const actual = (ir_instruction *) node_b;
+
+ /* Determine whether or not the types match. If the types are an
+ * exact match, the match score is zero. If the types don't match
+ * but the actual parameter can be coerced to the type of the declared
+ * parameter, the match score is one.
+ */
+ int score;
+ switch ((enum ir_variable_mode)(param->mode)) {
+ case ir_var_auto:
+ case ir_var_uniform:
+ case ir_var_temporary:
+ /* These are all error conditions. It is invalid for a parameter to
+ * a function to be declared as auto (not in, out, or inout) or
+ * as uniform.
+ */
+ assert(0);
+ return -1;
+
+ case ir_var_in:
+ score = type_compare(param->type, actual->type);
+ break;
+
+ case ir_var_out:
+ score = type_compare(actual->type, param->type);
+ break;
+
+ case ir_var_inout:
+ /* Since there are no bi-directional automatic conversions (e.g.,
+ * there is int -> float but no float -> int), inout parameters must
+ * be exact matches.
+ */
+ score = (type_compare(actual->type, param->type) == 0) ? 0 : -1;
+ break;
+ }
+
+ if (score < 0)
+ return -1;
+
+ total_score += score;
+ }
+
+ /* If all of the parameters from the other parameter list have been
+ * exhausted, the lists have different length and, by definition, do not
+ * match.
+ */
+ if (!node_b->is_tail_sentinel())
+ return -1;
+
+ return total_score;
+}
+
+
+ir_function_signature *
+ir_function::matching_signature(const exec_list *actual_parameters)
+{
+ ir_function_signature *match = NULL;
+
+ foreach_iter(exec_list_iterator, iter, signatures) {
+ ir_function_signature *const sig =
+ (ir_function_signature *) iter.get();
+
+ const int score = parameter_lists_match(& sig->parameters,
+ actual_parameters);
+
+ if (score == 0)
+ return sig;
+
+ if (score > 0) {
+ if (match != NULL)
+ return NULL;
+
+ match = sig;
+ }
+ }
+
+ return match;
+}
+
+
+static bool
+parameter_lists_match_exact(const exec_list *list_a, const exec_list *list_b)
+{
+ const exec_node *node_a = list_a->head;
+ const exec_node *node_b = list_b->head;
+
+ for (/* empty */
+ ; !node_a->is_tail_sentinel() && !node_b->is_tail_sentinel()
+ ; node_a = node_a->next, node_b = node_b->next) {
+ ir_variable *a = (ir_variable *) node_a;
+ ir_variable *b = (ir_variable *) node_b;
+
+ /* If the types of the parameters do not match, the parameters lists
+ * are different.
+ */
+ if (a->type != b->type)
+ return false;
+ }
+
+ /* Unless both lists are exhausted, they differ in length and, by
+ * definition, do not match.
+ */
+ return (node_a->is_tail_sentinel() == node_b->is_tail_sentinel());
+}
+
+ir_function_signature *
+ir_function::exact_matching_signature(const exec_list *actual_parameters)
+{
+ foreach_iter(exec_list_iterator, iter, signatures) {
+ ir_function_signature *const sig =
+ (ir_function_signature *) iter.get();
+
+ if (parameter_lists_match_exact(&sig->parameters, actual_parameters))
+ return sig;
+ }
+ return NULL;
+}
diff --git a/src/glsl/ir_function_can_inline.cpp b/src/glsl/ir_function_can_inline.cpp
new file mode 100644
index 00000000000..8bb8e0d9ed7
--- /dev/null
+++ b/src/glsl/ir_function_can_inline.cpp
@@ -0,0 +1,71 @@
+/*
+ * Copyright © 2010 Intel Corporation
+ *
+ * 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 (including the next
+ * paragraph) 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
+ * THE AUTHORS OR COPYRIGHT HOLDERS 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 ir_function_can_inline.cpp
+ *
+ * Determines if we can inline a function call using ir_function_inlining.cpp.
+ *
+ * The primary restriction is that we can't return from the function
+ * other than as the last instruction. We could potentially work
+ * around this for some constructs by flattening control flow and
+ * moving the return to the end, or by using breaks from a do {} while
+ * (0) loop surrounding the function body.
+ */
+
+#include "ir.h"
+
+class ir_function_can_inline_visitor : public ir_hierarchical_visitor {
+public:
+ ir_function_can_inline_visitor()
+ {
+ this->num_returns = 0;
+ }
+
+ virtual ir_visitor_status visit_enter(ir_return *);
+
+ int num_returns;
+};
+
+ir_visitor_status
+ir_function_can_inline_visitor::visit_enter(ir_return *ir)
+{
+ (void) ir;
+ this->num_returns++;
+ return visit_continue;
+}
+
+bool
+can_inline(ir_call *call)
+{
+ ir_function_can_inline_visitor v;
+ const ir_function_signature *callee = call->get_callee();
+
+ v.run((exec_list *) &callee->body);
+
+ ir_instruction *last = (ir_instruction *)callee->body.get_tail();
+ if (last && !last->as_return())
+ v.num_returns++;
+
+ return v.num_returns == 1;
+}
diff --git a/src/glsl/ir_function_inlining.cpp b/src/glsl/ir_function_inlining.cpp
new file mode 100644
index 00000000000..56d29e3fd16
--- /dev/null
+++ b/src/glsl/ir_function_inlining.cpp
@@ -0,0 +1,417 @@
+/*
+ * Copyright © 2010 Intel Corporation
+ *
+ * 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 (including the next
+ * paragraph) 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
+ * THE AUTHORS OR COPYRIGHT HOLDERS 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 ir_function_inlining.cpp
+ *
+ * Replaces calls to functions with the body of the function.
+ */
+
+#include <stdint.h>
+#include "ir.h"
+#include "ir_visitor.h"
+#include "ir_function_inlining.h"
+#include "ir_expression_flattening.h"
+#include "glsl_types.h"
+#include "program/hash_table.h"
+
+static void
+do_sampler_replacement(exec_list *instructions,
+ ir_variable *sampler,
+ ir_dereference *deref);
+
+class ir_function_inlining_visitor : public ir_hierarchical_visitor {
+public:
+ ir_function_inlining_visitor()
+ {
+ progress = false;
+ }
+
+ virtual ~ir_function_inlining_visitor()
+ {
+ /* empty */
+ }
+
+ virtual ir_visitor_status visit_enter(ir_expression *);
+ virtual ir_visitor_status visit_enter(ir_call *);
+ virtual ir_visitor_status visit_enter(ir_assignment *);
+ virtual ir_visitor_status visit_enter(ir_return *);
+ virtual ir_visitor_status visit_enter(ir_texture *);
+ virtual ir_visitor_status visit_enter(ir_swizzle *);
+
+ bool progress;
+};
+
+
+bool
+automatic_inlining_predicate(ir_instruction *ir)
+{
+ ir_call *call = ir->as_call();
+
+ if (call && can_inline(call))
+ return true;
+
+ return false;
+}
+
+bool
+do_function_inlining(exec_list *instructions)
+{
+ ir_function_inlining_visitor v;
+
+ do_expression_flattening(instructions, automatic_inlining_predicate);
+
+ v.run(instructions);
+
+ return v.progress;
+}
+
+static void
+replace_return_with_assignment(ir_instruction *ir, void *data)
+{
+ void *ctx = talloc_parent(ir);
+ ir_variable *retval = (ir_variable *)data;
+ ir_return *ret = ir->as_return();
+
+ if (ret) {
+ if (ret->value) {
+ ir_rvalue *lhs = new(ctx) ir_dereference_variable(retval);
+ ret->replace_with(new(ctx) ir_assignment(lhs, ret->value, NULL));
+ } else {
+ /* un-valued return has to be the last return, or we shouldn't
+ * have reached here. (see can_inline()).
+ */
+ assert(ret->next->is_tail_sentinel());
+ ret->remove();
+ }
+ }
+}
+
+ir_rvalue *
+ir_call::generate_inline(ir_instruction *next_ir)
+{
+ void *ctx = talloc_parent(this);
+ ir_variable **parameters;
+ int num_parameters;
+ int i;
+ ir_variable *retval = NULL;
+ struct hash_table *ht;
+
+ ht = hash_table_ctor(0, hash_table_pointer_hash, hash_table_pointer_compare);
+
+ num_parameters = 0;
+ foreach_iter(exec_list_iterator, iter_sig, this->callee->parameters)
+ num_parameters++;
+
+ parameters = new ir_variable *[num_parameters];
+
+ /* Generate storage for the return value. */
+ if (this->callee->return_type) {
+ retval = new(ctx) ir_variable(this->callee->return_type, "_ret_val",
+ ir_var_auto);
+ next_ir->insert_before(retval);
+ }
+
+ /* Generate the declarations for the parameters to our inlined code,
+ * and set up the mapping of real function body variables to ours.
+ */
+ i = 0;
+ exec_list_iterator sig_param_iter = this->callee->parameters.iterator();
+ exec_list_iterator param_iter = this->actual_parameters.iterator();
+ for (i = 0; i < num_parameters; i++) {
+ ir_variable *sig_param = (ir_variable *) sig_param_iter.get();
+ ir_rvalue *param = (ir_rvalue *) param_iter.get();
+
+ /* Generate a new variable for the parameter. */
+ if (sig_param->type->base_type == GLSL_TYPE_SAMPLER) {
+ /* For samplers, we want the inlined sampler references
+ * referencing the passed in sampler variable, since that
+ * will have the location information, which an assignment of
+ * a sampler wouldn't. Fix it up below.
+ */
+ parameters[i] = NULL;
+ } else {
+ parameters[i] = sig_param->clone(ctx, ht);
+ parameters[i]->mode = ir_var_auto;
+ next_ir->insert_before(parameters[i]);
+ }
+
+ /* Move the actual param into our param variable if it's an 'in' type. */
+ if (parameters[i] && (sig_param->mode == ir_var_in ||
+ sig_param->mode == ir_var_inout)) {
+ ir_assignment *assign;
+
+ assign = new(ctx) ir_assignment(new(ctx) ir_dereference_variable(parameters[i]),
+ param, NULL);
+ next_ir->insert_before(assign);
+ }
+
+ sig_param_iter.next();
+ param_iter.next();
+ }
+
+ exec_list new_instructions;
+
+ /* Generate the inlined body of the function to a new list */
+ foreach_iter(exec_list_iterator, iter, callee->body) {
+ ir_instruction *ir = (ir_instruction *)iter.get();
+ ir_instruction *new_ir = ir->clone(ctx, ht);
+
+ new_instructions.push_tail(new_ir);
+ visit_tree(new_ir, replace_return_with_assignment, retval);
+ }
+
+ /* If any samplers were passed in, replace any deref of the sampler
+ * with a deref of the sampler argument.
+ */
+ param_iter = this->actual_parameters.iterator();
+ sig_param_iter = this->callee->parameters.iterator();
+ for (i = 0; i < num_parameters; i++) {
+ ir_instruction *const param = (ir_instruction *) param_iter.get();
+ ir_variable *sig_param = (ir_variable *) sig_param_iter.get();
+
+ if (sig_param->type->base_type == GLSL_TYPE_SAMPLER) {
+ ir_dereference *deref = param->as_dereference();
+
+ assert(deref);
+ do_sampler_replacement(&new_instructions, sig_param, deref);
+ }
+ param_iter.next();
+ sig_param_iter.next();
+ }
+
+ /* Now push those new instructions in. */
+ foreach_iter(exec_list_iterator, iter, new_instructions) {
+ ir_instruction *ir = (ir_instruction *)iter.get();
+ next_ir->insert_before(ir);
+ }
+
+ /* Copy back the value of any 'out' parameters from the function body
+ * variables to our own.
+ */
+ i = 0;
+ param_iter = this->actual_parameters.iterator();
+ sig_param_iter = this->callee->parameters.iterator();
+ for (i = 0; i < num_parameters; i++) {
+ ir_instruction *const param = (ir_instruction *) param_iter.get();
+ const ir_variable *const sig_param = (ir_variable *) sig_param_iter.get();
+
+ /* Move our param variable into the actual param if it's an 'out' type. */
+ if (parameters[i] && (sig_param->mode == ir_var_out ||
+ sig_param->mode == ir_var_inout)) {
+ ir_assignment *assign;
+
+ assign = new(ctx) ir_assignment(param->clone(ctx, NULL)->as_rvalue(),
+ new(ctx) ir_dereference_variable(parameters[i]),
+ NULL);
+ next_ir->insert_before(assign);
+ }
+
+ param_iter.next();
+ sig_param_iter.next();
+ }
+
+ delete [] parameters;
+
+ hash_table_dtor(ht);
+
+ if (retval)
+ return new(ctx) ir_dereference_variable(retval);
+ else
+ return NULL;
+}
+
+
+ir_visitor_status
+ir_function_inlining_visitor::visit_enter(ir_expression *ir)
+{
+ (void) ir;
+ return visit_continue_with_parent;
+}
+
+
+ir_visitor_status
+ir_function_inlining_visitor::visit_enter(ir_return *ir)
+{
+ (void) ir;
+ return visit_continue_with_parent;
+}
+
+
+ir_visitor_status
+ir_function_inlining_visitor::visit_enter(ir_texture *ir)
+{
+ (void) ir;
+ return visit_continue_with_parent;
+}
+
+
+ir_visitor_status
+ir_function_inlining_visitor::visit_enter(ir_swizzle *ir)
+{
+ (void) ir;
+ return visit_continue_with_parent;
+}
+
+
+ir_visitor_status
+ir_function_inlining_visitor::visit_enter(ir_call *ir)
+{
+ if (can_inline(ir)) {
+ /* If the call was part of some tree, then it should have been
+ * flattened out or we shouldn't have seen it because of a
+ * visit_continue_with_parent in this visitor.
+ */
+ assert(ir == base_ir);
+
+ (void) ir->generate_inline(ir);
+ ir->remove();
+ this->progress = true;
+ }
+
+ return visit_continue;
+}
+
+
+ir_visitor_status
+ir_function_inlining_visitor::visit_enter(ir_assignment *ir)
+{
+ ir_call *call = ir->rhs->as_call();
+ if (!call || !can_inline(call))
+ return visit_continue;
+
+ /* generates the parameter setup, function body, and returns the return
+ * value of the function
+ */
+ ir_rvalue *rhs = call->generate_inline(ir);
+ assert(rhs);
+
+ ir->rhs = rhs;
+ this->progress = true;
+
+ return visit_continue;
+}
+
+/**
+ * Replaces references to the "sampler" variable with a clone of "deref."
+ *
+ * From the spec, samplers can appear in the tree as function
+ * (non-out) parameters and as the result of array indexing and
+ * structure field selection. In our builtin implementation, they
+ * also appear in the sampler field of an ir_tex instruction.
+ */
+
+class ir_sampler_replacement_visitor : public ir_hierarchical_visitor {
+public:
+ ir_sampler_replacement_visitor(ir_variable *sampler, ir_dereference *deref)
+ {
+ this->sampler = sampler;
+ this->deref = deref;
+ }
+
+ virtual ~ir_sampler_replacement_visitor()
+ {
+ }
+
+ virtual ir_visitor_status visit_leave(ir_call *);
+ virtual ir_visitor_status visit_leave(ir_dereference_array *);
+ virtual ir_visitor_status visit_leave(ir_dereference_record *);
+ virtual ir_visitor_status visit_leave(ir_texture *);
+
+ void replace_deref(ir_dereference **deref);
+ void replace_rvalue(ir_rvalue **rvalue);
+
+ ir_variable *sampler;
+ ir_dereference *deref;
+};
+
+void
+ir_sampler_replacement_visitor::replace_deref(ir_dereference **deref)
+{
+ ir_dereference_variable *deref_var = (*deref)->as_dereference_variable();
+ if (deref_var && deref_var->var == this->sampler) {
+ *deref = this->deref->clone(talloc_parent(*deref), NULL);
+ }
+}
+
+void
+ir_sampler_replacement_visitor::replace_rvalue(ir_rvalue **rvalue)
+{
+ if (!*rvalue)
+ return;
+
+ ir_dereference *deref = (*rvalue)->as_dereference();
+
+ if (!deref)
+ return;
+
+ replace_deref(&deref);
+ *rvalue = deref;
+}
+
+ir_visitor_status
+ir_sampler_replacement_visitor::visit_leave(ir_texture *ir)
+{
+ replace_deref(&ir->sampler);
+
+ return visit_continue;
+}
+
+ir_visitor_status
+ir_sampler_replacement_visitor::visit_leave(ir_dereference_array *ir)
+{
+ replace_rvalue(&ir->array);
+ return visit_continue;
+}
+
+ir_visitor_status
+ir_sampler_replacement_visitor::visit_leave(ir_dereference_record *ir)
+{
+ replace_rvalue(&ir->record);
+ return visit_continue;
+}
+
+ir_visitor_status
+ir_sampler_replacement_visitor::visit_leave(ir_call *ir)
+{
+ foreach_iter(exec_list_iterator, iter, *ir) {
+ ir_rvalue *param = (ir_rvalue *)iter.get();
+ ir_rvalue *new_param = param;
+ replace_rvalue(&new_param);
+
+ if (new_param != param) {
+ param->replace_with(new_param);
+ }
+ }
+ return visit_continue;
+}
+
+static void
+do_sampler_replacement(exec_list *instructions,
+ ir_variable *sampler,
+ ir_dereference *deref)
+{
+ ir_sampler_replacement_visitor v(sampler, deref);
+
+ visit_list_elements(&v, instructions);
+}
diff --git a/src/glsl/ir_function_inlining.h b/src/glsl/ir_function_inlining.h
new file mode 100644
index 00000000000..6db011bbcae
--- /dev/null
+++ b/src/glsl/ir_function_inlining.h
@@ -0,0 +1,30 @@
+/*
+ * Copyright © 2010 Intel Corporation
+ *
+ * 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 (including the next
+ * paragraph) 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
+ * THE AUTHORS OR COPYRIGHT HOLDERS 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 ir_function_inlining.h
+ *
+ * Replaces calls to functions with the body of the function.
+ */
+
+bool can_inline(ir_call *call);
diff --git a/src/glsl/ir_hierarchical_visitor.cpp b/src/glsl/ir_hierarchical_visitor.cpp
new file mode 100644
index 00000000000..d475df62fce
--- /dev/null
+++ b/src/glsl/ir_hierarchical_visitor.cpp
@@ -0,0 +1,295 @@
+/*
+ * Copyright © 2010 Intel Corporation
+ *
+ * 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 (including the next
+ * paragraph) 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
+ * THE AUTHORS OR COPYRIGHT HOLDERS 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.
+ */
+
+#include "ir.h"
+#include "ir_hierarchical_visitor.h"
+
+ir_hierarchical_visitor::ir_hierarchical_visitor()
+{
+ this->callback = NULL;
+ this->data = NULL;
+}
+
+ir_visitor_status
+ir_hierarchical_visitor::visit(ir_variable *ir)
+{
+ if (this->callback != NULL)
+ this->callback(ir, this->data);
+
+ return visit_continue;
+}
+
+ir_visitor_status
+ir_hierarchical_visitor::visit(ir_constant *ir)
+{
+ if (this->callback != NULL)
+ this->callback(ir, this->data);
+
+ return visit_continue;
+}
+
+ir_visitor_status
+ir_hierarchical_visitor::visit(ir_loop_jump *ir)
+{
+ if (this->callback != NULL)
+ this->callback(ir, this->data);
+
+ return visit_continue;
+}
+
+ir_visitor_status
+ir_hierarchical_visitor::visit(ir_dereference_variable *ir)
+{
+ if (this->callback != NULL)
+ this->callback(ir, this->data);
+
+ return visit_continue;
+}
+
+ir_visitor_status
+ir_hierarchical_visitor::visit_enter(ir_loop *ir)
+{
+ if (this->callback != NULL)
+ this->callback(ir, this->data);
+
+ return visit_continue;
+}
+
+ir_visitor_status
+ir_hierarchical_visitor::visit_leave(ir_loop *ir)
+{
+ (void) ir;
+ return visit_continue;
+}
+
+ir_visitor_status
+ir_hierarchical_visitor::visit_enter(ir_function_signature *ir)
+{
+ if (this->callback != NULL)
+ this->callback(ir, this->data);
+
+ return visit_continue;
+}
+
+ir_visitor_status
+ir_hierarchical_visitor::visit_leave(ir_function_signature *ir)
+{
+ (void) ir;
+ return visit_continue;
+}
+
+ir_visitor_status
+ir_hierarchical_visitor::visit_enter(ir_function *ir)
+{
+ if (this->callback != NULL)
+ this->callback(ir, this->data);
+
+ return visit_continue;
+}
+
+ir_visitor_status
+ir_hierarchical_visitor::visit_leave(ir_function *ir)
+{
+ (void) ir;
+ return visit_continue;
+}
+
+ir_visitor_status
+ir_hierarchical_visitor::visit_enter(ir_expression *ir)
+{
+ if (this->callback != NULL)
+ this->callback(ir, this->data);
+
+ return visit_continue;
+}
+
+ir_visitor_status
+ir_hierarchical_visitor::visit_leave(ir_expression *ir)
+{
+ (void) ir;
+ return visit_continue;
+}
+
+ir_visitor_status
+ir_hierarchical_visitor::visit_enter(ir_texture *ir)
+{
+ if (this->callback != NULL)
+ this->callback(ir, this->data);
+
+ return visit_continue;
+}
+
+ir_visitor_status
+ir_hierarchical_visitor::visit_leave(ir_texture *ir)
+{
+ (void) ir;
+ return visit_continue;
+}
+
+ir_visitor_status
+ir_hierarchical_visitor::visit_enter(ir_swizzle *ir)
+{
+ if (this->callback != NULL)
+ this->callback(ir, this->data);
+
+ return visit_continue;
+}
+
+ir_visitor_status
+ir_hierarchical_visitor::visit_leave(ir_swizzle *ir)
+{
+ (void) ir;
+ return visit_continue;
+}
+
+ir_visitor_status
+ir_hierarchical_visitor::visit_enter(ir_dereference_array *ir)
+{
+ if (this->callback != NULL)
+ this->callback(ir, this->data);
+
+ return visit_continue;
+}
+
+ir_visitor_status
+ir_hierarchical_visitor::visit_leave(ir_dereference_array *ir)
+{
+ (void) ir;
+ return visit_continue;
+}
+
+ir_visitor_status
+ir_hierarchical_visitor::visit_enter(ir_dereference_record *ir)
+{
+ if (this->callback != NULL)
+ this->callback(ir, this->data);
+
+ return visit_continue;
+}
+
+ir_visitor_status
+ir_hierarchical_visitor::visit_leave(ir_dereference_record *ir)
+{
+ (void) ir;
+ return visit_continue;
+}
+
+ir_visitor_status
+ir_hierarchical_visitor::visit_enter(ir_assignment *ir)
+{
+ if (this->callback != NULL)
+ this->callback(ir, this->data);
+
+ return visit_continue;
+}
+
+ir_visitor_status
+ir_hierarchical_visitor::visit_leave(ir_assignment *ir)
+{
+ (void) ir;
+ return visit_continue;
+}
+
+ir_visitor_status
+ir_hierarchical_visitor::visit_enter(ir_call *ir)
+{
+ if (this->callback != NULL)
+ this->callback(ir, this->data);
+
+ return visit_continue;
+}
+
+ir_visitor_status
+ir_hierarchical_visitor::visit_leave(ir_call *ir)
+{
+ (void) ir;
+ return visit_continue;
+}
+
+ir_visitor_status
+ir_hierarchical_visitor::visit_enter(ir_return *ir)
+{
+ if (this->callback != NULL)
+ this->callback(ir, this->data);
+
+ return visit_continue;
+}
+
+ir_visitor_status
+ir_hierarchical_visitor::visit_leave(ir_return *ir)
+{
+ (void) ir;
+ return visit_continue;
+}
+
+ir_visitor_status
+ir_hierarchical_visitor::visit_enter(ir_discard *ir)
+{
+ if (this->callback != NULL)
+ this->callback(ir, this->data);
+
+ return visit_continue;
+}
+
+ir_visitor_status
+ir_hierarchical_visitor::visit_leave(ir_discard *ir)
+{
+ (void) ir;
+ return visit_continue;
+}
+
+ir_visitor_status
+ir_hierarchical_visitor::visit_enter(ir_if *ir)
+{
+ if (this->callback != NULL)
+ this->callback(ir, this->data);
+
+ return visit_continue;
+}
+
+ir_visitor_status
+ir_hierarchical_visitor::visit_leave(ir_if *ir)
+{
+ (void) ir;
+ return visit_continue;
+}
+
+void
+ir_hierarchical_visitor::run(exec_list *instructions)
+{
+ visit_list_elements(this, instructions);
+}
+
+
+void
+visit_tree(ir_instruction *ir,
+ void (*callback)(class ir_instruction *ir, void *data),
+ void *data)
+{
+ ir_hierarchical_visitor v;
+
+ v.callback = callback;
+ v.data = data;
+
+ ir->accept(&v);
+}
diff --git a/src/glsl/ir_hierarchical_visitor.h b/src/glsl/ir_hierarchical_visitor.h
new file mode 100644
index 00000000000..afa780dc912
--- /dev/null
+++ b/src/glsl/ir_hierarchical_visitor.h
@@ -0,0 +1,176 @@
+/* -*- c++ -*- */
+/*
+ * Copyright © 2010 Intel Corporation
+ *
+ * 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 (including the next
+ * paragraph) 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
+ * THE AUTHORS OR COPYRIGHT HOLDERS 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.
+ */
+
+#pragma once
+#ifndef IR_HIERARCHICAL_VISITOR_H
+#define IR_HIERARCHICAL_VISITOR_H
+
+/**
+ * Enumeration values returned by visit methods to guide processing
+ */
+enum ir_visitor_status {
+ visit_continue, /**< Continue visiting as normal. */
+ visit_continue_with_parent, /**< Don't visit siblings, continue w/parent. */
+ visit_stop /**< Stop visiting immediately. */
+};
+
+
+/**
+ * Base class of hierarchical visitors of IR instruction trees
+ *
+ * Hierarchical visitors differ from traditional visitors in a couple of
+ * important ways. Rather than having a single \c visit method for each
+ * subclass in the composite, there are three kinds of visit methods.
+ * Leaf-node classes have a traditional \c visit method. Internal-node
+ * classes have a \c visit_enter method, which is invoked just before
+ * processing child nodes, and a \c visit_leave method which is invoked just
+ * after processing child nodes.
+ *
+ * In addition, each visit method and the \c accept methods in the composite
+ * have a return value which guides the navigation. Any of the visit methods
+ * can choose to continue visiting the tree as normal (by returning \c
+ * visit_continue), terminate visiting any further nodes immediately (by
+ * returning \c visit_stop), or stop visiting sibling nodes (by returning \c
+ * visit_continue_with_parent).
+ *
+ * These two changes combine to allow nagivation of children to be implemented
+ * in the composite's \c accept method. The \c accept method for a leaf-node
+ * class will simply call the \c visit method, as usual, and pass its return
+ * value on. The \c accept method for internal-node classes will call the \c
+ * visit_enter method, call the \c accpet method of each child node, and,
+ * finally, call the \c visit_leave method. If any of these return a value
+ * other that \c visit_continue, the correct action must be taken.
+ *
+ * The final benefit is that the hierarchical visitor base class need not be
+ * abstract. Default implementations of every \c visit, \c visit_enter, and
+ * \c visit_leave method can be provided. By default each of these methods
+ * simply returns \c visit_continue. This allows a significant reduction in
+ * derived class code.
+ *
+ * For more information about hierarchical visitors, see:
+ *
+ * http://c2.com/cgi/wiki?HierarchicalVisitorPattern
+ * http://c2.com/cgi/wiki?HierarchicalVisitorDiscussion
+ */
+
+class ir_hierarchical_visitor {
+public:
+ ir_hierarchical_visitor();
+
+ /**
+ * \name Visit methods for leaf-node classes
+ */
+ /*@{*/
+ virtual ir_visitor_status visit(class ir_variable *);
+ virtual ir_visitor_status visit(class ir_constant *);
+ virtual ir_visitor_status visit(class ir_loop_jump *);
+
+ /**
+ * ir_dereference_variable isn't technically a leaf, but it is treated as a
+ * leaf here for a couple reasons. By not automatically visiting the one
+ * child ir_variable node from the ir_dereference_variable, ir_variable
+ * nodes can always be handled as variable declarations. Code that used
+ * non-hierarchical visitors had to set an "in a dereference" flag to
+ * determine how to handle an ir_variable. By forcing the visitor to
+ * handle the ir_variable within the ir_dereference_variable visitor, this
+ * kludge can be avoided.
+ *
+ * In addition, I can envision no use for having separate enter and leave
+ * methods. Anything that could be done in the enter and leave methods
+ * that couldn't just be done in the visit method.
+ */
+ virtual ir_visitor_status visit(class ir_dereference_variable *);
+ /*@}*/
+
+ /**
+ * \name Visit methods for internal-node classes
+ */
+ /*@{*/
+ virtual ir_visitor_status visit_enter(class ir_loop *);
+ virtual ir_visitor_status visit_leave(class ir_loop *);
+ virtual ir_visitor_status visit_enter(class ir_function_signature *);
+ virtual ir_visitor_status visit_leave(class ir_function_signature *);
+ virtual ir_visitor_status visit_enter(class ir_function *);
+ virtual ir_visitor_status visit_leave(class ir_function *);
+ virtual ir_visitor_status visit_enter(class ir_expression *);
+ virtual ir_visitor_status visit_leave(class ir_expression *);
+ virtual ir_visitor_status visit_enter(class ir_texture *);
+ virtual ir_visitor_status visit_leave(class ir_texture *);
+ virtual ir_visitor_status visit_enter(class ir_swizzle *);
+ virtual ir_visitor_status visit_leave(class ir_swizzle *);
+ virtual ir_visitor_status visit_enter(class ir_dereference_array *);
+ virtual ir_visitor_status visit_leave(class ir_dereference_array *);
+ virtual ir_visitor_status visit_enter(class ir_dereference_record *);
+ virtual ir_visitor_status visit_leave(class ir_dereference_record *);
+ virtual ir_visitor_status visit_enter(class ir_assignment *);
+ virtual ir_visitor_status visit_leave(class ir_assignment *);
+ virtual ir_visitor_status visit_enter(class ir_call *);
+ virtual ir_visitor_status visit_leave(class ir_call *);
+ virtual ir_visitor_status visit_enter(class ir_return *);
+ virtual ir_visitor_status visit_leave(class ir_return *);
+ virtual ir_visitor_status visit_enter(class ir_discard *);
+ virtual ir_visitor_status visit_leave(class ir_discard *);
+ virtual ir_visitor_status visit_enter(class ir_if *);
+ virtual ir_visitor_status visit_leave(class ir_if *);
+ /*@}*/
+
+
+ /**
+ * Utility function to process a linked list of instructions with a visitor
+ */
+ void run(struct exec_list *instructions);
+
+ /* Some visitors may need to insert new variable declarations and
+ * assignments for portions of a subtree, which means they need a
+ * pointer to the current instruction in the stream, not just their
+ * node in the tree rooted at that instruction.
+ *
+ * This is implemented by visit_list_elements -- if the visitor is
+ * not called by it, nothing good will happen.
+ */
+ class ir_instruction *base_ir;
+
+ /**
+ * Callback function that is invoked on entry to each node visited.
+ *
+ * \warning
+ * Visitor classes derived from \c ir_hierarchical_visitor \b may \b not
+ * invoke this function. This can be used, for example, to cause the
+ * callback to be invoked on every node type execpt one.
+ */
+ void (*callback)(class ir_instruction *ir, void *data);
+
+ /**
+ * Extra data parameter passed to the per-node callback function
+ */
+ void *data;
+};
+
+void visit_tree(ir_instruction *ir,
+ void (*callback)(class ir_instruction *ir, void *data),
+ void *data);
+
+ir_visitor_status visit_list_elements(ir_hierarchical_visitor *v, exec_list *l);
+
+#endif /* IR_HIERARCHICAL_VISITOR_H */
diff --git a/src/glsl/ir_hv_accept.cpp b/src/glsl/ir_hv_accept.cpp
new file mode 100644
index 00000000000..6dae4ed2f3f
--- /dev/null
+++ b/src/glsl/ir_hv_accept.cpp
@@ -0,0 +1,369 @@
+/*
+ * Copyright © 2010 Intel Corporation
+ *
+ * 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 (including the next
+ * paragraph) 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
+ * THE AUTHORS OR COPYRIGHT HOLDERS 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.
+ */
+
+#include "ir.h"
+
+/**
+ * \file ir_hv_accept.cpp
+ * Implementations of all hierarchical visitor accept methods for IR
+ * instructions.
+ */
+
+/**
+ * Process a list of nodes using a hierarchical vistor
+ *
+ * \warning
+ * This function will operate correctly if a node being processed is removed
+ * from the list. However, if nodes are added to the list after the node being
+ * processed, some of the added nodes may not be processed.
+ */
+ir_visitor_status
+visit_list_elements(ir_hierarchical_visitor *v, exec_list *l)
+{
+ ir_instruction *prev_base_ir = v->base_ir;
+
+ foreach_list_safe(n, l) {
+ ir_instruction *const ir = (ir_instruction *) n;
+ v->base_ir = ir;
+ ir_visitor_status s = ir->accept(v);
+
+ if (s != visit_continue)
+ return s;
+ }
+ v->base_ir = prev_base_ir;
+
+ return visit_continue;
+}
+
+
+ir_visitor_status
+ir_variable::accept(ir_hierarchical_visitor *v)
+{
+ return v->visit(this);
+}
+
+
+ir_visitor_status
+ir_loop::accept(ir_hierarchical_visitor *v)
+{
+ ir_visitor_status s = v->visit_enter(this);
+
+ if (s != visit_continue)
+ return (s == visit_continue_with_parent) ? visit_continue : s;
+
+ s = visit_list_elements(v, &this->body_instructions);
+ if (s == visit_stop)
+ return s;
+
+ if (s != visit_continue_with_parent) {
+ if (this->from) {
+ s = this->from->accept(v);
+ if (s != visit_continue)
+ return (s == visit_continue_with_parent) ? visit_continue : s;
+ }
+
+ if (this->to) {
+ s = this->to->accept(v);
+ if (s != visit_continue)
+ return (s == visit_continue_with_parent) ? visit_continue : s;
+ }
+
+ if (this->increment) {
+ s = this->increment->accept(v);
+ if (s != visit_continue)
+ return (s == visit_continue_with_parent) ? visit_continue : s;
+ }
+ }
+
+ return v->visit_leave(this);
+}
+
+
+ir_visitor_status
+ir_loop_jump::accept(ir_hierarchical_visitor *v)
+{
+ return v->visit(this);
+}
+
+
+ir_visitor_status
+ir_function_signature::accept(ir_hierarchical_visitor *v)
+{
+ ir_visitor_status s = v->visit_enter(this);
+ if (s != visit_continue)
+ return (s == visit_continue_with_parent) ? visit_continue : s;
+
+ s = visit_list_elements(v, &this->parameters);
+ if (s == visit_stop)
+ return s;
+
+ s = visit_list_elements(v, &this->body);
+ return (s == visit_stop) ? s : v->visit_leave(this);
+}
+
+
+ir_visitor_status
+ir_function::accept(ir_hierarchical_visitor *v)
+{
+ ir_visitor_status s = v->visit_enter(this);
+ if (s != visit_continue)
+ return (s == visit_continue_with_parent) ? visit_continue : s;
+
+ s = visit_list_elements(v, &this->signatures);
+ return (s == visit_stop) ? s : v->visit_leave(this);
+}
+
+
+ir_visitor_status
+ir_expression::accept(ir_hierarchical_visitor *v)
+{
+ ir_visitor_status s = v->visit_enter(this);
+
+ if (s != visit_continue)
+ return (s == visit_continue_with_parent) ? visit_continue : s;
+
+ for (unsigned i = 0; i < this->get_num_operands(); i++) {
+ switch (this->operands[i]->accept(v)) {
+ case visit_continue:
+ break;
+
+ case visit_continue_with_parent:
+ // I wish for Java's labeled break-statement here.
+ goto done;
+
+ case visit_stop:
+ return s;
+ }
+ }
+
+done:
+ return v->visit_leave(this);
+}
+
+ir_visitor_status
+ir_texture::accept(ir_hierarchical_visitor *v)
+{
+ ir_visitor_status s = v->visit_enter(this);
+ if (s != visit_continue)
+ return (s == visit_continue_with_parent) ? visit_continue : s;
+
+ s = this->sampler->accept(v);
+ if (s != visit_continue)
+ return (s == visit_continue_with_parent) ? visit_continue : s;
+
+ s = this->coordinate->accept(v);
+ if (s != visit_continue)
+ return (s == visit_continue_with_parent) ? visit_continue : s;
+
+ if (this->projector) {
+ s = this->projector->accept(v);
+ if (s != visit_continue)
+ return (s == visit_continue_with_parent) ? visit_continue : s;
+ }
+
+ if (this->shadow_comparitor) {
+ s = this->shadow_comparitor->accept(v);
+ if (s != visit_continue)
+ return (s == visit_continue_with_parent) ? visit_continue : s;
+ }
+
+ switch (this->op) {
+ case ir_tex:
+ break;
+ case ir_txb:
+ s = this->lod_info.bias->accept(v);
+ if (s != visit_continue)
+ return (s == visit_continue_with_parent) ? visit_continue : s;
+ break;
+ case ir_txl:
+ case ir_txf:
+ s = this->lod_info.lod->accept(v);
+ if (s != visit_continue)
+ return (s == visit_continue_with_parent) ? visit_continue : s;
+ break;
+ case ir_txd:
+ s = this->lod_info.grad.dPdx->accept(v);
+ if (s != visit_continue)
+ return (s == visit_continue_with_parent) ? visit_continue : s;
+
+ s = this->lod_info.grad.dPdy->accept(v);
+ if (s != visit_continue)
+ return (s == visit_continue_with_parent) ? visit_continue : s;
+ break;
+ }
+
+ return (s == visit_stop) ? s : v->visit_leave(this);
+}
+
+
+ir_visitor_status
+ir_swizzle::accept(ir_hierarchical_visitor *v)
+{
+ ir_visitor_status s = v->visit_enter(this);
+ if (s != visit_continue)
+ return (s == visit_continue_with_parent) ? visit_continue : s;
+
+ s = this->val->accept(v);
+ return (s == visit_stop) ? s : v->visit_leave(this);
+}
+
+
+ir_visitor_status
+ir_dereference_variable::accept(ir_hierarchical_visitor *v)
+{
+ return v->visit(this);
+}
+
+
+ir_visitor_status
+ir_dereference_array::accept(ir_hierarchical_visitor *v)
+{
+ ir_visitor_status s = v->visit_enter(this);
+ if (s != visit_continue)
+ return (s == visit_continue_with_parent) ? visit_continue : s;
+
+ s = this->array_index->accept(v);
+ if (s != visit_continue)
+ return (s == visit_continue_with_parent) ? visit_continue : s;
+
+ s = this->array->accept(v);
+ return (s == visit_stop) ? s : v->visit_leave(this);
+}
+
+
+ir_visitor_status
+ir_dereference_record::accept(ir_hierarchical_visitor *v)
+{
+ ir_visitor_status s = v->visit_enter(this);
+ if (s != visit_continue)
+ return (s == visit_continue_with_parent) ? visit_continue : s;
+
+ s = this->record->accept(v);
+ return (s == visit_stop) ? s : v->visit_leave(this);
+}
+
+
+ir_visitor_status
+ir_assignment::accept(ir_hierarchical_visitor *v)
+{
+ ir_visitor_status s = v->visit_enter(this);
+ if (s != visit_continue)
+ return (s == visit_continue_with_parent) ? visit_continue : s;
+
+ s = this->lhs->accept(v);
+ if (s != visit_continue)
+ return (s == visit_continue_with_parent) ? visit_continue : s;
+
+ s = this->rhs->accept(v);
+ if (s != visit_continue)
+ return (s == visit_continue_with_parent) ? visit_continue : s;
+
+ if (this->condition)
+ s = this->condition->accept(v);
+
+ return (s == visit_stop) ? s : v->visit_leave(this);
+}
+
+
+ir_visitor_status
+ir_constant::accept(ir_hierarchical_visitor *v)
+{
+ return v->visit(this);
+}
+
+
+ir_visitor_status
+ir_call::accept(ir_hierarchical_visitor *v)
+{
+ ir_visitor_status s = v->visit_enter(this);
+ if (s != visit_continue)
+ return (s == visit_continue_with_parent) ? visit_continue : s;
+
+ s = visit_list_elements(v, &this->actual_parameters);
+ if (s == visit_stop)
+ return s;
+
+ return v->visit_leave(this);
+}
+
+
+ir_visitor_status
+ir_return::accept(ir_hierarchical_visitor *v)
+{
+ ir_visitor_status s = v->visit_enter(this);
+ if (s != visit_continue)
+ return (s == visit_continue_with_parent) ? visit_continue : s;
+
+ ir_rvalue *val = this->get_value();
+ if (val) {
+ s = val->accept(v);
+ if (s != visit_continue)
+ return (s == visit_continue_with_parent) ? visit_continue : s;
+ }
+
+ return v->visit_leave(this);
+}
+
+
+ir_visitor_status
+ir_discard::accept(ir_hierarchical_visitor *v)
+{
+ ir_visitor_status s = v->visit_enter(this);
+ if (s != visit_continue)
+ return (s == visit_continue_with_parent) ? visit_continue : s;
+
+ if (this->condition != NULL) {
+ s = this->condition->accept(v);
+ if (s != visit_continue)
+ return (s == visit_continue_with_parent) ? visit_continue : s;
+ }
+
+ return v->visit_leave(this);
+}
+
+
+ir_visitor_status
+ir_if::accept(ir_hierarchical_visitor *v)
+{
+ ir_visitor_status s = v->visit_enter(this);
+ if (s != visit_continue)
+ return (s == visit_continue_with_parent) ? visit_continue : s;
+
+ s = this->condition->accept(v);
+ if (s != visit_continue)
+ return (s == visit_continue_with_parent) ? visit_continue : s;
+
+ if (s != visit_continue_with_parent) {
+ s = visit_list_elements(v, &this->then_instructions);
+ if (s == visit_stop)
+ return s;
+ }
+
+ if (s != visit_continue_with_parent) {
+ s = visit_list_elements(v, &this->else_instructions);
+ if (s == visit_stop)
+ return s;
+ }
+
+ return v->visit_leave(this);
+}
diff --git a/src/glsl/ir_if_return.cpp b/src/glsl/ir_if_return.cpp
new file mode 100644
index 00000000000..5ab8759958f
--- /dev/null
+++ b/src/glsl/ir_if_return.cpp
@@ -0,0 +1,246 @@
+/*
+ * Copyright © 2010 Intel Corporation
+ *
+ * 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 (including the next
+ * paragraph) 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
+ * THE AUTHORS OR COPYRIGHT HOLDERS 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 ir_if_return.cpp
+ *
+ * This pass tries to normalize functions to always return from one
+ * place by moving around blocks of code in if statements.
+ *
+ * This helps on hardware with no branching support, and may even be a
+ * useful transform on hardware supporting control flow by turning
+ * masked returns into normal returns.
+ */
+
+#include <string.h>
+#include "glsl_types.h"
+#include "ir.h"
+
+class ir_if_return_visitor : public ir_hierarchical_visitor {
+public:
+ ir_if_return_visitor()
+ {
+ this->progress = false;
+ }
+
+ ir_visitor_status visit_enter(ir_function_signature *);
+ ir_visitor_status visit_leave(ir_if *);
+
+ ir_visitor_status move_outer_block_inside(ir_instruction *ir,
+ exec_list *inner_block);
+ void move_returns_after_block(ir_instruction *ir,
+ ir_return *then_return,
+ ir_return *else_return);
+ bool progress;
+};
+
+bool
+do_if_return(exec_list *instructions)
+{
+ ir_if_return_visitor v;
+
+ do {
+ v.progress = false;
+ visit_list_elements(&v, instructions);
+ } while (v.progress);
+
+ return v.progress;
+}
+
+/**
+ * Removes any instructions after a (unconditional) return, since they will
+ * never be executed.
+ */
+static void
+truncate_after_instruction(ir_instruction *ir)
+{
+ if (!ir)
+ return;
+
+ while (!ir->get_next()->is_tail_sentinel())
+ ((ir_instruction *)ir->get_next())->remove();
+}
+
+/**
+ * Returns an ir_instruction of the first ir_return in the exec_list, or NULL.
+ */
+static ir_return *
+find_return_in_block(exec_list *instructions)
+{
+ foreach_iter(exec_list_iterator, iter, *instructions) {
+ ir_instruction *ir = (ir_instruction *)iter.get();
+ if (ir->ir_type == ir_type_return)
+ return (ir_return *)ir;
+ }
+
+ return NULL;
+}
+
+void
+ir_if_return_visitor::move_returns_after_block(ir_instruction *ir,
+ ir_return *then_return,
+ ir_return *else_return)
+{
+
+ if (!then_return->value) {
+ then_return->remove();
+ else_return->remove();
+ ir->insert_after(new(ir) ir_return(NULL));
+ } else {
+ ir_assignment *assign;
+ ir_variable *new_var = new(ir) ir_variable(then_return->value->type,
+ "if_return_tmp",
+ ir_var_temporary);
+ ir->insert_before(new_var);
+
+ assign = new(ir) ir_assignment(new(ir) ir_dereference_variable(new_var),
+ then_return->value, NULL);
+ then_return->replace_with(assign);
+
+ assign = new(ir) ir_assignment(new(ir) ir_dereference_variable(new_var),
+ else_return->value, NULL);
+ else_return->replace_with(assign);
+
+ ir_dereference_variable *deref = new(ir) ir_dereference_variable(new_var);
+ ir->insert_after(new(ir) ir_return(deref));
+ }
+ this->progress = true;
+}
+
+ir_visitor_status
+ir_if_return_visitor::move_outer_block_inside(ir_instruction *ir,
+ exec_list *inner_block)
+{
+ if (!ir->get_next()->is_tail_sentinel()) {
+ while (!ir->get_next()->is_tail_sentinel()) {
+ ir_instruction *move_ir = (ir_instruction *)ir->get_next();
+
+ move_ir->remove();
+ inner_block->push_tail(move_ir);
+ }
+
+ /* If we move the instructions following ir inside the block, it
+ * will confuse the exec_list iteration in the parent that visited
+ * us. So stop the visit at this point.
+ */
+ return visit_stop;
+ } else {
+ return visit_continue;
+ }
+}
+
+/* Normalize a function to always have a return statement at the end.
+ *
+ * This avoids the ir_if handler needing to know whether it is at the
+ * top level of the function to know if there's an implicit return at
+ * the end of the outer block.
+ */
+ir_visitor_status
+ir_if_return_visitor::visit_enter(ir_function_signature *ir)
+{
+ ir_return *ret;
+
+ if (!ir->is_defined)
+ return visit_continue_with_parent;
+ if (strcmp(ir->function_name(), "main") == 0)
+ return visit_continue_with_parent;
+
+ ret = find_return_in_block(&ir->body);
+
+ if (ret) {
+ truncate_after_instruction(ret);
+ } else {
+ if (ir->return_type->is_void()) {
+ ir->body.push_tail(new(ir) ir_return(NULL));
+ } else {
+ /* Probably, if we've got a function with a return value
+ * hitting this point, it's something like:
+ *
+ * float reduce_below_half(float val)
+ * {
+ * while () {
+ * if (val >= 0.5)
+ * val /= 2.0;
+ * else
+ * return val;
+ * }
+ * }
+ *
+ * So we gain a junk return statement of an undefined value
+ * at the end that never gets executed. However, a backend
+ * using this pass is probably desperate to get rid of
+ * function calls, so go ahead and do it for their sake in
+ * case it fixes apps.
+ */
+ ir_variable *undef = new(ir) ir_variable(ir->return_type,
+ "if_return_undef",
+ ir_var_temporary);
+ ir->body.push_tail(undef);
+
+ ir_dereference_variable *deref = new(ir) ir_dereference_variable(undef);
+ ir->body.push_tail(new(ir) ir_return(deref));
+ }
+ }
+
+ return visit_continue;
+}
+
+ir_visitor_status
+ir_if_return_visitor::visit_leave(ir_if *ir)
+{
+ ir_return *then_return;
+ ir_return *else_return;
+
+ then_return = find_return_in_block(&ir->then_instructions);
+ else_return = find_return_in_block(&ir->else_instructions);
+ if (!then_return && !else_return)
+ return visit_continue;
+
+ /* Trim off any trailing instructions after the return statements
+ * on both sides.
+ */
+ truncate_after_instruction(then_return);
+ truncate_after_instruction(else_return);
+
+ /* If both sides return, then we can move the returns to a single
+ * one outside the if statement.
+ */
+ if (then_return && else_return) {
+ move_returns_after_block(ir, then_return, else_return);
+ return visit_continue;
+ }
+
+ /* If only one side returns, then the block of code after the "if"
+ * is only executed by the other side, so those instructions don't
+ * need to be anywhere but that other side.
+ *
+ * This will usually pull a return statement up into the other
+ * side, so we'll trigger the above case on the next pass.
+ */
+ if (then_return) {
+ return move_outer_block_inside(ir, &ir->else_instructions);
+ } else {
+ assert(else_return);
+ return move_outer_block_inside(ir, &ir->then_instructions);
+ }
+}
diff --git a/src/glsl/ir_if_simplification.cpp b/src/glsl/ir_if_simplification.cpp
new file mode 100644
index 00000000000..6882ef72b95
--- /dev/null
+++ b/src/glsl/ir_if_simplification.cpp
@@ -0,0 +1,84 @@
+/*
+ * Copyright © 2010 Intel Corporation
+ *
+ * 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 (including the next
+ * paragraph) 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
+ * THE AUTHORS OR COPYRIGHT HOLDERS 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 ir_function_inlining.cpp
+ *
+ * Moves constant branches of if statements out to the surrounding
+ * instruction stream.
+ */
+
+#include "ir.h"
+
+class ir_if_simplification_visitor : public ir_hierarchical_visitor {
+public:
+ ir_if_simplification_visitor()
+ {
+ this->made_progress = false;
+ }
+
+ ir_visitor_status visit_leave(ir_if *);
+
+ bool made_progress;
+};
+
+bool
+do_if_simplification(exec_list *instructions)
+{
+ ir_if_simplification_visitor v;
+
+ v.run(instructions);
+ return v.made_progress;
+}
+
+
+ir_visitor_status
+ir_if_simplification_visitor::visit_leave(ir_if *ir)
+{
+ /* FINISHME: Ideally there would be a way to note that the condition results
+ * FINISHME: in a constant before processing both of the other subtrees.
+ * FINISHME: This can probably be done with some flags, but it would take
+ * FINISHME: some work to get right.
+ */
+ ir_constant *condition_constant = ir->condition->constant_expression_value();
+ if (condition_constant) {
+ /* Move the contents of the one branch of the conditional
+ * that matters out.
+ */
+ if (condition_constant->value.b[0]) {
+ foreach_iter(exec_list_iterator, then_iter, ir->then_instructions) {
+ ir_instruction *then_ir = (ir_instruction *)then_iter.get();
+ ir->insert_before(then_ir);
+ }
+ } else {
+ foreach_iter(exec_list_iterator, else_iter, ir->else_instructions) {
+ ir_instruction *else_ir = (ir_instruction *)else_iter.get();
+ ir->insert_before(else_ir);
+ }
+ }
+ ir->remove();
+ this->made_progress = true;
+ }
+
+ return visit_continue;
+}
diff --git a/src/glsl/ir_if_to_cond_assign.cpp b/src/glsl/ir_if_to_cond_assign.cpp
new file mode 100644
index 00000000000..0b87413941a
--- /dev/null
+++ b/src/glsl/ir_if_to_cond_assign.cpp
@@ -0,0 +1,168 @@
+/*
+ * Copyright © 2010 Intel Corporation
+ *
+ * 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 (including the next
+ * paragraph) 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
+ * THE AUTHORS OR COPYRIGHT HOLDERS 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 ir_if_to_cond_assign.cpp
+ *
+ * This attempts to flatten all if statements to conditional
+ * assignments for GPUs that don't do control flow.
+ *
+ * It can't handle other control flow being inside of its block, such
+ * as calls or loops. Hopefully loop unrolling and inlining will take
+ * care of those.
+ */
+
+#include "glsl_types.h"
+#include "ir.h"
+
+class ir_if_to_cond_assign_visitor : public ir_hierarchical_visitor {
+public:
+ ir_if_to_cond_assign_visitor()
+ {
+ this->progress = false;
+ }
+
+ ir_visitor_status visit_leave(ir_if *);
+
+ bool progress;
+};
+
+bool
+do_if_to_cond_assign(exec_list *instructions)
+{
+ ir_if_to_cond_assign_visitor v;
+
+ visit_list_elements(&v, instructions);
+
+ return v.progress;
+}
+
+void
+check_control_flow(ir_instruction *ir, void *data)
+{
+ bool *found_control_flow = (bool *)data;
+ switch (ir->ir_type) {
+ case ir_type_call:
+ case ir_type_discard:
+ case ir_type_loop:
+ case ir_type_loop_jump:
+ case ir_type_return:
+ *found_control_flow = true;
+ break;
+ default:
+ break;
+ }
+}
+
+void
+move_block_to_cond_assign(void *mem_ctx,
+ ir_if *if_ir, ir_variable *cond_var, bool then)
+{
+ exec_list *instructions;
+
+ if (then) {
+ instructions = &if_ir->then_instructions;
+ } else {
+ instructions = &if_ir->else_instructions;
+ }
+
+ foreach_iter(exec_list_iterator, iter, *instructions) {
+ ir_instruction *ir = (ir_instruction *)iter.get();
+
+ if (ir->ir_type == ir_type_assignment) {
+ ir_assignment *assign = (ir_assignment *)ir;
+ ir_rvalue *cond_expr;
+ ir_dereference *deref = new(mem_ctx) ir_dereference_variable(cond_var);
+
+ if (then) {
+ cond_expr = deref;
+ } else {
+ cond_expr = new(mem_ctx) ir_expression(ir_unop_logic_not,
+ glsl_type::bool_type,
+ deref,
+ NULL);
+ }
+
+ if (!assign->condition) {
+ assign->condition = cond_expr;
+ } else {
+ assign->condition = new(mem_ctx) ir_expression(ir_binop_logic_and,
+ glsl_type::bool_type,
+ cond_expr,
+ assign->condition);
+ }
+ }
+
+ /* Now, move from the if block to the block surrounding it. */
+ ir->remove();
+ if_ir->insert_before(ir);
+ }
+}
+
+ir_visitor_status
+ir_if_to_cond_assign_visitor::visit_leave(ir_if *ir)
+{
+ bool found_control_flow = false;
+ ir_variable *cond_var;
+ ir_assignment *assign;
+ ir_dereference_variable *deref;
+
+ /* Check that both blocks don't contain anything we can't support. */
+ foreach_iter(exec_list_iterator, then_iter, ir->then_instructions) {
+ ir_instruction *then_ir = (ir_instruction *)then_iter.get();
+ visit_tree(then_ir, check_control_flow, &found_control_flow);
+ }
+ foreach_iter(exec_list_iterator, else_iter, ir->else_instructions) {
+ ir_instruction *else_ir = (ir_instruction *)else_iter.get();
+ visit_tree(else_ir, check_control_flow, &found_control_flow);
+ }
+ if (found_control_flow)
+ return visit_continue;
+
+ void *mem_ctx = talloc_parent(ir);
+
+ /* Store the condition to a variable so the assignment conditions are
+ * simpler.
+ */
+ cond_var = new(mem_ctx) ir_variable(glsl_type::bool_type,
+ "if_to_cond_assign_condition",
+ ir_var_temporary);
+ ir->insert_before(cond_var);
+
+ deref = new(mem_ctx) ir_dereference_variable(cond_var);
+ assign = new(mem_ctx) ir_assignment(deref,
+ ir->condition, NULL);
+ ir->insert_before(assign);
+
+ /* Now, move all of the instructions out of the if blocks, putting
+ * conditions on assignments.
+ */
+ move_block_to_cond_assign(mem_ctx, ir, cond_var, true);
+ move_block_to_cond_assign(mem_ctx, ir, cond_var, false);
+
+ ir->remove();
+
+ this->progress = true;
+
+ return visit_continue;
+}
diff --git a/src/glsl/ir_import_prototypes.cpp b/src/glsl/ir_import_prototypes.cpp
new file mode 100644
index 00000000000..e553e12a491
--- /dev/null
+++ b/src/glsl/ir_import_prototypes.cpp
@@ -0,0 +1,138 @@
+/*
+ * Copyright © 2010 Intel Corporation
+ *
+ * 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 (including the next
+ * paragraph) 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
+ * THE AUTHORS OR COPYRIGHT HOLDERS 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 ir_import_prototypes.cpp
+ * Import function prototypes from one IR tree into another.
+ *
+ * \author Ian Romanick
+ */
+#include <cstdio>
+#include "ir.h"
+#include "glsl_symbol_table.h"
+
+/**
+ * Visitor used to import function prototypes
+ *
+ * Normally the \c clone method of either \c ir_function or
+ * \c ir_function_signature could be used. However, we don't want a complete
+ * clone of the \c ir_function_signature. We want everything \b except the
+ * body of the function.
+ */
+class import_prototype_visitor : public ir_hierarchical_visitor {
+public:
+ /**
+ */
+ import_prototype_visitor(exec_list *list, glsl_symbol_table *symbols,
+ void *mem_ctx)
+ {
+ this->mem_ctx = mem_ctx;
+ this->list = list;
+ this->symbols = symbols;
+ this->function = NULL;
+ }
+
+ virtual ir_visitor_status visit_enter(ir_function *ir)
+ {
+ assert(this->function == NULL);
+
+ this->function = this->symbols->get_function(ir->name);
+ if (!this->function) {
+ this->function = new(this->mem_ctx) ir_function(ir->name);
+
+ list->push_tail(this->function);
+
+ /* Add the new function to the symbol table.
+ */
+ this->symbols->add_function(this->function->name, this->function);
+ }
+ return visit_continue;
+ }
+
+ virtual ir_visitor_status visit_leave(ir_function *ir)
+ {
+ (void) ir;
+ assert(this->function != NULL);
+
+ this->function = NULL;
+ return visit_continue;
+ }
+
+ ir_visitor_status visit_enter(ir_function_signature *ir)
+ {
+ assert(this->function != NULL);
+
+ ir_function_signature *copy =
+ new(mem_ctx) ir_function_signature(ir->return_type);
+
+ copy->is_defined = false;
+ copy->is_built_in = ir->is_built_in;
+
+ /* Clone the parameter list, but NOT the body.
+ */
+ foreach_list_const(node, &ir->parameters) {
+ const ir_variable *const param = (const ir_variable *) node;
+
+ assert(const_cast<ir_variable *>(param)->as_variable() != NULL);
+
+ ir_variable *const param_copy = param->clone(mem_ctx, NULL);
+ copy->parameters.push_tail(param_copy);
+ }
+
+ this->function->add_signature(copy);
+
+ /* Do not process child nodes of the ir_function_signature. There can
+ * never be any nodes inside the ir_function_signature that we care
+ * about. Instead continue with the next sibling.
+ */
+ return visit_continue_with_parent;
+ }
+
+private:
+ exec_list *list;
+ ir_function *function;
+ glsl_symbol_table *symbols;
+ void *mem_ctx;
+};
+
+
+/**
+ * Import function prototypes from one IR tree into another
+ *
+ * \param source Source instruction stream containing functions whose
+ * prototypes are to be imported
+ * \param dest Destination instruction stream where new \c ir_function and
+ * \c ir_function_signature nodes will be stored
+ * \param symbols Symbol table where new functions will be stored
+ * \param mem_ctx talloc memory context used for new allocations
+ */
+void
+import_prototypes(const exec_list *source, exec_list *dest,
+ glsl_symbol_table *symbols, void *mem_ctx)
+{
+ import_prototype_visitor v(dest, symbols, mem_ctx);
+
+ /* Making source be const is just extra documentation.
+ */
+ v.run(const_cast<exec_list *>(source));
+}
diff --git a/src/glsl/ir_mat_op_to_vec.cpp b/src/glsl/ir_mat_op_to_vec.cpp
new file mode 100644
index 00000000000..80e05799861
--- /dev/null
+++ b/src/glsl/ir_mat_op_to_vec.cpp
@@ -0,0 +1,397 @@
+/*
+ * Copyright © 2010 Intel Corporation
+ *
+ * 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 (including the next
+ * paragraph) 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
+ * THE AUTHORS OR COPYRIGHT HOLDERS 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 ir_mat_op_to_vec.cpp
+ *
+ * Breaks matrix operation expressions down to a series of vector operations.
+ *
+ * Generally this is how we have to codegen matrix operations for a
+ * GPU, so this gives us the chance to constant fold operations on a
+ * column or row.
+ */
+
+#include "ir.h"
+#include "ir_expression_flattening.h"
+#include "glsl_types.h"
+
+class ir_mat_op_to_vec_visitor : public ir_hierarchical_visitor {
+public:
+ ir_mat_op_to_vec_visitor()
+ {
+ this->made_progress = false;
+ }
+
+ ir_visitor_status visit_leave(ir_assignment *);
+
+ ir_dereference *get_column(ir_variable *var, int col);
+ ir_rvalue *get_element(ir_variable *var, int col, int row);
+
+ void do_mul_mat_mat(ir_variable *result_var,
+ ir_variable *a_var, ir_variable *b_var);
+ void do_mul_mat_vec(ir_variable *result_var,
+ ir_variable *a_var, ir_variable *b_var);
+ void do_mul_vec_mat(ir_variable *result_var,
+ ir_variable *a_var, ir_variable *b_var);
+ void do_mul_mat_scalar(ir_variable *result_var,
+ ir_variable *a_var, ir_variable *b_var);
+
+ bool made_progress;
+};
+
+static bool
+mat_op_to_vec_predicate(ir_instruction *ir)
+{
+ ir_expression *expr = ir->as_expression();
+ unsigned int i;
+
+ if (!expr)
+ return false;
+
+ for (i = 0; i < expr->get_num_operands(); i++) {
+ if (expr->operands[i]->type->is_matrix())
+ return true;
+ }
+
+ return false;
+}
+
+bool
+do_mat_op_to_vec(exec_list *instructions)
+{
+ ir_mat_op_to_vec_visitor v;
+
+ /* Pull out any matrix expression to a separate assignment to a
+ * temp. This will make our handling of the breakdown to
+ * operations on the matrix's vector components much easier.
+ */
+ do_expression_flattening(instructions, mat_op_to_vec_predicate);
+
+ visit_list_elements(&v, instructions);
+
+ return v.made_progress;
+}
+
+ir_rvalue *
+ir_mat_op_to_vec_visitor::get_element(ir_variable *var, int col, int row)
+{
+ ir_dereference *deref;
+
+ deref = new(base_ir) ir_dereference_variable(var);
+
+ if (var->type->is_matrix()) {
+ deref = new(base_ir) ir_dereference_array(var,
+ new(base_ir) ir_constant(col));
+ } else {
+ assert(col == 0);
+ }
+
+ return new(base_ir) ir_swizzle(deref, row, 0, 0, 0, 1);
+}
+
+ir_dereference *
+ir_mat_op_to_vec_visitor::get_column(ir_variable *var, int row)
+{
+ ir_dereference *deref;
+
+ if (!var->type->is_matrix()) {
+ deref = new(base_ir) ir_dereference_variable(var);
+ } else {
+ deref = new(base_ir) ir_dereference_variable(var);
+ deref = new(base_ir) ir_dereference_array(deref,
+ new(base_ir) ir_constant(row));
+ }
+
+ return deref;
+}
+
+void
+ir_mat_op_to_vec_visitor::do_mul_mat_mat(ir_variable *result_var,
+ ir_variable *a_var,
+ ir_variable *b_var)
+{
+ int b_col, i;
+ ir_assignment *assign;
+ ir_expression *expr;
+
+ for (b_col = 0; b_col < b_var->type->matrix_columns; b_col++) {
+ ir_rvalue *a = get_column(a_var, 0);
+ ir_rvalue *b = get_element(b_var, b_col, 0);
+
+ /* first column */
+ expr = new(base_ir) ir_expression(ir_binop_mul,
+ a->type,
+ a,
+ b);
+
+ /* following columns */
+ for (i = 1; i < a_var->type->matrix_columns; i++) {
+ ir_expression *mul_expr;
+
+ a = get_column(a_var, i);
+ b = get_element(b_var, b_col, i);
+
+ mul_expr = new(base_ir) ir_expression(ir_binop_mul,
+ a->type,
+ a,
+ b);
+ expr = new(base_ir) ir_expression(ir_binop_add,
+ a->type,
+ expr,
+ mul_expr);
+ }
+
+ ir_rvalue *result = get_column(result_var, b_col);
+ assign = new(base_ir) ir_assignment(result,
+ expr,
+ NULL);
+ base_ir->insert_before(assign);
+ }
+}
+
+void
+ir_mat_op_to_vec_visitor::do_mul_mat_vec(ir_variable *result_var,
+ ir_variable *a_var,
+ ir_variable *b_var)
+{
+ int i;
+ ir_rvalue *a = get_column(a_var, 0);
+ ir_rvalue *b = get_element(b_var, 0, 0);
+ ir_assignment *assign;
+ ir_expression *expr;
+
+ /* first column */
+ expr = new(base_ir) ir_expression(ir_binop_mul,
+ result_var->type,
+ a,
+ b);
+
+ /* following columns */
+ for (i = 1; i < a_var->type->matrix_columns; i++) {
+ ir_expression *mul_expr;
+
+ a = get_column(a_var, i);
+ b = get_element(b_var, 0, i);
+
+ mul_expr = new(base_ir) ir_expression(ir_binop_mul,
+ result_var->type,
+ a,
+ b);
+ expr = new(base_ir) ir_expression(ir_binop_add,
+ result_var->type,
+ expr,
+ mul_expr);
+ }
+
+ ir_rvalue *result = new(base_ir) ir_dereference_variable(result_var);
+ assign = new(base_ir) ir_assignment(result,
+ expr,
+ NULL);
+ base_ir->insert_before(assign);
+}
+
+void
+ir_mat_op_to_vec_visitor::do_mul_vec_mat(ir_variable *result_var,
+ ir_variable *a_var,
+ ir_variable *b_var)
+{
+ int i;
+
+ for (i = 0; i < b_var->type->matrix_columns; i++) {
+ ir_rvalue *a = new(base_ir) ir_dereference_variable(a_var);
+ ir_rvalue *b = get_column(b_var, i);
+ ir_rvalue *result;
+ ir_expression *column_expr;
+ ir_assignment *column_assign;
+
+ result = new(base_ir) ir_dereference_variable(result_var);
+ result = new(base_ir) ir_swizzle(result, i, 0, 0, 0, 1);
+
+ column_expr = new(base_ir) ir_expression(ir_binop_dot,
+ result->type,
+ a,
+ b);
+
+ column_assign = new(base_ir) ir_assignment(result,
+ column_expr,
+ NULL);
+ base_ir->insert_before(column_assign);
+ }
+}
+
+void
+ir_mat_op_to_vec_visitor::do_mul_mat_scalar(ir_variable *result_var,
+ ir_variable *a_var,
+ ir_variable *b_var)
+{
+ int i;
+
+ for (i = 0; i < a_var->type->matrix_columns; i++) {
+ ir_rvalue *a = get_column(a_var, i);
+ ir_rvalue *b = new(base_ir) ir_dereference_variable(b_var);
+ ir_rvalue *result = get_column(result_var, i);
+ ir_expression *column_expr;
+ ir_assignment *column_assign;
+
+ column_expr = new(base_ir) ir_expression(ir_binop_mul,
+ result->type,
+ a,
+ b);
+
+ column_assign = new(base_ir) ir_assignment(result,
+ column_expr,
+ NULL);
+ base_ir->insert_before(column_assign);
+ }
+}
+
+ir_visitor_status
+ir_mat_op_to_vec_visitor::visit_leave(ir_assignment *assign)
+{
+ ir_expression *expr = assign->rhs->as_expression();
+ bool found_matrix = false;
+ unsigned int i, matrix_columns = 1;
+ ir_variable *op_var[2];
+
+ if (!expr)
+ return visit_continue;
+
+ for (i = 0; i < expr->get_num_operands(); i++) {
+ if (expr->operands[i]->type->is_matrix()) {
+ found_matrix = true;
+ matrix_columns = expr->operands[i]->type->matrix_columns;
+ break;
+ }
+ }
+ if (!found_matrix)
+ return visit_continue;
+
+ ir_dereference_variable *lhs_deref = assign->lhs->as_dereference_variable();
+ assert(lhs_deref);
+
+ ir_variable *result_var = lhs_deref->var;
+
+ /* Store the expression operands in temps so we can use them
+ * multiple times.
+ */
+ for (i = 0; i < expr->get_num_operands(); i++) {
+ ir_assignment *assign;
+
+ op_var[i] = new(base_ir) ir_variable(expr->operands[i]->type,
+ "mat_op_to_vec",
+ ir_var_temporary);
+ base_ir->insert_before(op_var[i]);
+
+ lhs_deref = new(base_ir) ir_dereference_variable(op_var[i]);
+ assign = new(base_ir) ir_assignment(lhs_deref,
+ expr->operands[i],
+ NULL);
+ base_ir->insert_before(assign);
+ }
+
+ /* OK, time to break down this matrix operation. */
+ switch (expr->operation) {
+ case ir_unop_neg: {
+ const unsigned mask = (1U << result_var->type->vector_elements) - 1;
+
+ /* Apply the operation to each column.*/
+ for (i = 0; i < matrix_columns; i++) {
+ ir_rvalue *op0 = get_column(op_var[0], i);
+ ir_dereference *result = get_column(result_var, i);
+ ir_expression *column_expr;
+ ir_assignment *column_assign;
+
+ column_expr = new(base_ir) ir_expression(expr->operation,
+ result->type,
+ op0,
+ NULL);
+
+ column_assign = new(base_ir) ir_assignment(result,
+ column_expr,
+ NULL,
+ mask);
+ assert(column_assign->write_mask != 0);
+ base_ir->insert_before(column_assign);
+ }
+ break;
+ }
+ case ir_binop_add:
+ case ir_binop_sub:
+ case ir_binop_div:
+ case ir_binop_mod: {
+ const unsigned mask = (1U << result_var->type->vector_elements) - 1;
+
+ /* For most operations, the matrix version is just going
+ * column-wise through and applying the operation to each column
+ * if available.
+ */
+ for (i = 0; i < matrix_columns; i++) {
+ ir_rvalue *op0 = get_column(op_var[0], i);
+ ir_rvalue *op1 = get_column(op_var[1], i);
+ ir_dereference *result = get_column(result_var, i);
+ ir_expression *column_expr;
+ ir_assignment *column_assign;
+
+ column_expr = new(base_ir) ir_expression(expr->operation,
+ result->type,
+ op0,
+ op1);
+
+ column_assign = new(base_ir) ir_assignment(result,
+ column_expr,
+ NULL,
+ mask);
+ assert(column_assign->write_mask != 0);
+ base_ir->insert_before(column_assign);
+ }
+ break;
+ }
+ case ir_binop_mul:
+ if (op_var[0]->type->is_matrix()) {
+ if (op_var[1]->type->is_matrix()) {
+ do_mul_mat_mat(result_var, op_var[0], op_var[1]);
+ } else if (op_var[1]->type->is_vector()) {
+ do_mul_mat_vec(result_var, op_var[0], op_var[1]);
+ } else {
+ assert(op_var[1]->type->is_scalar());
+ do_mul_mat_scalar(result_var, op_var[0], op_var[1]);
+ }
+ } else {
+ assert(op_var[1]->type->is_matrix());
+ if (op_var[0]->type->is_vector()) {
+ do_mul_vec_mat(result_var, op_var[0], op_var[1]);
+ } else {
+ assert(op_var[0]->type->is_scalar());
+ do_mul_mat_scalar(result_var, op_var[1], op_var[0]);
+ }
+ }
+ break;
+ default:
+ printf("FINISHME: Handle matrix operation for %s\n", expr->operator_string());
+ abort();
+ }
+ assign->remove();
+ this->made_progress = true;
+
+ return visit_continue;
+}
diff --git a/src/glsl/ir_mod_to_fract.cpp b/src/glsl/ir_mod_to_fract.cpp
new file mode 100644
index 00000000000..71c9472b12b
--- /dev/null
+++ b/src/glsl/ir_mod_to_fract.cpp
@@ -0,0 +1,90 @@
+/*
+ * Copyright © 2010 Intel Corporation
+ *
+ * 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 (including the next
+ * paragraph) 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
+ * THE AUTHORS OR COPYRIGHT HOLDERS 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 ir_mod_to_floor.cpp
+ *
+ * Breaks an ir_unop_mod expression down to (op1 * fract(op0 / op1))
+ *
+ * Many GPUs don't have a MOD instruction (945 and 965 included), and
+ * if we have to break it down like this anyway, it gives an
+ * opportunity to do things like constant fold the (1.0 / op1) easily.
+ */
+
+#include "ir.h"
+
+class ir_mod_to_fract_visitor : public ir_hierarchical_visitor {
+public:
+ ir_mod_to_fract_visitor()
+ {
+ this->made_progress = false;
+ }
+
+ ir_visitor_status visit_leave(ir_expression *);
+
+ bool made_progress;
+};
+
+bool
+do_mod_to_fract(exec_list *instructions)
+{
+ ir_mod_to_fract_visitor v;
+
+ visit_list_elements(&v, instructions);
+ return v.made_progress;
+}
+
+ir_visitor_status
+ir_mod_to_fract_visitor::visit_leave(ir_expression *ir)
+{
+ if (ir->operation != ir_binop_mod)
+ return visit_continue;
+
+ ir_variable *temp = new(ir) ir_variable(ir->operands[1]->type, "mod_b",
+ ir_var_temporary);
+ this->base_ir->insert_before(temp);
+
+ ir_assignment *assign;
+ ir_rvalue *expr;
+
+ assign = new(ir) ir_assignment(new(ir) ir_dereference_variable(temp),
+ ir->operands[1], NULL);
+ this->base_ir->insert_before(assign);
+
+ expr = new(ir) ir_expression(ir_binop_div,
+ ir->operands[0]->type,
+ ir->operands[0],
+ new(ir) ir_dereference_variable(temp));
+
+ expr = new(ir) ir_expression(ir_unop_fract,
+ ir->operands[0]->type,
+ expr,
+ NULL);
+
+ ir->operation = ir_binop_mul;
+ ir->operands[0] = new(ir) ir_dereference_variable(temp);
+ ir->operands[1] = expr;
+ this->made_progress = true;
+
+ return visit_continue;
+}
diff --git a/src/glsl/ir_noop_swizzle.cpp b/src/glsl/ir_noop_swizzle.cpp
new file mode 100644
index 00000000000..b78c87b47f3
--- /dev/null
+++ b/src/glsl/ir_noop_swizzle.cpp
@@ -0,0 +1,80 @@
+/*
+ * Copyright © 2010 Intel Corporation
+ *
+ * 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 (including the next
+ * paragraph) 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
+ * THE AUTHORS OR COPYRIGHT HOLDERS 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 ir_noop_swizzle.cpp
+ *
+ * If a swizzle doesn't change the order or count of components, then
+ * remove the swizzle so that other optimization passes see the value
+ * behind it.
+ */
+
+#include "ir.h"
+#include "ir_visitor.h"
+#include "ir_rvalue_visitor.h"
+#include "ir_print_visitor.h"
+#include "glsl_types.h"
+
+class ir_noop_swizzle_visitor : public ir_rvalue_visitor {
+public:
+ ir_noop_swizzle_visitor()
+ {
+ this->progress = false;
+ }
+
+ void handle_rvalue(ir_rvalue **rvalue);
+ bool progress;
+};
+
+void
+ir_noop_swizzle_visitor::handle_rvalue(ir_rvalue **rvalue)
+{
+ if (!*rvalue)
+ return;
+
+ ir_swizzle *swiz = (*rvalue)->as_swizzle();
+ if (!swiz || swiz->type != swiz->val->type)
+ return;
+
+ int elems = swiz->val->type->vector_elements;
+ if (swiz->mask.x != 0)
+ return;
+ if (elems >= 2 && swiz->mask.y != 1)
+ return;
+ if (elems >= 3 && swiz->mask.z != 1)
+ return;
+ if (elems >= 4 && swiz->mask.w != 1)
+ return;
+
+ this->progress = true;
+ *rvalue = swiz->val;
+}
+
+bool
+do_noop_swizzle(exec_list *instructions)
+{
+ ir_noop_swizzle_visitor v;
+ visit_list_elements(&v, instructions);
+
+ return v.progress;
+}
diff --git a/src/glsl/ir_optimization.h b/src/glsl/ir_optimization.h
new file mode 100644
index 00000000000..33f4bc78f79
--- /dev/null
+++ b/src/glsl/ir_optimization.h
@@ -0,0 +1,57 @@
+/*
+ * Copyright © 2010 Intel Corporation
+ *
+ * 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 (including the next
+ * paragraph) 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
+ * THE AUTHORS OR COPYRIGHT HOLDERS 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 ir_optimization.h
+ *
+ * Prototypes for optimization passes to be called by the compiler and drivers.
+ */
+
+bool do_common_optimization(exec_list *ir, bool linked);
+
+bool do_algebraic(exec_list *instructions);
+bool do_constant_folding(exec_list *instructions);
+bool do_constant_variable(exec_list *instructions);
+bool do_constant_variable_unlinked(exec_list *instructions);
+bool do_copy_propagation(exec_list *instructions);
+bool do_constant_propagation(exec_list *instructions);
+bool do_dead_code(exec_list *instructions);
+bool do_dead_code_local(exec_list *instructions);
+bool do_dead_code_unlinked(exec_list *instructions);
+bool do_dead_functions(exec_list *instructions);
+bool do_div_to_mul_rcp(exec_list *instructions);
+bool do_explog_to_explog2(exec_list *instructions);
+bool do_function_inlining(exec_list *instructions);
+bool do_if_return(exec_list *instructions);
+bool do_if_simplification(exec_list *instructions);
+bool do_if_to_cond_assign(exec_list *instructions);
+bool do_mat_op_to_vec(exec_list *instructions);
+bool do_mod_to_fract(exec_list *instructions);
+bool do_noop_swizzle(exec_list *instructions);
+bool do_structure_splitting(exec_list *instructions);
+bool do_sub_to_add_neg(exec_list *instructions);
+bool do_swizzle_swizzle(exec_list *instructions);
+bool do_tree_grafting(exec_list *instructions);
+bool do_vec_index_to_cond_assign(exec_list *instructions);
+bool do_vec_index_to_swizzle(exec_list *instructions);
diff --git a/src/glsl/ir_print_visitor.cpp b/src/glsl/ir_print_visitor.cpp
new file mode 100644
index 00000000000..83e64032723
--- /dev/null
+++ b/src/glsl/ir_print_visitor.cpp
@@ -0,0 +1,465 @@
+/*
+ * Copyright © 2010 Intel Corporation
+ *
+ * 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 (including the next
+ * paragraph) 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
+ * THE AUTHORS OR COPYRIGHT HOLDERS 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.
+ */
+
+#include "ir_print_visitor.h"
+#include "glsl_types.h"
+#include "glsl_parser_extras.h"
+
+static void print_type(const glsl_type *t);
+
+void
+ir_instruction::print(void) const
+{
+ ir_instruction *deconsted = const_cast<ir_instruction *>(this);
+
+ ir_print_visitor v;
+ deconsted->accept(&v);
+}
+
+void
+_mesa_print_ir(exec_list *instructions,
+ struct _mesa_glsl_parse_state *state)
+{
+ if (state) {
+ for (unsigned i = 0; i < state->num_user_structures; i++) {
+ const glsl_type *const s = state->user_structures[i];
+
+ printf("(structure (%s) (%s@%p) (%u) (\n",
+ s->name, s->name, (void *) s, s->length);
+
+ for (unsigned j = 0; j < s->length; j++) {
+ printf("\t((");
+ print_type(s->fields.structure[j].type);
+ printf(")(%s))\n", s->fields.structure[j].name);
+ }
+
+ printf(")\n");
+ }
+ }
+
+ printf("(\n");
+ foreach_iter(exec_list_iterator, iter, *instructions) {
+ ir_instruction *ir = (ir_instruction *)iter.get();
+ ir->print();
+ if (ir->ir_type != ir_type_function)
+ printf("\n");
+ }
+ printf("\n)");
+}
+
+
+void ir_print_visitor::indent(void)
+{
+ for (int i = 0; i < indentation; i++)
+ printf(" ");
+}
+
+static void
+print_type(const glsl_type *t)
+{
+ if (t->base_type == GLSL_TYPE_ARRAY) {
+ printf("(array ");
+ print_type(t->fields.array);
+ printf(" %u)", t->length);
+ } else if ((t->base_type == GLSL_TYPE_STRUCT)
+ && (strncmp("gl_", t->name, 3) != 0)) {
+ printf("%s@%p", t->name, (void *) t);
+ } else {
+ printf("%s", t->name);
+ }
+}
+
+
+void ir_print_visitor::visit(ir_variable *ir)
+{
+ printf("(declare ");
+
+ const char *const cent = (ir->centroid) ? "centroid " : "";
+ const char *const inv = (ir->invariant) ? "invariant " : "";
+ const char *const mode[] = { "", "uniform ", "in ", "out ", "inout ",
+ "temporary " };
+ const char *const interp[] = { "", "flat", "noperspective" };
+
+ printf("(%s%s%s%s) ",
+ cent, inv, mode[ir->mode], interp[ir->interpolation]);
+
+ print_type(ir->type);
+ printf(" %s@%p)", ir->name, (void *) ir);
+}
+
+
+void ir_print_visitor::visit(ir_function_signature *ir)
+{
+ printf("(signature ");
+ indentation++;
+
+ print_type(ir->return_type);
+ printf("\n");
+ indent();
+
+ printf("(parameters\n");
+ indentation++;
+
+ foreach_iter(exec_list_iterator, iter, ir->parameters) {
+ ir_variable *const inst = (ir_variable *) iter.get();
+
+ indent();
+ inst->accept(this);
+ printf("\n");
+ }
+ indentation--;
+
+ indent();
+ printf(")\n");
+
+ indent();
+
+ printf("(\n");
+ indentation++;
+
+ foreach_iter(exec_list_iterator, iter, ir->body) {
+ ir_instruction *const inst = (ir_instruction *) iter.get();
+
+ indent();
+ inst->accept(this);
+ printf("\n");
+ }
+ indentation--;
+ indent();
+ printf("))\n");
+ indentation--;
+}
+
+
+void ir_print_visitor::visit(ir_function *ir)
+{
+ bool found_non_builtin_proto = false;
+
+ foreach_iter(exec_list_iterator, iter, *ir) {
+ ir_function_signature *const sig = (ir_function_signature *) iter.get();
+ if (sig->is_defined || !sig->is_built_in)
+ found_non_builtin_proto = true;
+ }
+ if (!found_non_builtin_proto)
+ return;
+
+ printf("(function %s\n", ir->name);
+ indentation++;
+ foreach_iter(exec_list_iterator, iter, *ir) {
+ ir_function_signature *const sig = (ir_function_signature *) iter.get();
+
+ indent();
+ sig->accept(this);
+ printf("\n");
+ }
+ indentation--;
+ indent();
+ printf(")\n\n");
+}
+
+
+void ir_print_visitor::visit(ir_expression *ir)
+{
+ printf("(expression ");
+
+ print_type(ir->type);
+
+ printf(" %s ", ir->operator_string());
+
+ if (ir->operands[0])
+ ir->operands[0]->accept(this);
+
+ if (ir->operands[1])
+ ir->operands[1]->accept(this);
+ printf(") ");
+}
+
+
+void ir_print_visitor::visit(ir_texture *ir)
+{
+ printf("(%s ", ir->opcode_string());
+
+ ir->sampler->accept(this);
+ printf(" ");
+
+ ir->coordinate->accept(this);
+
+ printf(" (%d %d %d) ", ir->offsets[0], ir->offsets[1], ir->offsets[2]);
+
+ if (ir->op != ir_txf) {
+ if (ir->projector)
+ ir->projector->accept(this);
+ else
+ printf("1");
+
+ if (ir->shadow_comparitor) {
+ printf(" ");
+ ir->shadow_comparitor->accept(this);
+ } else {
+ printf(" ()");
+ }
+ }
+
+ printf(" ");
+ switch (ir->op)
+ {
+ case ir_tex:
+ break;
+ case ir_txb:
+ ir->lod_info.bias->accept(this);
+ break;
+ case ir_txl:
+ case ir_txf:
+ ir->lod_info.lod->accept(this);
+ break;
+ case ir_txd:
+ printf("(");
+ ir->lod_info.grad.dPdx->accept(this);
+ printf(" ");
+ ir->lod_info.grad.dPdy->accept(this);
+ printf(")");
+ break;
+ };
+ printf(")");
+}
+
+
+void ir_print_visitor::visit(ir_swizzle *ir)
+{
+ const unsigned swiz[4] = {
+ ir->mask.x,
+ ir->mask.y,
+ ir->mask.z,
+ ir->mask.w,
+ };
+
+ printf("(swiz ");
+ for (unsigned i = 0; i < ir->mask.num_components; i++) {
+ printf("%c", "xyzw"[swiz[i]]);
+ }
+ printf(" ");
+ ir->val->accept(this);
+ printf(")");
+}
+
+
+void ir_print_visitor::visit(ir_dereference_variable *ir)
+{
+ ir_variable *var = ir->variable_referenced();
+ printf("(var_ref %s@%p) ", var->name, (void *) var);
+}
+
+
+void ir_print_visitor::visit(ir_dereference_array *ir)
+{
+ printf("(array_ref ");
+ ir->array->accept(this);
+ ir->array_index->accept(this);
+ printf(") ");
+}
+
+
+void ir_print_visitor::visit(ir_dereference_record *ir)
+{
+ printf("(record_ref ");
+ ir->record->accept(this);
+ printf(" %s) ", ir->field);
+}
+
+
+void ir_print_visitor::visit(ir_assignment *ir)
+{
+ printf("(assign ");
+
+ if (ir->condition)
+ ir->condition->accept(this);
+ else
+ printf("(constant bool (1))");
+
+
+ char mask[5];
+ unsigned j = 0;
+
+ for (unsigned i = 0; i < 4; i++) {
+ if ((ir->write_mask & (1 << i)) != 0) {
+ mask[j] = "xyzw"[i];
+ j++;
+ }
+ }
+ mask[j] = '\0';
+
+ printf(" (%s) ", mask);
+
+ ir->lhs->accept(this);
+
+ printf(" ");
+
+ ir->rhs->accept(this);
+ printf(") ");
+}
+
+
+void ir_print_visitor::visit(ir_constant *ir)
+{
+ const glsl_type *const base_type = ir->type->get_base_type();
+
+ printf("(constant ");
+ print_type(ir->type);
+ printf(" (");
+
+ if (ir->type->is_array()) {
+ for (unsigned i = 0; i < ir->type->length; i++)
+ ir->get_array_element(i)->accept(this);
+ } else {
+ for (unsigned i = 0; i < ir->type->components(); i++) {
+ if (i != 0)
+ printf(" ");
+ switch (base_type->base_type) {
+ case GLSL_TYPE_UINT: printf("%u", ir->value.u[i]); break;
+ case GLSL_TYPE_INT: printf("%d", ir->value.i[i]); break;
+ case GLSL_TYPE_FLOAT: printf("%f", ir->value.f[i]); break;
+ case GLSL_TYPE_BOOL: printf("%d", ir->value.b[i]); break;
+ default: assert(0);
+ }
+ }
+ }
+ printf(")) ");
+}
+
+
+void
+ir_print_visitor::visit(ir_call *ir)
+{
+ printf("(call %s (", ir->callee_name());
+ foreach_iter(exec_list_iterator, iter, *ir) {
+ ir_instruction *const inst = (ir_instruction *) iter.get();
+
+ inst->accept(this);
+ }
+ printf("))\n");
+}
+
+
+void
+ir_print_visitor::visit(ir_return *ir)
+{
+ printf("(return");
+
+ ir_rvalue *const value = ir->get_value();
+ if (value) {
+ printf(" ");
+ value->accept(this);
+ }
+
+ printf(")");
+}
+
+
+void
+ir_print_visitor::visit(ir_discard *ir)
+{
+ printf("(discard ");
+
+ if (ir->condition != NULL) {
+ printf(" ");
+ ir->condition->accept(this);
+ }
+
+ printf(")");
+}
+
+
+void
+ir_print_visitor::visit(ir_if *ir)
+{
+ printf("(if ");
+ ir->condition->accept(this);
+
+ printf("(\n");
+ indentation++;
+
+ foreach_iter(exec_list_iterator, iter, ir->then_instructions) {
+ ir_instruction *const inst = (ir_instruction *) iter.get();
+
+ indent();
+ inst->accept(this);
+ printf("\n");
+ }
+
+ indentation--;
+ indent();
+ printf(")\n");
+
+ indent();
+ printf("(\n");
+ indentation++;
+
+ foreach_iter(exec_list_iterator, iter, ir->else_instructions) {
+ ir_instruction *const inst = (ir_instruction *) iter.get();
+
+ indent();
+ inst->accept(this);
+ printf("\n");
+ }
+ indentation--;
+ indent();
+ printf("))\n");
+}
+
+
+void
+ir_print_visitor::visit(ir_loop *ir)
+{
+ printf("(loop (");
+ if (ir->counter != NULL)
+ ir->counter->accept(this);
+ printf(") (");
+ if (ir->from != NULL)
+ ir->from->accept(this);
+ printf(") (");
+ if (ir->to != NULL)
+ ir->to->accept(this);
+ printf(") (");
+ if (ir->increment != NULL)
+ ir->increment->accept(this);
+ printf(") (\n");
+ indentation++;
+
+ foreach_iter(exec_list_iterator, iter, ir->body_instructions) {
+ ir_instruction *const inst = (ir_instruction *) iter.get();
+
+ indent();
+ inst->accept(this);
+ printf("\n");
+ }
+ indentation--;
+ indent();
+ printf("))\n");
+}
+
+
+void
+ir_print_visitor::visit(ir_loop_jump *ir)
+{
+ printf("%s", ir->is_break() ? "break" : "continue");
+}
diff --git a/src/glsl/ir_print_visitor.h b/src/glsl/ir_print_visitor.h
new file mode 100644
index 00000000000..4feeb8c184d
--- /dev/null
+++ b/src/glsl/ir_print_visitor.h
@@ -0,0 +1,83 @@
+/* -*- c++ -*- */
+/*
+ * Copyright © 2010 Intel Corporation
+ *
+ * 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 (including the next
+ * paragraph) 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
+ * THE AUTHORS OR COPYRIGHT HOLDERS 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.
+ */
+
+#pragma once
+#ifndef IR_PRINT_VISITOR_H
+#define IR_PRINT_VISITOR_H
+
+#include "ir.h"
+#include "ir_visitor.h"
+
+extern void _mesa_print_ir(exec_list *instructions,
+ struct _mesa_glsl_parse_state *state);
+
+/**
+ * Abstract base class of visitors of IR instruction trees
+ */
+class ir_print_visitor : public ir_visitor {
+public:
+ ir_print_visitor()
+ {
+ indentation = 0;
+ }
+
+ virtual ~ir_print_visitor()
+ {
+ /* empty */
+ }
+
+ void indent(void);
+
+ /**
+ * \name Visit methods
+ *
+ * As typical for the visitor pattern, there must be one \c visit method for
+ * each concrete subclass of \c ir_instruction. Virtual base classes within
+ * the hierarchy should not have \c visit methods.
+ */
+ /*@{*/
+ virtual void visit(ir_variable *);
+ virtual void visit(ir_function_signature *);
+ virtual void visit(ir_function *);
+ virtual void visit(ir_expression *);
+ virtual void visit(ir_texture *);
+ virtual void visit(ir_swizzle *);
+ virtual void visit(ir_dereference_variable *);
+ virtual void visit(ir_dereference_array *);
+ virtual void visit(ir_dereference_record *);
+ virtual void visit(ir_assignment *);
+ virtual void visit(ir_constant *);
+ virtual void visit(ir_call *);
+ virtual void visit(ir_return *);
+ virtual void visit(ir_discard *);
+ virtual void visit(ir_if *);
+ virtual void visit(ir_loop *);
+ virtual void visit(ir_loop_jump *);
+ /*@}*/
+
+private:
+ int indentation;
+};
+
+#endif /* IR_PRINT_VISITOR_H */
diff --git a/src/glsl/ir_reader.cpp b/src/glsl/ir_reader.cpp
new file mode 100644
index 00000000000..3e221c0e5ff
--- /dev/null
+++ b/src/glsl/ir_reader.cpp
@@ -0,0 +1,1088 @@
+/*
+ * Copyright © 2010 Intel Corporation
+ *
+ * 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 (including the next
+ * paragraph) 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
+ * THE AUTHORS OR COPYRIGHT HOLDERS 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.
+ */
+
+#include <cstdarg>
+
+extern "C" {
+#include <talloc.h>
+}
+
+#include "ir_reader.h"
+#include "glsl_parser_extras.h"
+#include "glsl_types.h"
+#include "s_expression.h"
+
+static void ir_read_error(_mesa_glsl_parse_state *, s_expression *,
+ const char *fmt, ...);
+static const glsl_type *read_type(_mesa_glsl_parse_state *, s_expression *);
+
+static void scan_for_prototypes(_mesa_glsl_parse_state *, exec_list *,
+ s_expression *);
+static ir_function *read_function(_mesa_glsl_parse_state *, s_list *,
+ bool skip_body);
+static void read_function_sig(_mesa_glsl_parse_state *, ir_function *,
+ s_list *, bool skip_body);
+
+static void read_instructions(_mesa_glsl_parse_state *, exec_list *,
+ s_expression *, ir_loop *);
+static ir_instruction *read_instruction(_mesa_glsl_parse_state *,
+ s_expression *, ir_loop *);
+static ir_variable *read_declaration(_mesa_glsl_parse_state *, s_list *);
+static ir_if *read_if(_mesa_glsl_parse_state *, s_list *, ir_loop *);
+static ir_loop *read_loop(_mesa_glsl_parse_state *st, s_list *list);
+static ir_return *read_return(_mesa_glsl_parse_state *, s_list *);
+
+static ir_rvalue *read_rvalue(_mesa_glsl_parse_state *, s_expression *);
+static ir_assignment *read_assignment(_mesa_glsl_parse_state *, s_list *);
+static ir_expression *read_expression(_mesa_glsl_parse_state *, s_list *);
+static ir_call *read_call(_mesa_glsl_parse_state *, s_list *);
+static ir_swizzle *read_swizzle(_mesa_glsl_parse_state *, s_list *);
+static ir_constant *read_constant(_mesa_glsl_parse_state *, s_list *);
+static ir_texture *read_texture(_mesa_glsl_parse_state *, s_list *);
+
+static ir_dereference *read_dereference(_mesa_glsl_parse_state *,
+ s_expression *);
+static ir_dereference *read_var_ref(_mesa_glsl_parse_state *, s_list *);
+static ir_dereference *read_array_ref(_mesa_glsl_parse_state *, s_list *);
+static ir_dereference *read_record_ref(_mesa_glsl_parse_state *, s_list *);
+
+void
+_mesa_glsl_read_ir(_mesa_glsl_parse_state *state, exec_list *instructions,
+ const char *src, bool scan_for_protos)
+{
+ s_expression *expr = s_expression::read_expression(state, src);
+ if (expr == NULL) {
+ ir_read_error(state, NULL, "couldn't parse S-Expression.");
+ return;
+ }
+
+ if (scan_for_protos) {
+ scan_for_prototypes(state, instructions, expr);
+ if (state->error)
+ return;
+ }
+
+ read_instructions(state, instructions, expr, NULL);
+ talloc_free(expr);
+}
+
+static void
+ir_read_error(_mesa_glsl_parse_state *state, s_expression *expr,
+ const char *fmt, ...)
+{
+ va_list ap;
+
+ state->error = true;
+
+ state->info_log = talloc_strdup_append(state->info_log, "error: ");
+
+ va_start(ap, fmt);
+ state->info_log = talloc_vasprintf_append(state->info_log, fmt, ap);
+ va_end(ap);
+ state->info_log = talloc_strdup_append(state->info_log, "\n");
+
+ if (expr != NULL) {
+ state->info_log = talloc_strdup_append(state->info_log,
+ "...in this context:\n ");
+ expr->print();
+ state->info_log = talloc_strdup_append(state->info_log, "\n\n");
+ }
+}
+
+static const glsl_type *
+read_type(_mesa_glsl_parse_state *st, s_expression *expr)
+{
+ s_list *list = SX_AS_LIST(expr);
+ if (list != NULL) {
+ s_symbol *type_sym = SX_AS_SYMBOL(list->subexpressions.get_head());
+ if (type_sym == NULL) {
+ ir_read_error(st, expr, "expected type (array ...) or (struct ...)");
+ return NULL;
+ }
+ if (strcmp(type_sym->value(), "array") == 0) {
+ if (list->length() != 3) {
+ ir_read_error(st, expr, "expected type (array <type> <int>)");
+ return NULL;
+ }
+
+ // Read base type
+ s_expression *base_expr = (s_expression*) type_sym->next;
+ const glsl_type *base_type = read_type(st, base_expr);
+ if (base_type == NULL) {
+ ir_read_error(st, NULL, "when reading base type of array");
+ return NULL;
+ }
+
+ // Read array size
+ s_int *size = SX_AS_INT(base_expr->next);
+ if (size == NULL) {
+ ir_read_error(st, expr, "found non-integer array size");
+ return NULL;
+ }
+
+ return glsl_type::get_array_instance(base_type, size->value());
+ } else if (strcmp(type_sym->value(), "struct") == 0) {
+ assert(false); // FINISHME
+ } else {
+ ir_read_error(st, expr, "expected (array ...) or (struct ...); "
+ "found (%s ...)", type_sym->value());
+ return NULL;
+ }
+ }
+
+ s_symbol *type_sym = SX_AS_SYMBOL(expr);
+ if (type_sym == NULL) {
+ ir_read_error(st, expr, "expected <type> (symbol or list)");
+ return NULL;
+ }
+
+ const glsl_type *type = st->symbols->get_type(type_sym->value());
+ if (type == NULL)
+ ir_read_error(st, expr, "invalid type: %s", type_sym->value());
+
+ return type;
+}
+
+
+static void
+scan_for_prototypes(_mesa_glsl_parse_state *st, exec_list *instructions,
+ s_expression *expr)
+{
+ s_list *list = SX_AS_LIST(expr);
+ if (list == NULL) {
+ ir_read_error(st, expr, "Expected (<instruction> ...); found an atom.");
+ return;
+ }
+
+ foreach_iter(exec_list_iterator, it, list->subexpressions) {
+ s_list *sub = SX_AS_LIST(it.get());
+ if (sub == NULL)
+ continue; // not a (function ...); ignore it.
+
+ s_symbol *tag = SX_AS_SYMBOL(sub->subexpressions.get_head());
+ if (tag == NULL || strcmp(tag->value(), "function") != 0)
+ continue; // not a (function ...); ignore it.
+
+ ir_function *f = read_function(st, sub, true);
+ if (f == NULL)
+ return;
+ instructions->push_tail(f);
+ }
+}
+
+static ir_function *
+read_function(_mesa_glsl_parse_state *st, s_list *list, bool skip_body)
+{
+ void *ctx = st;
+ bool added = false;
+ if (list->length() < 3) {
+ ir_read_error(st, list, "Expected (function <name> (signature ...) ...)");
+ return NULL;
+ }
+
+ s_symbol *name = SX_AS_SYMBOL(list->subexpressions.head->next);
+ if (name == NULL) {
+ ir_read_error(st, list, "Expected (function <name> ...)");
+ return NULL;
+ }
+
+ ir_function *f = st->symbols->get_function(name->value());
+ if (f == NULL) {
+ f = new(ctx) ir_function(name->value());
+ added = st->symbols->add_function(f->name, f);
+ assert(added);
+ }
+
+ exec_list_iterator it = list->subexpressions.iterator();
+ it.next(); // skip "function" tag
+ it.next(); // skip function name
+ for (/* nothing */; it.has_next(); it.next()) {
+ s_list *siglist = SX_AS_LIST(it.get());
+ if (siglist == NULL) {
+ ir_read_error(st, list, "Expected (function (signature ...) ...)");
+ return NULL;
+ }
+
+ s_symbol *tag = SX_AS_SYMBOL(siglist->subexpressions.get_head());
+ if (tag == NULL || strcmp(tag->value(), "signature") != 0) {
+ ir_read_error(st, siglist, "Expected (signature ...)");
+ return NULL;
+ }
+
+ read_function_sig(st, f, siglist, skip_body);
+ }
+ return added ? f : NULL;
+}
+
+static void
+read_function_sig(_mesa_glsl_parse_state *st, ir_function *f, s_list *list,
+ bool skip_body)
+{
+ void *ctx = st;
+ if (list->length() != 4) {
+ ir_read_error(st, list, "Expected (signature <type> (parameters ...) "
+ "(<instruction> ...))");
+ return;
+ }
+
+ s_expression *type_expr = (s_expression*) list->subexpressions.head->next;
+ const glsl_type *return_type = read_type(st, type_expr);
+ if (return_type == NULL)
+ return;
+
+ s_list *paramlist = SX_AS_LIST(type_expr->next);
+ s_list *body_list = SX_AS_LIST(paramlist->next);
+ if (paramlist == NULL || body_list == NULL) {
+ ir_read_error(st, list, "Expected (signature <type> (parameters ...) "
+ "(<instruction> ...))");
+ return;
+ }
+ s_symbol *paramtag = SX_AS_SYMBOL(paramlist->subexpressions.get_head());
+ if (paramtag == NULL || strcmp(paramtag->value(), "parameters") != 0) {
+ ir_read_error(st, paramlist, "Expected (parameters ...)");
+ return;
+ }
+
+ // Read the parameters list into a temporary place.
+ exec_list hir_parameters;
+ st->symbols->push_scope();
+
+ exec_list_iterator it = paramlist->subexpressions.iterator();
+ for (it.next() /* skip "parameters" */; it.has_next(); it.next()) {
+ s_list *decl = SX_AS_LIST(it.get());
+ ir_variable *var = read_declaration(st, decl);
+ if (var == NULL)
+ return;
+
+ hir_parameters.push_tail(var);
+ }
+
+ ir_function_signature *sig = f->exact_matching_signature(&hir_parameters);
+ if (sig == NULL && skip_body) {
+ /* If scanning for prototypes, generate a new signature. */
+ sig = new(ctx) ir_function_signature(return_type);
+ sig->is_built_in = true;
+ f->add_signature(sig);
+ } else if (sig != NULL) {
+ const char *badvar = sig->qualifiers_match(&hir_parameters);
+ if (badvar != NULL) {
+ ir_read_error(st, list, "function `%s' parameter `%s' qualifiers "
+ "don't match prototype", f->name, badvar);
+ return;
+ }
+
+ if (sig->return_type != return_type) {
+ ir_read_error(st, list, "function `%s' return type doesn't "
+ "match prototype", f->name);
+ return;
+ }
+ } else {
+ /* No prototype for this body exists - skip it. */
+ st->symbols->pop_scope();
+ return;
+ }
+ assert(sig != NULL);
+
+ sig->replace_parameters(&hir_parameters);
+
+ if (!skip_body && !body_list->subexpressions.is_empty()) {
+ if (sig->is_defined) {
+ ir_read_error(st, list, "function %s redefined", f->name);
+ return;
+ }
+ read_instructions(st, &sig->body, body_list, NULL);
+ sig->is_defined = true;
+ }
+
+ st->symbols->pop_scope();
+}
+
+static void
+read_instructions(_mesa_glsl_parse_state *st, exec_list *instructions,
+ s_expression *expr, ir_loop *loop_ctx)
+{
+ // Read in a list of instructions
+ s_list *list = SX_AS_LIST(expr);
+ if (list == NULL) {
+ ir_read_error(st, expr, "Expected (<instruction> ...); found an atom.");
+ return;
+ }
+
+ foreach_iter(exec_list_iterator, it, list->subexpressions) {
+ s_expression *sub = (s_expression*) it.get();
+ ir_instruction *ir = read_instruction(st, sub, loop_ctx);
+ if (ir != NULL)
+ instructions->push_tail(ir);
+ }
+}
+
+
+static ir_instruction *
+read_instruction(_mesa_glsl_parse_state *st, s_expression *expr,
+ ir_loop *loop_ctx)
+{
+ void *ctx = st;
+ s_symbol *symbol = SX_AS_SYMBOL(expr);
+ if (symbol != NULL) {
+ if (strcmp(symbol->value(), "break") == 0 && loop_ctx != NULL)
+ return new(ctx) ir_loop_jump(ir_loop_jump::jump_break);
+ if (strcmp(symbol->value(), "continue") == 0 && loop_ctx != NULL)
+ return new(ctx) ir_loop_jump(ir_loop_jump::jump_continue);
+ }
+
+ s_list *list = SX_AS_LIST(expr);
+ if (list == NULL || list->subexpressions.is_empty()) {
+ ir_read_error(st, expr, "Invalid instruction.\n");
+ return NULL;
+ }
+
+ s_symbol *tag = SX_AS_SYMBOL(list->subexpressions.get_head());
+ if (tag == NULL) {
+ ir_read_error(st, expr, "expected instruction tag");
+ return NULL;
+ }
+
+ ir_instruction *inst = NULL;
+ if (strcmp(tag->value(), "declare") == 0) {
+ inst = read_declaration(st, list);
+ } else if (strcmp(tag->value(), "assign") == 0) {
+ inst = read_assignment(st, list);
+ } else if (strcmp(tag->value(), "if") == 0) {
+ inst = read_if(st, list, loop_ctx);
+ } else if (strcmp(tag->value(), "loop") == 0) {
+ inst = read_loop(st, list);
+ } else if (strcmp(tag->value(), "return") == 0) {
+ inst = read_return(st, list);
+ } else if (strcmp(tag->value(), "function") == 0) {
+ inst = read_function(st, list, false);
+ } else {
+ inst = read_rvalue(st, list);
+ if (inst == NULL)
+ ir_read_error(st, NULL, "when reading instruction");
+ }
+ return inst;
+}
+
+
+static ir_variable *
+read_declaration(_mesa_glsl_parse_state *st, s_list *list)
+{
+ void *ctx = st;
+ if (list->length() != 4) {
+ ir_read_error(st, list, "expected (declare (<qualifiers>) <type> "
+ "<name>)");
+ return NULL;
+ }
+
+ s_list *quals = SX_AS_LIST(list->subexpressions.head->next);
+ if (quals == NULL) {
+ ir_read_error(st, list, "expected a list of variable qualifiers");
+ return NULL;
+ }
+
+ s_expression *type_expr = (s_expression*) quals->next;
+ const glsl_type *type = read_type(st, type_expr);
+ if (type == NULL)
+ return NULL;
+
+ s_symbol *var_name = SX_AS_SYMBOL(type_expr->next);
+ if (var_name == NULL) {
+ ir_read_error(st, list, "expected variable name, found non-symbol");
+ return NULL;
+ }
+
+ ir_variable *var = new(ctx) ir_variable(type, var_name->value(),
+ ir_var_auto);
+
+ foreach_iter(exec_list_iterator, it, quals->subexpressions) {
+ s_symbol *qualifier = SX_AS_SYMBOL(it.get());
+ if (qualifier == NULL) {
+ ir_read_error(st, list, "qualifier list must contain only symbols");
+ delete var;
+ return NULL;
+ }
+
+ // FINISHME: Check for duplicate/conflicting qualifiers.
+ if (strcmp(qualifier->value(), "centroid") == 0) {
+ var->centroid = 1;
+ } else if (strcmp(qualifier->value(), "invariant") == 0) {
+ var->invariant = 1;
+ } else if (strcmp(qualifier->value(), "uniform") == 0) {
+ var->mode = ir_var_uniform;
+ } else if (strcmp(qualifier->value(), "auto") == 0) {
+ var->mode = ir_var_auto;
+ } else if (strcmp(qualifier->value(), "in") == 0) {
+ var->mode = ir_var_in;
+ } else if (strcmp(qualifier->value(), "out") == 0) {
+ var->mode = ir_var_out;
+ } else if (strcmp(qualifier->value(), "inout") == 0) {
+ var->mode = ir_var_inout;
+ } else if (strcmp(qualifier->value(), "smooth") == 0) {
+ var->interpolation = ir_var_smooth;
+ } else if (strcmp(qualifier->value(), "flat") == 0) {
+ var->interpolation = ir_var_flat;
+ } else if (strcmp(qualifier->value(), "noperspective") == 0) {
+ var->interpolation = ir_var_noperspective;
+ } else {
+ ir_read_error(st, list, "unknown qualifier: %s", qualifier->value());
+ delete var;
+ return NULL;
+ }
+ }
+
+ // Add the variable to the symbol table
+ st->symbols->add_variable(var->name, var);
+
+ return var;
+}
+
+
+static ir_if *
+read_if(_mesa_glsl_parse_state *st, s_list *list, ir_loop *loop_ctx)
+{
+ void *ctx = st;
+ if (list->length() != 4) {
+ ir_read_error(st, list, "expected (if <condition> (<then> ...) "
+ "(<else> ...))");
+ return NULL;
+ }
+
+ s_expression *cond_expr = (s_expression*) list->subexpressions.head->next;
+ ir_rvalue *condition = read_rvalue(st, cond_expr);
+ if (condition == NULL) {
+ ir_read_error(st, NULL, "when reading condition of (if ...)");
+ return NULL;
+ }
+
+ s_expression *then_expr = (s_expression*) cond_expr->next;
+ s_expression *else_expr = (s_expression*) then_expr->next;
+
+ ir_if *iff = new(ctx) ir_if(condition);
+
+ read_instructions(st, &iff->then_instructions, then_expr, loop_ctx);
+ read_instructions(st, &iff->else_instructions, else_expr, loop_ctx);
+ if (st->error) {
+ delete iff;
+ iff = NULL;
+ }
+ return iff;
+}
+
+
+static ir_loop *
+read_loop(_mesa_glsl_parse_state *st, s_list *list)
+{
+ void *ctx = st;
+ if (list->length() != 6) {
+ ir_read_error(st, list, "expected (loop <counter> <from> <to> "
+ "<increment> <body>)");
+ return NULL;
+ }
+
+ s_expression *count_expr = (s_expression*) list->subexpressions.head->next;
+ s_expression *from_expr = (s_expression*) count_expr->next;
+ s_expression *to_expr = (s_expression*) from_expr->next;
+ s_expression *inc_expr = (s_expression*) to_expr->next;
+ s_expression *body_expr = (s_expression*) inc_expr->next;
+
+ // FINISHME: actually read the count/from/to fields.
+
+ ir_loop *loop = new(ctx) ir_loop;
+ read_instructions(st, &loop->body_instructions, body_expr, loop);
+ if (st->error) {
+ delete loop;
+ loop = NULL;
+ }
+ return loop;
+}
+
+
+static ir_return *
+read_return(_mesa_glsl_parse_state *st, s_list *list)
+{
+ void *ctx = st;
+ if (list->length() != 2) {
+ ir_read_error(st, list, "expected (return <rvalue>)");
+ return NULL;
+ }
+
+ s_expression *expr = (s_expression*) list->subexpressions.head->next;
+
+ ir_rvalue *retval = read_rvalue(st, expr);
+ if (retval == NULL) {
+ ir_read_error(st, NULL, "when reading return value");
+ return NULL;
+ }
+
+ return new(ctx) ir_return(retval);
+}
+
+
+static ir_rvalue *
+read_rvalue(_mesa_glsl_parse_state *st, s_expression *expr)
+{
+ s_list *list = SX_AS_LIST(expr);
+ if (list == NULL || list->subexpressions.is_empty())
+ return NULL;
+
+ s_symbol *tag = SX_AS_SYMBOL(list->subexpressions.get_head());
+ if (tag == NULL) {
+ ir_read_error(st, expr, "expected rvalue tag");
+ return NULL;
+ }
+
+ ir_rvalue *rvalue = read_dereference(st, list);
+ if (rvalue != NULL || st->error)
+ return rvalue;
+ else if (strcmp(tag->value(), "swiz") == 0) {
+ rvalue = read_swizzle(st, list);
+ } else if (strcmp(tag->value(), "expression") == 0) {
+ rvalue = read_expression(st, list);
+ } else if (strcmp(tag->value(), "call") == 0) {
+ rvalue = read_call(st, list);
+ } else if (strcmp(tag->value(), "constant") == 0) {
+ rvalue = read_constant(st, list);
+ } else {
+ rvalue = read_texture(st, list);
+ if (rvalue == NULL && !st->error)
+ ir_read_error(st, expr, "unrecognized rvalue tag: %s", tag->value());
+ }
+
+ return rvalue;
+}
+
+static ir_assignment *
+read_assignment(_mesa_glsl_parse_state *st, s_list *list)
+{
+ void *ctx = st;
+ if (list->length() != 4) {
+ ir_read_error(st, list, "expected (assign <condition> <lhs> <rhs>)");
+ return NULL;
+ }
+
+ s_expression *cond_expr = (s_expression*) list->subexpressions.head->next;
+ s_expression *lhs_expr = (s_expression*) cond_expr->next;
+ s_expression *rhs_expr = (s_expression*) lhs_expr->next;
+
+ // FINISHME: Deal with "true" condition
+ ir_rvalue *condition = read_rvalue(st, cond_expr);
+ if (condition == NULL) {
+ ir_read_error(st, NULL, "when reading condition of assignment");
+ return NULL;
+ }
+
+ ir_rvalue *lhs = read_rvalue(st, lhs_expr);
+ if (lhs == NULL) {
+ ir_read_error(st, NULL, "when reading left-hand side of assignment");
+ return NULL;
+ }
+
+ ir_rvalue *rhs = read_rvalue(st, rhs_expr);
+ if (rhs == NULL) {
+ ir_read_error(st, NULL, "when reading right-hand side of assignment");
+ return NULL;
+ }
+
+ return new(ctx) ir_assignment(lhs, rhs, condition);
+}
+
+static ir_call *
+read_call(_mesa_glsl_parse_state *st, s_list *list)
+{
+ void *ctx = st;
+ if (list->length() != 3) {
+ ir_read_error(st, list, "expected (call <name> (<param> ...))");
+ return NULL;
+ }
+
+ s_symbol *name = SX_AS_SYMBOL(list->subexpressions.head->next);
+ s_list *params = SX_AS_LIST(name->next);
+ if (name == NULL || params == NULL) {
+ ir_read_error(st, list, "expected (call <name> (<param> ...))");
+ return NULL;
+ }
+
+ exec_list parameters;
+
+ foreach_iter(exec_list_iterator, it, params->subexpressions) {
+ s_expression *expr = (s_expression*) it.get();
+ ir_rvalue *param = read_rvalue(st, expr);
+ if (param == NULL) {
+ ir_read_error(st, list, "when reading parameter to function call");
+ return NULL;
+ }
+ parameters.push_tail(param);
+ }
+
+ ir_function *f = st->symbols->get_function(name->value());
+ if (f == NULL) {
+ ir_read_error(st, list, "found call to undefined function %s",
+ name->value());
+ return NULL;
+ }
+
+ ir_function_signature *callee = f->matching_signature(&parameters);
+ if (callee == NULL) {
+ ir_read_error(st, list, "couldn't find matching signature for function "
+ "%s", name->value());
+ return NULL;
+ }
+
+ return new(ctx) ir_call(callee, &parameters);
+}
+
+static ir_expression *
+read_expression(_mesa_glsl_parse_state *st, s_list *list)
+{
+ void *ctx = st;
+ const unsigned list_length = list->length();
+ if (list_length < 4) {
+ ir_read_error(st, list, "expected (expression <type> <operator> "
+ "<operand> [<operand>])");
+ return NULL;
+ }
+
+ s_expression *type_expr = (s_expression*) list->subexpressions.head->next;
+ const glsl_type *type = read_type(st, type_expr);
+ if (type == NULL)
+ return NULL;
+
+ /* Read the operator */
+ s_symbol *op_sym = SX_AS_SYMBOL(type_expr->next);
+ if (op_sym == NULL) {
+ ir_read_error(st, list, "expected operator, found non-symbol");
+ return NULL;
+ }
+
+ ir_expression_operation op = ir_expression::get_operator(op_sym->value());
+ if (op == (ir_expression_operation) -1) {
+ ir_read_error(st, list, "invalid operator: %s", op_sym->value());
+ return NULL;
+ }
+
+ /* Now that we know the operator, check for the right number of operands */
+ if (ir_expression::get_num_operands(op) == 2) {
+ if (list_length != 5) {
+ ir_read_error(st, list, "expected (expression <type> %s <operand> "
+ " <operand>)", op_sym->value());
+ return NULL;
+ }
+ } else {
+ if (list_length != 4) {
+ ir_read_error(st, list, "expected (expression <type> %s <operand>)",
+ op_sym->value());
+ return NULL;
+ }
+ }
+
+ s_expression *exp1 = (s_expression*) (op_sym->next);
+ ir_rvalue *arg1 = read_rvalue(st, exp1);
+ if (arg1 == NULL) {
+ ir_read_error(st, NULL, "when reading first operand of %s",
+ op_sym->value());
+ return NULL;
+ }
+
+ ir_rvalue *arg2 = NULL;
+ if (ir_expression::get_num_operands(op) == 2) {
+ s_expression *exp2 = (s_expression*) (exp1->next);
+ arg2 = read_rvalue(st, exp2);
+ if (arg2 == NULL) {
+ ir_read_error(st, NULL, "when reading second operand of %s",
+ op_sym->value());
+ return NULL;
+ }
+ }
+
+ return new(ctx) ir_expression(op, type, arg1, arg2);
+}
+
+static ir_swizzle *
+read_swizzle(_mesa_glsl_parse_state *st, s_list *list)
+{
+ if (list->length() != 3) {
+ ir_read_error(st, list, "expected (swiz <swizzle> <rvalue>)");
+ return NULL;
+ }
+
+ s_symbol *swiz = SX_AS_SYMBOL(list->subexpressions.head->next);
+ if (swiz == NULL) {
+ ir_read_error(st, list, "expected a valid swizzle; found non-symbol");
+ return NULL;
+ }
+
+ if (strlen(swiz->value()) > 4) {
+ ir_read_error(st, list, "expected a valid swizzle; found %s",
+ swiz->value());
+ return NULL;
+ }
+
+ s_expression *sub = (s_expression*) swiz->next;
+ if (sub == NULL) {
+ ir_read_error(st, list, "expected rvalue: (swizzle %s <rvalue>)",
+ swiz->value());
+ return NULL;
+ }
+
+ ir_rvalue *rvalue = read_rvalue(st, sub);
+ if (rvalue == NULL)
+ return NULL;
+
+ ir_swizzle *ir = ir_swizzle::create(rvalue, swiz->value(),
+ rvalue->type->vector_elements);
+ if (ir == NULL)
+ ir_read_error(st, list, "invalid swizzle");
+
+ return ir;
+}
+
+static ir_constant *
+read_constant(_mesa_glsl_parse_state *st, s_list *list)
+{
+ void *ctx = st;
+ if (list->length() != 3) {
+ ir_read_error(st, list, "expected (constant <type> (...))");
+ return NULL;
+ }
+
+ s_expression *type_expr = (s_expression*) list->subexpressions.head->next;
+ const glsl_type *type = read_type(st, type_expr);
+ if (type == NULL)
+ return NULL;
+
+ s_list *values = SX_AS_LIST(type_expr->next);
+ if (values == NULL) {
+ ir_read_error(st, list, "expected (constant <type> (...))");
+ return NULL;
+ }
+
+ if (type->is_array()) {
+ const unsigned elements_supplied = values->length();
+ if (elements_supplied != type->length) {
+ ir_read_error(st, values, "expected exactly %u array elements, "
+ "given %u", type->length, elements_supplied);
+ return NULL;
+ }
+
+ exec_list elements;
+ foreach_iter(exec_list_iterator, it, values->subexpressions) {
+ s_expression *expr = (s_expression *) it.get();
+ s_list *elt = SX_AS_LIST(expr);
+ if (elt == NULL) {
+ ir_read_error(st, expr, "expected (constant ...) array element");
+ return NULL;
+ }
+
+ ir_constant *ir_elt = read_constant(st, elt);
+ if (ir_elt == NULL)
+ return NULL;
+ elements.push_tail(ir_elt);
+ }
+ return new(ctx) ir_constant(type, &elements);
+ }
+
+ const glsl_type *const base_type = type->get_base_type();
+
+ ir_constant_data data;
+
+ // Read in list of values (at most 16).
+ int k = 0;
+ foreach_iter(exec_list_iterator, it, values->subexpressions) {
+ if (k >= 16) {
+ ir_read_error(st, values, "expected at most 16 numbers");
+ return NULL;
+ }
+
+ s_expression *expr = (s_expression*) it.get();
+
+ if (base_type->base_type == GLSL_TYPE_FLOAT) {
+ s_number *value = SX_AS_NUMBER(expr);
+ if (value == NULL) {
+ ir_read_error(st, values, "expected numbers");
+ return NULL;
+ }
+ data.f[k] = value->fvalue();
+ } else {
+ s_int *value = SX_AS_INT(expr);
+ if (value == NULL) {
+ ir_read_error(st, values, "expected integers");
+ return NULL;
+ }
+
+ switch (base_type->base_type) {
+ case GLSL_TYPE_UINT: {
+ data.u[k] = value->value();
+ break;
+ }
+ case GLSL_TYPE_INT: {
+ data.i[k] = value->value();
+ break;
+ }
+ case GLSL_TYPE_BOOL: {
+ data.b[k] = value->value();
+ break;
+ }
+ default:
+ ir_read_error(st, values, "unsupported constant type");
+ return NULL;
+ }
+ }
+ ++k;
+ }
+
+ return new(ctx) ir_constant(type, &data);
+}
+
+static ir_dereference *
+read_dereference(_mesa_glsl_parse_state *st, s_expression *expr)
+{
+ s_list *list = SX_AS_LIST(expr);
+ if (list == NULL || list->subexpressions.is_empty())
+ return NULL;
+
+ s_symbol *tag = SX_AS_SYMBOL(list->subexpressions.head);
+ assert(tag != NULL);
+
+ if (strcmp(tag->value(), "var_ref") == 0)
+ return read_var_ref(st, list);
+ if (strcmp(tag->value(), "array_ref") == 0)
+ return read_array_ref(st, list);
+ if (strcmp(tag->value(), "record_ref") == 0)
+ return read_record_ref(st, list);
+ return NULL;
+}
+
+static ir_dereference *
+read_var_ref(_mesa_glsl_parse_state *st, s_list *list)
+{
+ void *ctx = st;
+ if (list->length() != 2) {
+ ir_read_error(st, list, "expected (var_ref <variable name>)");
+ return NULL;
+ }
+ s_symbol *var_name = SX_AS_SYMBOL(list->subexpressions.head->next);
+ if (var_name == NULL) {
+ ir_read_error(st, list, "expected (var_ref <variable name>)");
+ return NULL;
+ }
+
+ ir_variable *var = st->symbols->get_variable(var_name->value());
+ if (var == NULL) {
+ ir_read_error(st, list, "undeclared variable: %s", var_name->value());
+ return NULL;
+ }
+
+ return new(ctx) ir_dereference_variable(var);
+}
+
+static ir_dereference *
+read_array_ref(_mesa_glsl_parse_state *st, s_list *list)
+{
+ void *ctx = st;
+ if (list->length() != 3) {
+ ir_read_error(st, list, "expected (array_ref <rvalue> <index>)");
+ return NULL;
+ }
+
+ s_expression *subj_expr = (s_expression*) list->subexpressions.head->next;
+ ir_rvalue *subject = read_rvalue(st, subj_expr);
+ if (subject == NULL) {
+ ir_read_error(st, NULL, "when reading the subject of an array_ref");
+ return NULL;
+ }
+
+ s_expression *idx_expr = (s_expression*) subj_expr->next;
+ ir_rvalue *idx = read_rvalue(st, idx_expr);
+ return new(ctx) ir_dereference_array(subject, idx);
+}
+
+static ir_dereference *
+read_record_ref(_mesa_glsl_parse_state *st, s_list *list)
+{
+ void *ctx = st;
+ if (list->length() != 3) {
+ ir_read_error(st, list, "expected (record_ref <rvalue> <field>)");
+ return NULL;
+ }
+
+ s_expression *subj_expr = (s_expression*) list->subexpressions.head->next;
+ ir_rvalue *subject = read_rvalue(st, subj_expr);
+ if (subject == NULL) {
+ ir_read_error(st, NULL, "when reading the subject of a record_ref");
+ return NULL;
+ }
+
+ s_symbol *field = SX_AS_SYMBOL(subj_expr->next);
+ if (field == NULL) {
+ ir_read_error(st, list, "expected (record_ref ... <field name>)");
+ return NULL;
+ }
+ return new(ctx) ir_dereference_record(subject, field->value());
+}
+
+static bool
+valid_texture_list_length(ir_texture_opcode op, s_list *list)
+{
+ unsigned required_length = 7;
+ if (op == ir_txf)
+ required_length = 5;
+ else if (op == ir_tex)
+ required_length = 6;
+
+ return list->length() == required_length;
+}
+
+static ir_texture *
+read_texture(_mesa_glsl_parse_state *st, s_list *list)
+{
+ void *ctx = st;
+ s_symbol *tag = SX_AS_SYMBOL(list->subexpressions.head);
+ assert(tag != NULL);
+
+ ir_texture_opcode op = ir_texture::get_opcode(tag->value());
+ if (op == (ir_texture_opcode) -1)
+ return NULL;
+
+ if (!valid_texture_list_length(op, list)) {
+ ir_read_error(st, NULL, "invalid list size in (%s ...)", tag->value());
+ return NULL;
+ }
+
+ ir_texture *tex = new(ctx) ir_texture(op);
+
+ // Read sampler (must be a deref)
+ s_expression *sampler_expr = (s_expression *) tag->next;
+ ir_dereference *sampler = read_dereference(st, sampler_expr);
+ if (sampler == NULL) {
+ ir_read_error(st, NULL, "when reading sampler in (%s ...)", tag->value());
+ return NULL;
+ }
+ tex->set_sampler(sampler);
+
+ // Read coordinate (any rvalue)
+ s_expression *coordinate_expr = (s_expression *) sampler_expr->next;
+ tex->coordinate = read_rvalue(st, coordinate_expr);
+ if (tex->coordinate == NULL) {
+ ir_read_error(st, NULL, "when reading coordinate in (%s ...)",
+ tag->value());
+ return NULL;
+ }
+
+ // Read texel offset, i.e. (0 0 0)
+ s_list *offset_list = SX_AS_LIST(coordinate_expr->next);
+ if (offset_list == NULL || offset_list->length() != 3) {
+ ir_read_error(st, offset_list, "expected (<int> <int> <int>)");
+ return NULL;
+ }
+ s_int *offset_x = SX_AS_INT(offset_list->subexpressions.head);
+ s_int *offset_y = SX_AS_INT(offset_x->next);
+ s_int *offset_z = SX_AS_INT(offset_y->next);
+ if (offset_x == NULL || offset_y == NULL || offset_z == NULL) {
+ ir_read_error(st, offset_list, "expected (<int> <int> <int>)");
+ return NULL;
+ }
+ tex->offsets[0] = offset_x->value();
+ tex->offsets[1] = offset_y->value();
+ tex->offsets[2] = offset_z->value();
+
+ if (op == ir_txf) {
+ s_expression *lod_expr = (s_expression *) offset_list->next;
+ tex->lod_info.lod = read_rvalue(st, lod_expr);
+ if (tex->lod_info.lod == NULL) {
+ ir_read_error(st, NULL, "when reading LOD in (txf ...)");
+ return NULL;
+ }
+ } else {
+ s_expression *proj_expr = (s_expression *) offset_list->next;
+ s_int *proj_as_int = SX_AS_INT(proj_expr);
+ if (proj_as_int && proj_as_int->value() == 1) {
+ tex->projector = NULL;
+ } else {
+ tex->projector = read_rvalue(st, proj_expr);
+ if (tex->projector == NULL) {
+ ir_read_error(st, NULL, "when reading projective divide in (%s ..)",
+ tag->value());
+ return NULL;
+ }
+ }
+
+ s_list *shadow_list = SX_AS_LIST(proj_expr->next);
+ if (shadow_list == NULL) {
+ ir_read_error(st, NULL, "shadow comparitor must be a list");
+ return NULL;
+ }
+ if (shadow_list->subexpressions.is_empty()) {
+ tex->shadow_comparitor= NULL;
+ } else {
+ tex->shadow_comparitor = read_rvalue(st, shadow_list);
+ if (tex->shadow_comparitor == NULL) {
+ ir_read_error(st, NULL, "when reading shadow comparitor in (%s ..)",
+ tag->value());
+ return NULL;
+ }
+ }
+ s_expression *lod_expr = (s_expression *) shadow_list->next;
+
+ switch (op) {
+ case ir_txb:
+ tex->lod_info.bias = read_rvalue(st, lod_expr);
+ if (tex->lod_info.bias == NULL) {
+ ir_read_error(st, NULL, "when reading LOD bias in (txb ...)");
+ return NULL;
+ }
+ break;
+ case ir_txl:
+ tex->lod_info.lod = read_rvalue(st, lod_expr);
+ if (tex->lod_info.lod == NULL) {
+ ir_read_error(st, NULL, "when reading LOD in (txl ...)");
+ return NULL;
+ }
+ break;
+ case ir_txd: {
+ s_list *lod_list = SX_AS_LIST(lod_expr);
+ if (lod_list->length() != 2) {
+ ir_read_error(st, lod_expr, "expected (dPdx dPdy) in (txd ...)");
+ return NULL;
+ }
+ s_expression *dx_expr = (s_expression *) lod_list->subexpressions.head;
+ s_expression *dy_expr = (s_expression *) dx_expr->next;
+
+ tex->lod_info.grad.dPdx = read_rvalue(st, dx_expr);
+ if (tex->lod_info.grad.dPdx == NULL) {
+ ir_read_error(st, NULL, "when reading dPdx in (txd ...)");
+ return NULL;
+ }
+ tex->lod_info.grad.dPdy = read_rvalue(st, dy_expr);
+ if (tex->lod_info.grad.dPdy == NULL) {
+ ir_read_error(st, NULL, "when reading dPdy in (txd ...)");
+ return NULL;
+ }
+ break;
+ }
+ default:
+ // tex doesn't have any extra parameters and txf was handled earlier.
+ break;
+ };
+ }
+ return tex;
+}
diff --git a/src/glsl/ir_reader.h b/src/glsl/ir_reader.h
new file mode 100644
index 00000000000..aef2ca23bd2
--- /dev/null
+++ b/src/glsl/ir_reader.h
@@ -0,0 +1,34 @@
+/* -*- c++ -*- */
+/*
+ * Copyright © 2010 Intel Corporation
+ *
+ * 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 (including the next
+ * paragraph) 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
+ * THE AUTHORS OR COPYRIGHT HOLDERS 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.
+ */
+
+#pragma once
+#ifndef IR_READER_H
+#define IR_READER_H
+
+#include "ir.h"
+
+void _mesa_glsl_read_ir(_mesa_glsl_parse_state *state, exec_list *instructions,
+ const char *src, bool scan_for_prototypes);
+
+#endif /* IR_READER_H */
diff --git a/src/glsl/ir_rvalue_visitor.cpp b/src/glsl/ir_rvalue_visitor.cpp
new file mode 100644
index 00000000000..613b07c3029
--- /dev/null
+++ b/src/glsl/ir_rvalue_visitor.cpp
@@ -0,0 +1,134 @@
+/*
+ * Copyright © 2010 Intel Corporation
+ *
+ * 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 (including the next
+ * paragraph) 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
+ * THE AUTHORS OR COPYRIGHT HOLDERS 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 ir_rvalue_visitor.cpp
+ *
+ * Generic class to implement the common pattern we have of wanting to
+ * visit each ir_rvalue * and possibly change that node to a different
+ * class.
+ */
+
+#include "ir.h"
+#include "ir_visitor.h"
+#include "ir_rvalue_visitor.h"
+#include "ir_print_visitor.h"
+#include "glsl_types.h"
+
+ir_visitor_status
+ir_rvalue_visitor::visit_leave(ir_expression *ir)
+{
+ unsigned int operand;
+
+ for (operand = 0; operand < ir->get_num_operands(); operand++) {
+ handle_rvalue(&ir->operands[operand]);
+ }
+
+ return visit_continue;
+}
+
+ir_visitor_status
+ir_rvalue_visitor::visit_leave(ir_texture *ir)
+{
+ handle_rvalue(&ir->coordinate);
+ handle_rvalue(&ir->projector);
+ handle_rvalue(&ir->shadow_comparitor);
+
+ switch (ir->op) {
+ case ir_tex:
+ break;
+ case ir_txb:
+ handle_rvalue(&ir->lod_info.bias);
+ break;
+ case ir_txf:
+ case ir_txl:
+ handle_rvalue(&ir->lod_info.lod);
+ break;
+ case ir_txd:
+ handle_rvalue(&ir->lod_info.grad.dPdx);
+ handle_rvalue(&ir->lod_info.grad.dPdy);
+ break;
+ }
+
+ return visit_continue;
+}
+
+ir_visitor_status
+ir_rvalue_visitor::visit_leave(ir_swizzle *ir)
+{
+ handle_rvalue(&ir->val);
+ return visit_continue;
+}
+
+ir_visitor_status
+ir_rvalue_visitor::visit_leave(ir_dereference_array *ir)
+{
+ handle_rvalue(&ir->array_index);
+ handle_rvalue(&ir->array);
+ return visit_continue;
+}
+
+ir_visitor_status
+ir_rvalue_visitor::visit_leave(ir_dereference_record *ir)
+{
+ handle_rvalue(&ir->record);
+ return visit_continue;
+}
+
+ir_visitor_status
+ir_rvalue_visitor::visit_leave(ir_assignment *ir)
+{
+ handle_rvalue(&ir->rhs);
+ handle_rvalue(&ir->condition);
+
+ return visit_continue;
+}
+
+ir_visitor_status
+ir_rvalue_visitor::visit_leave(ir_call *ir)
+{
+ foreach_iter(exec_list_iterator, iter, *ir) {
+ ir_rvalue *param = (ir_rvalue *)iter.get();
+ ir_rvalue *new_param = param;
+ handle_rvalue(&new_param);
+
+ if (new_param != param) {
+ param->replace_with(new_param);
+ }
+ }
+ return visit_continue;
+}
+
+ir_visitor_status
+ir_rvalue_visitor::visit_leave(ir_return *ir)
+{
+ handle_rvalue(&ir->value);;
+ return visit_continue;
+}
+
+ir_visitor_status
+ir_rvalue_visitor::visit_leave(ir_if *ir)
+{
+ handle_rvalue(&ir->condition);
+ return visit_continue;
+}
diff --git a/src/glsl/ir_rvalue_visitor.h b/src/glsl/ir_rvalue_visitor.h
new file mode 100644
index 00000000000..31a56beb9b8
--- /dev/null
+++ b/src/glsl/ir_rvalue_visitor.h
@@ -0,0 +1,47 @@
+/*
+ * Copyright © 2010 Intel Corporation
+ *
+ * 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 (including the next
+ * paragraph) 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
+ * THE AUTHORS OR COPYRIGHT HOLDERS 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 ir_rvalue_visitor.h
+ *
+ * Generic class to implement the common pattern we have of wanting to
+ * visit each ir_rvalue * and possibly change that node to a different
+ * class. Just implement handle_rvalue() and you will be called with
+ * a pointer to each rvalue in the tree.
+ */
+
+class ir_rvalue_visitor : public ir_hierarchical_visitor {
+public:
+
+ virtual ir_visitor_status visit_leave(ir_assignment *);
+ virtual ir_visitor_status visit_leave(ir_call *);
+ virtual ir_visitor_status visit_leave(ir_dereference_array *);
+ virtual ir_visitor_status visit_leave(ir_dereference_record *);
+ virtual ir_visitor_status visit_leave(ir_expression *);
+ virtual ir_visitor_status visit_leave(ir_if *);
+ virtual ir_visitor_status visit_leave(ir_return *);
+ virtual ir_visitor_status visit_leave(ir_swizzle *);
+ virtual ir_visitor_status visit_leave(ir_texture *);
+
+ virtual void handle_rvalue(ir_rvalue **rvalue) = 0;
+};
diff --git a/src/glsl/ir_set_program_inouts.cpp b/src/glsl/ir_set_program_inouts.cpp
new file mode 100644
index 00000000000..658637775a4
--- /dev/null
+++ b/src/glsl/ir_set_program_inouts.cpp
@@ -0,0 +1,167 @@
+/*
+ * Copyright © 2010 Intel Corporation
+ *
+ * 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 (including the next
+ * paragraph) 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
+ * THE AUTHORS OR COPYRIGHT HOLDERS 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 ir_set_program_inouts.cpp
+ *
+ * Sets the InputsRead and OutputsWritten of Mesa programs.
+ *
+ * Mesa programs (gl_program, not gl_shader_program) have a set of
+ * flags indicating which varyings are read and written. Computing
+ * which are actually read from some sort of backend code can be
+ * tricky when variable array indexing involved. So this pass
+ * provides support for setting InputsRead and OutputsWritten right
+ * from the GLSL IR.
+ */
+
+extern "C" {
+#include "main/mtypes.h"
+#include "program/hash_table.h"
+}
+#include "ir.h"
+#include "ir_visitor.h"
+#include "glsl_types.h"
+
+class ir_set_program_inouts_visitor : public ir_hierarchical_visitor {
+public:
+ ir_set_program_inouts_visitor(struct gl_program *prog)
+ {
+ this->prog = prog;
+ this->ht = hash_table_ctor(0,
+ hash_table_pointer_hash,
+ hash_table_pointer_compare);
+ }
+ ir_set_program_inouts_visitor()
+ {
+ hash_table_dtor(this->ht);
+ }
+
+ virtual ir_visitor_status visit_enter(ir_dereference_array *);
+ virtual ir_visitor_status visit_enter(ir_function_signature *);
+ virtual ir_visitor_status visit(ir_dereference_variable *);
+ virtual ir_visitor_status visit(ir_variable *);
+
+ struct gl_program *prog;
+ struct hash_table *ht;
+};
+
+static void
+mark(struct gl_program *prog, ir_variable *var, int index)
+{
+ /* As of GLSL 1.20, varyings can only be floats, floating-point
+ * vectors or matrices, or arrays of them. For Mesa programs using
+ * InputsRead/OutputsWritten, everything but matrices uses one
+ * slot, while matrices use a slot per column. Presumably
+ * something doing a more clever packing would use something other
+ * than InputsRead/OutputsWritten.
+ */
+ const glsl_type *element_type;
+ int element_size;
+
+ if (var->type->is_array())
+ element_type = var->type->fields.array;
+ else
+ element_type = var->type;
+
+ if (element_type->is_matrix())
+ element_size = element_type->matrix_columns;
+ else
+ element_size = 1;
+
+ index *= element_size;
+ for (int i = 0; i < element_size; i++) {
+ if (var->mode == ir_var_in)
+ prog->InputsRead |= BITFIELD64_BIT(var->location + index + i);
+ else
+ prog->OutputsWritten |= BITFIELD64_BIT(var->location + index + i);
+ }
+}
+
+/* Default handler: Mark all the locations in the variable as used. */
+ir_visitor_status
+ir_set_program_inouts_visitor::visit(ir_dereference_variable *ir)
+{
+ if (hash_table_find(this->ht, ir->var) == NULL)
+ return visit_continue;
+
+ if (ir->type->is_array()) {
+ for (unsigned int i = 0; i < ir->type->length; i++) {
+ mark(this->prog, ir->var, i);
+ }
+ } else {
+ mark(this->prog, ir->var, 0);
+ }
+
+ return visit_continue;
+}
+
+ir_visitor_status
+ir_set_program_inouts_visitor::visit_enter(ir_dereference_array *ir)
+{
+ ir_dereference_variable *deref_var;
+ ir_constant *index = ir->array_index->as_constant();
+ deref_var = ir->array->as_dereference_variable();
+ ir_variable *var = NULL;
+
+ /* Check that we're dereferencing a shader in or out */
+ if (deref_var)
+ var = (ir_variable *)hash_table_find(this->ht, deref_var->var);
+
+ if (index && var) {
+ mark(this->prog, var, index->value.i[0]);
+ return visit_continue_with_parent;
+ }
+
+ return visit_continue;
+}
+
+ir_visitor_status
+ir_set_program_inouts_visitor::visit(ir_variable *ir)
+{
+ if (ir->mode == ir_var_in ||
+ ir->mode == ir_var_out) {
+ hash_table_insert(this->ht, ir, ir);
+ }
+
+ return visit_continue;
+}
+
+ir_visitor_status
+ir_set_program_inouts_visitor::visit_enter(ir_function_signature *ir)
+{
+ /* We don't want to descend into the function parameters and
+ * consider them as shader inputs or outputs.
+ */
+ visit_list_elements(this, &ir->body);
+ return visit_continue_with_parent;
+}
+
+void
+do_set_program_inouts(exec_list *instructions, struct gl_program *prog)
+{
+ ir_set_program_inouts_visitor v(prog);
+
+ prog->InputsRead = 0;
+ prog->OutputsWritten = 0;
+ visit_list_elements(&v, instructions);
+}
diff --git a/src/glsl/ir_structure_splitting.cpp b/src/glsl/ir_structure_splitting.cpp
new file mode 100644
index 00000000000..e257defb1a1
--- /dev/null
+++ b/src/glsl/ir_structure_splitting.cpp
@@ -0,0 +1,355 @@
+/*
+ * Copyright © 2010 Intel Corporation
+ *
+ * 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 (including the next
+ * paragraph) 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
+ * THE AUTHORS OR COPYRIGHT HOLDERS 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 ir_structure_splitting.cpp
+ *
+ * If a structure is only ever referenced by its components, then
+ * split those components out to individual variables so they can be
+ * handled normally by other optimization passes.
+ *
+ * This skips structures like uniforms, which need to be accessible as
+ * structures for their access by the GL.
+ */
+
+#include "ir.h"
+#include "ir_visitor.h"
+#include "ir_print_visitor.h"
+#include "ir_rvalue_visitor.h"
+#include "glsl_types.h"
+
+static bool debug = false;
+
+class variable_entry : public exec_node
+{
+public:
+ variable_entry(ir_variable *var)
+ {
+ this->var = var;
+ this->whole_structure_access = 0;
+ this->declaration = false;
+ this->components = NULL;
+ this->mem_ctx = NULL;
+ }
+
+ ir_variable *var; /* The key: the variable's pointer. */
+
+ /** Number of times the variable is referenced, including assignments. */
+ unsigned whole_structure_access;
+
+ bool declaration; /* If the variable had a decl in the instruction stream */
+
+ ir_variable **components;
+
+ /** talloc_parent(this->var) -- the shader's talloc context. */
+ void *mem_ctx;
+};
+
+class ir_structure_reference_visitor : public ir_hierarchical_visitor {
+public:
+ ir_structure_reference_visitor(void)
+ {
+ this->mem_ctx = talloc_new(NULL);
+ this->variable_list.make_empty();
+ }
+
+ ~ir_structure_reference_visitor(void)
+ {
+ talloc_free(mem_ctx);
+ }
+
+ virtual ir_visitor_status visit(ir_variable *);
+ virtual ir_visitor_status visit(ir_dereference_variable *);
+ virtual ir_visitor_status visit_enter(ir_dereference_record *);
+ virtual ir_visitor_status visit_enter(ir_assignment *);
+ virtual ir_visitor_status visit_enter(ir_function_signature *);
+
+ variable_entry *get_variable_entry(ir_variable *var);
+
+ /* List of variable_entry */
+ exec_list variable_list;
+
+ void *mem_ctx;
+};
+
+variable_entry *
+ir_structure_reference_visitor::get_variable_entry(ir_variable *var)
+{
+ assert(var);
+
+ if (!var->type->is_record() || var->mode == ir_var_uniform)
+ return NULL;
+
+ foreach_iter(exec_list_iterator, iter, this->variable_list) {
+ variable_entry *entry = (variable_entry *)iter.get();
+ if (entry->var == var)
+ return entry;
+ }
+
+ variable_entry *entry = new(mem_ctx) variable_entry(var);
+ this->variable_list.push_tail(entry);
+ return entry;
+}
+
+
+ir_visitor_status
+ir_structure_reference_visitor::visit(ir_variable *ir)
+{
+ variable_entry *entry = this->get_variable_entry(ir);
+
+ if (entry)
+ entry->declaration = true;
+
+ return visit_continue;
+}
+
+ir_visitor_status
+ir_structure_reference_visitor::visit(ir_dereference_variable *ir)
+{
+ ir_variable *const var = ir->variable_referenced();
+ variable_entry *entry = this->get_variable_entry(var);
+
+ if (entry)
+ entry->whole_structure_access++;
+
+ return visit_continue;
+}
+
+ir_visitor_status
+ir_structure_reference_visitor::visit_enter(ir_dereference_record *ir)
+{
+ /* Don't descend into the ir_dereference_variable below. */
+ return visit_continue_with_parent;
+}
+
+ir_visitor_status
+ir_structure_reference_visitor::visit_enter(ir_assignment *ir)
+{
+ if (ir->lhs->as_dereference_variable() &&
+ ir->rhs->as_dereference_variable() &&
+ !ir->condition) {
+ /* We'll split copies of a structure to copies of components, so don't
+ * descend to the ir_dereference_variables.
+ */
+ return visit_continue_with_parent;
+ }
+ return visit_continue;
+}
+
+ir_visitor_status
+ir_structure_reference_visitor::visit_enter(ir_function_signature *ir)
+{
+ /* We don't want to descend into the function parameters and
+ * dead-code eliminate them, so just accept the body here.
+ */
+ visit_list_elements(this, &ir->body);
+ return visit_continue_with_parent;
+}
+
+class ir_structure_splitting_visitor : public ir_rvalue_visitor {
+public:
+ ir_structure_splitting_visitor(exec_list *vars)
+ {
+ this->variable_list = vars;
+ }
+
+ virtual ~ir_structure_splitting_visitor()
+ {
+ }
+
+ virtual ir_visitor_status visit_leave(ir_assignment *);
+
+ void split_deref(ir_dereference **deref);
+ void handle_rvalue(ir_rvalue **rvalue);
+ struct variable_entry *get_splitting_entry(ir_variable *var);
+
+ exec_list *variable_list;
+ void *mem_ctx;
+};
+
+struct variable_entry *
+ir_structure_splitting_visitor::get_splitting_entry(ir_variable *var)
+{
+ assert(var);
+
+ if (!var->type->is_record())
+ return NULL;
+
+ foreach_iter(exec_list_iterator, iter, *this->variable_list) {
+ variable_entry *entry = (variable_entry *)iter.get();
+ if (entry->var == var) {
+ return entry;
+ }
+ }
+
+ return NULL;
+}
+
+void
+ir_structure_splitting_visitor::split_deref(ir_dereference **deref)
+{
+ if ((*deref)->ir_type != ir_type_dereference_record)
+ return;
+
+ ir_dereference_record *deref_record = (ir_dereference_record *)*deref;
+ ir_dereference_variable *deref_var = deref_record->record->as_dereference_variable();
+ if (!deref_var)
+ return;
+
+ variable_entry *entry = get_splitting_entry(deref_var->var);
+ if (!entry)
+ return;
+
+ unsigned int i;
+ for (i = 0; i < entry->var->type->length; i++) {
+ if (strcmp(deref_record->field,
+ entry->var->type->fields.structure[i].name) == 0)
+ break;
+ }
+ assert(i != entry->var->type->length);
+
+ *deref = new(entry->mem_ctx) ir_dereference_variable(entry->components[i]);
+}
+
+void
+ir_structure_splitting_visitor::handle_rvalue(ir_rvalue **rvalue)
+{
+ if (!*rvalue)
+ return;
+
+ ir_dereference *deref = (*rvalue)->as_dereference();
+
+ if (!deref)
+ return;
+
+ split_deref(&deref);
+ *rvalue = deref;
+}
+
+ir_visitor_status
+ir_structure_splitting_visitor::visit_leave(ir_assignment *ir)
+{
+ ir_dereference_variable *lhs_deref = ir->lhs->as_dereference_variable();
+ ir_dereference_variable *rhs_deref = ir->rhs->as_dereference_variable();
+ variable_entry *lhs_entry = lhs_deref ? get_splitting_entry(lhs_deref->var) : NULL;
+ variable_entry *rhs_entry = rhs_deref ? get_splitting_entry(rhs_deref->var) : NULL;
+ const glsl_type *type = ir->rhs->type;
+
+ if ((lhs_entry || rhs_entry) && !ir->condition) {
+ for (unsigned int i = 0; i < type->length; i++) {
+ ir_dereference *new_lhs, *new_rhs;
+ void *mem_ctx = lhs_entry ? lhs_entry->mem_ctx : rhs_entry->mem_ctx;
+
+ if (lhs_entry) {
+ new_lhs = new(mem_ctx) ir_dereference_variable(lhs_entry->components[i]);
+ } else {
+ new_lhs = new(mem_ctx)
+ ir_dereference_record(ir->lhs->clone(mem_ctx, NULL),
+ type->fields.structure[i].name);
+ }
+
+ if (rhs_entry) {
+ new_rhs = new(mem_ctx) ir_dereference_variable(rhs_entry->components[i]);
+ } else {
+ new_rhs = new(mem_ctx)
+ ir_dereference_record(ir->rhs->clone(mem_ctx, NULL),
+ type->fields.structure[i].name);
+ }
+
+ ir->insert_before(new(mem_ctx) ir_assignment(new_lhs,
+ new_rhs,
+ NULL));
+ }
+ ir->remove();
+ } else {
+ handle_rvalue(&ir->rhs);
+ split_deref(&ir->lhs);
+ }
+
+ handle_rvalue(&ir->condition);
+
+ return visit_continue;
+}
+
+bool
+do_structure_splitting(exec_list *instructions)
+{
+ ir_structure_reference_visitor refs;
+
+ visit_list_elements(&refs, instructions);
+
+ /* Trim out variables we can't split. */
+ foreach_iter(exec_list_iterator, iter, refs.variable_list) {
+ variable_entry *entry = (variable_entry *)iter.get();
+
+ if (debug) {
+ printf("structure %s@%p: decl %d, whole_access %d\n",
+ entry->var->name, (void *) entry->var, entry->declaration,
+ entry->whole_structure_access);
+ }
+
+ if (!entry->declaration || entry->whole_structure_access) {
+ entry->remove();
+ }
+ }
+
+ if (refs.variable_list.is_empty())
+ return false;
+
+ void *mem_ctx = talloc_new(NULL);
+
+ /* Replace the decls of the structures to be split with their split
+ * components.
+ */
+ foreach_iter(exec_list_iterator, iter, refs.variable_list) {
+ variable_entry *entry = (variable_entry *)iter.get();
+ const struct glsl_type *type = entry->var->type;
+
+ entry->mem_ctx = talloc_parent(entry->var);
+
+ entry->components = talloc_array(mem_ctx,
+ ir_variable *,
+ type->length);
+
+ for (unsigned int i = 0; i < entry->var->type->length; i++) {
+ const char *name = talloc_asprintf(mem_ctx, "%s_%s",
+ entry->var->name,
+ type->fields.structure[i].name);
+
+ entry->components[i] =
+ new(entry->mem_ctx) ir_variable(type->fields.structure[i].type,
+ name,
+ ir_var_temporary);
+ entry->var->insert_before(entry->components[i]);
+ }
+
+ entry->var->remove();
+ }
+
+ ir_structure_splitting_visitor split(&refs.variable_list);
+ visit_list_elements(&split, instructions);
+
+ talloc_free(mem_ctx);
+
+ return true;
+}
diff --git a/src/glsl/ir_sub_to_add_neg.cpp b/src/glsl/ir_sub_to_add_neg.cpp
new file mode 100644
index 00000000000..7ed8c1495e3
--- /dev/null
+++ b/src/glsl/ir_sub_to_add_neg.cpp
@@ -0,0 +1,76 @@
+/*
+ * Copyright © 2010 Intel Corporation
+ *
+ * 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 (including the next
+ * paragraph) 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
+ * THE AUTHORS OR COPYRIGHT HOLDERS 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 ir_sub_to_add_neg.cpp
+ *
+ * Breaks an ir_binop_sub expression down to add(op0, neg(op1))
+ *
+ * This simplifies expression reassociation, and for many backends
+ * there is no subtract operation separate from adding the negation.
+ * For backends with native subtract operations, they will probably
+ * want to recognize add(op0, neg(op1)) or the other way around to
+ * produce a subtract anyway.
+ */
+
+#include "ir.h"
+
+class ir_sub_to_add_neg_visitor : public ir_hierarchical_visitor {
+public:
+ ir_sub_to_add_neg_visitor()
+ {
+ this->progress = false;
+ }
+
+ ir_visitor_status visit_leave(ir_expression *);
+
+ bool progress;
+};
+
+bool
+do_sub_to_add_neg(exec_list *instructions)
+{
+ ir_sub_to_add_neg_visitor v;
+
+ visit_list_elements(&v, instructions);
+ return v.progress;
+}
+
+ir_visitor_status
+ir_sub_to_add_neg_visitor::visit_leave(ir_expression *ir)
+{
+ if (ir->operation != ir_binop_sub)
+ return visit_continue;
+
+ void *mem_ctx = talloc_parent(ir);
+
+ ir->operation = ir_binop_add;
+ ir->operands[1] = new(mem_ctx) ir_expression(ir_unop_neg,
+ ir->operands[1]->type,
+ ir->operands[1],
+ NULL);
+
+ this->progress = true;
+
+ return visit_continue;
+}
diff --git a/src/glsl/ir_swizzle_swizzle.cpp b/src/glsl/ir_swizzle_swizzle.cpp
new file mode 100644
index 00000000000..0ffb4fa3133
--- /dev/null
+++ b/src/glsl/ir_swizzle_swizzle.cpp
@@ -0,0 +1,93 @@
+/*
+ * Copyright © 2010 Intel Corporation
+ *
+ * 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 (including the next
+ * paragraph) 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
+ * THE AUTHORS OR COPYRIGHT HOLDERS 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 ir_swizzle_swizzle.cpp
+ *
+ * Eliminates the second swizzle in a swizzle chain.
+ */
+
+#include "ir.h"
+#include "ir_visitor.h"
+#include "ir_optimization.h"
+#include "glsl_types.h"
+
+class ir_swizzle_swizzle_visitor : public ir_hierarchical_visitor {
+public:
+ ir_swizzle_swizzle_visitor()
+ {
+ progress = false;
+ }
+
+ virtual ir_visitor_status visit_enter(ir_swizzle *);
+
+ bool progress;
+};
+
+ir_visitor_status
+ir_swizzle_swizzle_visitor::visit_enter(ir_swizzle *ir)
+{
+ int mask2[4];
+
+ ir_swizzle *swiz2 = ir->val->as_swizzle();
+ if (!swiz2)
+ return visit_continue;
+
+ memset(&mask2, 0, sizeof(mask2));
+ if (swiz2->mask.num_components >= 1)
+ mask2[0] = swiz2->mask.x;
+ if (swiz2->mask.num_components >= 2)
+ mask2[1] = swiz2->mask.y;
+ if (swiz2->mask.num_components >= 3)
+ mask2[2] = swiz2->mask.z;
+ if (swiz2->mask.num_components >= 4)
+ mask2[3] = swiz2->mask.w;
+
+ if (ir->mask.num_components >= 1)
+ ir->mask.x = mask2[ir->mask.x];
+ if (ir->mask.num_components >= 2)
+ ir->mask.y = mask2[ir->mask.y];
+ if (ir->mask.num_components >= 3)
+ ir->mask.z = mask2[ir->mask.z];
+ if (ir->mask.num_components >= 4)
+ ir->mask.w = mask2[ir->mask.w];
+
+ ir->val = swiz2->val;
+
+ this->progress = true;
+
+ return visit_continue;
+}
+
+/**
+ * Does a copy propagation pass on the code present in the instruction stream.
+ */
+bool
+do_swizzle_swizzle(exec_list *instructions)
+{
+ ir_swizzle_swizzle_visitor v;
+
+ v.run(instructions);
+
+ return v.progress;
+}
diff --git a/src/glsl/ir_tree_grafting.cpp b/src/glsl/ir_tree_grafting.cpp
new file mode 100644
index 00000000000..e80db31cb30
--- /dev/null
+++ b/src/glsl/ir_tree_grafting.cpp
@@ -0,0 +1,361 @@
+/*
+ * Copyright © 2010 Intel Corporation
+ *
+ * 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 (including the next
+ * paragraph) 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
+ * THE AUTHORS OR COPYRIGHT HOLDERS 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 ir_tree_grafting.cpp
+ *
+ * Takes assignments to variables that are dereferenced only once and
+ * pastes the RHS expression into where the variable is dereferenced.
+ *
+ * In the process of various operations like function inlining and
+ * tertiary op handling, we'll end up with our expression trees having
+ * been chopped up into a series of assignments of short expressions
+ * to temps. Other passes like ir_algebraic.cpp would prefer to see
+ * the deepest expression trees they can to try to optimize them.
+ *
+ * This is a lot like copy propagaton. In comparison, copy
+ * propagation only acts on plain copies, not arbitrary expressions on
+ * the RHS. Generally, we wouldn't want to go pasting some
+ * complicated expression everywhere it got used, though, so we don't
+ * handle expressions in that pass.
+ *
+ * The hard part is making sure we don't move an expression across
+ * some other assignments that would change the value of the
+ * expression. So we split this into two passes: First, find the
+ * variables in our scope which are written to once and read once, and
+ * then go through basic blocks seeing if we find an opportunity to
+ * move those expressions safely.
+ */
+
+#include "ir.h"
+#include "ir_visitor.h"
+#include "ir_variable_refcount.h"
+#include "ir_basic_block.h"
+#include "ir_optimization.h"
+#include "glsl_types.h"
+
+static bool debug = false;
+
+class ir_tree_grafting_visitor : public ir_hierarchical_visitor {
+public:
+ ir_tree_grafting_visitor(ir_assignment *graft_assign,
+ ir_variable *graft_var)
+ {
+ this->progress = false;
+ this->graft_assign = graft_assign;
+ this->graft_var = graft_var;
+ }
+
+ virtual ir_visitor_status visit_leave(class ir_assignment *);
+ virtual ir_visitor_status visit_enter(class ir_call *);
+ virtual ir_visitor_status visit_enter(class ir_expression *);
+ virtual ir_visitor_status visit_enter(class ir_function *);
+ virtual ir_visitor_status visit_enter(class ir_function_signature *);
+ virtual ir_visitor_status visit_enter(class ir_if *);
+ virtual ir_visitor_status visit_enter(class ir_loop *);
+ virtual ir_visitor_status visit_enter(class ir_swizzle *);
+ virtual ir_visitor_status visit_enter(class ir_texture *);
+
+ bool do_graft(ir_rvalue **rvalue);
+
+ bool progress;
+ ir_variable *graft_var;
+ ir_assignment *graft_assign;
+};
+
+struct find_deref_info {
+ ir_variable *var;
+ bool found;
+};
+
+void
+dereferences_variable_callback(ir_instruction *ir, void *data)
+{
+ struct find_deref_info *info = (struct find_deref_info *)data;
+ ir_dereference_variable *deref = ir->as_dereference_variable();
+
+ if (deref && deref->var == info->var)
+ info->found = true;
+}
+
+static bool
+dereferences_variable(ir_instruction *ir, ir_variable *var)
+{
+ struct find_deref_info info;
+
+ info.var = var;
+ info.found = false;
+
+ visit_tree(ir, dereferences_variable_callback, &info);
+
+ return info.found;
+}
+
+bool
+ir_tree_grafting_visitor::do_graft(ir_rvalue **rvalue)
+{
+ if (!*rvalue)
+ return false;
+
+ ir_dereference_variable *deref = (*rvalue)->as_dereference_variable();
+
+ if (!deref || deref->var != this->graft_var)
+ return false;
+
+ if (debug) {
+ printf("GRAFTING:\n");
+ this->graft_assign->print();
+ printf("\n");
+ printf("TO:\n");
+ (*rvalue)->print();
+ printf("\n");
+ }
+
+ this->graft_assign->remove();
+ *rvalue = this->graft_assign->rhs;
+
+ this->progress = true;
+ return true;
+}
+
+ir_visitor_status
+ir_tree_grafting_visitor::visit_enter(ir_loop *ir)
+{
+ (void)ir;
+ /* Do not traverse into the body of the loop since that is a
+ * different basic block.
+ */
+ return visit_stop;
+}
+
+ir_visitor_status
+ir_tree_grafting_visitor::visit_leave(ir_assignment *ir)
+{
+ if (do_graft(&ir->rhs) ||
+ do_graft(&ir->condition))
+ return visit_stop;
+
+ /* If this assignment updates a variable used in the assignment
+ * we're trying to graft, then we're done.
+ */
+ if (dereferences_variable(this->graft_assign->rhs,
+ ir->lhs->variable_referenced())) {
+ if (debug) {
+ printf("graft killed by: ");
+ ir->print();
+ printf("\n");
+ }
+ return visit_stop;
+ }
+
+ return visit_continue;
+}
+
+ir_visitor_status
+ir_tree_grafting_visitor::visit_enter(ir_function *ir)
+{
+ (void) ir;
+ return visit_continue_with_parent;
+}
+
+ir_visitor_status
+ir_tree_grafting_visitor::visit_enter(ir_function_signature *ir)
+{
+ (void)ir;
+ return visit_continue_with_parent;
+}
+
+ir_visitor_status
+ir_tree_grafting_visitor::visit_enter(ir_call *ir)
+{
+ /* Reminder: iterating ir_call iterates its parameters. */
+ foreach_iter(exec_list_iterator, iter, *ir) {
+ ir_rvalue *ir = (ir_rvalue *)iter.get();
+ ir_rvalue *new_ir = ir;
+
+ if (do_graft(&new_ir)) {
+ ir->replace_with(new_ir);
+ return visit_stop;
+ }
+ }
+
+ return visit_continue;
+}
+
+ir_visitor_status
+ir_tree_grafting_visitor::visit_enter(ir_expression *ir)
+{
+ for (unsigned int i = 0; i < ir->get_num_operands(); i++) {
+ if (do_graft(&ir->operands[i]))
+ return visit_stop;
+ }
+
+ return visit_continue;
+}
+
+ir_visitor_status
+ir_tree_grafting_visitor::visit_enter(ir_if *ir)
+{
+ if (do_graft(&ir->condition))
+ return visit_stop;
+
+ /* Do not traverse into the body of the if-statement since that is a
+ * different basic block.
+ */
+ return visit_continue_with_parent;
+}
+
+ir_visitor_status
+ir_tree_grafting_visitor::visit_enter(ir_swizzle *ir)
+{
+ if (do_graft(&ir->val))
+ return visit_stop;
+
+ return visit_continue;
+}
+
+ir_visitor_status
+ir_tree_grafting_visitor::visit_enter(ir_texture *ir)
+{
+ if (do_graft(&ir->coordinate) ||
+ do_graft(&ir->projector) ||
+ do_graft(&ir->shadow_comparitor))
+ return visit_stop;
+
+ switch (ir->op) {
+ case ir_tex:
+ break;
+ case ir_txb:
+ if (do_graft(&ir->lod_info.bias))
+ return visit_stop;
+ break;
+ case ir_txf:
+ case ir_txl:
+ if (do_graft(&ir->lod_info.lod))
+ return visit_stop;
+ break;
+ case ir_txd:
+ if (do_graft(&ir->lod_info.grad.dPdx) ||
+ do_graft(&ir->lod_info.grad.dPdy))
+ return visit_stop;
+ break;
+ }
+
+ return visit_continue;
+}
+
+struct tree_grafting_info {
+ ir_variable_refcount_visitor *refs;
+ bool progress;
+};
+
+static bool
+try_tree_grafting(ir_assignment *start,
+ ir_variable *lhs_var,
+ ir_instruction *bb_last)
+{
+ ir_tree_grafting_visitor v(start, lhs_var);
+
+ if (debug) {
+ printf("trying to graft: ");
+ lhs_var->print();
+ printf("\n");
+ }
+
+ for (ir_instruction *ir = (ir_instruction *)start->next;
+ ir != bb_last->next;
+ ir = (ir_instruction *)ir->next) {
+
+ if (debug) {
+ printf("- ");
+ ir->print();
+ printf("\n");
+ }
+
+ ir_visitor_status s = ir->accept(&v);
+ if (s == visit_stop)
+ return v.progress;
+ }
+
+ return false;
+}
+
+static void
+tree_grafting_basic_block(ir_instruction *bb_first,
+ ir_instruction *bb_last,
+ void *data)
+{
+ struct tree_grafting_info *info = (struct tree_grafting_info *)data;
+ ir_instruction *ir, *next;
+
+ for (ir = bb_first, next = (ir_instruction *)ir->next;
+ ir != bb_last->next;
+ ir = next, next = (ir_instruction *)ir->next) {
+ ir_assignment *assign = ir->as_assignment();
+
+ if (!assign)
+ continue;
+
+ ir_variable *lhs_var = assign->whole_variable_written();
+ if (!lhs_var)
+ continue;
+
+ if (lhs_var->mode == ir_var_out ||
+ lhs_var->mode == ir_var_inout)
+ continue;
+
+ struct variable_entry *entry = info->refs->get_variable_entry(lhs_var);
+
+ if (!entry->declaration ||
+ entry->assigned_count != 1 ||
+ entry->referenced_count != 2)
+ continue;
+
+ assert(assign == entry->assign);
+
+ /* Found a possibly graftable assignment. Now, walk through the
+ * rest of the BB seeing if the deref is here, and if nothing interfered with
+ * pasting its expression's values in between.
+ */
+ info->progress |= try_tree_grafting(assign, lhs_var, bb_last);
+ }
+}
+
+/**
+ * Does a copy propagation pass on the code present in the instruction stream.
+ */
+bool
+do_tree_grafting(exec_list *instructions)
+{
+ ir_variable_refcount_visitor refs;
+ struct tree_grafting_info info;
+
+ info.progress = false;
+ info.refs = &refs;
+
+ visit_list_elements(info.refs, instructions);
+
+ call_for_basic_blocks(instructions, tree_grafting_basic_block, &info);
+
+ return info.progress;
+}
diff --git a/src/glsl/ir_validate.cpp b/src/glsl/ir_validate.cpp
new file mode 100644
index 00000000000..905b3c76721
--- /dev/null
+++ b/src/glsl/ir_validate.cpp
@@ -0,0 +1,397 @@
+/*
+ * Copyright © 2010 Intel Corporation
+ *
+ * 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 (including the next
+ * paragraph) 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
+ * THE AUTHORS OR COPYRIGHT HOLDERS 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 ir_validate.cpp
+ *
+ * Attempts to verify that various invariants of the IR tree are true.
+ *
+ * In particular, at the moment it makes sure that no single
+ * ir_instruction node except for ir_variable appears multiple times
+ * in the ir tree. ir_variable does appear multiple times: Once as a
+ * declaration in an exec_list, and multiple times as the endpoint of
+ * a dereference chain.
+ */
+
+#include <stdint.h>
+#include "ir.h"
+#include "ir_hierarchical_visitor.h"
+#include "program/hash_table.h"
+#include "glsl_types.h"
+
+class ir_validate : public ir_hierarchical_visitor {
+public:
+ ir_validate()
+ {
+ this->ht = hash_table_ctor(0, hash_table_pointer_hash,
+ hash_table_pointer_compare);
+
+ this->current_function = NULL;
+
+ this->callback = ir_validate::validate_ir;
+ this->data = ht;
+ }
+
+ ~ir_validate()
+ {
+ hash_table_dtor(this->ht);
+ }
+
+ virtual ir_visitor_status visit(ir_variable *v);
+ virtual ir_visitor_status visit(ir_dereference_variable *ir);
+ virtual ir_visitor_status visit(ir_if *ir);
+
+ virtual ir_visitor_status visit_enter(ir_function *ir);
+ virtual ir_visitor_status visit_leave(ir_function *ir);
+ virtual ir_visitor_status visit_enter(ir_function_signature *ir);
+
+ virtual ir_visitor_status visit_leave(ir_expression *ir);
+
+ virtual ir_visitor_status visit_enter(ir_assignment *ir);
+
+ static void validate_ir(ir_instruction *ir, void *data);
+
+ ir_function *current_function;
+
+ struct hash_table *ht;
+};
+
+
+ir_visitor_status
+ir_validate::visit(ir_dereference_variable *ir)
+{
+ if ((ir->var == NULL) || (ir->var->as_variable() == NULL)) {
+ printf("ir_dereference_variable @ %p does not specify a variable %p\n",
+ (void *) ir, (void *) ir->var);
+ abort();
+ }
+
+ if (hash_table_find(ht, ir->var) == NULL) {
+ printf("ir_dereference_variable @ %p specifies undeclared variable "
+ "`%s' @ %p\n",
+ (void *) ir, ir->var->name, (void *) ir->var);
+ abort();
+ }
+
+ this->validate_ir(ir, this->data);
+
+ return visit_continue;
+}
+
+ir_visitor_status
+ir_validate::visit(ir_if *ir)
+{
+ if (ir->condition->type != glsl_type::bool_type) {
+ printf("ir_if condition %s type instead of bool.\n",
+ ir->condition->type->name);
+ ir->print();
+ printf("\n");
+ abort();
+ }
+
+ return visit_continue;
+}
+
+
+ir_visitor_status
+ir_validate::visit_enter(ir_function *ir)
+{
+ /* Function definitions cannot be nested.
+ */
+ if (this->current_function != NULL) {
+ printf("Function definition nested inside another function "
+ "definition:\n");
+ printf("%s %p inside %s %p\n",
+ ir->name, (void *) ir,
+ this->current_function->name, (void *) this->current_function);
+ abort();
+ }
+
+ /* Store the current function hierarchy being traversed. This is used
+ * by the function signature visitor to ensure that the signatures are
+ * linked with the correct functions.
+ */
+ this->current_function = ir;
+
+ this->validate_ir(ir, this->data);
+
+ return visit_continue;
+}
+
+ir_visitor_status
+ir_validate::visit_leave(ir_function *ir)
+{
+ assert(talloc_parent(ir->name) == ir);
+
+ this->current_function = NULL;
+ return visit_continue;
+}
+
+ir_visitor_status
+ir_validate::visit_enter(ir_function_signature *ir)
+{
+ if (this->current_function != ir->function()) {
+ printf("Function signature nested inside wrong function "
+ "definition:\n");
+ printf("%p inside %s %p instead of %s %p\n",
+ (void *) ir,
+ this->current_function->name, (void *) this->current_function,
+ ir->function_name(), (void *) ir->function());
+ abort();
+ }
+
+ this->validate_ir(ir, this->data);
+
+ return visit_continue;
+}
+
+ir_visitor_status
+ir_validate::visit_leave(ir_expression *ir)
+{
+ switch (ir->operation) {
+ case ir_unop_bit_not:
+ assert(ir->operands[0]->type == ir->type);
+ break;
+ case ir_unop_logic_not:
+ assert(ir->type->base_type == GLSL_TYPE_BOOL);
+ assert(ir->operands[0]->type->base_type == GLSL_TYPE_BOOL);
+ break;
+
+ case ir_unop_neg:
+ case ir_unop_abs:
+ case ir_unop_sign:
+ case ir_unop_rcp:
+ case ir_unop_rsq:
+ case ir_unop_sqrt:
+ assert(ir->type == ir->operands[0]->type);
+ break;
+
+ case ir_unop_exp:
+ case ir_unop_log:
+ case ir_unop_exp2:
+ case ir_unop_log2:
+ assert(ir->operands[0]->type->base_type == GLSL_TYPE_FLOAT);
+ assert(ir->type == ir->operands[0]->type);
+ break;
+
+ case ir_unop_f2i:
+ assert(ir->operands[0]->type->base_type == GLSL_TYPE_FLOAT);
+ assert(ir->type->base_type == GLSL_TYPE_INT);
+ break;
+ case ir_unop_i2f:
+ assert(ir->operands[0]->type->base_type == GLSL_TYPE_INT);
+ assert(ir->type->base_type == GLSL_TYPE_FLOAT);
+ break;
+ case ir_unop_f2b:
+ assert(ir->operands[0]->type->base_type == GLSL_TYPE_FLOAT);
+ assert(ir->type->base_type == GLSL_TYPE_BOOL);
+ break;
+ case ir_unop_b2f:
+ assert(ir->operands[0]->type->base_type == GLSL_TYPE_BOOL);
+ assert(ir->type->base_type == GLSL_TYPE_FLOAT);
+ break;
+ case ir_unop_i2b:
+ assert(ir->operands[0]->type->base_type == GLSL_TYPE_INT);
+ assert(ir->type->base_type == GLSL_TYPE_BOOL);
+ break;
+ case ir_unop_b2i:
+ assert(ir->operands[0]->type->base_type == GLSL_TYPE_BOOL);
+ assert(ir->type->base_type == GLSL_TYPE_INT);
+ break;
+ case ir_unop_u2f:
+ assert(ir->operands[0]->type->base_type == GLSL_TYPE_UINT);
+ assert(ir->type->base_type == GLSL_TYPE_FLOAT);
+ break;
+
+ case ir_unop_trunc:
+ case ir_unop_ceil:
+ case ir_unop_floor:
+ case ir_unop_fract:
+ case ir_unop_sin:
+ case ir_unop_cos:
+ case ir_unop_dFdx:
+ case ir_unop_dFdy:
+ assert(ir->operands[0]->type->base_type == GLSL_TYPE_FLOAT);
+ assert(ir->operands[0]->type == ir->type);
+ break;
+
+ case ir_binop_add:
+ case ir_binop_sub:
+ case ir_binop_mul:
+ case ir_binop_div:
+ case ir_binop_mod:
+ case ir_binop_min:
+ case ir_binop_max:
+ case ir_binop_pow:
+ if (ir->operands[0]->type->is_scalar())
+ assert(ir->operands[1]->type == ir->type);
+ else if (ir->operands[1]->type->is_scalar())
+ assert(ir->operands[0]->type == ir->type);
+ else if (ir->operands[0]->type->is_vector() &&
+ ir->operands[1]->type->is_vector()) {
+ assert(ir->operands[0]->type == ir->operands[1]->type);
+ assert(ir->operands[0]->type == ir->type);
+ }
+ break;
+ case ir_binop_less:
+ case ir_binop_greater:
+ case ir_binop_lequal:
+ case ir_binop_gequal:
+ /* GLSL < > <= >= operators take scalar floats/ints, but in the
+ * IR we may want to do them for vectors instead to support the
+ * lessEqual() and friends builtins.
+ */
+ assert(ir->type == glsl_type::bool_type);
+ assert(ir->operands[0]->type == ir->operands[1]->type);
+ break;
+
+ case ir_binop_equal:
+ case ir_binop_nequal:
+ /* GLSL == and != operate on vectors and return a bool, and the
+ * IR matches that. We may want to switch up the IR to work on
+ * vectors and return a bvec and make the operators break down
+ * to ANDing/ORing the results of the vector comparison.
+ */
+ assert(ir->type == glsl_type::bool_type);
+ assert(ir->operands[0]->type == ir->operands[1]->type);
+ break;
+
+ case ir_binop_lshift:
+ case ir_binop_rshift:
+ case ir_binop_bit_and:
+ case ir_binop_bit_xor:
+ case ir_binop_bit_or:
+ assert(ir->operands[0]->type == ir->operands[1]->type);
+ assert(ir->type == ir->operands[0]->type);
+ assert(ir->type->base_type == GLSL_TYPE_INT ||
+ ir->type->base_type == GLSL_TYPE_UINT);
+ break;
+
+ case ir_binop_logic_and:
+ case ir_binop_logic_xor:
+ case ir_binop_logic_or:
+ assert(ir->type == glsl_type::bool_type);
+ assert(ir->operands[0]->type == glsl_type::bool_type);
+ assert(ir->operands[1]->type == glsl_type::bool_type);
+ break;
+
+ case ir_binop_dot:
+ assert(ir->type == glsl_type::float_type);
+ assert(ir->operands[0]->type->base_type == GLSL_TYPE_FLOAT);
+ assert(ir->operands[0]->type == ir->operands[1]->type);
+ break;
+
+ case ir_binop_cross:
+ assert(ir->operands[0]->type == glsl_type::vec3_type);
+ assert(ir->operands[1]->type == glsl_type::vec3_type);
+ assert(ir->type == glsl_type::vec3_type);
+ break;
+ }
+
+ return visit_continue;
+}
+
+ir_visitor_status
+ir_validate::visit(ir_variable *ir)
+{
+ /* An ir_variable is the one thing that can (and will) appear multiple times
+ * in an IR tree. It is added to the hashtable so that it can be used
+ * in the ir_dereference_variable handler to ensure that a variable is
+ * declared before it is dereferenced.
+ */
+ if (ir->name)
+ assert(talloc_parent(ir->name) == ir);
+
+ hash_table_insert(ht, ir, ir);
+ return visit_continue;
+}
+
+ir_visitor_status
+ir_validate::visit_enter(ir_assignment *ir)
+{
+ const ir_dereference *const lhs = ir->lhs;
+ if (lhs->type->is_scalar() || lhs->type->is_vector()) {
+ if (ir->write_mask == 0) {
+ printf("Assignment LHS is %s, but write mask is 0:\n",
+ lhs->type->is_scalar() ? "scalar" : "vector");
+ ir->print();
+ abort();
+ }
+
+ /* Mask of fields that do not exist in the destination. These should
+ * not be written by the assignment.
+ */
+ const unsigned invalid_mask = ~((1U << lhs->type->components()) - 1);
+
+ if ((invalid_mask & ir->write_mask) != 0) {
+ printf("Assignment write mask enables invalid components for "
+ "type %s:\n", lhs->type->name);
+ ir->print();
+ abort();
+ }
+ }
+
+ this->validate_ir(ir, this->data);
+
+ return visit_continue;
+}
+
+void
+ir_validate::validate_ir(ir_instruction *ir, void *data)
+{
+ struct hash_table *ht = (struct hash_table *) data;
+
+ if (hash_table_find(ht, ir)) {
+ printf("Instruction node present twice in ir tree:\n");
+ ir->print();
+ printf("\n");
+ abort();
+ }
+ hash_table_insert(ht, ir, ir);
+}
+
+void
+check_node_type(ir_instruction *ir, void *data)
+{
+ (void) data;
+
+ if (ir->ir_type <= ir_type_unset || ir->ir_type >= ir_type_max) {
+ printf("Instruction node with unset type\n");
+ ir->print(); printf("\n");
+ }
+ assert(ir->type != glsl_type::error_type);
+}
+
+void
+validate_ir_tree(exec_list *instructions)
+{
+ ir_validate v;
+
+ v.run(instructions);
+
+ foreach_iter(exec_list_iterator, iter, *instructions) {
+ ir_instruction *ir = (ir_instruction *)iter.get();
+
+ visit_tree(ir, check_node_type, NULL);
+ }
+}
diff --git a/src/glsl/ir_variable.cpp b/src/glsl/ir_variable.cpp
new file mode 100644
index 00000000000..917c06743b4
--- /dev/null
+++ b/src/glsl/ir_variable.cpp
@@ -0,0 +1,416 @@
+/*
+ * Copyright © 2010 Intel Corporation
+ *
+ * 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 (including the next
+ * paragraph) 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
+ * THE AUTHORS OR COPYRIGHT HOLDERS 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.
+ */
+
+#include "main/compiler.h"
+#include "ir.h"
+#include "glsl_parser_extras.h"
+#include "glsl_symbol_table.h"
+#include "builtin_variables.h"
+
+static void generate_ARB_draw_buffers_variables(exec_list *,
+ struct _mesa_glsl_parse_state *,
+ bool, _mesa_glsl_parser_targets);
+
+static ir_variable *
+add_variable(const char *name, enum ir_variable_mode mode, int slot,
+ const glsl_type *type, exec_list *instructions,
+ glsl_symbol_table *symtab)
+{
+ ir_variable *var = new(symtab) ir_variable(type, name, mode);
+
+ switch (var->mode) {
+ case ir_var_auto:
+ case ir_var_in:
+ case ir_var_uniform:
+ var->read_only = true;
+ break;
+ case ir_var_inout:
+ case ir_var_out:
+ break;
+ default:
+ assert(0);
+ break;
+ }
+
+ var->location = slot;
+
+ /* Once the variable is created an initialized, add it to the symbol table
+ * and add the declaration to the IR stream.
+ */
+ instructions->push_tail(var);
+
+ symtab->add_variable(var->name, var);
+ return var;
+}
+
+static ir_variable *
+add_uniform(exec_list *instructions,
+ struct _mesa_glsl_parse_state *state,
+ const char *name, const glsl_type *type)
+{
+ return add_variable(name, ir_var_uniform, -1, type, instructions,
+ state->symbols);
+}
+
+static void
+add_builtin_variable(const builtin_variable *proto, exec_list *instructions,
+ glsl_symbol_table *symtab)
+{
+ /* Create a new variable declaration from the description supplied by
+ * the caller.
+ */
+ const glsl_type *const type = symtab->get_type(proto->type);
+
+ assert(type != NULL);
+
+ add_variable(proto->name, proto->mode, proto->slot, type, instructions,
+ symtab);
+}
+
+static void
+add_builtin_constant(exec_list *instructions,
+ struct _mesa_glsl_parse_state *state,
+ const char *name, int value)
+{
+ ir_variable *const var = add_variable(name, ir_var_auto,
+ -1, glsl_type::int_type,
+ instructions, state->symbols);
+ var->constant_value = new(var) ir_constant(value);
+}
+
+static void
+generate_110_uniforms(exec_list *instructions,
+ struct _mesa_glsl_parse_state *state)
+{
+ for (unsigned i = 0
+ ; i < Elements(builtin_110_deprecated_uniforms)
+ ; i++) {
+ add_builtin_variable(& builtin_110_deprecated_uniforms[i],
+ instructions, state->symbols);
+ }
+
+ add_builtin_constant(instructions, state, "gl_MaxLights",
+ state->Const.MaxLights);
+ add_builtin_constant(instructions, state, "gl_MaxClipPlanes",
+ state->Const.MaxClipPlanes);
+ add_builtin_constant(instructions, state, "gl_MaxTextureUnits",
+ state->Const.MaxTextureUnits);
+ add_builtin_constant(instructions, state, "gl_MaxTextureCoords",
+ state->Const.MaxTextureCoords);
+ add_builtin_constant(instructions, state, "gl_MaxVertexAttribs",
+ state->Const.MaxVertexAttribs);
+ add_builtin_constant(instructions, state, "gl_MaxVertexUniformComponents",
+ state->Const.MaxVertexUniformComponents);
+ add_builtin_constant(instructions, state, "gl_MaxVaryingFloats",
+ state->Const.MaxVaryingFloats);
+ add_builtin_constant(instructions, state, "gl_MaxVertexTextureImageUnits",
+ state->Const.MaxVertexTextureImageUnits);
+ add_builtin_constant(instructions, state, "gl_MaxCombinedTextureImageUnits",
+ state->Const.MaxCombinedTextureImageUnits);
+ add_builtin_constant(instructions, state, "gl_MaxTextureImageUnits",
+ state->Const.MaxTextureImageUnits);
+ add_builtin_constant(instructions, state, "gl_MaxFragmentUniformComponents",
+ state->Const.MaxFragmentUniformComponents);
+
+ const glsl_type *const mat4_array_type =
+ glsl_type::get_array_instance(glsl_type::mat4_type,
+ state->Const.MaxTextureCoords);
+
+ add_uniform(instructions, state, "gl_TextureMatrix", mat4_array_type);
+
+ add_uniform(instructions, state, "gl_DepthRange",
+ state->symbols->get_type("gl_DepthRangeParameters"));
+
+ add_uniform(instructions, state, "gl_ClipPlane",
+ glsl_type::get_array_instance(glsl_type::vec4_type,
+ state->Const.MaxClipPlanes));
+ add_uniform(instructions, state, "gl_Point",
+ state->symbols->get_type("gl_PointParameters"));
+
+ const glsl_type *const material_parameters_type =
+ state->symbols->get_type("gl_MaterialParameters");
+ add_uniform(instructions, state, "gl_FrontMaterial", material_parameters_type);
+ add_uniform(instructions, state, "gl_BackMaterial", material_parameters_type);
+
+ const glsl_type *const light_source_array_type =
+ glsl_type::get_array_instance(state->symbols->get_type("gl_LightSourceParameters"), state->Const.MaxLights);
+
+ add_uniform(instructions, state, "gl_LightSource", light_source_array_type);
+
+ const glsl_type *const light_model_products_type =
+ state->symbols->get_type("gl_LightModelProducts");
+ add_uniform(instructions, state, "gl_FrontLightModelProduct",
+ light_model_products_type);
+ add_uniform(instructions, state, "gl_BackLightModelProduct",
+ light_model_products_type);
+
+ const glsl_type *const light_products_type =
+ glsl_type::get_array_instance(state->symbols->get_type("gl_LightProducts"),
+ state->Const.MaxLights);
+ add_uniform(instructions, state, "gl_FrontLightProduct", light_products_type);
+ add_uniform(instructions, state, "gl_BackLightProduct", light_products_type);
+
+ add_uniform(instructions, state, "gl_TextureEnvColor",
+ glsl_type::get_array_instance(glsl_type::vec4_type,
+ state->Const.MaxTextureUnits));
+
+ const glsl_type *const texcoords_vec4 =
+ glsl_type::get_array_instance(glsl_type::vec4_type,
+ state->Const.MaxTextureCoords);
+ add_uniform(instructions, state, "gl_EyePlaneS", texcoords_vec4);
+ add_uniform(instructions, state, "gl_EyePlaneT", texcoords_vec4);
+ add_uniform(instructions, state, "gl_EyePlaneR", texcoords_vec4);
+ add_uniform(instructions, state, "gl_EyePlaneQ", texcoords_vec4);
+ add_uniform(instructions, state, "gl_ObjectPlaneS", texcoords_vec4);
+ add_uniform(instructions, state, "gl_ObjectPlaneT", texcoords_vec4);
+ add_uniform(instructions, state, "gl_ObjectPlaneR", texcoords_vec4);
+ add_uniform(instructions, state, "gl_ObjectPlaneQ", texcoords_vec4);
+
+ add_uniform(instructions, state, "gl_Fog",
+ state->symbols->get_type("gl_FogParameters"));
+}
+
+static void
+generate_110_vs_variables(exec_list *instructions,
+ struct _mesa_glsl_parse_state *state)
+{
+ for (unsigned i = 0; i < Elements(builtin_core_vs_variables); i++) {
+ add_builtin_variable(& builtin_core_vs_variables[i],
+ instructions, state->symbols);
+ }
+
+ for (unsigned i = 0
+ ; i < Elements(builtin_110_deprecated_vs_variables)
+ ; i++) {
+ add_builtin_variable(& builtin_110_deprecated_vs_variables[i],
+ instructions, state->symbols);
+ }
+ generate_110_uniforms(instructions, state);
+
+ /* From page 54 (page 60 of the PDF) of the GLSL 1.20 spec:
+ *
+ * "As with all arrays, indices used to subscript gl_TexCoord must
+ * either be an integral constant expressions, or this array must be
+ * re-declared by the shader with a size. The size can be at most
+ * gl_MaxTextureCoords. Using indexes close to 0 may aid the
+ * implementation in preserving varying resources."
+ */
+ const glsl_type *const vec4_array_type =
+ glsl_type::get_array_instance(glsl_type::vec4_type, 0);
+
+ add_variable("gl_TexCoord", ir_var_out, VERT_RESULT_TEX0, vec4_array_type,
+ instructions, state->symbols);
+
+ generate_ARB_draw_buffers_variables(instructions, state, false,
+ vertex_shader);
+}
+
+
+static void
+generate_120_vs_variables(exec_list *instructions,
+ struct _mesa_glsl_parse_state *state)
+{
+ /* GLSL version 1.20 did not add any built-in variables in the vertex
+ * shader.
+ */
+ generate_110_vs_variables(instructions, state);
+}
+
+
+static void
+generate_130_vs_variables(exec_list *instructions,
+ struct _mesa_glsl_parse_state *state)
+{
+ generate_120_vs_variables(instructions, state);
+
+ for (unsigned i = 0; i < Elements(builtin_130_vs_variables); i++) {
+ add_builtin_variable(& builtin_130_vs_variables[i],
+ instructions, state->symbols);
+ }
+
+ const glsl_type *const clip_distance_array_type =
+ glsl_type::get_array_instance(glsl_type::float_type,
+ state->Const.MaxClipPlanes);
+
+ /* FINISHME: gl_ClipDistance needs a real location assigned. */
+ add_variable("gl_ClipDistance", ir_var_out, -1, clip_distance_array_type,
+ instructions, state->symbols);
+
+}
+
+
+static void
+initialize_vs_variables(exec_list *instructions,
+ struct _mesa_glsl_parse_state *state)
+{
+
+ switch (state->language_version) {
+ case 110:
+ generate_110_vs_variables(instructions, state);
+ break;
+ case 120:
+ generate_120_vs_variables(instructions, state);
+ break;
+ case 130:
+ generate_130_vs_variables(instructions, state);
+ break;
+ }
+}
+
+static void
+generate_110_fs_variables(exec_list *instructions,
+ struct _mesa_glsl_parse_state *state)
+{
+ for (unsigned i = 0; i < Elements(builtin_core_fs_variables); i++) {
+ add_builtin_variable(& builtin_core_fs_variables[i],
+ instructions, state->symbols);
+ }
+
+ for (unsigned i = 0
+ ; i < Elements(builtin_110_deprecated_fs_variables)
+ ; i++) {
+ add_builtin_variable(& builtin_110_deprecated_fs_variables[i],
+ instructions, state->symbols);
+ }
+ generate_110_uniforms(instructions, state);
+
+ /* From page 54 (page 60 of the PDF) of the GLSL 1.20 spec:
+ *
+ * "As with all arrays, indices used to subscript gl_TexCoord must
+ * either be an integral constant expressions, or this array must be
+ * re-declared by the shader with a size. The size can be at most
+ * gl_MaxTextureCoords. Using indexes close to 0 may aid the
+ * implementation in preserving varying resources."
+ */
+ const glsl_type *const vec4_array_type =
+ glsl_type::get_array_instance(glsl_type::vec4_type, 0);
+
+ add_variable("gl_TexCoord", ir_var_in, FRAG_ATTRIB_TEX0, vec4_array_type,
+ instructions, state->symbols);
+
+ generate_ARB_draw_buffers_variables(instructions, state, false,
+ fragment_shader);
+}
+
+
+static void
+generate_ARB_draw_buffers_variables(exec_list *instructions,
+ struct _mesa_glsl_parse_state *state,
+ bool warn, _mesa_glsl_parser_targets target)
+{
+ /* gl_MaxDrawBuffers is available in all shader stages.
+ */
+ ir_variable *const mdb =
+ add_variable("gl_MaxDrawBuffers", ir_var_auto, -1,
+ glsl_type::int_type, instructions, state->symbols);
+
+ if (warn)
+ mdb->warn_extension = "GL_ARB_draw_buffers";
+
+ mdb->constant_value = new(mdb)
+ ir_constant(int(state->Const.MaxDrawBuffers));
+
+
+ /* gl_FragData is only available in the fragment shader.
+ */
+ if (target == fragment_shader) {
+ const glsl_type *const vec4_array_type =
+ glsl_type::get_array_instance(glsl_type::vec4_type,
+ state->Const.MaxDrawBuffers);
+
+ ir_variable *const fd =
+ add_variable("gl_FragData", ir_var_out, FRAG_RESULT_DATA0,
+ vec4_array_type, instructions, state->symbols);
+
+ if (warn)
+ fd->warn_extension = "GL_ARB_draw_buffers";
+ }
+}
+
+
+static void
+generate_120_fs_variables(exec_list *instructions,
+ struct _mesa_glsl_parse_state *state)
+{
+ generate_110_fs_variables(instructions, state);
+
+ for (unsigned i = 0
+ ; i < Elements(builtin_120_fs_variables)
+ ; i++) {
+ add_builtin_variable(& builtin_120_fs_variables[i],
+ instructions, state->symbols);
+ }
+}
+
+static void
+generate_130_fs_variables(exec_list *instructions,
+ struct _mesa_glsl_parse_state *state)
+{
+ generate_120_fs_variables(instructions, state);
+
+ const glsl_type *const clip_distance_array_type =
+ glsl_type::get_array_instance(glsl_type::float_type,
+ state->Const.MaxClipPlanes);
+
+ /* FINISHME: gl_ClipDistance needs a real location assigned. */
+ add_variable("gl_ClipDistance", ir_var_in, -1, clip_distance_array_type,
+ instructions, state->symbols);
+}
+
+static void
+initialize_fs_variables(exec_list *instructions,
+ struct _mesa_glsl_parse_state *state)
+{
+
+ switch (state->language_version) {
+ case 110:
+ generate_110_fs_variables(instructions, state);
+ break;
+ case 120:
+ generate_120_fs_variables(instructions, state);
+ break;
+ case 130:
+ generate_130_fs_variables(instructions, state);
+ break;
+ }
+}
+
+void
+_mesa_glsl_initialize_variables(exec_list *instructions,
+ struct _mesa_glsl_parse_state *state)
+{
+ switch (state->target) {
+ case vertex_shader:
+ initialize_vs_variables(instructions, state);
+ break;
+ case geometry_shader:
+ break;
+ case fragment_shader:
+ initialize_fs_variables(instructions, state);
+ break;
+ case ir_shader:
+ fprintf(stderr, "ir reader has no builtin variables");
+ exit(1);
+ break;
+ }
+}
diff --git a/src/glsl/ir_variable_refcount.cpp b/src/glsl/ir_variable_refcount.cpp
new file mode 100644
index 00000000000..20c2f6602bf
--- /dev/null
+++ b/src/glsl/ir_variable_refcount.cpp
@@ -0,0 +1,100 @@
+/*
+ * Copyright © 2010 Intel Corporation
+ *
+ * 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 (including the next
+ * paragraph) 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
+ * THE AUTHORS OR COPYRIGHT HOLDERS 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 ir_variable_refcount.cpp
+ *
+ * Provides a visitor which produces a list of variables referenced,
+ * how many times they were referenced and assigned, and whether they
+ * were defined in the scope.
+ */
+
+#include "ir.h"
+#include "ir_visitor.h"
+#include "ir_variable_refcount.h"
+#include "glsl_types.h"
+
+variable_entry *
+ir_variable_refcount_visitor::get_variable_entry(ir_variable *var)
+{
+ assert(var);
+ foreach_iter(exec_list_iterator, iter, this->variable_list) {
+ variable_entry *entry = (variable_entry *)iter.get();
+ if (entry->var == var)
+ return entry;
+ }
+
+ variable_entry *entry = new(mem_ctx) variable_entry(var);
+ this->variable_list.push_tail(entry);
+ return entry;
+}
+
+
+ir_visitor_status
+ir_variable_refcount_visitor::visit(ir_variable *ir)
+{
+ variable_entry *entry = this->get_variable_entry(ir);
+ if (entry)
+ entry->declaration = true;
+
+ return visit_continue;
+}
+
+
+ir_visitor_status
+ir_variable_refcount_visitor::visit(ir_dereference_variable *ir)
+{
+ ir_variable *const var = ir->variable_referenced();
+ variable_entry *entry = this->get_variable_entry(var);
+
+ if (entry)
+ entry->referenced_count++;
+
+ return visit_continue;
+}
+
+
+ir_visitor_status
+ir_variable_refcount_visitor::visit_enter(ir_function_signature *ir)
+{
+ /* We don't want to descend into the function parameters and
+ * dead-code eliminate them, so just accept the body here.
+ */
+ visit_list_elements(this, &ir->body);
+ return visit_continue_with_parent;
+}
+
+
+ir_visitor_status
+ir_variable_refcount_visitor::visit_leave(ir_assignment *ir)
+{
+ variable_entry *entry;
+ entry = this->get_variable_entry(ir->lhs->variable_referenced());
+ if (entry) {
+ entry->assigned_count++;
+ if (entry->assign == NULL)
+ entry->assign = ir;
+ }
+
+ return visit_continue;
+}
diff --git a/src/glsl/ir_variable_refcount.h b/src/glsl/ir_variable_refcount.h
new file mode 100644
index 00000000000..30dd2bd587e
--- /dev/null
+++ b/src/glsl/ir_variable_refcount.h
@@ -0,0 +1,85 @@
+/*
+ * Copyright © 2010 Intel Corporation
+ *
+ * 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 (including the next
+ * paragraph) 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
+ * THE AUTHORS OR COPYRIGHT HOLDERS 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 ir_variable_refcount.h
+ *
+ * Provides a visitor which produces a list of variables referenced,
+ * how many times they were referenced and assigned, and whether they
+ * were defined in the scope.
+ */
+
+#include "ir.h"
+#include "ir_visitor.h"
+#include "glsl_types.h"
+
+class variable_entry : public exec_node
+{
+public:
+ variable_entry(ir_variable *var)
+ {
+ this->var = var;
+ assign = NULL;
+ referenced_count = 0;
+ assigned_count = 0;
+ declaration = false;
+ }
+
+ ir_variable *var; /* The key: the variable's pointer. */
+ ir_assignment *assign; /* An assignment to the variable, if any */
+
+ /** Number of times the variable is referenced, including assignments. */
+ unsigned referenced_count;
+
+ /** Number of times the variable is assigned. */
+ unsigned assigned_count;
+
+ bool declaration; /* If the variable had a decl in the instruction stream */
+};
+
+class ir_variable_refcount_visitor : public ir_hierarchical_visitor {
+public:
+ ir_variable_refcount_visitor(void)
+ {
+ this->mem_ctx = talloc_new(NULL);
+ this->variable_list.make_empty();
+ }
+
+ ~ir_variable_refcount_visitor(void)
+ {
+ this->mem_ctx = talloc_new(NULL);
+ }
+
+ virtual ir_visitor_status visit(ir_variable *);
+ virtual ir_visitor_status visit(ir_dereference_variable *);
+
+ virtual ir_visitor_status visit_enter(ir_function_signature *);
+ virtual ir_visitor_status visit_leave(ir_assignment *);
+
+ variable_entry *get_variable_entry(ir_variable *var);
+
+ /* List of variable_entry */
+ exec_list variable_list;
+
+ void *mem_ctx;
+};
diff --git a/src/glsl/ir_vec_index_to_cond_assign.cpp b/src/glsl/ir_vec_index_to_cond_assign.cpp
new file mode 100644
index 00000000000..cd8dedf2fe1
--- /dev/null
+++ b/src/glsl/ir_vec_index_to_cond_assign.cpp
@@ -0,0 +1,258 @@
+/*
+ * Copyright © 2010 Intel Corporation
+ *
+ * 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 (including the next
+ * paragraph) 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
+ * THE AUTHORS OR COPYRIGHT HOLDERS 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 ir_vec_index_to_cond_assign.cpp
+ *
+ * Turns indexing into vector types to a series of conditional moves
+ * of each channel's swizzle into a temporary.
+ *
+ * Most GPUs don't have a native way to do this operation, and this
+ * works around that. For drivers using both this pass and
+ * ir_vec_index_to_swizzle, there's a risk that this pass will happen
+ * before sufficient constant folding to find that the array index is
+ * constant. However, we hope that other optimization passes,
+ * particularly constant folding of assignment conditions and copy
+ * propagation, will result in the same code in the end.
+ */
+
+#include "ir.h"
+#include "ir_visitor.h"
+#include "ir_optimization.h"
+#include "glsl_types.h"
+
+/**
+ * Visitor class for replacing expressions with ir_constant values.
+ */
+
+class ir_vec_index_to_cond_assign_visitor : public ir_hierarchical_visitor {
+public:
+ ir_vec_index_to_cond_assign_visitor()
+ {
+ progress = false;
+ }
+
+ ir_rvalue *convert_vec_index_to_cond_assign(ir_rvalue *val);
+
+ virtual ir_visitor_status visit_enter(ir_expression *);
+ virtual ir_visitor_status visit_enter(ir_swizzle *);
+ virtual ir_visitor_status visit_leave(ir_assignment *);
+ virtual ir_visitor_status visit_enter(ir_return *);
+ virtual ir_visitor_status visit_enter(ir_call *);
+ virtual ir_visitor_status visit_enter(ir_if *);
+
+ bool progress;
+};
+
+ir_rvalue *
+ir_vec_index_to_cond_assign_visitor::convert_vec_index_to_cond_assign(ir_rvalue *ir)
+{
+ ir_dereference_array *orig_deref = ir->as_dereference_array();
+ ir_assignment *assign;
+ ir_variable *index, *var;
+ ir_dereference *deref;
+ ir_expression *condition;
+ ir_swizzle *swizzle;
+ int i;
+
+ if (!orig_deref)
+ return ir;
+
+ if (orig_deref->array->type->is_matrix() ||
+ orig_deref->array->type->is_array())
+ return ir;
+
+ void *mem_ctx = talloc_parent(ir);
+
+ assert(orig_deref->array_index->type->base_type == GLSL_TYPE_INT);
+
+ /* Store the index to a temporary to avoid reusing its tree. */
+ index = new(base_ir) ir_variable(glsl_type::int_type,
+ "vec_index_tmp_i",
+ ir_var_temporary);
+ base_ir->insert_before(index);
+ deref = new(base_ir) ir_dereference_variable(index);
+ assign = new(base_ir) ir_assignment(deref, orig_deref->array_index, NULL);
+ base_ir->insert_before(assign);
+
+ /* Temporary where we store whichever value we swizzle out. */
+ var = new(base_ir) ir_variable(ir->type, "vec_index_tmp_v",
+ ir_var_temporary);
+ base_ir->insert_before(var);
+
+ /* Generate a conditional move of each vector element to the temp. */
+ for (i = 0; i < orig_deref->array->type->vector_elements; i++) {
+ deref = new(base_ir) ir_dereference_variable(index);
+ condition = new(base_ir) ir_expression(ir_binop_equal,
+ glsl_type::bool_type,
+ deref,
+ new(base_ir) ir_constant(i));
+
+ /* Just clone the rest of the deref chain when trying to get at the
+ * underlying variable.
+ */
+ swizzle = new(base_ir) ir_swizzle(orig_deref->array->clone(mem_ctx, NULL),
+ i, 0, 0, 0, 1);
+
+ deref = new(base_ir) ir_dereference_variable(var);
+ assign = new(base_ir) ir_assignment(deref, swizzle, condition);
+ base_ir->insert_before(assign);
+ }
+
+ this->progress = true;
+ return new(base_ir) ir_dereference_variable(var);
+}
+
+ir_visitor_status
+ir_vec_index_to_cond_assign_visitor::visit_enter(ir_expression *ir)
+{
+ unsigned int i;
+
+ for (i = 0; i < ir->get_num_operands(); i++) {
+ ir->operands[i] = convert_vec_index_to_cond_assign(ir->operands[i]);
+ }
+
+ return visit_continue;
+}
+
+ir_visitor_status
+ir_vec_index_to_cond_assign_visitor::visit_enter(ir_swizzle *ir)
+{
+ /* Can't be hit from normal GLSL, since you can't swizzle a scalar (which
+ * the result of indexing a vector is. But maybe at some point we'll end up
+ * using swizzling of scalars for vector construction.
+ */
+ ir->val = convert_vec_index_to_cond_assign(ir->val);
+
+ return visit_continue;
+}
+
+ir_visitor_status
+ir_vec_index_to_cond_assign_visitor::visit_leave(ir_assignment *ir)
+{
+ ir_variable *index, *var;
+ ir_dereference_variable *deref;
+ ir_assignment *assign;
+ int i;
+
+ ir->rhs = convert_vec_index_to_cond_assign(ir->rhs);
+ if (ir->condition)
+ ir->condition = convert_vec_index_to_cond_assign(ir->condition);
+
+ /* Last, handle the LHS */
+ ir_dereference_array *orig_deref = ir->lhs->as_dereference_array();
+
+ if (!orig_deref ||
+ orig_deref->array->type->is_matrix() ||
+ orig_deref->array->type->is_array())
+ return visit_continue;
+
+ void *mem_ctx = talloc_parent(ir);
+
+ assert(orig_deref->array_index->type->base_type == GLSL_TYPE_INT);
+
+ /* Store the index to a temporary to avoid reusing its tree. */
+ index = new(ir) ir_variable(glsl_type::int_type, "vec_index_tmp_i",
+ ir_var_temporary);
+ ir->insert_before(index);
+ deref = new(ir) ir_dereference_variable(index);
+ assign = new(ir) ir_assignment(deref, orig_deref->array_index, NULL);
+ ir->insert_before(assign);
+
+ /* Store the RHS to a temporary to avoid reusing its tree. */
+ var = new(ir) ir_variable(ir->rhs->type, "vec_index_tmp_v",
+ ir_var_temporary);
+ ir->insert_before(var);
+ deref = new(ir) ir_dereference_variable(var);
+ assign = new(ir) ir_assignment(deref, ir->rhs, NULL);
+ ir->insert_before(assign);
+
+ /* Generate a conditional move of each vector element to the temp. */
+ for (i = 0; i < orig_deref->array->type->vector_elements; i++) {
+ ir_rvalue *condition, *swizzle;
+
+ deref = new(ir) ir_dereference_variable(index);
+ condition = new(ir) ir_expression(ir_binop_equal,
+ glsl_type::bool_type,
+ deref,
+ new(ir) ir_constant(i));
+
+ /* Just clone the rest of the deref chain when trying to get at the
+ * underlying variable.
+ */
+ swizzle = new(ir) ir_swizzle(orig_deref->array->clone(mem_ctx, NULL),
+ i, 0, 0, 0, 1);
+
+ deref = new(ir) ir_dereference_variable(var);
+ assign = new(ir) ir_assignment(swizzle, deref, condition);
+ ir->insert_before(assign);
+ }
+ ir->remove();
+
+ this->progress = true;
+
+ return visit_continue;
+}
+
+ir_visitor_status
+ir_vec_index_to_cond_assign_visitor::visit_enter(ir_call *ir)
+{
+ foreach_iter(exec_list_iterator, iter, *ir) {
+ ir_rvalue *param = (ir_rvalue *)iter.get();
+ ir_rvalue *new_param = convert_vec_index_to_cond_assign(param);
+
+ if (new_param != param) {
+ param->replace_with(new_param);
+ }
+ }
+
+ return visit_continue;
+}
+
+ir_visitor_status
+ir_vec_index_to_cond_assign_visitor::visit_enter(ir_return *ir)
+{
+ if (ir->value) {
+ ir->value = convert_vec_index_to_cond_assign(ir->value);
+ }
+
+ return visit_continue;
+}
+
+ir_visitor_status
+ir_vec_index_to_cond_assign_visitor::visit_enter(ir_if *ir)
+{
+ ir->condition = convert_vec_index_to_cond_assign(ir->condition);
+
+ return visit_continue;
+}
+
+bool
+do_vec_index_to_cond_assign(exec_list *instructions)
+{
+ ir_vec_index_to_cond_assign_visitor v;
+
+ visit_list_elements(&v, instructions);
+
+ return v.progress;
+}
diff --git a/src/glsl/ir_vec_index_to_swizzle.cpp b/src/glsl/ir_vec_index_to_swizzle.cpp
new file mode 100644
index 00000000000..969dc8f94a2
--- /dev/null
+++ b/src/glsl/ir_vec_index_to_swizzle.cpp
@@ -0,0 +1,157 @@
+/*
+ * Copyright © 2010 Intel Corporation
+ *
+ * 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 (including the next
+ * paragraph) 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
+ * THE AUTHORS OR COPYRIGHT HOLDERS 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 ir_vec_index_to_swizzle.cpp
+ *
+ * Turns constant indexing into vector types to swizzles. This will
+ * let other swizzle-aware optimization passes catch these constructs,
+ * and codegen backends not have to worry about this case.
+ */
+
+#include "ir.h"
+#include "ir_visitor.h"
+#include "ir_optimization.h"
+#include "glsl_types.h"
+
+/**
+ * Visitor class for replacing expressions with ir_constant values.
+ */
+
+class ir_vec_index_to_swizzle_visitor : public ir_hierarchical_visitor {
+public:
+ ir_vec_index_to_swizzle_visitor()
+ {
+ progress = false;
+ }
+
+ ir_rvalue *convert_vec_index_to_swizzle(ir_rvalue *val);
+
+ virtual ir_visitor_status visit_enter(ir_expression *);
+ virtual ir_visitor_status visit_enter(ir_swizzle *);
+ virtual ir_visitor_status visit_enter(ir_assignment *);
+ virtual ir_visitor_status visit_enter(ir_return *);
+ virtual ir_visitor_status visit_enter(ir_call *);
+ virtual ir_visitor_status visit_enter(ir_if *);
+
+ bool progress;
+};
+
+ir_rvalue *
+ir_vec_index_to_swizzle_visitor::convert_vec_index_to_swizzle(ir_rvalue *ir)
+{
+ ir_dereference_array *deref = ir->as_dereference_array();
+ ir_constant *ir_constant;
+
+ if (!deref)
+ return ir;
+
+ if (deref->array->type->is_matrix() || deref->array->type->is_array())
+ return ir;
+
+ assert(deref->array_index->type->base_type == GLSL_TYPE_INT);
+ ir_constant = deref->array_index->constant_expression_value();
+ if (!ir_constant)
+ return ir;
+
+ void *ctx = talloc_parent(ir);
+ this->progress = true;
+ return new(ctx) ir_swizzle(deref->array,
+ ir_constant->value.i[0], 0, 0, 0, 1);
+}
+
+ir_visitor_status
+ir_vec_index_to_swizzle_visitor::visit_enter(ir_expression *ir)
+{
+ unsigned int i;
+
+ for (i = 0; i < ir->get_num_operands(); i++) {
+ ir->operands[i] = convert_vec_index_to_swizzle(ir->operands[i]);
+ }
+
+ return visit_continue;
+}
+
+ir_visitor_status
+ir_vec_index_to_swizzle_visitor::visit_enter(ir_swizzle *ir)
+{
+ /* Can't be hit from normal GLSL, since you can't swizzle a scalar (which
+ * the result of indexing a vector is. But maybe at some point we'll end up
+ * using swizzling of scalars for vector construction.
+ */
+ ir->val = convert_vec_index_to_swizzle(ir->val);
+
+ return visit_continue;
+}
+
+ir_visitor_status
+ir_vec_index_to_swizzle_visitor::visit_enter(ir_assignment *ir)
+{
+ ir->set_lhs(convert_vec_index_to_swizzle(ir->lhs));
+ ir->rhs = convert_vec_index_to_swizzle(ir->rhs);
+
+ return visit_continue;
+}
+
+ir_visitor_status
+ir_vec_index_to_swizzle_visitor::visit_enter(ir_call *ir)
+{
+ foreach_iter(exec_list_iterator, iter, *ir) {
+ ir_rvalue *param = (ir_rvalue *)iter.get();
+ ir_rvalue *new_param = convert_vec_index_to_swizzle(param);
+
+ if (new_param != param) {
+ param->replace_with(new_param);
+ }
+ }
+
+ return visit_continue;
+}
+
+ir_visitor_status
+ir_vec_index_to_swizzle_visitor::visit_enter(ir_return *ir)
+{
+ if (ir->value) {
+ ir->value = convert_vec_index_to_swizzle(ir->value);
+ }
+
+ return visit_continue;
+}
+
+ir_visitor_status
+ir_vec_index_to_swizzle_visitor::visit_enter(ir_if *ir)
+{
+ ir->condition = convert_vec_index_to_swizzle(ir->condition);
+
+ return visit_continue;
+}
+
+bool
+do_vec_index_to_swizzle(exec_list *instructions)
+{
+ ir_vec_index_to_swizzle_visitor v;
+
+ v.run(instructions);
+
+ return v.progress;
+}
diff --git a/src/glsl/ir_visitor.h b/src/glsl/ir_visitor.h
new file mode 100644
index 00000000000..b87d7373180
--- /dev/null
+++ b/src/glsl/ir_visitor.h
@@ -0,0 +1,67 @@
+/* -*- c++ -*- */
+/*
+ * Copyright © 2010 Intel Corporation
+ *
+ * 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 (including the next
+ * paragraph) 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
+ * THE AUTHORS OR COPYRIGHT HOLDERS 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.
+ */
+
+#pragma once
+#ifndef IR_VISITOR_H
+#define IR_VISITOR_H
+
+/**
+ * Abstract base class of visitors of IR instruction trees
+ */
+class ir_visitor {
+public:
+ virtual ~ir_visitor()
+ {
+ /* empty */
+ }
+
+ /**
+ * \name Visit methods
+ *
+ * As typical for the visitor pattern, there must be one \c visit method for
+ * each concrete subclass of \c ir_instruction. Virtual base classes within
+ * the hierarchy should not have \c visit methods.
+ */
+ /*@{*/
+ virtual void visit(class ir_variable *) = 0;
+ virtual void visit(class ir_function_signature *) = 0;
+ virtual void visit(class ir_function *) = 0;
+ virtual void visit(class ir_expression *) = 0;
+ virtual void visit(class ir_texture *) = 0;
+ virtual void visit(class ir_swizzle *) = 0;
+ virtual void visit(class ir_dereference_variable *) = 0;
+ virtual void visit(class ir_dereference_array *) = 0;
+ virtual void visit(class ir_dereference_record *) = 0;
+ virtual void visit(class ir_assignment *) = 0;
+ virtual void visit(class ir_constant *) = 0;
+ virtual void visit(class ir_call *) = 0;
+ virtual void visit(class ir_return *) = 0;
+ virtual void visit(class ir_discard *) = 0;
+ virtual void visit(class ir_if *) = 0;
+ virtual void visit(class ir_loop *) = 0;
+ virtual void visit(class ir_loop_jump *) = 0;
+ /*@}*/
+};
+
+#endif /* IR_VISITOR_H */
diff --git a/src/glsl/link_functions.cpp b/src/glsl/link_functions.cpp
new file mode 100644
index 00000000000..dfda05fcbe5
--- /dev/null
+++ b/src/glsl/link_functions.cpp
@@ -0,0 +1,262 @@
+/*
+ * Copyright © 2010 Intel Corporation
+ *
+ * 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 (including the next
+ * paragraph) 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
+ * THE AUTHORS OR COPYRIGHT HOLDERS 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.
+ */
+
+#include <cstdlib>
+#include <cstdio>
+#include <cstdarg>
+
+extern "C" {
+#include <talloc.h>
+}
+
+#include "main/mtypes.h"
+#include "glsl_symbol_table.h"
+#include "glsl_parser_extras.h"
+#include "ir.h"
+#include "program.h"
+#include "program/hash_table.h"
+#include "linker.h"
+
+static ir_function_signature *
+find_matching_signature(const char *name, const exec_list *actual_parameters,
+ gl_shader **shader_list, unsigned num_shaders);
+
+class call_link_visitor : public ir_hierarchical_visitor {
+public:
+ call_link_visitor(gl_shader_program *prog, gl_shader *linked,
+ gl_shader **shader_list, unsigned num_shaders)
+ {
+ this->prog = prog;
+ this->shader_list = shader_list;
+ this->num_shaders = num_shaders;
+ this->success = true;
+ this->linked = linked;
+
+ this->locals = hash_table_ctor(0, hash_table_pointer_hash,
+ hash_table_pointer_compare);
+ }
+
+ ~call_link_visitor()
+ {
+ hash_table_dtor(this->locals);
+ }
+
+ virtual ir_visitor_status visit(ir_variable *ir)
+ {
+ hash_table_insert(locals, ir, ir);
+ return visit_continue;
+ }
+
+ virtual ir_visitor_status visit_enter(ir_call *ir)
+ {
+ /* If ir is an ir_call from a function that was imported from another
+ * shader callee will point to an ir_function_signature in the original
+ * shader. In this case the function signature MUST NOT BE MODIFIED.
+ * Doing so will modify the original shader. This may prevent that
+ * shader from being linkable in other programs.
+ */
+ const ir_function_signature *const callee = ir->get_callee();
+ assert(callee != NULL);
+ const char *const name = callee->function_name();
+
+ /* Determine if the requested function signature already exists in the
+ * final linked shader. If it does, use it as the target of the call.
+ */
+ ir_function_signature *sig =
+ find_matching_signature(name, &callee->parameters, &linked, 1);
+ if (sig != NULL) {
+ ir->set_callee(sig);
+ return visit_continue;
+ }
+
+ /* Try to find the signature in one of the other shaders that is being
+ * linked. If it's not found there, return an error.
+ */
+ sig = find_matching_signature(name, &ir->actual_parameters, shader_list,
+ num_shaders);
+ if (sig == NULL) {
+ /* FINISHME: Log the full signature of unresolved function.
+ */
+ linker_error_printf(this->prog, "unresolved reference to function "
+ "`%s'\n", name);
+ this->success = false;
+ return visit_stop;
+ }
+
+ /* Find the prototype information in the linked shader. Generate any
+ * details that may be missing.
+ */
+ ir_function *f = linked->symbols->get_function(name);
+ if (f == NULL)
+ f = new(linked) ir_function(name);
+
+ ir_function_signature *linked_sig =
+ f->matching_signature(&callee->parameters);
+ if (linked_sig == NULL) {
+ linked_sig = new(linked) ir_function_signature(callee->return_type);
+ f->add_signature(linked_sig);
+ }
+
+ /* At this point linked_sig and called may be the same. If ir is an
+ * ir_call from linked then linked_sig and callee will be
+ * ir_function_signatures that have no definitions (is_defined is false).
+ */
+ assert(!linked_sig->is_defined);
+ assert(linked_sig->body.is_empty());
+
+ /* Create an in-place clone of the function definition. This multistep
+ * process introduces some complexity here, but it has some advantages.
+ * The parameter list and the and function body are cloned separately.
+ * The clone of the parameter list is used to prime the hashtable used
+ * to replace variable references in the cloned body.
+ *
+ * The big advantage is that the ir_function_signature does not change.
+ * This means that we don't have to process the rest of the IR tree to
+ * patch ir_call nodes. In addition, there is no way to remove or
+ * replace signature stored in a function. One could easily be added,
+ * but this avoids the need.
+ */
+ struct hash_table *ht = hash_table_ctor(0, hash_table_pointer_hash,
+ hash_table_pointer_compare);
+ exec_list formal_parameters;
+ foreach_list_const(node, &sig->parameters) {
+ const ir_instruction *const original = (ir_instruction *) node;
+ assert(const_cast<ir_instruction *>(original)->as_variable());
+
+ ir_instruction *copy = original->clone(linked, ht);
+ formal_parameters.push_tail(copy);
+ }
+
+ linked_sig->replace_parameters(&formal_parameters);
+
+ foreach_list_const(node, &sig->body) {
+ const ir_instruction *const original = (ir_instruction *) node;
+
+ ir_instruction *copy = original->clone(linked, ht);
+ linked_sig->body.push_tail(copy);
+ }
+
+ linked_sig->is_defined = true;
+ hash_table_dtor(ht);
+
+ /* Patch references inside the function to things outside the function
+ * (i.e., function calls and global variables).
+ */
+ linked_sig->accept(this);
+
+ ir->set_callee(linked_sig);
+
+ return visit_continue;
+ }
+
+ virtual ir_visitor_status visit(ir_dereference_variable *ir)
+ {
+ if (hash_table_find(locals, ir->var) == NULL) {
+ /* The non-function variable must be a global, so try to find the
+ * variable in the shader's symbol table. If the variable is not
+ * found, then it's a global that *MUST* be defined in the original
+ * shader.
+ */
+ ir_variable *var = linked->symbols->get_variable(ir->var->name);
+ if (var == NULL) {
+ /* Clone the ir_variable that the dereference already has and add
+ * it to the linked shader.
+ */
+ var = ir->var->clone(linked, NULL);
+ linked->symbols->add_variable(var->name, var);
+ linked->ir->push_head(var);
+ }
+
+ ir->var = var;
+ }
+
+ return visit_continue;
+ }
+
+ /** Was function linking successful? */
+ bool success;
+
+private:
+ /**
+ * Shader program being linked
+ *
+ * This is only used for logging error messages.
+ */
+ gl_shader_program *prog;
+
+ /** List of shaders available for linking. */
+ gl_shader **shader_list;
+
+ /** Number of shaders available for linking. */
+ unsigned num_shaders;
+
+ /**
+ * Final linked shader
+ *
+ * This is used two ways. It is used to find global variables in the
+ * linked shader that are accessed by the function. It is also used to add
+ * global variables from the shader where the function originated.
+ */
+ gl_shader *linked;
+
+ /**
+ * Table of variables local to the function.
+ */
+ hash_table *locals;
+};
+
+
+/**
+ * Searches a list of shaders for a particular function definition
+ */
+ir_function_signature *
+find_matching_signature(const char *name, const exec_list *actual_parameters,
+ gl_shader **shader_list, unsigned num_shaders)
+{
+ for (unsigned i = 0; i < num_shaders; i++) {
+ ir_function *const f = shader_list[i]->symbols->get_function(name);
+
+ if (f == NULL)
+ continue;
+
+ ir_function_signature *sig = f->matching_signature(actual_parameters);
+
+ if ((sig == NULL) || !sig->is_defined)
+ continue;
+
+ return sig;
+ }
+
+ return NULL;
+}
+
+
+bool
+link_function_calls(gl_shader_program *prog, gl_shader *main,
+ gl_shader **shader_list, unsigned num_shaders)
+{
+ call_link_visitor v(prog, main, shader_list, num_shaders);
+
+ v.run(main->ir);
+ return v.success;
+}
diff --git a/src/glsl/linker.cpp b/src/glsl/linker.cpp
new file mode 100644
index 00000000000..9931251f404
--- /dev/null
+++ b/src/glsl/linker.cpp
@@ -0,0 +1,1340 @@
+/*
+ * Copyright © 2010 Intel Corporation
+ *
+ * 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 (including the next
+ * paragraph) 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
+ * THE AUTHORS OR COPYRIGHT HOLDERS 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 linker.cpp
+ * GLSL linker implementation
+ *
+ * Given a set of shaders that are to be linked to generate a final program,
+ * there are three distinct stages.
+ *
+ * In the first stage shaders are partitioned into groups based on the shader
+ * type. All shaders of a particular type (e.g., vertex shaders) are linked
+ * together.
+ *
+ * - Undefined references in each shader are resolve to definitions in
+ * another shader.
+ * - Types and qualifiers of uniforms, outputs, and global variables defined
+ * in multiple shaders with the same name are verified to be the same.
+ * - Initializers for uniforms and global variables defined
+ * in multiple shaders with the same name are verified to be the same.
+ *
+ * The result, in the terminology of the GLSL spec, is a set of shader
+ * executables for each processing unit.
+ *
+ * After the first stage is complete, a series of semantic checks are performed
+ * on each of the shader executables.
+ *
+ * - Each shader executable must define a \c main function.
+ * - Each vertex shader executable must write to \c gl_Position.
+ * - Each fragment shader executable must write to either \c gl_FragData or
+ * \c gl_FragColor.
+ *
+ * In the final stage individual shader executables are linked to create a
+ * complete exectuable.
+ *
+ * - Types of uniforms defined in multiple shader stages with the same name
+ * are verified to be the same.
+ * - Initializers for uniforms defined in multiple shader stages with the
+ * same name are verified to be the same.
+ * - Types and qualifiers of outputs defined in one stage are verified to
+ * be the same as the types and qualifiers of inputs defined with the same
+ * name in a later stage.
+ *
+ * \author Ian Romanick <[email protected]>
+ */
+#include <cstdlib>
+#include <cstdio>
+#include <cstdarg>
+#include <climits>
+
+extern "C" {
+#include <talloc.h>
+}
+
+#include "main/mtypes.h"
+#include "main/macros.h"
+#include "main/shaderobj.h"
+#include "glsl_symbol_table.h"
+#include "ir.h"
+#include "program.h"
+#include "program/hash_table.h"
+#include "linker.h"
+#include "ir_optimization.h"
+
+/**
+ * Visitor that determines whether or not a variable is ever written.
+ */
+class find_assignment_visitor : public ir_hierarchical_visitor {
+public:
+ find_assignment_visitor(const char *name)
+ : name(name), found(false)
+ {
+ /* empty */
+ }
+
+ virtual ir_visitor_status visit_enter(ir_assignment *ir)
+ {
+ ir_variable *const var = ir->lhs->variable_referenced();
+
+ if (strcmp(name, var->name) == 0) {
+ found = true;
+ return visit_stop;
+ }
+
+ return visit_continue_with_parent;
+ }
+
+ bool variable_found()
+ {
+ return found;
+ }
+
+private:
+ const char *name; /**< Find writes to a variable with this name. */
+ bool found; /**< Was a write to the variable found? */
+};
+
+
+/**
+ * Visitor that determines whether or not a variable is ever read.
+ */
+class find_deref_visitor : public ir_hierarchical_visitor {
+public:
+ find_deref_visitor(const char *name)
+ : name(name), found(false)
+ {
+ /* empty */
+ }
+
+ virtual ir_visitor_status visit(ir_dereference_variable *ir)
+ {
+ if (strcmp(this->name, ir->var->name) == 0) {
+ this->found = true;
+ return visit_stop;
+ }
+
+ return visit_continue;
+ }
+
+ bool variable_found() const
+ {
+ return this->found;
+ }
+
+private:
+ const char *name; /**< Find writes to a variable with this name. */
+ bool found; /**< Was a write to the variable found? */
+};
+
+
+void
+linker_error_printf(gl_shader_program *prog, const char *fmt, ...)
+{
+ va_list ap;
+
+ prog->InfoLog = talloc_strdup_append(prog->InfoLog, "error: ");
+ va_start(ap, fmt);
+ prog->InfoLog = talloc_vasprintf_append(prog->InfoLog, fmt, ap);
+ va_end(ap);
+}
+
+
+void
+invalidate_variable_locations(gl_shader *sh, enum ir_variable_mode mode,
+ int generic_base)
+{
+ foreach_list(node, sh->ir) {
+ ir_variable *const var = ((ir_instruction *) node)->as_variable();
+
+ if ((var == NULL) || (var->mode != (unsigned) mode))
+ continue;
+
+ /* Only assign locations for generic attributes / varyings / etc.
+ */
+ if (var->location >= generic_base)
+ var->location = -1;
+ }
+}
+
+
+/**
+ * Determine the number of attribute slots required for a particular type
+ *
+ * This code is here because it implements the language rules of a specific
+ * GLSL version. Since it's a property of the language and not a property of
+ * types in general, it doesn't really belong in glsl_type.
+ */
+unsigned
+count_attribute_slots(const glsl_type *t)
+{
+ /* From page 31 (page 37 of the PDF) of the GLSL 1.50 spec:
+ *
+ * "A scalar input counts the same amount against this limit as a vec4,
+ * so applications may want to consider packing groups of four
+ * unrelated float inputs together into a vector to better utilize the
+ * capabilities of the underlying hardware. A matrix input will use up
+ * multiple locations. The number of locations used will equal the
+ * number of columns in the matrix."
+ *
+ * The spec does not explicitly say how arrays are counted. However, it
+ * should be safe to assume the total number of slots consumed by an array
+ * is the number of entries in the array multiplied by the number of slots
+ * consumed by a single element of the array.
+ */
+
+ if (t->is_array())
+ return t->array_size() * count_attribute_slots(t->element_type());
+
+ if (t->is_matrix())
+ return t->matrix_columns;
+
+ return 1;
+}
+
+
+/**
+ * Verify that a vertex shader executable meets all semantic requirements
+ *
+ * \param shader Vertex shader executable to be verified
+ */
+bool
+validate_vertex_shader_executable(struct gl_shader_program *prog,
+ struct gl_shader *shader)
+{
+ if (shader == NULL)
+ return true;
+
+ find_assignment_visitor find("gl_Position");
+ find.run(shader->ir);
+ if (!find.variable_found()) {
+ linker_error_printf(prog,
+ "vertex shader does not write to `gl_Position'\n");
+ return false;
+ }
+
+ return true;
+}
+
+
+/**
+ * Verify that a fragment shader executable meets all semantic requirements
+ *
+ * \param shader Fragment shader executable to be verified
+ */
+bool
+validate_fragment_shader_executable(struct gl_shader_program *prog,
+ struct gl_shader *shader)
+{
+ if (shader == NULL)
+ return true;
+
+ find_assignment_visitor frag_color("gl_FragColor");
+ find_assignment_visitor frag_data("gl_FragData");
+
+ frag_color.run(shader->ir);
+ frag_data.run(shader->ir);
+
+ if (frag_color.variable_found() && frag_data.variable_found()) {
+ linker_error_printf(prog, "fragment shader writes to both "
+ "`gl_FragColor' and `gl_FragData'\n");
+ return false;
+ }
+
+ return true;
+}
+
+
+/**
+ * Generate a string describing the mode of a variable
+ */
+static const char *
+mode_string(const ir_variable *var)
+{
+ switch (var->mode) {
+ case ir_var_auto:
+ return (var->read_only) ? "global constant" : "global variable";
+
+ case ir_var_uniform: return "uniform";
+ case ir_var_in: return "shader input";
+ case ir_var_out: return "shader output";
+ case ir_var_inout: return "shader inout";
+
+ case ir_var_temporary:
+ default:
+ assert(!"Should not get here.");
+ return "invalid variable";
+ }
+}
+
+
+/**
+ * Perform validation of global variables used across multiple shaders
+ */
+bool
+cross_validate_globals(struct gl_shader_program *prog,
+ struct gl_shader **shader_list,
+ unsigned num_shaders,
+ bool uniforms_only)
+{
+ /* Examine all of the uniforms in all of the shaders and cross validate
+ * them.
+ */
+ glsl_symbol_table variables;
+ for (unsigned i = 0; i < num_shaders; i++) {
+ foreach_list(node, shader_list[i]->ir) {
+ ir_variable *const var = ((ir_instruction *) node)->as_variable();
+
+ if (var == NULL)
+ continue;
+
+ if (uniforms_only && (var->mode != ir_var_uniform))
+ continue;
+
+ /* Don't cross validate temporaries that are at global scope. These
+ * will eventually get pulled into the shaders 'main'.
+ */
+ if (var->mode == ir_var_temporary)
+ continue;
+
+ /* If a global with this name has already been seen, verify that the
+ * new instance has the same type. In addition, if the globals have
+ * initializers, the values of the initializers must be the same.
+ */
+ ir_variable *const existing = variables.get_variable(var->name);
+ if (existing != NULL) {
+ if (var->type != existing->type) {
+ linker_error_printf(prog, "%s `%s' declared as type "
+ "`%s' and type `%s'\n",
+ mode_string(var),
+ var->name, var->type->name,
+ existing->type->name);
+ return false;
+ }
+
+ /* FINISHME: Handle non-constant initializers.
+ */
+ if (var->constant_value != NULL) {
+ if (existing->constant_value != NULL) {
+ if (!var->constant_value->has_value(existing->constant_value)) {
+ linker_error_printf(prog, "initializers for %s "
+ "`%s' have differing values\n",
+ mode_string(var), var->name);
+ return false;
+ }
+ } else
+ /* If the first-seen instance of a particular uniform did not
+ * have an initializer but a later instance does, copy the
+ * initializer to the version stored in the symbol table.
+ */
+ /* FINISHME: This is wrong. The constant_value field should
+ * FINISHME: not be modified! Imagine a case where a shader
+ * FINISHME: without an initializer is linked in two different
+ * FINISHME: programs with shaders that have differing
+ * FINISHME: initializers. Linking with the first will
+ * FINISHME: modify the shader, and linking with the second
+ * FINISHME: will fail.
+ */
+ existing->constant_value =
+ var->constant_value->clone(talloc_parent(existing), NULL);
+ }
+ } else
+ variables.add_variable(var->name, var);
+ }
+ }
+
+ return true;
+}
+
+
+/**
+ * Perform validation of uniforms used across multiple shader stages
+ */
+bool
+cross_validate_uniforms(struct gl_shader_program *prog)
+{
+ return cross_validate_globals(prog, prog->_LinkedShaders,
+ prog->_NumLinkedShaders, true);
+}
+
+
+/**
+ * Validate that outputs from one stage match inputs of another
+ */
+bool
+cross_validate_outputs_to_inputs(struct gl_shader_program *prog,
+ gl_shader *producer, gl_shader *consumer)
+{
+ glsl_symbol_table parameters;
+ /* FINISHME: Figure these out dynamically. */
+ const char *const producer_stage = "vertex";
+ const char *const consumer_stage = "fragment";
+
+ /* Find all shader outputs in the "producer" stage.
+ */
+ foreach_list(node, producer->ir) {
+ ir_variable *const var = ((ir_instruction *) node)->as_variable();
+
+ /* FINISHME: For geometry shaders, this should also look for inout
+ * FINISHME: variables.
+ */
+ if ((var == NULL) || (var->mode != ir_var_out))
+ continue;
+
+ parameters.add_variable(var->name, var);
+ }
+
+
+ /* Find all shader inputs in the "consumer" stage. Any variables that have
+ * matching outputs already in the symbol table must have the same type and
+ * qualifiers.
+ */
+ foreach_list(node, consumer->ir) {
+ ir_variable *const input = ((ir_instruction *) node)->as_variable();
+
+ /* FINISHME: For geometry shaders, this should also look for inout
+ * FINISHME: variables.
+ */
+ if ((input == NULL) || (input->mode != ir_var_in))
+ continue;
+
+ ir_variable *const output = parameters.get_variable(input->name);
+ if (output != NULL) {
+ /* Check that the types match between stages.
+ */
+ if (input->type != output->type) {
+ linker_error_printf(prog,
+ "%s shader output `%s' delcared as "
+ "type `%s', but %s shader input declared "
+ "as type `%s'\n",
+ producer_stage, output->name,
+ output->type->name,
+ consumer_stage, input->type->name);
+ return false;
+ }
+
+ /* Check that all of the qualifiers match between stages.
+ */
+ if (input->centroid != output->centroid) {
+ linker_error_printf(prog,
+ "%s shader output `%s' %s centroid qualifier, "
+ "but %s shader input %s centroid qualifier\n",
+ producer_stage,
+ output->name,
+ (output->centroid) ? "has" : "lacks",
+ consumer_stage,
+ (input->centroid) ? "has" : "lacks");
+ return false;
+ }
+
+ if (input->invariant != output->invariant) {
+ linker_error_printf(prog,
+ "%s shader output `%s' %s invariant qualifier, "
+ "but %s shader input %s invariant qualifier\n",
+ producer_stage,
+ output->name,
+ (output->invariant) ? "has" : "lacks",
+ consumer_stage,
+ (input->invariant) ? "has" : "lacks");
+ return false;
+ }
+
+ if (input->interpolation != output->interpolation) {
+ linker_error_printf(prog,
+ "%s shader output `%s' specifies %s "
+ "interpolation qualifier, "
+ "but %s shader input specifies %s "
+ "interpolation qualifier\n",
+ producer_stage,
+ output->name,
+ output->interpolation_string(),
+ consumer_stage,
+ input->interpolation_string());
+ return false;
+ }
+ }
+ }
+
+ return true;
+}
+
+
+/**
+ * Populates a shaders symbol table with all global declarations
+ */
+static void
+populate_symbol_table(gl_shader *sh)
+{
+ sh->symbols = new(sh) glsl_symbol_table;
+
+ foreach_list(node, sh->ir) {
+ ir_instruction *const inst = (ir_instruction *) node;
+ ir_variable *var;
+ ir_function *func;
+
+ if ((func = inst->as_function()) != NULL) {
+ sh->symbols->add_function(func->name, func);
+ } else if ((var = inst->as_variable()) != NULL) {
+ sh->symbols->add_variable(var->name, var);
+ }
+ }
+}
+
+
+/**
+ * Remap variables referenced in an instruction tree
+ *
+ * This is used when instruction trees are cloned from one shader and placed in
+ * another. These trees will contain references to \c ir_variable nodes that
+ * do not exist in the target shader. This function finds these \c ir_variable
+ * references and replaces the references with matching variables in the target
+ * shader.
+ *
+ * If there is no matching variable in the target shader, a clone of the
+ * \c ir_variable is made and added to the target shader. The new variable is
+ * added to \b both the instruction stream and the symbol table.
+ *
+ * \param inst IR tree that is to be processed.
+ * \param symbols Symbol table containing global scope symbols in the
+ * linked shader.
+ * \param instructions Instruction stream where new variable declarations
+ * should be added.
+ */
+void
+remap_variables(ir_instruction *inst, struct gl_shader *target,
+ hash_table *temps)
+{
+ class remap_visitor : public ir_hierarchical_visitor {
+ public:
+ remap_visitor(struct gl_shader *target,
+ hash_table *temps)
+ {
+ this->target = target;
+ this->symbols = target->symbols;
+ this->instructions = target->ir;
+ this->temps = temps;
+ }
+
+ virtual ir_visitor_status visit(ir_dereference_variable *ir)
+ {
+ if (ir->var->mode == ir_var_temporary) {
+ ir_variable *var = (ir_variable *) hash_table_find(temps, ir->var);
+
+ assert(var != NULL);
+ ir->var = var;
+ return visit_continue;
+ }
+
+ ir_variable *const existing =
+ this->symbols->get_variable(ir->var->name);
+ if (existing != NULL)
+ ir->var = existing;
+ else {
+ ir_variable *copy = ir->var->clone(this->target, NULL);
+
+ this->symbols->add_variable(copy->name, copy);
+ this->instructions->push_head(copy);
+ ir->var = copy;
+ }
+
+ return visit_continue;
+ }
+
+ private:
+ struct gl_shader *target;
+ glsl_symbol_table *symbols;
+ exec_list *instructions;
+ hash_table *temps;
+ };
+
+ remap_visitor v(target, temps);
+
+ inst->accept(&v);
+}
+
+
+/**
+ * Move non-declarations from one instruction stream to another
+ *
+ * The intended usage pattern of this function is to pass the pointer to the
+ * head sentinel of a list (i.e., a pointer to the list cast to an \c exec_node
+ * pointer) for \c last and \c false for \c make_copies on the first
+ * call. Successive calls pass the return value of the previous call for
+ * \c last and \c true for \c make_copies.
+ *
+ * \param instructions Source instruction stream
+ * \param last Instruction after which new instructions should be
+ * inserted in the target instruction stream
+ * \param make_copies Flag selecting whether instructions in \c instructions
+ * should be copied (via \c ir_instruction::clone) into the
+ * target list or moved.
+ *
+ * \return
+ * The new "last" instruction in the target instruction stream. This pointer
+ * is suitable for use as the \c last parameter of a later call to this
+ * function.
+ */
+exec_node *
+move_non_declarations(exec_list *instructions, exec_node *last,
+ bool make_copies, gl_shader *target)
+{
+ hash_table *temps = NULL;
+
+ if (make_copies)
+ temps = hash_table_ctor(0, hash_table_pointer_hash,
+ hash_table_pointer_compare);
+
+ foreach_list_safe(node, instructions) {
+ ir_instruction *inst = (ir_instruction *) node;
+
+ if (inst->as_function())
+ continue;
+
+ ir_variable *var = inst->as_variable();
+ if ((var != NULL) && (var->mode != ir_var_temporary))
+ continue;
+
+ assert(inst->as_assignment()
+ || ((var != NULL) && (var->mode == ir_var_temporary)));
+
+ if (make_copies) {
+ inst = inst->clone(target, NULL);
+
+ if (var != NULL)
+ hash_table_insert(temps, inst, var);
+ else
+ remap_variables(inst, target, temps);
+ } else {
+ inst->remove();
+ }
+
+ last->insert_after(inst);
+ last = inst;
+ }
+
+ if (make_copies)
+ hash_table_dtor(temps);
+
+ return last;
+}
+
+/**
+ * Get the function signature for main from a shader
+ */
+static ir_function_signature *
+get_main_function_signature(gl_shader *sh)
+{
+ ir_function *const f = sh->symbols->get_function("main");
+ if (f != NULL) {
+ exec_list void_parameters;
+
+ /* Look for the 'void main()' signature and ensure that it's defined.
+ * This keeps the linker from accidentally pick a shader that just
+ * contains a prototype for main.
+ *
+ * We don't have to check for multiple definitions of main (in multiple
+ * shaders) because that would have already been caught above.
+ */
+ ir_function_signature *sig = f->matching_signature(&void_parameters);
+ if ((sig != NULL) && sig->is_defined) {
+ return sig;
+ }
+ }
+
+ return NULL;
+}
+
+
+/**
+ * Combine a group of shaders for a single stage to generate a linked shader
+ *
+ * \note
+ * If this function is supplied a single shader, it is cloned, and the new
+ * shader is returned.
+ */
+static struct gl_shader *
+link_intrastage_shaders(struct gl_shader_program *prog,
+ struct gl_shader **shader_list,
+ unsigned num_shaders)
+{
+ /* Check that global variables defined in multiple shaders are consistent.
+ */
+ if (!cross_validate_globals(prog, shader_list, num_shaders, false))
+ return NULL;
+
+ /* Check that there is only a single definition of each function signature
+ * across all shaders.
+ */
+ for (unsigned i = 0; i < (num_shaders - 1); i++) {
+ foreach_list(node, shader_list[i]->ir) {
+ ir_function *const f = ((ir_instruction *) node)->as_function();
+
+ if (f == NULL)
+ continue;
+
+ for (unsigned j = i + 1; j < num_shaders; j++) {
+ ir_function *const other =
+ shader_list[j]->symbols->get_function(f->name);
+
+ /* If the other shader has no function (and therefore no function
+ * signatures) with the same name, skip to the next shader.
+ */
+ if (other == NULL)
+ continue;
+
+ foreach_iter (exec_list_iterator, iter, *f) {
+ ir_function_signature *sig =
+ (ir_function_signature *) iter.get();
+
+ if (!sig->is_defined || sig->is_built_in)
+ continue;
+
+ ir_function_signature *other_sig =
+ other->exact_matching_signature(& sig->parameters);
+
+ if ((other_sig != NULL) && other_sig->is_defined
+ && !other_sig->is_built_in) {
+ linker_error_printf(prog,
+ "function `%s' is multiply defined",
+ f->name);
+ return NULL;
+ }
+ }
+ }
+ }
+ }
+
+ /* Find the shader that defines main, and make a clone of it.
+ *
+ * Starting with the clone, search for undefined references. If one is
+ * found, find the shader that defines it. Clone the reference and add
+ * it to the shader. Repeat until there are no undefined references or
+ * until a reference cannot be resolved.
+ */
+ gl_shader *main = NULL;
+ for (unsigned i = 0; i < num_shaders; i++) {
+ if (get_main_function_signature(shader_list[i]) != NULL) {
+ main = shader_list[i];
+ break;
+ }
+ }
+
+ if (main == NULL) {
+ linker_error_printf(prog, "%s shader lacks `main'\n",
+ (shader_list[0]->Type == GL_VERTEX_SHADER)
+ ? "vertex" : "fragment");
+ return NULL;
+ }
+
+ gl_shader *const linked = _mesa_new_shader(NULL, 0, main->Type);
+ linked->ir = new(linked) exec_list;
+ clone_ir_list(linked, linked->ir, main->ir);
+
+ populate_symbol_table(linked);
+
+ /* The a pointer to the main function in the final linked shader (i.e., the
+ * copy of the original shader that contained the main function).
+ */
+ ir_function_signature *const main_sig = get_main_function_signature(linked);
+
+ /* Move any instructions other than variable declarations or function
+ * declarations into main.
+ */
+ exec_node *insertion_point =
+ move_non_declarations(linked->ir, (exec_node *) &main_sig->body, false,
+ linked);
+
+ for (unsigned i = 0; i < num_shaders; i++) {
+ if (shader_list[i] == main)
+ continue;
+
+ insertion_point = move_non_declarations(shader_list[i]->ir,
+ insertion_point, true, linked);
+ }
+
+ /* Resolve initializers for global variables in the linked shader.
+ */
+ unsigned num_linking_shaders = num_shaders;
+ for (unsigned i = 0; i < num_shaders; i++)
+ num_linking_shaders += shader_list[i]->num_builtins_to_link;
+
+ gl_shader **linking_shaders =
+ (gl_shader **) calloc(num_linking_shaders, sizeof(gl_shader *));
+
+ memcpy(linking_shaders, shader_list,
+ sizeof(linking_shaders[0]) * num_shaders);
+
+ unsigned idx = num_shaders;
+ for (unsigned i = 0; i < num_shaders; i++) {
+ memcpy(&linking_shaders[idx], shader_list[i]->builtins_to_link,
+ sizeof(linking_shaders[0]) * shader_list[i]->num_builtins_to_link);
+ idx += shader_list[i]->num_builtins_to_link;
+ }
+
+ assert(idx == num_linking_shaders);
+
+ link_function_calls(prog, linked, linking_shaders, num_linking_shaders);
+
+ free(linking_shaders);
+
+ return linked;
+}
+
+
+struct uniform_node {
+ exec_node link;
+ struct gl_uniform *u;
+ unsigned slots;
+};
+
+void
+assign_uniform_locations(struct gl_shader_program *prog)
+{
+ /* */
+ exec_list uniforms;
+ unsigned total_uniforms = 0;
+ hash_table *ht = hash_table_ctor(32, hash_table_string_hash,
+ hash_table_string_compare);
+
+ for (unsigned i = 0; i < prog->_NumLinkedShaders; i++) {
+ unsigned next_position = 0;
+
+ foreach_list(node, prog->_LinkedShaders[i]->ir) {
+ ir_variable *const var = ((ir_instruction *) node)->as_variable();
+
+ if ((var == NULL) || (var->mode != ir_var_uniform))
+ continue;
+
+ const unsigned vec4_slots = (var->component_slots() + 3) / 4;
+ if (vec4_slots == 0) {
+ /* If we've got a sampler or an aggregate of them, the size can
+ * end up zero. Don't allocate any space.
+ */
+ continue;
+ }
+
+ uniform_node *n = (uniform_node *) hash_table_find(ht, var->name);
+ if (n == NULL) {
+ n = (uniform_node *) calloc(1, sizeof(struct uniform_node));
+ n->u = (gl_uniform *) calloc(vec4_slots, sizeof(struct gl_uniform));
+ n->slots = vec4_slots;
+
+ n->u[0].Name = strdup(var->name);
+ for (unsigned j = 1; j < vec4_slots; j++)
+ n->u[j].Name = n->u[0].Name;
+
+ hash_table_insert(ht, n, n->u[0].Name);
+ uniforms.push_tail(& n->link);
+ total_uniforms += vec4_slots;
+ }
+
+ if (var->constant_value != NULL)
+ for (unsigned j = 0; j < vec4_slots; j++)
+ n->u[j].Initialized = true;
+
+ var->location = next_position;
+
+ for (unsigned j = 0; j < vec4_slots; j++) {
+ switch (prog->_LinkedShaders[i]->Type) {
+ case GL_VERTEX_SHADER:
+ n->u[j].VertPos = next_position;
+ break;
+ case GL_FRAGMENT_SHADER:
+ n->u[j].FragPos = next_position;
+ break;
+ case GL_GEOMETRY_SHADER:
+ /* FINISHME: Support geometry shaders. */
+ assert(prog->_LinkedShaders[i]->Type != GL_GEOMETRY_SHADER);
+ break;
+ }
+
+ next_position++;
+ }
+ }
+ }
+
+ gl_uniform_list *ul = (gl_uniform_list *)
+ calloc(1, sizeof(gl_uniform_list));
+
+ ul->Size = total_uniforms;
+ ul->NumUniforms = total_uniforms;
+ ul->Uniforms = (gl_uniform *) calloc(total_uniforms, sizeof(gl_uniform));
+
+ unsigned idx = 0;
+ uniform_node *next;
+ for (uniform_node *node = (uniform_node *) uniforms.head
+ ; node->link.next != NULL
+ ; node = next) {
+ next = (uniform_node *) node->link.next;
+
+ node->link.remove();
+ memcpy(&ul->Uniforms[idx], node->u, sizeof(gl_uniform) * node->slots);
+ idx += node->slots;
+
+ free(node->u);
+ free(node);
+ }
+
+ hash_table_dtor(ht);
+
+ prog->Uniforms = ul;
+}
+
+
+/**
+ * Find a contiguous set of available bits in a bitmask
+ *
+ * \param used_mask Bits representing used (1) and unused (0) locations
+ * \param needed_count Number of contiguous bits needed.
+ *
+ * \return
+ * Base location of the available bits on success or -1 on failure.
+ */
+int
+find_available_slots(unsigned used_mask, unsigned needed_count)
+{
+ unsigned needed_mask = (1 << needed_count) - 1;
+ const int max_bit_to_test = (8 * sizeof(used_mask)) - needed_count;
+
+ /* The comparison to 32 is redundant, but without it GCC emits "warning:
+ * cannot optimize possibly infinite loops" for the loop below.
+ */
+ if ((needed_count == 0) || (max_bit_to_test < 0) || (max_bit_to_test > 32))
+ return -1;
+
+ for (int i = 0; i <= max_bit_to_test; i++) {
+ if ((needed_mask & ~used_mask) == needed_mask)
+ return i;
+
+ needed_mask <<= 1;
+ }
+
+ return -1;
+}
+
+
+bool
+assign_attribute_locations(gl_shader_program *prog, unsigned max_attribute_index)
+{
+ /* Mark invalid attribute locations as being used.
+ */
+ unsigned used_locations = (max_attribute_index >= 32)
+ ? ~0 : ~((1 << max_attribute_index) - 1);
+
+ gl_shader *const sh = prog->_LinkedShaders[0];
+ assert(sh->Type == GL_VERTEX_SHADER);
+
+ /* Operate in a total of four passes.
+ *
+ * 1. Invalidate the location assignments for all vertex shader inputs.
+ *
+ * 2. Assign locations for inputs that have user-defined (via
+ * glBindVertexAttribLocation) locatoins.
+ *
+ * 3. Sort the attributes without assigned locations by number of slots
+ * required in decreasing order. Fragmentation caused by attribute
+ * locations assigned by the application may prevent large attributes
+ * from having enough contiguous space.
+ *
+ * 4. Assign locations to any inputs without assigned locations.
+ */
+
+ invalidate_variable_locations(sh, ir_var_in, VERT_ATTRIB_GENERIC0);
+
+ if (prog->Attributes != NULL) {
+ for (unsigned i = 0; i < prog->Attributes->NumParameters; i++) {
+ ir_variable *const var =
+ sh->symbols->get_variable(prog->Attributes->Parameters[i].Name);
+
+ /* Note: attributes that occupy multiple slots, such as arrays or
+ * matrices, may appear in the attrib array multiple times.
+ */
+ if ((var == NULL) || (var->location != -1))
+ continue;
+
+ /* From page 61 of the OpenGL 4.0 spec:
+ *
+ * "LinkProgram will fail if the attribute bindings assigned by
+ * BindAttribLocation do not leave not enough space to assign a
+ * location for an active matrix attribute or an active attribute
+ * array, both of which require multiple contiguous generic
+ * attributes."
+ *
+ * Previous versions of the spec contain similar language but omit the
+ * bit about attribute arrays.
+ *
+ * Page 61 of the OpenGL 4.0 spec also says:
+ *
+ * "It is possible for an application to bind more than one
+ * attribute name to the same location. This is referred to as
+ * aliasing. This will only work if only one of the aliased
+ * attributes is active in the executable program, or if no path
+ * through the shader consumes more than one attribute of a set
+ * of attributes aliased to the same location. A link error can
+ * occur if the linker determines that every path through the
+ * shader consumes multiple aliased attributes, but
+ * implementations are not required to generate an error in this
+ * case."
+ *
+ * These two paragraphs are either somewhat contradictory, or I don't
+ * fully understand one or both of them.
+ */
+ /* FINISHME: The code as currently written does not support attribute
+ * FINISHME: location aliasing (see comment above).
+ */
+ const int attr = prog->Attributes->Parameters[i].StateIndexes[0];
+ const unsigned slots = count_attribute_slots(var->type);
+
+ /* Mask representing the contiguous slots that will be used by this
+ * attribute.
+ */
+ const unsigned use_mask = (1 << slots) - 1;
+
+ /* Generate a link error if the set of bits requested for this
+ * attribute overlaps any previously allocated bits.
+ */
+ if ((~(use_mask << attr) & used_locations) != used_locations) {
+ linker_error_printf(prog,
+ "insufficient contiguous attribute locations "
+ "available for vertex shader input `%s'",
+ var->name);
+ return false;
+ }
+
+ var->location = VERT_ATTRIB_GENERIC0 + attr;
+ used_locations |= (use_mask << attr);
+ }
+ }
+
+ /* Temporary storage for the set of attributes that need locations assigned.
+ */
+ struct temp_attr {
+ unsigned slots;
+ ir_variable *var;
+
+ /* Used below in the call to qsort. */
+ static int compare(const void *a, const void *b)
+ {
+ const temp_attr *const l = (const temp_attr *) a;
+ const temp_attr *const r = (const temp_attr *) b;
+
+ /* Reversed because we want a descending order sort below. */
+ return r->slots - l->slots;
+ }
+ } to_assign[16];
+
+ unsigned num_attr = 0;
+
+ foreach_list(node, sh->ir) {
+ ir_variable *const var = ((ir_instruction *) node)->as_variable();
+
+ if ((var == NULL) || (var->mode != ir_var_in))
+ continue;
+
+ /* The location was explicitly assigned, nothing to do here.
+ */
+ if (var->location != -1)
+ continue;
+
+ to_assign[num_attr].slots = count_attribute_slots(var->type);
+ to_assign[num_attr].var = var;
+ num_attr++;
+ }
+
+ /* If all of the attributes were assigned locations by the application (or
+ * are built-in attributes with fixed locations), return early. This should
+ * be the common case.
+ */
+ if (num_attr == 0)
+ return true;
+
+ qsort(to_assign, num_attr, sizeof(to_assign[0]), temp_attr::compare);
+
+ /* VERT_ATTRIB_GENERIC0 is a psdueo-alias for VERT_ATTRIB_POS. It can only
+ * be explicitly assigned by via glBindAttribLocation. Mark it as reserved
+ * to prevent it from being automatically allocated below.
+ */
+ find_deref_visitor find("gl_Vertex");
+ find.run(sh->ir);
+ if (find.variable_found())
+ used_locations |= (1 << 0);
+
+ for (unsigned i = 0; i < num_attr; i++) {
+ /* Mask representing the contiguous slots that will be used by this
+ * attribute.
+ */
+ const unsigned use_mask = (1 << to_assign[i].slots) - 1;
+
+ int location = find_available_slots(used_locations, to_assign[i].slots);
+
+ if (location < 0) {
+ linker_error_printf(prog,
+ "insufficient contiguous attribute locations "
+ "available for vertex shader input `%s'",
+ to_assign[i].var->name);
+ return false;
+ }
+
+ to_assign[i].var->location = VERT_ATTRIB_GENERIC0 + location;
+ used_locations |= (use_mask << location);
+ }
+
+ return true;
+}
+
+
+void
+assign_varying_locations(struct gl_shader_program *prog,
+ gl_shader *producer, gl_shader *consumer)
+{
+ /* FINISHME: Set dynamically when geometry shader support is added. */
+ unsigned output_index = VERT_RESULT_VAR0;
+ unsigned input_index = FRAG_ATTRIB_VAR0;
+
+ /* Operate in a total of three passes.
+ *
+ * 1. Assign locations for any matching inputs and outputs.
+ *
+ * 2. Mark output variables in the producer that do not have locations as
+ * not being outputs. This lets the optimizer eliminate them.
+ *
+ * 3. Mark input variables in the consumer that do not have locations as
+ * not being inputs. This lets the optimizer eliminate them.
+ */
+
+ invalidate_variable_locations(producer, ir_var_out, VERT_RESULT_VAR0);
+ invalidate_variable_locations(consumer, ir_var_in, FRAG_ATTRIB_VAR0);
+
+ foreach_list(node, producer->ir) {
+ ir_variable *const output_var = ((ir_instruction *) node)->as_variable();
+
+ if ((output_var == NULL) || (output_var->mode != ir_var_out)
+ || (output_var->location != -1))
+ continue;
+
+ ir_variable *const input_var =
+ consumer->symbols->get_variable(output_var->name);
+
+ if ((input_var == NULL) || (input_var->mode != ir_var_in))
+ continue;
+
+ assert(input_var->location == -1);
+
+ /* FINISHME: Location assignment will need some changes when arrays,
+ * FINISHME: matrices, and structures are allowed as shader inputs /
+ * FINISHME: outputs.
+ */
+ output_var->location = output_index;
+ input_var->location = input_index;
+
+ output_index++;
+ input_index++;
+ }
+
+ foreach_list(node, producer->ir) {
+ ir_variable *const var = ((ir_instruction *) node)->as_variable();
+
+ if ((var == NULL) || (var->mode != ir_var_out))
+ continue;
+
+ /* An 'out' variable is only really a shader output if its value is read
+ * by the following stage.
+ */
+ if (var->location == -1) {
+ var->mode = ir_var_auto;
+ }
+ }
+
+ foreach_list(node, consumer->ir) {
+ ir_variable *const var = ((ir_instruction *) node)->as_variable();
+
+ if ((var == NULL) || (var->mode != ir_var_in))
+ continue;
+
+ if (var->location == -1) {
+ if (prog->Version <= 120) {
+ /* On page 25 (page 31 of the PDF) of the GLSL 1.20 spec:
+ *
+ * Only those varying variables used (i.e. read) in
+ * the fragment shader executable must be written to
+ * by the vertex shader executable; declaring
+ * superfluous varying variables in a vertex shader is
+ * permissible.
+ *
+ * We interpret this text as meaning that the VS must
+ * write the variable for the FS to read it. See
+ * "glsl1-varying read but not written" in piglit.
+ */
+
+ linker_error_printf(prog, "fragment shader varying %s not written "
+ "by vertex shader\n.", var->name);
+ prog->LinkStatus = false;
+ }
+
+ /* An 'in' variable is only really a shader input if its
+ * value is written by the previous stage.
+ */
+ var->mode = ir_var_auto;
+ }
+ }
+}
+
+
+void
+link_shaders(struct gl_shader_program *prog)
+{
+ prog->LinkStatus = false;
+ prog->Validated = false;
+ prog->_Used = false;
+
+ if (prog->InfoLog != NULL)
+ talloc_free(prog->InfoLog);
+
+ prog->InfoLog = talloc_strdup(NULL, "");
+
+ /* Separate the shaders into groups based on their type.
+ */
+ struct gl_shader **vert_shader_list;
+ unsigned num_vert_shaders = 0;
+ struct gl_shader **frag_shader_list;
+ unsigned num_frag_shaders = 0;
+
+ vert_shader_list = (struct gl_shader **)
+ calloc(2 * prog->NumShaders, sizeof(struct gl_shader *));
+ frag_shader_list = &vert_shader_list[prog->NumShaders];
+
+ unsigned min_version = UINT_MAX;
+ unsigned max_version = 0;
+ for (unsigned i = 0; i < prog->NumShaders; i++) {
+ min_version = MIN2(min_version, prog->Shaders[i]->Version);
+ max_version = MAX2(max_version, prog->Shaders[i]->Version);
+
+ switch (prog->Shaders[i]->Type) {
+ case GL_VERTEX_SHADER:
+ vert_shader_list[num_vert_shaders] = prog->Shaders[i];
+ num_vert_shaders++;
+ break;
+ case GL_FRAGMENT_SHADER:
+ frag_shader_list[num_frag_shaders] = prog->Shaders[i];
+ num_frag_shaders++;
+ break;
+ case GL_GEOMETRY_SHADER:
+ /* FINISHME: Support geometry shaders. */
+ assert(prog->Shaders[i]->Type != GL_GEOMETRY_SHADER);
+ break;
+ }
+ }
+
+ /* Previous to GLSL version 1.30, different compilation units could mix and
+ * match shading language versions. With GLSL 1.30 and later, the versions
+ * of all shaders must match.
+ */
+ assert(min_version >= 110);
+ assert(max_version <= 130);
+ if ((max_version >= 130) && (min_version != max_version)) {
+ linker_error_printf(prog, "all shaders must use same shading "
+ "language version\n");
+ goto done;
+ }
+
+ prog->Version = max_version;
+
+ /* Link all shaders for a particular stage and validate the result.
+ */
+ prog->_NumLinkedShaders = 0;
+ if (num_vert_shaders > 0) {
+ gl_shader *const sh =
+ link_intrastage_shaders(prog, vert_shader_list, num_vert_shaders);
+
+ if (sh == NULL)
+ goto done;
+
+ if (!validate_vertex_shader_executable(prog, sh))
+ goto done;
+
+ prog->_LinkedShaders[prog->_NumLinkedShaders] = sh;
+ prog->_NumLinkedShaders++;
+ }
+
+ if (num_frag_shaders > 0) {
+ gl_shader *const sh =
+ link_intrastage_shaders(prog, frag_shader_list, num_frag_shaders);
+
+ if (sh == NULL)
+ goto done;
+
+ if (!validate_fragment_shader_executable(prog, sh))
+ goto done;
+
+ prog->_LinkedShaders[prog->_NumLinkedShaders] = sh;
+ prog->_NumLinkedShaders++;
+ }
+
+ /* Here begins the inter-stage linking phase. Some initial validation is
+ * performed, then locations are assigned for uniforms, attributes, and
+ * varyings.
+ */
+ if (cross_validate_uniforms(prog)) {
+ /* Validate the inputs of each stage with the output of the preceeding
+ * stage.
+ */
+ for (unsigned i = 1; i < prog->_NumLinkedShaders; i++) {
+ if (!cross_validate_outputs_to_inputs(prog,
+ prog->_LinkedShaders[i - 1],
+ prog->_LinkedShaders[i]))
+ goto done;
+ }
+
+ prog->LinkStatus = true;
+ }
+
+ /* Do common optimization before assigning storage for attributes,
+ * uniforms, and varyings. Later optimization could possibly make
+ * some of that unused.
+ */
+ for (unsigned i = 0; i < prog->_NumLinkedShaders; i++) {
+ while (do_common_optimization(prog->_LinkedShaders[i]->ir, true))
+ ;
+ }
+
+ assign_uniform_locations(prog);
+
+ if (prog->_LinkedShaders[0]->Type == GL_VERTEX_SHADER)
+ /* FINISHME: The value of the max_attribute_index parameter is
+ * FINISHME: implementation dependent based on the value of
+ * FINISHME: GL_MAX_VERTEX_ATTRIBS. GL_MAX_VERTEX_ATTRIBS must be
+ * FINISHME: at least 16, so hardcode 16 for now.
+ */
+ if (!assign_attribute_locations(prog, 16))
+ goto done;
+
+ for (unsigned i = 1; i < prog->_NumLinkedShaders; i++)
+ assign_varying_locations(prog,
+ prog->_LinkedShaders[i - 1],
+ prog->_LinkedShaders[i]);
+
+ /* FINISHME: Assign fragment shader output locations. */
+
+done:
+ free(vert_shader_list);
+}
diff --git a/src/glsl/linker.h b/src/glsl/linker.h
new file mode 100644
index 00000000000..a8ce16a7ec1
--- /dev/null
+++ b/src/glsl/linker.h
@@ -0,0 +1,35 @@
+/*
+ * Copyright © 2010 Intel Corporation
+ *
+ * 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 (including the next
+ * paragraph) 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
+ * THE AUTHORS OR COPYRIGHT HOLDERS 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.
+ */
+
+#pragma once
+#ifndef GLSL_LINKER_H
+#define GLSL_LINKER_H
+
+extern void
+linker_error_printf(gl_shader_program *prog, const char *fmt, ...);
+
+extern bool
+link_function_calls(gl_shader_program *prog, gl_shader *main,
+ gl_shader **shader_list, unsigned num_shaders);
+
+#endif /* GLSL_LINKER_H */
diff --git a/src/glsl/list.h b/src/glsl/list.h
new file mode 100644
index 00000000000..a70b79d571f
--- /dev/null
+++ b/src/glsl/list.h
@@ -0,0 +1,465 @@
+/*
+ * Copyright © 2008, 2010 Intel Corporation
+ *
+ * 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 (including the next
+ * paragraph) 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
+ * THE AUTHORS OR COPYRIGHT HOLDERS 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 list.h
+ * \brief Doubly-linked list abstract container type.
+ *
+ * Each doubly-linked list has a sentinel head and tail node. These nodes
+ * contain no data. The head sentinel can be identified by its \c prev
+ * pointer being \c NULL. The tail sentinel can be identified by its
+ * \c next pointer being \c NULL.
+ *
+ * A list is empty if either the head sentinel's \c next pointer points to the
+ * tail sentinel or the tail sentinel's \c prev poiner points to the head
+ * sentinel.
+ *
+ * Instead of tracking two separate \c node structures and a \c list structure
+ * that points to them, the sentinel nodes are in a single structure. Noting
+ * that each sentinel node always has one \c NULL pointer, the \c NULL
+ * pointers occupy the same memory location. In the \c list structure
+ * contains a the following:
+ *
+ * - A \c head pointer that represents the \c next pointer of the
+ * head sentinel node.
+ * - A \c tail pointer that represents the \c prev pointer of the head
+ * sentinel node and the \c next pointer of the tail sentinel node. This
+ * pointer is \b always \c NULL.
+ * - A \c tail_prev pointer that represents the \c prev pointer of the
+ * tail sentinel node.
+ *
+ * Therefore, if \c head->next is \c NULL or \c tail_prev->prev is \c NULL,
+ * the list is empty.
+ *
+ * To anyone familiar with "exec lists" on the Amiga, this structure should
+ * be immediately recognizable. See the following link for the original Amiga
+ * operating system documentation on the subject.
+ *
+ * http://www.natami.net/dev/Libraries_Manual_guide/node02D7.html
+ *
+ * \author Ian Romanick <[email protected]>
+ */
+
+#pragma once
+#ifndef LIST_CONTAINER_H
+#define LIST_CONTAINER_H
+
+#ifndef __cplusplus
+#include <stddef.h>
+#include <talloc.h>
+#else
+extern "C" {
+#include <talloc.h>
+}
+#endif
+
+#include <assert.h>
+
+struct exec_node {
+ struct exec_node *next;
+ struct exec_node *prev;
+
+#ifdef __cplusplus
+ /* Callers of this talloc-based new need not call delete. It's
+ * easier to just talloc_free 'ctx' (or any of its ancestors). */
+ static void* operator new(size_t size, void *ctx)
+ {
+ void *node;
+
+ node = talloc_size(ctx, size);
+ assert(node != NULL);
+
+ return node;
+ }
+
+ /* If the user *does* call delete, that's OK, we will just
+ * talloc_free in that case. */
+ static void operator delete(void *node)
+ {
+ talloc_free(node);
+ }
+
+ exec_node() : next(NULL), prev(NULL)
+ {
+ /* empty */
+ }
+
+ const exec_node *get_next() const
+ {
+ return next;
+ }
+
+ exec_node *get_next()
+ {
+ return next;
+ }
+
+ const exec_node *get_prev() const
+ {
+ return prev;
+ }
+
+ exec_node *get_prev()
+ {
+ return prev;
+ }
+
+ void remove()
+ {
+ next->prev = prev;
+ prev->next = next;
+ next = NULL;
+ prev = NULL;
+ }
+
+ /**
+ * Link a node with itself
+ *
+ * This creates a sort of degenerate list that is occasionally useful.
+ */
+ void self_link()
+ {
+ next = this;
+ prev = this;
+ }
+
+ /**
+ * Insert a node in the list after the current node
+ */
+ void insert_after(exec_node *after)
+ {
+ after->next = this->next;
+ after->prev = this;
+
+ this->next->prev = after;
+ this->next = after;
+ }
+ /**
+ * Insert a node in the list before the current node
+ */
+ void insert_before(exec_node *before)
+ {
+ before->next = this;
+ before->prev = this->prev;
+
+ this->prev->next = before;
+ this->prev = before;
+ }
+ /**
+ * Replace the current node with the given node.
+ */
+ void replace_with(exec_node *replacement)
+ {
+ replacement->prev = this->prev;
+ replacement->next = this->next;
+
+ this->prev->next = replacement;
+ this->next->prev = replacement;
+ }
+
+ /**
+ * Is this the sentinel at the tail of the list?
+ */
+ bool is_tail_sentinel() const
+ {
+ return this->next == NULL;
+ }
+
+ /**
+ * Is this the sentinel at the head of the list?
+ */
+ bool is_head_sentinel() const
+ {
+ return this->prev == NULL;
+ }
+#endif
+};
+
+
+#ifdef __cplusplus
+/* This macro will not work correctly if `t' uses virtual inheritance. If you
+ * are using virtual inheritance, you deserve a slow and painful death. Enjoy!
+ */
+#define exec_list_offsetof(t, f, p) \
+ (((char *) &((t *) p)->f) - ((char *) p))
+#else
+#define exec_list_offsetof(t, f, p) offsetof(t, f)
+#endif
+
+/**
+ * Get a pointer to the structure containing an exec_node
+ *
+ * Given a pointer to an \c exec_node embedded in a structure, get a pointer to
+ * the containing structure.
+ *
+ * \param type Base type of the structure containing the node
+ * \param node Pointer to the \c exec_node
+ * \param field Name of the field in \c type that is the embedded \c exec_node
+ */
+#define exec_node_data(type, node, field) \
+ ((type *) (((char *) node) - exec_list_offsetof(type, field, node)))
+
+#ifdef __cplusplus
+struct exec_node;
+
+class iterator {
+public:
+ void next()
+ {
+ }
+
+ void *get()
+ {
+ return NULL;
+ }
+
+ bool has_next() const
+ {
+ return false;
+ }
+};
+
+class exec_list_iterator : public iterator {
+public:
+ exec_list_iterator(exec_node *n) : node(n), _next(n->next)
+ {
+ /* empty */
+ }
+
+ void next()
+ {
+ node = _next;
+ _next = node->next;
+ }
+
+ void remove()
+ {
+ node->remove();
+ }
+
+ exec_node *get()
+ {
+ return node;
+ }
+
+ bool has_next() const
+ {
+ return _next != NULL;
+ }
+
+private:
+ exec_node *node;
+ exec_node *_next;
+};
+
+#define foreach_iter(iter_type, iter, container) \
+ for (iter_type iter = (container) . iterator(); iter.has_next(); iter.next())
+#endif
+
+
+struct exec_list {
+ struct exec_node *head;
+ struct exec_node *tail;
+ struct exec_node *tail_pred;
+
+#ifdef __cplusplus
+ /* Callers of this talloc-based new need not call delete. It's
+ * easier to just talloc_free 'ctx' (or any of its ancestors). */
+ static void* operator new(size_t size, void *ctx)
+ {
+ void *node;
+
+ node = talloc_size(ctx, size);
+ assert(node != NULL);
+
+ return node;
+ }
+
+ /* If the user *does* call delete, that's OK, we will just
+ * talloc_free in that case. */
+ static void operator delete(void *node)
+ {
+ talloc_free(node);
+ }
+
+ exec_list()
+ {
+ make_empty();
+ }
+
+ void make_empty()
+ {
+ head = (exec_node *) & tail;
+ tail = NULL;
+ tail_pred = (exec_node *) & head;
+ }
+
+ bool is_empty() const
+ {
+ /* There are three ways to test whether a list is empty or not.
+ *
+ * - Check to see if the \c head points to the \c tail.
+ * - Check to see if the \c tail_pred points to the \c head.
+ * - Check to see if the \c head is the sentinel node by test whether its
+ * \c next pointer is \c NULL.
+ *
+ * The first two methods tend to generate better code on modern systems
+ * because they save a pointer dereference.
+ */
+ return head == (exec_node *) &tail;
+ }
+
+ const exec_node *get_head() const
+ {
+ return !is_empty() ? head : NULL;
+ }
+
+ exec_node *get_head()
+ {
+ return !is_empty() ? head : NULL;
+ }
+
+ const exec_node *get_tail() const
+ {
+ return !is_empty() ? tail_pred : NULL;
+ }
+
+ exec_node *get_tail()
+ {
+ return !is_empty() ? tail_pred : NULL;
+ }
+
+ void push_head(exec_node *n)
+ {
+ n->next = head;
+ n->prev = (exec_node *) &head;
+
+ n->next->prev = n;
+ head = n;
+ }
+
+ void push_tail(exec_node *n)
+ {
+ n->next = (exec_node *) &tail;
+ n->prev = tail_pred;
+
+ n->prev->next = n;
+ tail_pred = n;
+ }
+
+ void push_degenerate_list_at_head(exec_node *n)
+ {
+ assert(n->prev->next == n);
+
+ n->prev->next = head;
+ head->prev = n->prev;
+ n->prev = (exec_node *) &head;
+ head = n;
+ }
+
+ /**
+ * Move all of the nodes from this list to the target list
+ */
+ void move_nodes_to(exec_list *target)
+ {
+ if (is_empty()) {
+ target->make_empty();
+ } else {
+ target->head = head;
+ target->tail = NULL;
+ target->tail_pred = tail_pred;
+
+ target->head->prev = (exec_node *) &target->head;
+ target->tail_pred->next = (exec_node *) &target->tail;
+
+ make_empty();
+ }
+ }
+
+ /**
+ * Append all nodes from the source list to the target list
+ */
+ void
+ append_list(exec_list *source)
+ {
+ if (source->is_empty())
+ return;
+
+ /* Link the first node of the source with the last node of the target list.
+ */
+ this->tail_pred->next = source->head;
+ source->head->prev = this->tail_pred;
+
+ /* Make the tail of the source list be the tail of the target list.
+ */
+ this->tail_pred = source->tail_pred;
+ this->tail_pred->next = (exec_node *) &this->tail;
+
+ /* Make the source list empty for good measure.
+ */
+ source->make_empty();
+ }
+
+ exec_list_iterator iterator()
+ {
+ return exec_list_iterator(head);
+ }
+
+ exec_list_iterator iterator() const
+ {
+ return exec_list_iterator((exec_node *) head);
+ }
+#endif
+};
+
+/**
+ * This version is safe even if the current node is removed.
+ */
+#define foreach_list_safe(__node, __list) \
+ for (exec_node * __node = (__list)->head, * __next = __node->next \
+ ; __next != NULL \
+ ; __node = __next, __next = __next->next)
+
+#define foreach_list(__node, __list) \
+ for (exec_node * __node = (__list)->head \
+ ; (__node)->next != NULL \
+ ; (__node) = (__node)->next)
+
+#define foreach_list_const(__node, __list) \
+ for (const exec_node * __node = (__list)->head \
+ ; (__node)->next != NULL \
+ ; (__node) = (__node)->next)
+
+#define foreach_list_typed(__type, __node, __field, __list) \
+ for (__type * __node = \
+ exec_node_data(__type, (__list)->head, __field); \
+ (__node)->__field.next != NULL; \
+ (__node) = exec_node_data(__type, (__node)->__field.next, __field))
+
+#define foreach_list_typed_const(__type, __node, __field, __list) \
+ for (const __type * __node = \
+ exec_node_data(__type, (__list)->head, __field); \
+ (__node)->__field.next != NULL; \
+ (__node) = exec_node_data(__type, (__node)->__field.next, __field))
+
+#endif /* LIST_CONTAINER_H */
diff --git a/src/glsl/main.cpp b/src/glsl/main.cpp
new file mode 100644
index 00000000000..24d6076d07b
--- /dev/null
+++ b/src/glsl/main.cpp
@@ -0,0 +1,283 @@
+/*
+ * Copyright © 2008, 2009 Intel Corporation
+ *
+ * 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 (including the next
+ * paragraph) 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
+ * THE AUTHORS OR COPYRIGHT HOLDERS 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.
+ */
+#include <cstdlib>
+#include <cstdio>
+#include <getopt.h>
+
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+#include <unistd.h>
+
+#include "ast.h"
+#include "glsl_parser_extras.h"
+#include "glsl_parser.h"
+#include "ir_optimization.h"
+#include "ir_print_visitor.h"
+#include "program.h"
+
+extern "C" struct gl_shader *
+_mesa_new_shader(GLcontext *ctx, GLuint name, GLenum type);
+
+/* Copied from shader_api.c for the stand-alone compiler.
+ */
+struct gl_shader *
+_mesa_new_shader(GLcontext *ctx, GLuint name, GLenum type)
+{
+ struct gl_shader *shader;
+
+ (void) ctx;
+
+ assert(type == GL_FRAGMENT_SHADER || type == GL_VERTEX_SHADER);
+ shader = talloc_zero(NULL, struct gl_shader);
+ if (shader) {
+ shader->Type = type;
+ shader->Name = name;
+ shader->RefCount = 1;
+ }
+ return shader;
+}
+
+/* Returned string will have 'ctx' as its talloc owner. */
+static char *
+load_text_file(void *ctx, const char *file_name)
+{
+ char *text = NULL;
+ struct stat st;
+ ssize_t total_read = 0;
+ int fd = open(file_name, O_RDONLY);
+
+ if (fd < 0) {
+ return NULL;
+ }
+
+ if (fstat(fd, & st) == 0) {
+ text = (char *) talloc_size(ctx, st.st_size + 1);
+ if (text != NULL) {
+ do {
+ ssize_t bytes = read(fd, text + total_read,
+ st.st_size - total_read);
+ if (bytes < 0) {
+ free(text);
+ text = NULL;
+ break;
+ }
+
+ if (bytes == 0) {
+ break;
+ }
+
+ total_read += bytes;
+ } while (total_read < st.st_size);
+
+ text[total_read] = '\0';
+ }
+ }
+
+ close(fd);
+
+ return text;
+}
+
+
+void
+usage_fail(const char *name)
+{
+ printf("%s <filename.frag|filename.vert>\n", name);
+ exit(EXIT_FAILURE);
+}
+
+
+int dump_ast = 0;
+int dump_hir = 0;
+int dump_lir = 0;
+int do_link = 0;
+
+const struct option compiler_opts[] = {
+ { "dump-ast", 0, &dump_ast, 1 },
+ { "dump-hir", 0, &dump_hir, 1 },
+ { "dump-lir", 0, &dump_lir, 1 },
+ { "link", 0, &do_link, 1 },
+ { NULL, 0, NULL, 0 }
+};
+
+void
+compile_shader(struct gl_shader *shader)
+{
+ struct _mesa_glsl_parse_state *state =
+ new(shader) _mesa_glsl_parse_state(NULL, shader->Type, shader);
+
+ const char *source = shader->Source;
+ state->error = preprocess(state, &source, &state->info_log,
+ state->extensions);
+
+ if (!state->error) {
+ _mesa_glsl_lexer_ctor(state, source);
+ _mesa_glsl_parse(state);
+ _mesa_glsl_lexer_dtor(state);
+ }
+
+ if (dump_ast) {
+ foreach_list_const(n, &state->translation_unit) {
+ ast_node *ast = exec_node_data(ast_node, n, link);
+ ast->print();
+ }
+ printf("\n\n");
+ }
+
+ shader->ir = new(shader) exec_list;
+ if (!state->error && !state->translation_unit.is_empty())
+ _mesa_ast_to_hir(shader->ir, state);
+
+ /* Print out the unoptimized IR. */
+ if (!state->error && dump_hir) {
+ validate_ir_tree(shader->ir);
+ _mesa_print_ir(shader->ir, state);
+ }
+
+ /* Optimization passes */
+ if (!state->error && !shader->ir->is_empty()) {
+ bool progress;
+ do {
+ progress = false;
+
+ progress = do_function_inlining(shader->ir) || progress;
+ progress = do_if_simplification(shader->ir) || progress;
+ progress = do_copy_propagation(shader->ir) || progress;
+ progress = do_dead_code_local(shader->ir) || progress;
+ progress = do_dead_code_unlinked(shader->ir) || progress;
+ progress = do_tree_grafting(shader->ir) || progress;
+ progress = do_constant_propagation(shader->ir) || progress;
+ progress = do_constant_variable_unlinked(shader->ir) || progress;
+ progress = do_constant_folding(shader->ir) || progress;
+ progress = do_algebraic(shader->ir) || progress;
+ progress = do_vec_index_to_swizzle(shader->ir) || progress;
+ progress = do_vec_index_to_cond_assign(shader->ir) || progress;
+ progress = do_swizzle_swizzle(shader->ir) || progress;
+ } while (progress);
+
+ validate_ir_tree(shader->ir);
+ }
+
+
+ /* Print out the resulting IR */
+ if (!state->error && dump_lir) {
+ _mesa_print_ir(shader->ir, state);
+ }
+
+ shader->symbols = state->symbols;
+ shader->CompileStatus = !state->error;
+ shader->Version = state->language_version;
+ memcpy(shader->builtins_to_link, state->builtins_to_link,
+ sizeof(shader->builtins_to_link[0]) * state->num_builtins_to_link);
+ shader->num_builtins_to_link = state->num_builtins_to_link;
+
+ if (shader->InfoLog)
+ talloc_free(shader->InfoLog);
+
+ shader->InfoLog = state->info_log;
+
+ /* Retain any live IR, but trash the rest. */
+ reparent_ir(shader->ir, shader);
+
+ talloc_free(state);
+
+ return;
+}
+
+int
+main(int argc, char **argv)
+{
+ int status = EXIT_SUCCESS;
+
+ int c;
+ int idx = 0;
+ while ((c = getopt_long(argc, argv, "", compiler_opts, &idx)) != -1)
+ /* empty */ ;
+
+
+ if (argc <= optind)
+ usage_fail(argv[0]);
+
+ struct gl_shader_program *whole_program;
+
+ whole_program = talloc_zero (NULL, struct gl_shader_program);
+ assert(whole_program != NULL);
+
+ for (/* empty */; argc > optind; optind++) {
+ whole_program->Shaders = (struct gl_shader **)
+ talloc_realloc(whole_program, whole_program->Shaders,
+ struct gl_shader *, whole_program->NumShaders + 1);
+ assert(whole_program->Shaders != NULL);
+
+ struct gl_shader *shader = talloc_zero(whole_program, gl_shader);
+
+ whole_program->Shaders[whole_program->NumShaders] = shader;
+ whole_program->NumShaders++;
+
+ const unsigned len = strlen(argv[optind]);
+ if (len < 6)
+ usage_fail(argv[0]);
+
+ const char *const ext = & argv[optind][len - 5];
+ if (strncmp(".vert", ext, 5) == 0)
+ shader->Type = GL_VERTEX_SHADER;
+ else if (strncmp(".geom", ext, 5) == 0)
+ shader->Type = GL_GEOMETRY_SHADER;
+ else if (strncmp(".frag", ext, 5) == 0)
+ shader->Type = GL_FRAGMENT_SHADER;
+ else
+ usage_fail(argv[0]);
+
+ shader->Source = load_text_file(whole_program, argv[optind]);
+ if (shader->Source == NULL) {
+ printf("File \"%s\" does not exist.\n", argv[optind]);
+ exit(EXIT_FAILURE);
+ }
+
+ compile_shader(shader);
+
+ if (!shader->CompileStatus) {
+ printf("Info log for %s:\n%s\n", argv[optind], shader->InfoLog);
+ status = EXIT_FAILURE;
+ break;
+ }
+ }
+
+ if ((status == EXIT_SUCCESS) && do_link) {
+ link_shaders(whole_program);
+ status = (whole_program->LinkStatus) ? EXIT_SUCCESS : EXIT_FAILURE;
+
+ if (strlen(whole_program->InfoLog) > 0)
+ printf("Info log for linking:\n%s\n", whole_program->InfoLog);
+ }
+
+ for (unsigned i = 0; i < whole_program->_NumLinkedShaders; i++)
+ talloc_free(whole_program->_LinkedShaders[i]);
+
+ talloc_free(whole_program);
+ _mesa_glsl_release_types();
+ _mesa_glsl_release_functions();
+
+ return status;
+}
diff --git a/src/glsl/program.h b/src/glsl/program.h
new file mode 100644
index 00000000000..0a49203d4b2
--- /dev/null
+++ b/src/glsl/program.h
@@ -0,0 +1,33 @@
+/*
+ * Copyright (C) 1999-2008 Brian Paul All Rights Reserved.
+ * Copyright (C) 2009 VMware, Inc. All Rights Reserved.
+ * Copyright © 2010 Intel Corporation
+ *
+ * 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.
+ */
+
+#include <GL/gl.h>
+#include "main/mtypes.h"
+
+extern "C" {
+#include "program/prog_parameter.h"
+#include "program/prog_uniform.h"
+}
+
+extern void
+link_shaders(struct gl_shader_program *prog);
diff --git a/src/glsl/s_expression.cpp b/src/glsl/s_expression.cpp
new file mode 100644
index 00000000000..26be23ea8fa
--- /dev/null
+++ b/src/glsl/s_expression.cpp
@@ -0,0 +1,131 @@
+/* -*- c++ -*- */
+/*
+ * Copyright © 2010 Intel Corporation
+ *
+ * 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 (including the next
+ * paragraph) 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
+ * THE AUTHORS OR COPYRIGHT HOLDERS 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.
+ */
+
+#include <cstdio>
+#include <cstdlib>
+#include <cstring>
+#include <assert.h>
+#include "s_expression.h"
+
+s_symbol::s_symbol(const char *tmp)
+{
+ this->str = talloc_strdup (this, tmp);
+ assert(this->str != NULL);
+}
+
+s_list::s_list()
+{
+}
+
+unsigned
+s_list::length() const
+{
+ unsigned i = 0;
+ foreach_iter(exec_list_iterator, it, this->subexpressions) {
+ i++;
+ }
+ return i;
+}
+
+static s_expression *
+read_atom(void *ctx, const char *& src)
+{
+ char buf[101];
+ int n;
+ if (sscanf(src, " %100[^( \v\t\r\n)]%n", buf, &n) != 1)
+ return NULL; // no atom
+ src += n;
+
+ // Check if the atom is a number.
+ char *float_end = NULL;
+ double f = strtod(buf, &float_end);
+ if (float_end != buf) {
+ char *int_end = NULL;
+ int i = strtol(buf, &int_end, 10);
+ // If strtod matched more characters, it must have a decimal part
+ if (float_end > int_end)
+ return new(ctx) s_float(f);
+
+ return new(ctx) s_int(i);
+ }
+ // Not a number; return a symbol.
+ return new(ctx) s_symbol(buf);
+}
+
+s_expression *
+s_expression::read_expression(void *ctx, const char *&src)
+{
+ assert(src != NULL);
+
+ s_expression *atom = read_atom(ctx, src);
+ if (atom != NULL)
+ return atom;
+
+ char c;
+ int n;
+ if (sscanf(src, " %c%n", &c, &n) == 1 && c == '(') {
+ src += n;
+
+ s_list *list = new(ctx) s_list;
+ s_expression *expr;
+
+ while ((expr = read_expression(ctx, src)) != NULL) {
+ list->subexpressions.push_tail(expr);
+ }
+ if (sscanf(src, " %c%n", &c, &n) != 1 || c != ')') {
+ printf("Unclosed expression (check your parenthesis).\n");
+ return NULL;
+ }
+ src += n;
+ return list;
+ }
+ return NULL;
+}
+
+void s_int::print()
+{
+ printf("%d", this->val);
+}
+
+void s_float::print()
+{
+ printf("%f", this->val);
+}
+
+void s_symbol::print()
+{
+ printf("%s", this->str);
+}
+
+void s_list::print()
+{
+ printf("(");
+ foreach_iter(exec_list_iterator, it, this->subexpressions) {
+ s_expression *expr = (s_expression*) it.get();
+ expr->print();
+ printf(" ");
+ }
+ printf(")");
+}
+
diff --git a/src/glsl/s_expression.h b/src/glsl/s_expression.h
new file mode 100644
index 00000000000..1a0c03c2189
--- /dev/null
+++ b/src/glsl/s_expression.h
@@ -0,0 +1,142 @@
+/* -*- c++ -*- */
+/*
+ * Copyright © 2010 Intel Corporation
+ *
+ * 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 (including the next
+ * paragraph) 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
+ * THE AUTHORS OR COPYRIGHT HOLDERS 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.
+ */
+
+#pragma once
+#ifndef S_EXPRESSION_H
+#define S_EXPRESSION_H
+
+#include "list.h"
+
+#define SX_AS_(t,x) ((x) && ((s_expression*) x)->is_##t()) ? ((s_##t*) (x)) \
+ : NULL
+#define SX_AS_LIST(x) SX_AS_(list, x)
+#define SX_AS_SYMBOL(x) SX_AS_(symbol, x)
+#define SX_AS_NUMBER(x) SX_AS_(number, x)
+#define SX_AS_INT(x) SX_AS_(int, x)
+
+/* For our purposes, S-Expressions are:
+ * - <int>
+ * - <float>
+ * - symbol
+ * - (expr1 expr2 ... exprN) where exprN is an S-Expression
+ *
+ * Unlike LISP/Scheme, we do not support (foo . bar) pairs.
+ */
+class s_expression : public exec_node
+{
+public:
+ /**
+ * Read an S-Expression from the given string.
+ * Advances the supplied pointer to just after the expression read.
+ *
+ * Any allocation will be performed with 'ctx' as the talloc owner.
+ */
+ static s_expression *read_expression(void *ctx, const char *&src);
+
+ /**
+ * Print out an S-Expression. Useful for debugging.
+ */
+ virtual void print() = 0;
+
+ virtual bool is_list() const { return false; }
+ virtual bool is_symbol() const { return false; }
+ virtual bool is_number() const { return false; }
+ virtual bool is_int() const { return false; }
+
+protected:
+ s_expression() { }
+};
+
+/* Atoms */
+
+class s_number : public s_expression
+{
+public:
+ bool is_number() const { return true; }
+
+ virtual float fvalue() = 0;
+
+protected:
+ s_number() { }
+};
+
+class s_int : public s_number
+{
+public:
+ s_int(int x) : val(x) { }
+
+ bool is_int() const { return true; }
+
+ float fvalue() { return float(this->val); }
+ int value() { return this->val; }
+
+ void print();
+
+private:
+ int val;
+};
+
+class s_float : public s_number
+{
+public:
+ s_float(float x) : val(x) { }
+
+ float fvalue() { return this->val; }
+
+ void print();
+
+private:
+ float val;
+};
+
+class s_symbol : public s_expression
+{
+public:
+ s_symbol(const char *);
+
+ bool is_symbol() const { return true; }
+
+ const char *value() { return this->str; }
+
+ void print();
+
+private:
+ char *str;
+};
+
+/* Lists of expressions: (expr1 ... exprN) */
+class s_list : public s_expression
+{
+public:
+ s_list();
+
+ virtual bool is_list() const { return true; }
+ unsigned length() const;
+
+ void print();
+
+ exec_list subexpressions;
+};
+
+#endif /* S_EXPRESSION_H */
diff --git a/src/glsl/tests/array-01.glsl b/src/glsl/tests/array-01.glsl
new file mode 100644
index 00000000000..d14135fb3a8
--- /dev/null
+++ b/src/glsl/tests/array-01.glsl
@@ -0,0 +1,3 @@
+#version 120
+/* FAIL - array size type must be int */
+uniform vec4 [3.2] a;
diff --git a/src/glsl/tests/array-02.glsl b/src/glsl/tests/array-02.glsl
new file mode 100644
index 00000000000..d743617158d
--- /dev/null
+++ b/src/glsl/tests/array-02.glsl
@@ -0,0 +1,3 @@
+#version 120
+/* FAIL - array size type must be scalar */
+uniform vec4 [ivec4(3)] a;
diff --git a/src/glsl/tests/array-03.glsl b/src/glsl/tests/array-03.glsl
new file mode 100644
index 00000000000..0026913f019
--- /dev/null
+++ b/src/glsl/tests/array-03.glsl
@@ -0,0 +1,3 @@
+#version 120
+/* PASS */
+uniform vec4 [3] a;
diff --git a/src/glsl/tests/array-04.glsl b/src/glsl/tests/array-04.glsl
new file mode 100644
index 00000000000..70f434d8ab6
--- /dev/null
+++ b/src/glsl/tests/array-04.glsl
@@ -0,0 +1,2 @@
+/* FAIL - array size type must be int */
+uniform vec4 a[3.2];
diff --git a/src/glsl/tests/array-05.glsl b/src/glsl/tests/array-05.glsl
new file mode 100644
index 00000000000..168704096b0
--- /dev/null
+++ b/src/glsl/tests/array-05.glsl
@@ -0,0 +1,2 @@
+/* FAIL - array size type must be scalar */
+uniform vec4 a[ivec4(3)];
diff --git a/src/glsl/tests/array-06.glsl b/src/glsl/tests/array-06.glsl
new file mode 100644
index 00000000000..46b43795be1
--- /dev/null
+++ b/src/glsl/tests/array-06.glsl
@@ -0,0 +1,2 @@
+/* PASS */
+uniform vec4 a[3];
diff --git a/src/glsl/tests/array-07.glsl b/src/glsl/tests/array-07.glsl
new file mode 100644
index 00000000000..161ffbf2f2e
--- /dev/null
+++ b/src/glsl/tests/array-07.glsl
@@ -0,0 +1,2 @@
+/* FAIL - array size must be > 0 */
+uniform vec4 a[0];
diff --git a/src/glsl/tests/array-08.glsl b/src/glsl/tests/array-08.glsl
new file mode 100644
index 00000000000..4bf0c6bd513
--- /dev/null
+++ b/src/glsl/tests/array-08.glsl
@@ -0,0 +1,2 @@
+/* FAIL - array size must be > 0 */
+uniform vec4 a[-1];
diff --git a/src/glsl/tests/array-09.glsl b/src/glsl/tests/array-09.glsl
new file mode 100644
index 00000000000..cad6d0e54ec
--- /dev/null
+++ b/src/glsl/tests/array-09.glsl
@@ -0,0 +1,9 @@
+#version 120
+/* PASS */
+
+void main()
+{
+ vec4 a[2] = vec4 [2] (vec4(1.0), vec4(2.0));
+
+ gl_Position = gl_Vertex;
+}
diff --git a/src/glsl/tests/array-10.glsl b/src/glsl/tests/array-10.glsl
new file mode 100644
index 00000000000..019aa21150f
--- /dev/null
+++ b/src/glsl/tests/array-10.glsl
@@ -0,0 +1,11 @@
+/* FAIL - array constructors forbidden in GLSL 1.10
+ *
+ * This can also generate an error because the 'vec4[]' style syntax is
+ * illegal in GLSL 1.10.
+ */
+void main()
+{
+ vec4 a[2] = vec4 [2] (vec4(1.0), vec4(2.0));
+
+ gl_Position = gl_Vertex;
+}
diff --git a/src/glsl/tests/array-11.glsl b/src/glsl/tests/array-11.glsl
new file mode 100644
index 00000000000..51d94e94773
--- /dev/null
+++ b/src/glsl/tests/array-11.glsl
@@ -0,0 +1,9 @@
+#version 120
+/* PASS */
+
+void main()
+{
+ vec4 a[] = vec4 [] (vec4(1.0), vec4(2.0));
+
+ gl_Position = gl_Vertex;
+}
diff --git a/src/glsl/tests/array-12.glsl b/src/glsl/tests/array-12.glsl
new file mode 100644
index 00000000000..7fc9579452f
--- /dev/null
+++ b/src/glsl/tests/array-12.glsl
@@ -0,0 +1,11 @@
+#version 120
+/* FAIL - array must have an implicit or explicit size */
+
+void main()
+{
+ vec4 a[];
+
+ a = vec4 [2] (vec4(1.0), vec4(2.0));
+
+ gl_Position = gl_Vertex;
+}
diff --git a/src/glsl/tests/array-13.glsl b/src/glsl/tests/array-13.glsl
new file mode 100644
index 00000000000..cc7e29a5f76
--- /dev/null
+++ b/src/glsl/tests/array-13.glsl
@@ -0,0 +1,11 @@
+#version 120
+/* PASS */
+
+void main()
+{
+ vec4 a[2];
+
+ a = vec4 [] (vec4(1.0), vec4(2.0));
+
+ gl_Position = gl_Vertex;
+}
diff --git a/src/glsl/tests/attribute-01.glsl b/src/glsl/tests/attribute-01.glsl
new file mode 100644
index 00000000000..18e9e4468aa
--- /dev/null
+++ b/src/glsl/tests/attribute-01.glsl
@@ -0,0 +1,7 @@
+/* FAIL - attribute cannot have type int */
+attribute int i;
+
+void main()
+{
+ gl_Position = vec4(1.0);
+}
diff --git a/src/glsl/tests/attribute-02.glsl b/src/glsl/tests/attribute-02.glsl
new file mode 100644
index 00000000000..6b6df74d252
--- /dev/null
+++ b/src/glsl/tests/attribute-02.glsl
@@ -0,0 +1,7 @@
+/* FAIL - attribute cannot have type ivec2 */
+attribute ivec2 i;
+
+void main()
+{
+ gl_Position = vec4(1.0);
+}
diff --git a/src/glsl/tests/attribute-03.glsl b/src/glsl/tests/attribute-03.glsl
new file mode 100644
index 00000000000..870de9e8148
--- /dev/null
+++ b/src/glsl/tests/attribute-03.glsl
@@ -0,0 +1,7 @@
+/* FAIL - attribute cannot have type ivec3 */
+attribute ivec3 i;
+
+void main()
+{
+ gl_Position = vec4(1.0);
+}
diff --git a/src/glsl/tests/attribute-04.glsl b/src/glsl/tests/attribute-04.glsl
new file mode 100644
index 00000000000..14af2fcaadd
--- /dev/null
+++ b/src/glsl/tests/attribute-04.glsl
@@ -0,0 +1,7 @@
+/* FAIL - attribute cannot have type ivec4 */
+attribute ivec4 i;
+
+void main()
+{
+ gl_Position = vec4(1.0);
+}
diff --git a/src/glsl/tests/attribute-05.glsl b/src/glsl/tests/attribute-05.glsl
new file mode 100644
index 00000000000..18822c78541
--- /dev/null
+++ b/src/glsl/tests/attribute-05.glsl
@@ -0,0 +1,7 @@
+/* FAIL - attribute cannot have type bool */
+attribute bool i;
+
+void main()
+{
+ gl_Position = vec4(1.0);
+}
diff --git a/src/glsl/tests/attribute-06.glsl b/src/glsl/tests/attribute-06.glsl
new file mode 100644
index 00000000000..f18027b81af
--- /dev/null
+++ b/src/glsl/tests/attribute-06.glsl
@@ -0,0 +1,7 @@
+/* FAIL - attribute cannot have type bvec2 */
+attribute bvec2 i;
+
+void main()
+{
+ gl_Position = vec4(1.0);
+}
diff --git a/src/glsl/tests/attribute-07.glsl b/src/glsl/tests/attribute-07.glsl
new file mode 100644
index 00000000000..0af13ba84bf
--- /dev/null
+++ b/src/glsl/tests/attribute-07.glsl
@@ -0,0 +1,7 @@
+/* FAIL - attribute cannot have type bvec3 */
+attribute bvec3 i;
+
+void main()
+{
+ gl_Position = vec4(1.0);
+}
diff --git a/src/glsl/tests/attribute-08.glsl b/src/glsl/tests/attribute-08.glsl
new file mode 100644
index 00000000000..b069c04d1b4
--- /dev/null
+++ b/src/glsl/tests/attribute-08.glsl
@@ -0,0 +1,7 @@
+/* FAIL - attribute cannot have type bvec4 */
+attribute bvec4 i;
+
+void main()
+{
+ gl_Position = vec4(1.0);
+}
diff --git a/src/glsl/tests/attribute-09.glsl b/src/glsl/tests/attribute-09.glsl
new file mode 100644
index 00000000000..6a607244b9a
--- /dev/null
+++ b/src/glsl/tests/attribute-09.glsl
@@ -0,0 +1,7 @@
+/* FAIL - attribute cannot have array type in GLSL 1.10 */
+attribute vec4 i[10];
+
+void main()
+{
+ gl_Position = vec4(1.0);
+}
diff --git a/src/glsl/tests/attribute-10.glsl b/src/glsl/tests/attribute-10.glsl
new file mode 100644
index 00000000000..6f5ef63a015
--- /dev/null
+++ b/src/glsl/tests/attribute-10.glsl
@@ -0,0 +1,8 @@
+#version 120
+/* FAIL - attribute cannot have array type in GLSL 1.20 */
+attribute vec4 i[10];
+
+void main()
+{
+ gl_Position = vec4(1.0);
+}
diff --git a/src/glsl/tests/attribute-11.glsl b/src/glsl/tests/attribute-11.glsl
new file mode 100644
index 00000000000..47cb5a05833
--- /dev/null
+++ b/src/glsl/tests/attribute-11.glsl
@@ -0,0 +1,8 @@
+#version 130
+/* FAIL - attribute cannot have array type in GLSL 1.30 */
+attribute vec4 i[10];
+
+void main()
+{
+ gl_Position = vec4(1.0);
+}
diff --git a/src/glsl/tests/condition-01.glsl b/src/glsl/tests/condition-01.glsl
new file mode 100644
index 00000000000..d89c313117e
--- /dev/null
+++ b/src/glsl/tests/condition-01.glsl
@@ -0,0 +1,8 @@
+/* FAIL - :? condition is not bool scalar */
+
+uniform bvec4 a;
+
+void main()
+{
+ gl_Position = (a) ? vec4(1.0, 0.0, 0.0, 1.0) : vec4(0.0, 1.0, 0.0, 1.0);
+}
diff --git a/src/glsl/tests/condition-02.glsl b/src/glsl/tests/condition-02.glsl
new file mode 100644
index 00000000000..cbd0e18d9a8
--- /dev/null
+++ b/src/glsl/tests/condition-02.glsl
@@ -0,0 +1,8 @@
+/* FAIL - :? condition is not bool scalar */
+
+uniform float a;
+
+void main()
+{
+ gl_Position = (a) ? vec4(1.0, 0.0, 0.0, 1.0) : vec4(0.0, 1.0, 0.0, 1.0);
+}
diff --git a/src/glsl/tests/condition-03.glsl b/src/glsl/tests/condition-03.glsl
new file mode 100644
index 00000000000..9af5d7aa470
--- /dev/null
+++ b/src/glsl/tests/condition-03.glsl
@@ -0,0 +1,8 @@
+/* PASS */
+
+uniform bool a;
+
+void main()
+{
+ gl_Position = (a) ? vec4(1.0, 0.0, 0.0, 1.0) : vec4(0.0, 1.0, 0.0, 1.0);
+}
diff --git a/src/glsl/tests/condition-04.glsl b/src/glsl/tests/condition-04.glsl
new file mode 100644
index 00000000000..f440b7e9955
--- /dev/null
+++ b/src/glsl/tests/condition-04.glsl
@@ -0,0 +1,8 @@
+/* FAIL - type of second two operands must match */
+
+uniform bool a;
+
+void main()
+{
+ gl_Position = (a) ? vec4(1.0, 0.0, 0.0, 1.0) : vec3(0.0, 1.0, 0.0);
+}
diff --git a/src/glsl/tests/condition-05.glsl b/src/glsl/tests/condition-05.glsl
new file mode 100644
index 00000000000..3dff18f519d
--- /dev/null
+++ b/src/glsl/tests/condition-05.glsl
@@ -0,0 +1,13 @@
+#version 120
+/* PASS */
+
+uniform bool a;
+uniform int b;
+
+void main()
+{
+ float x;
+
+ x = (a) ? 2.0 : b;
+ gl_Position = vec4(x);
+}
diff --git a/src/glsl/tests/constructor-01.glsl b/src/glsl/tests/constructor-01.glsl
new file mode 100644
index 00000000000..fdfaf898663
--- /dev/null
+++ b/src/glsl/tests/constructor-01.glsl
@@ -0,0 +1,6 @@
+/* PASS */
+
+void main()
+{
+ gl_Position = vec4(1.0, 1.0, 1.0, 0.0);;
+}
diff --git a/src/glsl/tests/constructor-02.glsl b/src/glsl/tests/constructor-02.glsl
new file mode 100644
index 00000000000..47acbe9db14
--- /dev/null
+++ b/src/glsl/tests/constructor-02.glsl
@@ -0,0 +1,7 @@
+/* FAIL - cannot construct samplers */
+void main()
+{
+ int i;
+
+ i = sampler2D(0);
+}
diff --git a/src/glsl/tests/constructor-03.glsl b/src/glsl/tests/constructor-03.glsl
new file mode 100644
index 00000000000..07ec225633a
--- /dev/null
+++ b/src/glsl/tests/constructor-03.glsl
@@ -0,0 +1,12 @@
+/* FAIL - cannot construct a matrix from a matrix in GLSL 1.10 */
+
+uniform mat2 a;
+
+void main()
+{
+ mat2 b;
+
+ b = mat2(a);
+
+ gl_Position = gl_Vertex;
+}
diff --git a/src/glsl/tests/constructor-04.glsl b/src/glsl/tests/constructor-04.glsl
new file mode 100644
index 00000000000..19d5e011dea
--- /dev/null
+++ b/src/glsl/tests/constructor-04.glsl
@@ -0,0 +1,14 @@
+#version 120
+/* FAIL - matrix must be only parameter to matrix constructor */
+
+uniform mat2 a;
+uniform float x;
+
+void main()
+{
+ mat2 b;
+
+ b = mat2(a, x);
+
+ gl_Position = gl_Vertex;
+}
diff --git a/src/glsl/tests/constructor-05.glsl b/src/glsl/tests/constructor-05.glsl
new file mode 100644
index 00000000000..9c74f75a404
--- /dev/null
+++ b/src/glsl/tests/constructor-05.glsl
@@ -0,0 +1,13 @@
+/* FAIL - too few components supplied to constructor */
+
+uniform vec2 a;
+uniform float x;
+
+void main()
+{
+ mat2 b;
+
+ b = mat2(a, x);
+
+ gl_Position = gl_Vertex;
+}
diff --git a/src/glsl/tests/constructor-06.glsl b/src/glsl/tests/constructor-06.glsl
new file mode 100644
index 00000000000..d77a5f9e892
--- /dev/null
+++ b/src/glsl/tests/constructor-06.glsl
@@ -0,0 +1,13 @@
+#version 120
+/* PASS */
+
+uniform mat2 a;
+
+void main()
+{
+ mat2 b;
+
+ b = mat2(a);
+
+ gl_Position = gl_Vertex;
+}
diff --git a/src/glsl/tests/constructor-07.glsl b/src/glsl/tests/constructor-07.glsl
new file mode 100644
index 00000000000..92322506ed1
--- /dev/null
+++ b/src/glsl/tests/constructor-07.glsl
@@ -0,0 +1,13 @@
+/* PASS */
+
+uniform ivec2 a;
+uniform ivec2 b;
+
+void main()
+{
+ mat2 c;
+
+ c = mat2(a, b);
+
+ gl_Position = gl_Vertex;
+}
diff --git a/src/glsl/tests/constructor-08.glsl b/src/glsl/tests/constructor-08.glsl
new file mode 100644
index 00000000000..27153f0cda1
--- /dev/null
+++ b/src/glsl/tests/constructor-08.glsl
@@ -0,0 +1,13 @@
+/* PASS */
+
+uniform float a;
+uniform float b;
+
+void main()
+{
+ ivec2 c;
+
+ c = ivec2(a, b);
+
+ gl_Position = gl_Vertex;
+}
diff --git a/src/glsl/tests/constructor-09.glsl b/src/glsl/tests/constructor-09.glsl
new file mode 100644
index 00000000000..1985699b305
--- /dev/null
+++ b/src/glsl/tests/constructor-09.glsl
@@ -0,0 +1,26 @@
+/* PASS */
+
+uniform int a;
+uniform float b;
+uniform bool c;
+
+void main()
+{
+ float x;
+ int y;
+ bool z;
+
+ x = float(a);
+ x = float(b);
+ x = float(c);
+
+ y = int(a);
+ y = int(b);
+ y = int(c);
+
+ z = bool(a);
+ z = bool(b);
+ z = bool(c);
+
+ gl_Position = gl_Vertex;
+}
diff --git a/src/glsl/tests/function-01.glsl b/src/glsl/tests/function-01.glsl
new file mode 100644
index 00000000000..0eaa2397ab6
--- /dev/null
+++ b/src/glsl/tests/function-01.glsl
@@ -0,0 +1,16 @@
+/* FAIL - no function named 'foo' exists */
+
+vec4 bar(float x, float y, float z, float w)
+{
+ vec4 v;
+ v.x = x;
+ v.y = y;
+ v.z = z;
+ v.w = w;
+ return v;
+}
+
+void main()
+{
+ gl_Position = foo(1.0, 1.0, 1.0, 0.0);
+}
diff --git a/src/glsl/tests/function-02.glsl b/src/glsl/tests/function-02.glsl
new file mode 100644
index 00000000000..941fcc1ef7b
--- /dev/null
+++ b/src/glsl/tests/function-02.glsl
@@ -0,0 +1,16 @@
+/* FAIL - no version of 'foo' matches the call to 'foo' */
+
+vec4 foo(float x, float y, float z, float w)
+{
+ vec4 v;
+ v.x = x;
+ v.y = y;
+ v.z = z;
+ v.w = w;
+ return v;
+}
+
+void main()
+{
+ gl_Position = foo(1.0, 1.0, 1.0);
+}
diff --git a/src/glsl/tests/function-03.glsl b/src/glsl/tests/function-03.glsl
new file mode 100644
index 00000000000..b0da42f8e96
--- /dev/null
+++ b/src/glsl/tests/function-03.glsl
@@ -0,0 +1,16 @@
+/* PASS */
+
+vec4 foo(in float x, in float y, float z, float w)
+{
+ vec4 v;
+ v.x = x;
+ v.y = y;
+ v.z = z;
+ v.w = w;
+ return v;
+}
+
+void main()
+{
+ gl_Position = foo(1.0, 1.0, 1.0, 0.0);
+}
diff --git a/src/glsl/tests/function-04.glsl b/src/glsl/tests/function-04.glsl
new file mode 100644
index 00000000000..dfc0d2b7a6c
--- /dev/null
+++ b/src/glsl/tests/function-04.glsl
@@ -0,0 +1,15 @@
+/* FAIL - type mismatch in assignment */
+
+vec3 foo(float x, float y, float z)
+{
+ vec3 v;
+ v.x = x;
+ v.y = y;
+ v.z = z;
+ return v;
+}
+
+void main()
+{
+ gl_Position = foo(1.0, 1.0, 1.0);
+}
diff --git a/src/glsl/tests/function-05.glsl b/src/glsl/tests/function-05.glsl
new file mode 100644
index 00000000000..43365bf6062
--- /dev/null
+++ b/src/glsl/tests/function-05.glsl
@@ -0,0 +1,26 @@
+/* PASS */
+
+vec4 foo(in float x, in float y, float z, float w)
+{
+ vec4 v;
+ v.x = x;
+ v.y = y;
+ v.z = z;
+ v.w = w;
+ return v;
+}
+
+vec4 foo(in float x)
+{
+ vec4 v;
+ v.x = x;
+ v.y = x;
+ v.z = x;
+ v.w = x;
+}
+
+void main()
+{
+ gl_Position = foo(1.0, 1.0, 1.0, 0.0);
+ gl_Position = foo(2.0);
+}
diff --git a/src/glsl/tests/if-01.glsl b/src/glsl/tests/if-01.glsl
new file mode 100644
index 00000000000..ca9abd54f75
--- /dev/null
+++ b/src/glsl/tests/if-01.glsl
@@ -0,0 +1,11 @@
+/* FAIL - if-statement condition is not bool scalar */
+
+uniform bvec4 a;
+
+void main()
+{
+ if (a)
+ gl_Position = vec4(1.0, 0.0, 0.0, 1.0);
+ else
+ gl_Position = vec4(0.0, 1.0, 0.0, 1.0);
+}
diff --git a/src/glsl/tests/if-02.glsl b/src/glsl/tests/if-02.glsl
new file mode 100644
index 00000000000..7adccea0432
--- /dev/null
+++ b/src/glsl/tests/if-02.glsl
@@ -0,0 +1,11 @@
+/* FAIL - if-statement condition is not bool scalar */
+
+uniform float a;
+
+void main()
+{
+ if (a)
+ gl_Position = vec4(1.0, 0.0, 0.0, 1.0);
+ else
+ gl_Position = vec4(0.0, 1.0, 0.0, 1.0);
+}
diff --git a/src/glsl/tests/if-03.glsl b/src/glsl/tests/if-03.glsl
new file mode 100644
index 00000000000..179618c716e
--- /dev/null
+++ b/src/glsl/tests/if-03.glsl
@@ -0,0 +1,11 @@
+/* PASS */
+
+uniform bool a;
+
+void main()
+{
+ if (a)
+ gl_Position = vec4(1.0, 0.0, 0.0, 1.0);
+ else
+ gl_Position = vec4(0.0, 1.0, 0.0, 1.0);
+}
diff --git a/src/glsl/tests/if-04.glsl b/src/glsl/tests/if-04.glsl
new file mode 100644
index 00000000000..7b711fb7edf
--- /dev/null
+++ b/src/glsl/tests/if-04.glsl
@@ -0,0 +1,11 @@
+/* PASS */
+
+uniform bvec4 a;
+
+void main()
+{
+ if (a.x)
+ gl_Position = vec4(1.0, 0.0, 0.0, 1.0);
+ else
+ gl_Position = vec4(0.0, 1.0, 0.0, 1.0);
+}
diff --git a/src/glsl/tests/matrix-01.glsl b/src/glsl/tests/matrix-01.glsl
new file mode 100644
index 00000000000..f46416c8f67
--- /dev/null
+++ b/src/glsl/tests/matrix-01.glsl
@@ -0,0 +1,6 @@
+/* FAIL - non-square matrices are not available in GLSL 1.10 */
+
+void main()
+{
+ mat2x3 m;
+}
diff --git a/src/glsl/tests/matrix-02.glsl b/src/glsl/tests/matrix-02.glsl
new file mode 100644
index 00000000000..0630722b795
--- /dev/null
+++ b/src/glsl/tests/matrix-02.glsl
@@ -0,0 +1,6 @@
+/* FAIL - non-square matrices are not available in GLSL 1.10 */
+
+void main()
+{
+ mat2x4 m;
+}
diff --git a/src/glsl/tests/matrix-03.glsl b/src/glsl/tests/matrix-03.glsl
new file mode 100644
index 00000000000..925dc806258
--- /dev/null
+++ b/src/glsl/tests/matrix-03.glsl
@@ -0,0 +1,6 @@
+/* FAIL - non-square matrices are not available in GLSL 1.10 */
+
+void main()
+{
+ mat3x2 m;
+}
diff --git a/src/glsl/tests/matrix-04.glsl b/src/glsl/tests/matrix-04.glsl
new file mode 100644
index 00000000000..5275619b319
--- /dev/null
+++ b/src/glsl/tests/matrix-04.glsl
@@ -0,0 +1,6 @@
+/* FAIL - non-square matrices are not available in GLSL 1.10 */
+
+void main()
+{
+ mat3x4 m;
+}
diff --git a/src/glsl/tests/matrix-05.glsl b/src/glsl/tests/matrix-05.glsl
new file mode 100644
index 00000000000..74e1fd25148
--- /dev/null
+++ b/src/glsl/tests/matrix-05.glsl
@@ -0,0 +1,6 @@
+/* FAIL - non-square matrices are not available in GLSL 1.10 */
+
+void main()
+{
+ mat4x2 m;
+}
diff --git a/src/glsl/tests/matrix-06.glsl b/src/glsl/tests/matrix-06.glsl
new file mode 100644
index 00000000000..0a512b85234
--- /dev/null
+++ b/src/glsl/tests/matrix-06.glsl
@@ -0,0 +1,6 @@
+/* FAIL - non-square matrices are not available in GLSL 1.10 */
+
+void main()
+{
+ mat4x3 m;
+}
diff --git a/src/glsl/tests/matrix-07.glsl b/src/glsl/tests/matrix-07.glsl
new file mode 100644
index 00000000000..0b59aa69d50
--- /dev/null
+++ b/src/glsl/tests/matrix-07.glsl
@@ -0,0 +1,27 @@
+/* PASS */
+
+uniform mat2 a;
+uniform mat2 b;
+uniform mat2 c;
+uniform mat2 d;
+uniform mat3 e;
+uniform mat3 f;
+uniform mat3 g;
+uniform mat3 h;
+uniform mat4 i;
+uniform mat4 j;
+uniform mat4 k;
+uniform mat4 l;
+
+void main()
+{
+ mat2 x;
+ mat3 y;
+ mat4 z;
+
+ x = a * b + c / d;
+ y = e * f + g / h;
+ z = i * j + k / l;
+
+ gl_Position = gl_Vertex;
+}
diff --git a/src/glsl/tests/matrix-08.glsl b/src/glsl/tests/matrix-08.glsl
new file mode 100644
index 00000000000..38138d22de4
--- /dev/null
+++ b/src/glsl/tests/matrix-08.glsl
@@ -0,0 +1,19 @@
+#version 120
+/* PASS */
+
+uniform mat2x3 a;
+uniform mat3x2 b;
+uniform mat3x3 c;
+uniform mat3x3 d;
+
+void main()
+{
+ mat3x3 x;
+
+ /* Multiplying a 2 column, 3 row matrix with a 3 column, 2 row matrix
+ * results in a 3 column, 3 row matrix.
+ */
+ x = (a * b) + c / d;
+
+ gl_Position = gl_Vertex;
+}
diff --git a/src/glsl/tests/matrix-09.glsl b/src/glsl/tests/matrix-09.glsl
new file mode 100644
index 00000000000..18afbcacea7
--- /dev/null
+++ b/src/glsl/tests/matrix-09.glsl
@@ -0,0 +1,11 @@
+/* FAIL - matrix-to-matrix constructors are not available in GLSL 1.10 */
+
+uniform mat3 a;
+
+void main()
+{
+ mat2 m;
+
+ m = mat2(a);
+ gl_Position = gl_Vertex;
+}
diff --git a/src/glsl/tests/matrix-10.glsl b/src/glsl/tests/matrix-10.glsl
new file mode 100644
index 00000000000..20b55180cbb
--- /dev/null
+++ b/src/glsl/tests/matrix-10.glsl
@@ -0,0 +1,12 @@
+#version 120
+/* PASS */
+
+uniform mat3 a;
+
+void main()
+{
+ mat2 m;
+
+ m = mat2(a);
+ gl_Position = gl_Vertex;
+}
diff --git a/src/glsl/tests/parameters-01.glsl b/src/glsl/tests/parameters-01.glsl
new file mode 100644
index 00000000000..b485106e9d7
--- /dev/null
+++ b/src/glsl/tests/parameters-01.glsl
@@ -0,0 +1,11 @@
+/* FAIL: redefinition of a() */
+
+void a()
+{
+ ;
+}
+
+void a()
+{
+ ;
+}
diff --git a/src/glsl/tests/parameters-02.glsl b/src/glsl/tests/parameters-02.glsl
new file mode 100644
index 00000000000..7ff5f59ab79
--- /dev/null
+++ b/src/glsl/tests/parameters-02.glsl
@@ -0,0 +1,11 @@
+/* PASS */
+
+void a()
+{
+ ;
+}
+
+void a(float x)
+{
+ ;
+}
diff --git a/src/glsl/tests/parameters-03.glsl b/src/glsl/tests/parameters-03.glsl
new file mode 100644
index 00000000000..7ec30f80cc6
--- /dev/null
+++ b/src/glsl/tests/parameters-03.glsl
@@ -0,0 +1,9 @@
+/* FAIL - x is redeclared in the function body at the same scope as the
+ * parameter
+ */
+void a(float x, float y)
+{
+ float x;
+
+ x = y;
+}
diff --git a/src/glsl/tests/qualifier-01.glsl b/src/glsl/tests/qualifier-01.glsl
new file mode 100644
index 00000000000..54ec3572a24
--- /dev/null
+++ b/src/glsl/tests/qualifier-01.glsl
@@ -0,0 +1,3 @@
+#version 130
+/* FAIL - inout only allowed in parameter list */
+inout vec4 foo;
diff --git a/src/glsl/tests/qualifier-02.glsl b/src/glsl/tests/qualifier-02.glsl
new file mode 100644
index 00000000000..b635d52aa2a
--- /dev/null
+++ b/src/glsl/tests/qualifier-02.glsl
@@ -0,0 +1,2 @@
+/* FAIL - in only allowed in parameter list in GLSL 1.10 */
+in foo;
diff --git a/src/glsl/tests/qualifier-03.glsl b/src/glsl/tests/qualifier-03.glsl
new file mode 100644
index 00000000000..7e448034a7c
--- /dev/null
+++ b/src/glsl/tests/qualifier-03.glsl
@@ -0,0 +1,2 @@
+/* FAIL - out only allowed in parameter list in GLSL 1.10 */
+out vec4 foo;
diff --git a/src/glsl/tests/qualifier-04.glsl b/src/glsl/tests/qualifier-04.glsl
new file mode 100644
index 00000000000..d03cafc1db2
--- /dev/null
+++ b/src/glsl/tests/qualifier-04.glsl
@@ -0,0 +1,3 @@
+#version 130
+/* PASS */
+in vec4 foo;
diff --git a/src/glsl/tests/qualifier-05.glsl b/src/glsl/tests/qualifier-05.glsl
new file mode 100644
index 00000000000..15281f33840
--- /dev/null
+++ b/src/glsl/tests/qualifier-05.glsl
@@ -0,0 +1,3 @@
+#version 130
+/* PASS */
+out vec4 foo;
diff --git a/src/glsl/tests/qualifier-06.glsl b/src/glsl/tests/qualifier-06.glsl
new file mode 100644
index 00000000000..1907a087c8e
--- /dev/null
+++ b/src/glsl/tests/qualifier-06.glsl
@@ -0,0 +1,7 @@
+/* FAIL - in only allowed in parameter list in GLSL 1.10 */
+void main()
+{
+ in vec4 foo;
+
+ gl_Position = gl_Vertex;
+}
diff --git a/src/glsl/tests/qualifier-07.glsl b/src/glsl/tests/qualifier-07.glsl
new file mode 100644
index 00000000000..12568a57dbc
--- /dev/null
+++ b/src/glsl/tests/qualifier-07.glsl
@@ -0,0 +1,7 @@
+/* FAIL - out only allowed in parameter list in GLSL 1.10 */
+void main()
+{
+ out vec4 foo;
+
+ gl_Position = gl_Vertex;
+}
diff --git a/src/glsl/tests/swiz-01.glsl b/src/glsl/tests/swiz-01.glsl
new file mode 100644
index 00000000000..3268fa178c1
--- /dev/null
+++ b/src/glsl/tests/swiz-01.glsl
@@ -0,0 +1,11 @@
+/* PASS */
+#version 120
+
+void main()
+{
+ float a;
+ vec4 b;
+
+ b.x = 6.0;
+ a = b.x;
+}
diff --git a/src/glsl/tests/swiz-02.glsl b/src/glsl/tests/swiz-02.glsl
new file mode 100644
index 00000000000..e3f043c47bd
--- /dev/null
+++ b/src/glsl/tests/swiz-02.glsl
@@ -0,0 +1,11 @@
+/* FAIL: assignment of a vec2 to a float */
+#version 120
+
+void main()
+{
+ float a;
+ vec4 b;
+
+ b.x = 6.0;
+ a = b.xy;
+}
diff --git a/src/glsl/tests/void-01.glsl b/src/glsl/tests/void-01.glsl
new file mode 100644
index 00000000000..5719edc0b6c
--- /dev/null
+++ b/src/glsl/tests/void-01.glsl
@@ -0,0 +1,2 @@
+/* FAIL - cannot declare a variable as having type `void' */
+void foo;
diff --git a/src/mesa/Makefile b/src/mesa/Makefile
index 7073c92240b..f97720093c8 100644
--- a/src/mesa/Makefile
+++ b/src/mesa/Makefile
@@ -42,16 +42,26 @@ MESA_GALLIUM_OBJECTS := $(addprefix $(MESA_OBJ_DIR)/, $(MESA_GALLIUM_OBJECTS))
MESA_INCLUDES := $(INCLUDE_DIRS)
ES1_INCLUDES := -I$(TOP)/src/mapi/es1api $(INCLUDE_DIRS)
ES2_INCLUDES := -I$(TOP)/src/mapi/es2api $(INCLUDE_DIRS)
-
+MESA_INCLUDES := -I$(TOP)/src/glsl $(MESA_INCLUDES)
+# For symbol_table.h in glsl compiler headers.
+MESA_INCLUDES := -I$(TOP)/src/mesa/shader $(MESA_INCLUDES)
define mesa-cc-c
@mkdir -p $(dir $@)
$(CC) -c -o $@ $< $($(1)_CPPFLAGS) $($(1)_INCLUDES) $(CFLAGS)
endef
+define mesa-cxx-c
+ @mkdir -p $(dir $@)
+ $(CXX) -c -o $@ $< $($(1)_CPPFLAGS) $($(1)_INCLUDES) $(CXXFLAGS)
+endef
+
$(MESA_OBJ_DIR)/%.o: %.c
$(call mesa-cc-c,MESA)
+$(MESA_OBJ_DIR)/%.o: %.cpp
+ $(call mesa-cxx-c,MESA)
+
$(MESA_OBJ_DIR)/%.o: %.S
$(call mesa-cc-c,MESA)
@@ -70,7 +80,7 @@ $(ES2_OBJ_DIR)/%.o: %.S
# Default: build dependencies, then asm_subdirs, GLSL built-in lib,
# then convenience libs (.a) and finally the device drivers:
-default: $(DEPENDS) asm_subdirs glsl_builtin \
+default: $(DEPENDS) asm_subdirs \
$(MESA_LIBS) $(ES1_LIBS) $(ES2_LIBS) driver_subdirs
main/api_exec_es1.c: main/APIspec.xml main/es_generator.py main/APIspecutil.py main/APIspec.py
@@ -121,12 +131,6 @@ asm_subdirs:
######################################################################
-# GLSL built-in library
-glsl_builtin:
- (cd slang/library && $(MAKE)) || exit 1 ;
-
-
-######################################################################
# Dependency generation
depend: $(ALL_SOURCES)
@@ -241,7 +245,6 @@ clean: clean-es1 clean-es2
-rm -f depend depend.bak libmesa.a libmesagallium.a
-rm -f drivers/*/*.o
-rm -f *.pc
- -rm -f slang/library/*_gc.h
-@cd drivers/dri && $(MAKE) clean
-@cd drivers/x11 && $(MAKE) clean
-@cd drivers/osmesa && $(MAKE) clean
diff --git a/src/mesa/SConscript b/src/mesa/SConscript
index 79e9b4553b7..5200a244f26 100644
--- a/src/mesa/SConscript
+++ b/src/mesa/SConscript
@@ -10,6 +10,7 @@ if env['platform'] != 'winddk':
env.Append(CPPPATH = [
'#/src/mapi',
+ '#/src/glsl',
'#/src/mesa',
])
@@ -19,6 +20,7 @@ if env['platform'] != 'winddk':
'BUILD_GL32', # declare gl* as __declspec(dllexport) in Mesa headers
'WIN32_THREADS', # use Win32 thread API
])
+ env.Prepend(CPPPATH = ['#src/talloc'])
#
# Source files
@@ -200,6 +202,7 @@ if env['platform'] != 'winddk':
program_sources = [
'program/arbprogparse.c',
'program/hash_table.c',
+ 'program/ir_to_mesa.cpp',
'program/lex.yy.c',
'program/nvfragparse.c',
'program/nvvertparse.c',
@@ -248,8 +251,7 @@ if env['platform'] != 'winddk':
program_sources +
vbo_sources +
vf_sources +
- statetracker_sources +
- slang_sources
+ statetracker_sources
)
#
@@ -327,7 +329,7 @@ if env['platform'] != 'winddk':
# build dir) to the include path
env.Append(CPPPATH = [matypes[0].dir])
- SConscript('slang/library/SConscript')
+ #SConscript('slang/library/SConscript')
#
# Libraries
diff --git a/src/mesa/drivers/dri/Makefile.template b/src/mesa/drivers/dri/Makefile.template
index 8cb25439e48..35daacfacdc 100644
--- a/src/mesa/drivers/dri/Makefile.template
+++ b/src/mesa/drivers/dri/Makefile.template
@@ -54,9 +54,9 @@ lib: symlinks subdirs depend
$(LIBNAME): $(OBJECTS) $(MESA_MODULES) $(EXTRA_MODULES) Makefile \
$(TOP)/src/mesa/drivers/dri/Makefile.template $(TOP)/src/mesa/drivers/dri/common/dri_test.o
- $(MKLIB) -o [email protected] -noprefix -linker '$(CC)' -ldflags '$(LDFLAGS)' \
+ $(MKLIB) -o [email protected] -noprefix -linker '$(CXX)' -ldflags '$(LDFLAGS)' \
$(OBJECTS) $(MESA_MODULES) $(EXTRA_MODULES) $(DRI_LIB_DEPS)
- $(CC) $(CFLAGS) -o [email protected] $(TOP)/src/mesa/drivers/dri/common/dri_test.o [email protected] $(DRI_LIB_DEPS)
+ $(CXX) $(CFLAGS) -o [email protected] $(TOP)/src/mesa/drivers/dri/common/dri_test.o [email protected] $(DRI_LIB_DEPS)
diff --git a/src/mesa/drivers/dri/common/dri_util.h b/src/mesa/drivers/dri/common/dri_util.h
index bc647ff8130..e2fcdaa6389 100644
--- a/src/mesa/drivers/dri/common/dri_util.h
+++ b/src/mesa/drivers/dri/common/dri_util.h
@@ -513,7 +513,11 @@ struct __DRIscreenRec {
*
* This pointer is never touched by the DRI layer.
*/
+#ifdef __cplusplus
+ void *priv;
+#else
void *private;
+#endif
/* Extensions provided by the loader. */
const __DRIgetDrawableInfoExtension *getDrawableInfo;
diff --git a/src/mesa/drivers/dri/i915/i915_context.c b/src/mesa/drivers/dri/i915/i915_context.c
index b3fe1c05d66..d8715cf026d 100644
--- a/src/mesa/drivers/dri/i915/i915_context.c
+++ b/src/mesa/drivers/dri/i915/i915_context.c
@@ -174,6 +174,8 @@ i915CreateContext(int api,
ctx->FragmentProgram._MaintainTexEnvProgram = GL_TRUE;
+ ctx->Shader.EmitNoIfs = GL_TRUE;
+
ctx->Const.MaxDrawBuffers = 1;
_tnl_init_vertices(ctx, ctx->Const.MaxArrayLockSize + 12,
diff --git a/src/mesa/drivers/dri/i965/brw_program.c b/src/mesa/drivers/dri/i965/brw_program.c
index 4b08d2599bc..c6d11fed064 100644
--- a/src/mesa/drivers/dri/i965/brw_program.c
+++ b/src/mesa/drivers/dri/i965/brw_program.c
@@ -36,6 +36,7 @@
#include "program/program.h"
#include "program/programopt.h"
#include "tnl/tnl.h"
+#include "talloc.h"
#include "brw_context.h"
#include "brw_wm.h"
@@ -114,10 +115,7 @@ shader_error(GLcontext *ctx, struct gl_program *prog, const char *msg)
shader = _mesa_lookup_shader_program(ctx, prog->Id);
if (shader) {
- if (shader->InfoLog) {
- free(shader->InfoLog);
- }
- shader->InfoLog = _mesa_strdup(msg);
+ shader->InfoLog = talloc_strdup_append(shader->InfoLog, msg);
shader->LinkStatus = GL_FALSE;
}
}
diff --git a/src/mesa/drivers/dri/i965/brw_vs.c b/src/mesa/drivers/dri/i965/brw_vs.c
index 9a832af9a97..9f90e1e5e5c 100644
--- a/src/mesa/drivers/dri/i965/brw_vs.c
+++ b/src/mesa/drivers/dri/i965/brw_vs.c
@@ -75,10 +75,10 @@ static void do_vs_prog( struct brw_context *brw,
c.prog_data.outputs_written |= BITFIELD64_BIT(VERT_RESULT_TEX0 + i);
}
- if (0)
- _mesa_print_program(&c.vp->program.Base);
-
-
+ if (0) {
+ _mesa_fprint_program_opt(stdout, &c.vp->program.Base, PROG_PRINT_DEBUG,
+ GL_TRUE);
+ }
/* Emit GEN4 code.
*/
diff --git a/src/mesa/drivers/dri/i965/brw_vs_emit.c b/src/mesa/drivers/dri/i965/brw_vs_emit.c
index b6b558e9a69..fab6b4f3d5a 100644
--- a/src/mesa/drivers/dri/i965/brw_vs_emit.c
+++ b/src/mesa/drivers/dri/i965/brw_vs_emit.c
@@ -502,6 +502,23 @@ static void emit_cmp( struct brw_compile *p,
brw_set_predicate_control(p, BRW_PREDICATE_NONE);
}
+static void emit_sign(struct brw_vs_compile *c,
+ struct brw_reg dst,
+ struct brw_reg arg0)
+{
+ struct brw_compile *p = &c->func;
+
+ brw_MOV(p, dst, brw_imm_f(0));
+
+ brw_CMP(p, brw_null_reg(), BRW_CONDITIONAL_L, arg0, brw_imm_f(0));
+ brw_MOV(p, dst, brw_imm_f(-1.0));
+ brw_set_predicate_control(p, BRW_PREDICATE_NONE);
+
+ brw_CMP(p, brw_null_reg(), BRW_CONDITIONAL_G, arg0, brw_imm_f(0));
+ brw_MOV(p, dst, brw_imm_f(1.0));
+ brw_set_predicate_control(p, BRW_PREDICATE_NONE);
+}
+
static void emit_max( struct brw_compile *p,
struct brw_reg dst,
struct brw_reg arg0,
@@ -1547,7 +1564,8 @@ void brw_vs_emit(struct brw_vs_compile *c )
if (INTEL_DEBUG & DEBUG_VS) {
printf("vs-mesa:\n");
- _mesa_print_program(&c->vp->program.Base);
+ _mesa_fprint_program_opt(stdout, &c->vp->program.Base, PROG_PRINT_DEBUG,
+ GL_TRUE);
printf("\n");
}
@@ -1732,6 +1750,9 @@ void brw_vs_emit(struct brw_vs_compile *c )
case OPCODE_SLE:
unalias2(c, dst, args[0], args[1], emit_sle);
break;
+ case OPCODE_SSG:
+ unalias1(c, dst, args[0], emit_sign);
+ break;
case OPCODE_SUB:
brw_ADD(p, dst, args[0], negate(args[1]));
break;
@@ -1903,7 +1924,7 @@ void brw_vs_emit(struct brw_vs_compile *c )
printf("vs-native:\n");
for (i = 0; i < p->nr_insn; i++)
- brw_disasm(stderr, &p->store[i], intel->gen);
+ brw_disasm(stdout, &p->store[i], intel->gen);
printf("\n");
}
}
diff --git a/src/mesa/drivers/dri/i965/brw_wm.c b/src/mesa/drivers/dri/i965/brw_wm.c
index e182fc32029..34cefeea32a 100644
--- a/src/mesa/drivers/dri/i965/brw_wm.c
+++ b/src/mesa/drivers/dri/i965/brw_wm.c
@@ -32,7 +32,7 @@
#include "brw_context.h"
#include "brw_wm.h"
#include "brw_state.h"
-
+#include "main/formats.h"
/** Return number of src args for given instruction */
GLuint brw_wm_nr_args( GLuint opcode )
diff --git a/src/mesa/drivers/dri/i965/brw_wm.h b/src/mesa/drivers/dri/i965/brw_wm.h
index f40977fab8d..40f51c21c95 100644
--- a/src/mesa/drivers/dri/i965/brw_wm.h
+++ b/src/mesa/drivers/dri/i965/brw_wm.h
@@ -343,6 +343,11 @@ void emit_delta_xy(struct brw_compile *p,
const struct brw_reg *dst,
GLuint mask,
const struct brw_reg *arg0);
+void emit_dp2(struct brw_compile *p,
+ const struct brw_reg *dst,
+ GLuint mask,
+ const struct brw_reg *arg0,
+ const struct brw_reg *arg1);
void emit_dp3(struct brw_compile *p,
const struct brw_reg *dst,
GLuint mask,
@@ -425,6 +430,10 @@ void emit_sop(struct brw_compile *p,
GLuint cond,
const struct brw_reg *arg0,
const struct brw_reg *arg1);
+void emit_sign(struct brw_compile *p,
+ const struct brw_reg *dst,
+ GLuint mask,
+ const struct brw_reg *arg0);
void emit_tex(struct brw_wm_compile *c,
struct brw_reg *dst,
GLuint dst_flags,
diff --git a/src/mesa/drivers/dri/i965/brw_wm_emit.c b/src/mesa/drivers/dri/i965/brw_wm_emit.c
index d9fa2e63354..053cf13a011 100644
--- a/src/mesa/drivers/dri/i965/brw_wm_emit.c
+++ b/src/mesa/drivers/dri/i965/brw_wm_emit.c
@@ -668,6 +668,28 @@ void emit_cmp(struct brw_compile *p,
}
}
+void emit_sign(struct brw_compile *p,
+ const struct brw_reg *dst,
+ GLuint mask,
+ const struct brw_reg *arg0)
+{
+ GLuint i;
+
+ for (i = 0; i < 4; i++) {
+ if (mask & (1<<i)) {
+ brw_MOV(p, dst[i], brw_imm_f(0.0));
+
+ brw_CMP(p, brw_null_reg(), BRW_CONDITIONAL_L, arg0[i], brw_imm_f(0));
+ brw_MOV(p, dst[i], brw_imm_f(-1.0));
+ brw_set_predicate_control(p, BRW_PREDICATE_NONE);
+
+ brw_CMP(p, brw_null_reg(), BRW_CONDITIONAL_G, arg0[i], brw_imm_f(0));
+ brw_MOV(p, dst[i], brw_imm_f(1.0));
+ brw_set_predicate_control(p, BRW_PREDICATE_NONE);
+ }
+ }
+}
+
void emit_max(struct brw_compile *p,
const struct brw_reg *dst,
GLuint mask,
@@ -709,6 +731,27 @@ void emit_min(struct brw_compile *p,
}
+void emit_dp2(struct brw_compile *p,
+ const struct brw_reg *dst,
+ GLuint mask,
+ const struct brw_reg *arg0,
+ const struct brw_reg *arg1)
+{
+ int dst_chan = _mesa_ffs(mask & WRITEMASK_XYZW) - 1;
+
+ if (!(mask & WRITEMASK_XYZW))
+ return; /* Do not emit dead code */
+
+ assert(is_power_of_two(mask & WRITEMASK_XYZW));
+
+ brw_MUL(p, brw_null_reg(), arg0[0], arg1[0]);
+
+ brw_set_saturate(p, (mask & SATURATE) ? 1 : 0);
+ brw_MAC(p, dst[dst_chan], arg0[1], arg1[1]);
+ brw_set_saturate(p, 0);
+}
+
+
void emit_dp3(struct brw_compile *p,
const struct brw_reg *dst,
GLuint mask,
@@ -1562,6 +1605,10 @@ void brw_wm_emit( struct brw_wm_compile *c )
emit_ddxy(p, dst, dst_flags, GL_FALSE, args[0]);
break;
+ case OPCODE_DP2:
+ emit_dp2(p, dst, dst_flags, args[0], args[1]);
+ break;
+
case OPCODE_DP3:
emit_dp3(p, dst, dst_flags, args[0], args[1]);
break;
@@ -1673,6 +1720,10 @@ void brw_wm_emit( struct brw_wm_compile *c )
emit_sne(p, dst, dst_flags, args[0], args[1]);
break;
+ case OPCODE_SSG:
+ emit_sign(p, dst, dst_flags, args[0]);
+ break;
+
case OPCODE_LIT:
emit_lit(c, dst, dst_flags, args[0]);
break;
@@ -1724,7 +1775,7 @@ void brw_wm_emit( struct brw_wm_compile *c )
printf("wm-native:\n");
for (i = 0; i < p->nr_insn; i++)
- brw_disasm(stderr, &p->store[i], p->brw->intel.gen);
+ brw_disasm(stdout, &p->store[i], p->brw->intel.gen);
printf("\n");
}
}
diff --git a/src/mesa/drivers/dri/i965/brw_wm_fp.c b/src/mesa/drivers/dri/i965/brw_wm_fp.c
index 0bef874b887..3870bf10fcb 100644
--- a/src/mesa/drivers/dri/i965/brw_wm_fp.c
+++ b/src/mesa/drivers/dri/i965/brw_wm_fp.c
@@ -88,6 +88,7 @@ static struct prog_src_register src_reg(GLuint file, GLuint idx)
reg.RelAddr = 0;
reg.Negate = NEGATE_NONE;
reg.Abs = 0;
+ reg.HasIndex2 = 0;
return reg;
}
@@ -1036,13 +1037,12 @@ static void print_insns( const struct prog_instruction *insn,
for (i = 0; i < nr; i++, insn++) {
printf("%3d: ", i);
if (insn->Opcode < MAX_OPCODE)
- _mesa_print_instruction(insn);
+ _mesa_fprint_instruction_opt(stdout, insn, 0, PROG_PRINT_DEBUG, NULL);
else if (insn->Opcode < MAX_WM_OPCODE) {
GLuint idx = insn->Opcode - MAX_OPCODE;
- _mesa_print_alu_instruction(insn,
- wm_opcode_strings[idx],
- 3);
+ _mesa_fprint_alu_instruction(stdout, insn, wm_opcode_strings[idx],
+ 3, PROG_PRINT_DEBUG, NULL);
}
else
printf("965 Opcode %d\n", insn->Opcode);
@@ -1061,7 +1061,8 @@ void brw_wm_pass_fp( struct brw_wm_compile *c )
if (INTEL_DEBUG & DEBUG_WM) {
printf("pre-fp:\n");
- _mesa_print_program(&fp->program.Base);
+ _mesa_fprint_program_opt(stdout, &fp->program.Base, PROG_PRINT_DEBUG,
+ GL_TRUE);
printf("\n");
}
diff --git a/src/mesa/drivers/dri/i965/brw_wm_glsl.c b/src/mesa/drivers/dri/i965/brw_wm_glsl.c
index 575f89b17fa..f13b0aaf957 100644
--- a/src/mesa/drivers/dri/i965/brw_wm_glsl.c
+++ b/src/mesa/drivers/dri/i965/brw_wm_glsl.c
@@ -1903,6 +1903,9 @@ static void brw_wm_emit_glsl(struct brw_context *brw, struct brw_wm_compile *c)
case OPCODE_SWZ:
emit_alu1(p, brw_MOV, dst, dst_flags, args[0]);
break;
+ case OPCODE_DP2:
+ emit_dp2(p, dst, dst_flags, args[0], args[1]);
+ break;
case OPCODE_DP3:
emit_dp3(p, dst, dst_flags, args[0], args[1]);
break;
@@ -1971,6 +1974,9 @@ static void brw_wm_emit_glsl(struct brw_context *brw, struct brw_wm_compile *c)
emit_sop(p, dst, dst_flags,
BRW_CONDITIONAL_NEQ, args[0], args[1]);
break;
+ case OPCODE_SSG:
+ emit_sign(p, dst, dst_flags, args[0]);
+ break;
case OPCODE_MUL:
emit_alu2(p, brw_MUL, dst, dst_flags, args[0], args[1]);
break;
@@ -2111,7 +2117,7 @@ static void brw_wm_emit_glsl(struct brw_context *brw, struct brw_wm_compile *c)
if (INTEL_DEBUG & DEBUG_WM) {
printf("wm-native:\n");
for (i = 0; i < p->nr_insn; i++)
- brw_disasm(stderr, &p->store[i], intel->gen);
+ brw_disasm(stdout, &p->store[i], intel->gen);
printf("\n");
}
}
diff --git a/src/mesa/drivers/dri/i965/brw_wm_pass1.c b/src/mesa/drivers/dri/i965/brw_wm_pass1.c
index b4493940292..962515a99e9 100644
--- a/src/mesa/drivers/dri/i965/brw_wm_pass1.c
+++ b/src/mesa/drivers/dri/i965/brw_wm_pass1.c
@@ -158,6 +158,7 @@ void brw_wm_pass1( struct brw_wm_compile *c )
case OPCODE_FLR:
case OPCODE_FRC:
case OPCODE_MOV:
+ case OPCODE_SSG:
case OPCODE_SWZ:
case OPCODE_TRUNC:
read0 = writemask;
@@ -254,6 +255,11 @@ void brw_wm_pass1( struct brw_wm_compile *c )
read2 = WRITEMASK_W; /* pixel w */
break;
+ case OPCODE_DP2:
+ read0 = WRITEMASK_XY;
+ read1 = WRITEMASK_XY;
+ break;
+
case OPCODE_DP3:
read0 = WRITEMASK_XYZ;
read1 = WRITEMASK_XYZ;
diff --git a/src/mesa/drivers/dri/intel/intel_context.h b/src/mesa/drivers/dri/intel/intel_context.h
index c7ac2de01e6..f245ba843bd 100644
--- a/src/mesa/drivers/dri/intel/intel_context.h
+++ b/src/mesa/drivers/dri/intel/intel_context.h
@@ -32,7 +32,6 @@
#include "main/mtypes.h"
#include "main/mm.h"
-#include "texmem.h"
#include "dri_metaops.h"
#include "drm.h"
#include "intel_bufmgr.h"
diff --git a/src/mesa/drivers/dri/intel/intel_mipmap_tree.c b/src/mesa/drivers/dri/intel/intel_mipmap_tree.c
index 39ac0205fa1..42adb4cb4a7 100644
--- a/src/mesa/drivers/dri/intel/intel_mipmap_tree.c
+++ b/src/mesa/drivers/dri/intel/intel_mipmap_tree.c
@@ -30,6 +30,7 @@
#include "intel_regions.h"
#include "intel_tex_layout.h"
#include "main/enums.h"
+#include "main/formats.h"
#define FILE_DEBUG_FLAG DEBUG_MIPTREE
diff --git a/src/mesa/drivers/dri/intel/intel_tex.h b/src/mesa/drivers/dri/intel/intel_tex.h
index 4bb012dc65e..cd77dd5b8e4 100644
--- a/src/mesa/drivers/dri/intel/intel_tex.h
+++ b/src/mesa/drivers/dri/intel/intel_tex.h
@@ -31,8 +31,6 @@
#include "main/mtypes.h"
#include "main/formats.h"
#include "intel_context.h"
-#include "texmem.h"
-
void intelInitTextureFuncs(struct dd_function_table *functions);
diff --git a/src/mesa/drivers/osmesa/Makefile b/src/mesa/drivers/osmesa/Makefile
index c6b4a040851..091e6f66d9b 100644
--- a/src/mesa/drivers/osmesa/Makefile
+++ b/src/mesa/drivers/osmesa/Makefile
@@ -23,8 +23,7 @@ INCLUDE_DIRS = \
CORE_MESA = \
$(TOP)/src/mesa/libmesa.a \
$(TOP)/src/mapi/glapi/libglapi.a \
- $(TOP)/src/glsl/cl/libglslcl.a \
- $(TOP)/src/glsl/pp/libglslpp.a
+ $(TOP)/src/glsl/libglsl.a
.c.o:
$(CC) -c $(INCLUDE_DIRS) $(CFLAGS) $< -o $@
diff --git a/src/mesa/main/dd.h b/src/mesa/main/dd.h
index 825073ca886..71d0f570e4b 100644
--- a/src/mesa/main/dd.h
+++ b/src/mesa/main/dd.h
@@ -595,6 +595,27 @@ struct dd_function_table {
/*@}*/
+ /**
+ * \name GLSL shader/program functions.
+ */
+ /*@{*/
+ /**
+ * Called when a shader is compiled.
+ *
+ * Note that not all shader objects get ShaderCompile called on
+ * them. Notably, the shaders containing builtin functions do not
+ * have CompileShader() called, so if lowering passes are done they
+ * need to also be performed in LinkShader().
+ */
+ GLboolean (*CompileShader)(GLcontext *ctx, struct gl_shader *shader);
+ /**
+ * Called when a shader program is linked.
+ *
+ * This gives drivers an opportunity to clone the IR and make their
+ * own transformations on it for the purposes of code generation.
+ */
+ GLboolean (*LinkShader)(GLcontext *ctx, struct gl_shader_program *shader);
+ /*@}*/
/**
* \name State-changing functions.
diff --git a/src/mesa/main/imports.h b/src/mesa/main/imports.h
index 9c2ffd66d69..846a9a0faf4 100644
--- a/src/mesa/main/imports.h
+++ b/src/mesa/main/imports.h
@@ -116,6 +116,34 @@ typedef union { GLfloat f; GLint i; } fi_type;
#endif
+/**
+ * \name Work-arounds for platforms that lack C99 math functions
+ */
+/*@{*/
+#if (_XOPEN_SOURCE < 600) && !defined(_ISOC99_SOURCE) \
+ && (!defined(__STDC_VERSION__) || (__STDC_VERSION__ < 199901L))
+#define acosf(f) ((float) acos(f))
+#define asinf(f) ((float) asin(f))
+#define atan2f(f) ((float) atan2(f))
+#define atanf(f) ((float) atan(f))
+#define cielf(f) ((float) ciel(f))
+#define cosf(f) ((float) cos(f))
+#define coshf(f) ((float) cosh(f))
+#define expf(f) ((float) exp(f))
+#define exp2f(f) ((float) exp2(f))
+#define floorf(f) ((float) floor(f))
+#define logf(f) ((float) log(f))
+#define log2f(f) ((float) log2(f))
+#define powf(f) ((float) pow(f))
+#define sinf(f) ((float) sin(f))
+#define sinhf(f) ((float) sinh(f))
+#define sqrtf(f) ((float) sqrt(f))
+#define tanf(f) ((float) tan(f))
+#define tanhf(f) ((float) tanh(f))
+#define truncf(f) ((float) trunc(f))
+#endif
+/*@}*/
+
/***
*** LOG2: Log base 2 of float
***/
diff --git a/src/mesa/main/mtypes.h b/src/mesa/main/mtypes.h
index 3c2addb3a31..e89f55befe4 100644
--- a/src/mesa/main/mtypes.h
+++ b/src/mesa/main/mtypes.h
@@ -2084,6 +2084,15 @@ struct gl_shader
struct gl_program *Program; /**< Post-compile assembly code */
GLchar *InfoLog;
struct gl_sl_pragmas Pragmas;
+
+ unsigned Version; /**< GLSL version used for linking */
+
+ struct exec_list *ir;
+ struct glsl_symbol_table *symbols;
+
+ /** Shaders containing built-in functions that are used for linking. */
+ struct gl_shader *builtins_to_link[16];
+ unsigned num_builtins_to_link;
};
@@ -2129,6 +2138,16 @@ struct gl_shader_program
GLboolean Validated;
GLboolean _Used; /**< Ever used for drawing? */
GLchar *InfoLog;
+
+ unsigned Version; /**< GLSL version used for linking */
+
+ /**
+ * Per-stage shaders resulting from the first stage of linking.
+ */
+ /*@{*/
+ GLuint _NumLinkedShaders;
+ struct gl_shader *_LinkedShaders[2];
+ /*@}*/
};
@@ -2154,6 +2173,11 @@ struct gl_shader_state
GLboolean EmitCondCodes; /**< Use condition codes? */
GLboolean EmitComments; /**< Annotated instructions */
GLboolean EmitNVTempInitialization; /**< 0-fill NV temp registers */
+ /**
+ * Attempts to flatten all ir_if (OPCODE_IF) for GPUs that can't
+ * support control flow.
+ */
+ GLboolean EmitNoIfs;
void *MemPool;
GLbitfield Flags; /**< Mask of GLSL_x flags */
struct gl_sl_pragmas DefaultPragmas; /**< Default #pragma settings */
diff --git a/src/mesa/main/shaderapi.c b/src/mesa/main/shaderapi.c
index 9cb2391035d..89b9557e84f 100644
--- a/src/mesa/main/shaderapi.c
+++ b/src/mesa/main/shaderapi.c
@@ -48,6 +48,7 @@
#include "program/prog_uniform.h"
#include "slang/slang_compile.h"
#include "slang/slang_link.h"
+#include "talloc.h"
/** Define this to enable shader substitution (see below) */
@@ -99,6 +100,7 @@ _mesa_init_shader_state(GLcontext *ctx)
ctx->Shader.EmitContReturn = GL_TRUE;
ctx->Shader.EmitCondCodes = GL_FALSE;
ctx->Shader.EmitComments = GL_FALSE;
+ ctx->Shader.EmitNoIfs = GL_FALSE;
ctx->Shader.Flags = get_shader_flags();
/* Default pragma settings */
@@ -800,7 +802,7 @@ compile_shader(GLcontext *ctx, GLuint shaderObj)
/* this call will set the sh->CompileStatus field to indicate if
* compilation was successful.
*/
- (void) _slang_compile(ctx, sh);
+ _mesa_glsl_compile_shader(ctx, sh);
}
@@ -826,7 +828,7 @@ link_program(GLcontext *ctx, GLuint program)
FLUSH_VERTICES(ctx, _NEW_PROGRAM);
- _slang_link(ctx, program, shProg);
+ _mesa_glsl_link_shader(ctx, shProg);
/* debug code */
if (0) {
@@ -1051,9 +1053,9 @@ validate_program(GLcontext *ctx, GLuint program)
if (!shProg->Validated) {
/* update info log */
if (shProg->InfoLog) {
- free(shProg->InfoLog);
+ talloc_free(shProg->InfoLog);
}
- shProg->InfoLog = _mesa_strdup(errMsg);
+ shProg->InfoLog = talloc_strdup(shProg, errMsg);
}
}
diff --git a/src/mesa/main/shaderobj.c b/src/mesa/main/shaderobj.c
index 14bbb2e4bc3..863d50fbe55 100644
--- a/src/mesa/main/shaderobj.c
+++ b/src/mesa/main/shaderobj.c
@@ -36,7 +36,7 @@
#include "program/program.h"
#include "program/prog_parameter.h"
#include "program/prog_uniform.h"
-
+#include "talloc.h"
/**********************************************************************/
/*** Shader object functions ***/
@@ -92,13 +92,13 @@ _mesa_reference_shader(GLcontext *ctx, struct gl_shader **ptr,
* Allocate a new gl_shader object, initialize it.
* Called via ctx->Driver.NewShader()
*/
-static struct gl_shader *
+struct gl_shader *
_mesa_new_shader(GLcontext *ctx, GLuint name, GLenum type)
{
struct gl_shader *shader;
assert(type == GL_FRAGMENT_SHADER || type == GL_VERTEX_SHADER ||
type == GL_GEOMETRY_SHADER_ARB);
- shader = CALLOC_STRUCT(gl_shader);
+ shader = talloc_zero(NULL, struct gl_shader);
if (shader) {
shader->Type = type;
shader->Name = name;
@@ -117,10 +117,8 @@ __mesa_delete_shader(GLcontext *ctx, struct gl_shader *sh)
{
if (sh->Source)
free((void *) sh->Source);
- if (sh->InfoLog)
- free(sh->InfoLog);
_mesa_reference_program(ctx, &sh->Program, NULL);
- free(sh);
+ talloc_free(sh);
}
@@ -235,7 +233,7 @@ static struct gl_shader_program *
_mesa_new_shader_program(GLcontext *ctx, GLuint name)
{
struct gl_shader_program *shProg;
- shProg = CALLOC_STRUCT(gl_shader_program);
+ shProg = talloc_zero(NULL, struct gl_shader_program);
if (shProg) {
shProg->Type = GL_SHADER_PROGRAM_MESA;
shProg->Name = name;
@@ -305,7 +303,7 @@ _mesa_free_shader_program_data(GLcontext *ctx,
}
if (shProg->InfoLog) {
- free(shProg->InfoLog);
+ talloc_free(shProg->InfoLog);
shProg->InfoLog = NULL;
}
@@ -328,7 +326,7 @@ __mesa_delete_shader_program(GLcontext *ctx, struct gl_shader_program *shProg)
{
_mesa_free_shader_program_data(ctx, shProg);
- free(shProg);
+ talloc_free(shProg);
}
@@ -389,4 +387,6 @@ _mesa_init_shader_object_functions(struct dd_function_table *driver)
driver->DeleteShader = __mesa_delete_shader;
driver->NewShaderProgram = _mesa_new_shader_program;
driver->DeleteShaderProgram = __mesa_delete_shader_program;
+ driver->CompileShader = _mesa_ir_compile_shader;
+ driver->LinkShader = _mesa_ir_link_shader;
}
diff --git a/src/mesa/main/shaderobj.h b/src/mesa/main/shaderobj.h
index d6b37b45963..1b96316b67b 100644
--- a/src/mesa/main/shaderobj.h
+++ b/src/mesa/main/shaderobj.h
@@ -27,8 +27,22 @@
#define SHADEROBJ_H
-#include "glheader.h"
-#include "mtypes.h"
+#include "main/glheader.h"
+#include "main/mtypes.h"
+#include "program/ir_to_mesa.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+/**
+ * Internal functions
+ */
+
+extern void
+_mesa_init_shader_state(GLcontext * ctx);
+
+extern void
+_mesa_free_shader_state(GLcontext *ctx);
extern void
@@ -48,6 +62,9 @@ _mesa_reference_shader_program(GLcontext *ctx,
struct gl_shader_program **ptr,
struct gl_shader_program *shProg);
+extern struct gl_shader *
+_mesa_new_shader(GLcontext *ctx, GLuint name, GLenum type);
+
extern struct gl_shader_program *
_mesa_lookup_shader_program(GLcontext *ctx, GLuint name);
@@ -74,5 +91,8 @@ _mesa_init_shader_state(GLcontext *ctx);
extern void
_mesa_free_shader_state(GLcontext *ctx);
+#ifdef __cplusplus
+}
+#endif
#endif /* SHADEROBJ_H */
diff --git a/src/mesa/program/hash_table.c b/src/mesa/program/hash_table.c
index fa6ba2bfdfc..f7ef366c1a0 100644
--- a/src/mesa/program/hash_table.c
+++ b/src/mesa/program/hash_table.c
@@ -142,6 +142,23 @@ hash_table_insert(struct hash_table *ht, void *data, const void *key)
insert_at_head(& ht->buckets[bucket], & node->link);
}
+void
+hash_table_remove(struct hash_table *ht, const void *key)
+{
+ const unsigned hash_value = (*ht->hash)(key);
+ const unsigned bucket = hash_value % ht->num_buckets;
+ struct node *node;
+
+ foreach(node, & ht->buckets[bucket]) {
+ struct hash_node *hn = (struct hash_node *) node;
+
+ if ((*ht->compare)(hn->key, key) == 0) {
+ remove_from_list(node);
+ free(node);
+ return;
+ }
+ }
+}
unsigned
hash_table_string_hash(const void *key)
@@ -157,3 +174,17 @@ hash_table_string_hash(const void *key)
return hash;
}
+
+
+unsigned
+hash_table_pointer_hash(const void *key)
+{
+ return (unsigned)((uintptr_t) key / sizeof(void *));
+}
+
+
+int
+hash_table_pointer_compare(const void *key1, const void *key2)
+{
+ return key1 == key2 ? 0 : 1;
+}
diff --git a/src/mesa/program/hash_table.h b/src/mesa/program/hash_table.h
index 7b302f5dbee..ec088c7dde1 100644
--- a/src/mesa/program/hash_table.h
+++ b/src/mesa/program/hash_table.h
@@ -38,6 +38,10 @@ struct hash_table;
typedef unsigned (*hash_func_t)(const void *key);
typedef int (*hash_compare_func_t)(const void *key1, const void *key2);
+#ifdef __cplusplus
+extern "C" {
+#endif
+
/**
* Hash table constructor
*
@@ -90,6 +94,10 @@ extern void *hash_table_find(struct hash_table *ht, const void *key);
extern void hash_table_insert(struct hash_table *ht, void *data,
const void *key);
+/**
+ * Remove a specific element from a hash table.
+ */
+extern void hash_table_remove(struct hash_table *ht, const void *key);
/**
* Compute hash value of a string
@@ -114,4 +122,31 @@ extern unsigned hash_table_string_hash(const void *key);
*/
#define hash_table_string_compare ((hash_compare_func_t) strcmp)
+
+/**
+ * Compute hash value of a pointer
+ *
+ * \param key Pointer to be used as a hash key
+ *
+ * \note
+ * The memory pointed to by \c key is \b never accessed. The value of \c key
+ * itself is used as the hash key
+ *
+ * \sa hash_table_pointer_compare
+ */
+unsigned
+hash_table_pointer_hash(const void *key);
+
+
+/**
+ * Compare two pointers used as keys
+ *
+ * \sa hash_table_pointer_hash
+ */
+int
+hash_table_pointer_compare(const void *key1, const void *key2);
+
+#ifdef __cplusplus
+}
+#endif
#endif /* HASH_TABLE_H */
diff --git a/src/mesa/program/ir_to_mesa.cpp b/src/mesa/program/ir_to_mesa.cpp
new file mode 100644
index 00000000000..7490ffa4fe7
--- /dev/null
+++ b/src/mesa/program/ir_to_mesa.cpp
@@ -0,0 +1,2718 @@
+/*
+ * Copyright (C) 2005-2007 Brian Paul All Rights Reserved.
+ * Copyright (C) 2008 VMware, Inc. All Rights Reserved.
+ * Copyright © 2010 Intel Corporation
+ *
+ * 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 (including the next
+ * paragraph) 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
+ * THE AUTHORS OR COPYRIGHT HOLDERS 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 ir_to_mesa.cpp
+ *
+ * Translates the IR to ARB_fragment_program text if possible,
+ * printing the result
+ */
+
+#include <stdio.h>
+#include "main/compiler.h"
+#include "ir.h"
+#include "ir_visitor.h"
+#include "ir_print_visitor.h"
+#include "ir_expression_flattening.h"
+#include "glsl_types.h"
+#include "glsl_parser_extras.h"
+#include "../glsl/program.h"
+#include "ir_optimization.h"
+#include "ast.h"
+
+extern "C" {
+#include "main/mtypes.h"
+#include "main/shaderapi.h"
+#include "main/shaderobj.h"
+#include "main/uniforms.h"
+#include "program/hash_table.h"
+#include "program/prog_instruction.h"
+#include "program/prog_optimize.h"
+#include "program/prog_print.h"
+#include "program/program.h"
+#include "program/prog_uniform.h"
+#include "program/prog_parameter.h"
+}
+
+static int swizzle_for_size(int size);
+
+/**
+ * This struct is a corresponding struct to Mesa prog_src_register, with
+ * wider fields.
+ */
+typedef struct ir_to_mesa_src_reg {
+ ir_to_mesa_src_reg(int file, int index, const glsl_type *type)
+ {
+ this->file = file;
+ this->index = index;
+ if (type && (type->is_scalar() || type->is_vector() || type->is_matrix()))
+ this->swizzle = swizzle_for_size(type->vector_elements);
+ else
+ this->swizzle = SWIZZLE_XYZW;
+ this->negate = 0;
+ this->reladdr = NULL;
+ }
+
+ ir_to_mesa_src_reg()
+ {
+ this->file = PROGRAM_UNDEFINED;
+ }
+
+ int file; /**< PROGRAM_* from Mesa */
+ int index; /**< temporary index, VERT_ATTRIB_*, FRAG_ATTRIB_*, etc. */
+ GLuint swizzle; /**< SWIZZLE_XYZWONEZERO swizzles from Mesa. */
+ int negate; /**< NEGATE_XYZW mask from mesa */
+ /** Register index should be offset by the integer in this reg. */
+ ir_to_mesa_src_reg *reladdr;
+} ir_to_mesa_src_reg;
+
+typedef struct ir_to_mesa_dst_reg {
+ int file; /**< PROGRAM_* from Mesa */
+ int index; /**< temporary index, VERT_ATTRIB_*, FRAG_ATTRIB_*, etc. */
+ int writemask; /**< Bitfield of WRITEMASK_[XYZW] */
+ GLuint cond_mask:4;
+ /** Register index should be offset by the integer in this reg. */
+ ir_to_mesa_src_reg *reladdr;
+} ir_to_mesa_dst_reg;
+
+extern ir_to_mesa_src_reg ir_to_mesa_undef;
+
+class ir_to_mesa_instruction : public exec_node {
+public:
+ enum prog_opcode op;
+ ir_to_mesa_dst_reg dst_reg;
+ ir_to_mesa_src_reg src_reg[3];
+ /** Pointer to the ir source this tree came from for debugging */
+ ir_instruction *ir;
+ GLboolean cond_update;
+ int sampler; /**< sampler index */
+ int tex_target; /**< One of TEXTURE_*_INDEX */
+ GLboolean tex_shadow;
+
+ class function_entry *function; /* Set on OPCODE_CAL or OPCODE_BGNSUB */
+};
+
+class variable_storage : public exec_node {
+public:
+ variable_storage(ir_variable *var, int file, int index)
+ : file(file), index(index), var(var)
+ {
+ /* empty */
+ }
+
+ int file;
+ int index;
+ ir_variable *var; /* variable that maps to this, if any */
+};
+
+class function_entry : public exec_node {
+public:
+ ir_function_signature *sig;
+
+ /**
+ * identifier of this function signature used by the program.
+ *
+ * At the point that Mesa instructions for function calls are
+ * generated, we don't know the address of the first instruction of
+ * the function body. So we make the BranchTarget that is called a
+ * small integer and rewrite them during set_branchtargets().
+ */
+ int sig_id;
+
+ /**
+ * Pointer to first instruction of the function body.
+ *
+ * Set during function body emits after main() is processed.
+ */
+ ir_to_mesa_instruction *bgn_inst;
+
+ /**
+ * Index of the first instruction of the function body in actual
+ * Mesa IR.
+ *
+ * Set after convertion from ir_to_mesa_instruction to prog_instruction.
+ */
+ int inst;
+
+ /** Storage for the return value. */
+ ir_to_mesa_src_reg return_reg;
+};
+
+class ir_to_mesa_visitor : public ir_visitor {
+public:
+ ir_to_mesa_visitor();
+ ~ir_to_mesa_visitor();
+
+ function_entry *current_function;
+
+ GLcontext *ctx;
+ struct gl_program *prog;
+
+ int next_temp;
+
+ variable_storage *find_variable_storage(ir_variable *var);
+
+ function_entry *get_function_signature(ir_function_signature *sig);
+
+ ir_to_mesa_src_reg get_temp(const glsl_type *type);
+ void reladdr_to_temp(ir_instruction *ir,
+ ir_to_mesa_src_reg *reg, int *num_reladdr);
+
+ struct ir_to_mesa_src_reg src_reg_for_float(float val);
+
+ /**
+ * \name Visit methods
+ *
+ * As typical for the visitor pattern, there must be one \c visit method for
+ * each concrete subclass of \c ir_instruction. Virtual base classes within
+ * the hierarchy should not have \c visit methods.
+ */
+ /*@{*/
+ virtual void visit(ir_variable *);
+ virtual void visit(ir_loop *);
+ virtual void visit(ir_loop_jump *);
+ virtual void visit(ir_function_signature *);
+ virtual void visit(ir_function *);
+ virtual void visit(ir_expression *);
+ virtual void visit(ir_swizzle *);
+ virtual void visit(ir_dereference_variable *);
+ virtual void visit(ir_dereference_array *);
+ virtual void visit(ir_dereference_record *);
+ virtual void visit(ir_assignment *);
+ virtual void visit(ir_constant *);
+ virtual void visit(ir_call *);
+ virtual void visit(ir_return *);
+ virtual void visit(ir_discard *);
+ virtual void visit(ir_texture *);
+ virtual void visit(ir_if *);
+ /*@}*/
+
+ struct ir_to_mesa_src_reg result;
+
+ /** List of variable_storage */
+ exec_list variables;
+
+ /** List of function_entry */
+ exec_list function_signatures;
+ int next_signature_id;
+
+ /** List of ir_to_mesa_instruction */
+ exec_list instructions;
+
+ ir_to_mesa_instruction *ir_to_mesa_emit_op0(ir_instruction *ir,
+ enum prog_opcode op);
+
+ ir_to_mesa_instruction *ir_to_mesa_emit_op1(ir_instruction *ir,
+ enum prog_opcode op,
+ ir_to_mesa_dst_reg dst,
+ ir_to_mesa_src_reg src0);
+
+ ir_to_mesa_instruction *ir_to_mesa_emit_op2(ir_instruction *ir,
+ enum prog_opcode op,
+ ir_to_mesa_dst_reg dst,
+ ir_to_mesa_src_reg src0,
+ ir_to_mesa_src_reg src1);
+
+ ir_to_mesa_instruction *ir_to_mesa_emit_op3(ir_instruction *ir,
+ enum prog_opcode op,
+ ir_to_mesa_dst_reg dst,
+ ir_to_mesa_src_reg src0,
+ ir_to_mesa_src_reg src1,
+ ir_to_mesa_src_reg src2);
+
+ void ir_to_mesa_emit_scalar_op1(ir_instruction *ir,
+ enum prog_opcode op,
+ ir_to_mesa_dst_reg dst,
+ ir_to_mesa_src_reg src0);
+
+ void ir_to_mesa_emit_scalar_op2(ir_instruction *ir,
+ enum prog_opcode op,
+ ir_to_mesa_dst_reg dst,
+ ir_to_mesa_src_reg src0,
+ ir_to_mesa_src_reg src1);
+
+ GLboolean try_emit_mad(ir_expression *ir,
+ int mul_operand);
+
+ int add_uniform(const char *name,
+ const glsl_type *type,
+ ir_constant *constant);
+ void add_aggregate_uniform(ir_instruction *ir,
+ const char *name,
+ const struct glsl_type *type,
+ ir_constant *constant,
+ struct ir_to_mesa_dst_reg temp);
+
+ struct hash_table *sampler_map;
+
+ void set_sampler_location(ir_variable *sampler, int location);
+ int get_sampler_location(ir_variable *sampler);
+
+ void *mem_ctx;
+};
+
+ir_to_mesa_src_reg ir_to_mesa_undef = ir_to_mesa_src_reg(PROGRAM_UNDEFINED, 0, NULL);
+
+ir_to_mesa_dst_reg ir_to_mesa_undef_dst = {
+ PROGRAM_UNDEFINED, 0, SWIZZLE_NOOP, COND_TR, NULL,
+};
+
+ir_to_mesa_dst_reg ir_to_mesa_address_reg = {
+ PROGRAM_ADDRESS, 0, WRITEMASK_X, COND_TR, NULL
+};
+
+static int swizzle_for_size(int size)
+{
+ int size_swizzles[4] = {
+ MAKE_SWIZZLE4(SWIZZLE_X, SWIZZLE_X, SWIZZLE_X, SWIZZLE_X),
+ MAKE_SWIZZLE4(SWIZZLE_X, SWIZZLE_Y, SWIZZLE_Y, SWIZZLE_Y),
+ MAKE_SWIZZLE4(SWIZZLE_X, SWIZZLE_Y, SWIZZLE_Z, SWIZZLE_Z),
+ MAKE_SWIZZLE4(SWIZZLE_X, SWIZZLE_Y, SWIZZLE_Z, SWIZZLE_W),
+ };
+
+ return size_swizzles[size - 1];
+}
+
+ir_to_mesa_instruction *
+ir_to_mesa_visitor::ir_to_mesa_emit_op3(ir_instruction *ir,
+ enum prog_opcode op,
+ ir_to_mesa_dst_reg dst,
+ ir_to_mesa_src_reg src0,
+ ir_to_mesa_src_reg src1,
+ ir_to_mesa_src_reg src2)
+{
+ ir_to_mesa_instruction *inst = new(mem_ctx) ir_to_mesa_instruction();
+ int num_reladdr = 0;
+
+ /* If we have to do relative addressing, we want to load the ARL
+ * reg directly for one of the regs, and preload the other reladdr
+ * sources into temps.
+ */
+ num_reladdr += dst.reladdr != NULL;
+ num_reladdr += src0.reladdr != NULL;
+ num_reladdr += src1.reladdr != NULL;
+ num_reladdr += src2.reladdr != NULL;
+
+ reladdr_to_temp(ir, &src2, &num_reladdr);
+ reladdr_to_temp(ir, &src1, &num_reladdr);
+ reladdr_to_temp(ir, &src0, &num_reladdr);
+
+ if (dst.reladdr) {
+ ir_to_mesa_emit_op1(ir, OPCODE_ARL, ir_to_mesa_address_reg,
+ *dst.reladdr);
+
+ num_reladdr--;
+ }
+ assert(num_reladdr == 0);
+
+ inst->op = op;
+ inst->dst_reg = dst;
+ inst->src_reg[0] = src0;
+ inst->src_reg[1] = src1;
+ inst->src_reg[2] = src2;
+ inst->ir = ir;
+
+ inst->function = NULL;
+
+ this->instructions.push_tail(inst);
+
+ return inst;
+}
+
+
+ir_to_mesa_instruction *
+ir_to_mesa_visitor::ir_to_mesa_emit_op2(ir_instruction *ir,
+ enum prog_opcode op,
+ ir_to_mesa_dst_reg dst,
+ ir_to_mesa_src_reg src0,
+ ir_to_mesa_src_reg src1)
+{
+ return ir_to_mesa_emit_op3(ir, op, dst, src0, src1, ir_to_mesa_undef);
+}
+
+ir_to_mesa_instruction *
+ir_to_mesa_visitor::ir_to_mesa_emit_op1(ir_instruction *ir,
+ enum prog_opcode op,
+ ir_to_mesa_dst_reg dst,
+ ir_to_mesa_src_reg src0)
+{
+ assert(dst.writemask != 0);
+ return ir_to_mesa_emit_op3(ir, op, dst,
+ src0, ir_to_mesa_undef, ir_to_mesa_undef);
+}
+
+ir_to_mesa_instruction *
+ir_to_mesa_visitor::ir_to_mesa_emit_op0(ir_instruction *ir,
+ enum prog_opcode op)
+{
+ return ir_to_mesa_emit_op3(ir, op, ir_to_mesa_undef_dst,
+ ir_to_mesa_undef,
+ ir_to_mesa_undef,
+ ir_to_mesa_undef);
+}
+
+void
+ir_to_mesa_visitor::set_sampler_location(ir_variable *sampler, int location)
+{
+ if (this->sampler_map == NULL) {
+ this->sampler_map = hash_table_ctor(0, hash_table_pointer_hash,
+ hash_table_pointer_compare);
+ }
+
+ hash_table_insert(this->sampler_map, (void *)(uintptr_t)location, sampler);
+}
+
+int
+ir_to_mesa_visitor::get_sampler_location(ir_variable *sampler)
+{
+ void *result = hash_table_find(this->sampler_map, sampler);
+
+ return (int)(uintptr_t)result;
+}
+
+inline ir_to_mesa_dst_reg
+ir_to_mesa_dst_reg_from_src(ir_to_mesa_src_reg reg)
+{
+ ir_to_mesa_dst_reg dst_reg;
+
+ dst_reg.file = reg.file;
+ dst_reg.index = reg.index;
+ dst_reg.writemask = WRITEMASK_XYZW;
+ dst_reg.cond_mask = COND_TR;
+ dst_reg.reladdr = reg.reladdr;
+
+ return dst_reg;
+}
+
+inline ir_to_mesa_src_reg
+ir_to_mesa_src_reg_from_dst(ir_to_mesa_dst_reg reg)
+{
+ return ir_to_mesa_src_reg(reg.file, reg.index, NULL);
+}
+
+/**
+ * Emits Mesa scalar opcodes to produce unique answers across channels.
+ *
+ * Some Mesa opcodes are scalar-only, like ARB_fp/vp. The src X
+ * channel determines the result across all channels. So to do a vec4
+ * of this operation, we want to emit a scalar per source channel used
+ * to produce dest channels.
+ */
+void
+ir_to_mesa_visitor::ir_to_mesa_emit_scalar_op2(ir_instruction *ir,
+ enum prog_opcode op,
+ ir_to_mesa_dst_reg dst,
+ ir_to_mesa_src_reg orig_src0,
+ ir_to_mesa_src_reg orig_src1)
+{
+ int i, j;
+ int done_mask = ~dst.writemask;
+
+ /* Mesa RCP is a scalar operation splatting results to all channels,
+ * like ARB_fp/vp. So emit as many RCPs as necessary to cover our
+ * dst channels.
+ */
+ for (i = 0; i < 4; i++) {
+ GLuint this_mask = (1 << i);
+ ir_to_mesa_instruction *inst;
+ ir_to_mesa_src_reg src0 = orig_src0;
+ ir_to_mesa_src_reg src1 = orig_src1;
+
+ if (done_mask & this_mask)
+ continue;
+
+ GLuint src0_swiz = GET_SWZ(src0.swizzle, i);
+ GLuint src1_swiz = GET_SWZ(src1.swizzle, i);
+ for (j = i + 1; j < 4; j++) {
+ if (!(done_mask & (1 << j)) &&
+ GET_SWZ(src0.swizzle, j) == src0_swiz &&
+ GET_SWZ(src1.swizzle, j) == src1_swiz) {
+ this_mask |= (1 << j);
+ }
+ }
+ src0.swizzle = MAKE_SWIZZLE4(src0_swiz, src0_swiz,
+ src0_swiz, src0_swiz);
+ src1.swizzle = MAKE_SWIZZLE4(src1_swiz, src1_swiz,
+ src1_swiz, src1_swiz);
+
+ inst = ir_to_mesa_emit_op2(ir, op,
+ dst,
+ src0,
+ src1);
+ inst->dst_reg.writemask = this_mask;
+ done_mask |= this_mask;
+ }
+}
+
+void
+ir_to_mesa_visitor::ir_to_mesa_emit_scalar_op1(ir_instruction *ir,
+ enum prog_opcode op,
+ ir_to_mesa_dst_reg dst,
+ ir_to_mesa_src_reg src0)
+{
+ ir_to_mesa_src_reg undef = ir_to_mesa_undef;
+
+ undef.swizzle = SWIZZLE_XXXX;
+
+ ir_to_mesa_emit_scalar_op2(ir, op, dst, src0, undef);
+}
+
+struct ir_to_mesa_src_reg
+ir_to_mesa_visitor::src_reg_for_float(float val)
+{
+ ir_to_mesa_src_reg src_reg(PROGRAM_CONSTANT, -1, NULL);
+
+ src_reg.index = _mesa_add_unnamed_constant(this->prog->Parameters,
+ &val, 1, &src_reg.swizzle);
+
+ return src_reg;
+}
+
+static int
+type_size(const struct glsl_type *type)
+{
+ unsigned int i;
+ int size;
+
+ switch (type->base_type) {
+ case GLSL_TYPE_UINT:
+ case GLSL_TYPE_INT:
+ case GLSL_TYPE_FLOAT:
+ case GLSL_TYPE_BOOL:
+ if (type->is_matrix()) {
+ return type->matrix_columns;
+ } else {
+ /* Regardless of size of vector, it gets a vec4. This is bad
+ * packing for things like floats, but otherwise arrays become a
+ * mess. Hopefully a later pass over the code can pack scalars
+ * down if appropriate.
+ */
+ return 1;
+ }
+ case GLSL_TYPE_ARRAY:
+ return type_size(type->fields.array) * type->length;
+ case GLSL_TYPE_STRUCT:
+ size = 0;
+ for (i = 0; i < type->length; i++) {
+ size += type_size(type->fields.structure[i].type);
+ }
+ return size;
+ case GLSL_TYPE_SAMPLER:
+ /* Samplers take up no register space, since they're baked in at
+ * link time.
+ */
+ return 0;
+ default:
+ assert(0);
+ }
+}
+
+/**
+ * In the initial pass of codegen, we assign temporary numbers to
+ * intermediate results. (not SSA -- variable assignments will reuse
+ * storage). Actual register allocation for the Mesa VM occurs in a
+ * pass over the Mesa IR later.
+ */
+ir_to_mesa_src_reg
+ir_to_mesa_visitor::get_temp(const glsl_type *type)
+{
+ ir_to_mesa_src_reg src_reg;
+ int swizzle[4];
+ int i;
+
+ src_reg.file = PROGRAM_TEMPORARY;
+ src_reg.index = next_temp;
+ src_reg.reladdr = NULL;
+ next_temp += type_size(type);
+
+ if (type->is_array() || type->is_record()) {
+ src_reg.swizzle = SWIZZLE_NOOP;
+ } else {
+ for (i = 0; i < type->vector_elements; i++)
+ swizzle[i] = i;
+ for (; i < 4; i++)
+ swizzle[i] = type->vector_elements - 1;
+ src_reg.swizzle = MAKE_SWIZZLE4(swizzle[0], swizzle[1],
+ swizzle[2], swizzle[3]);
+ }
+ src_reg.negate = 0;
+
+ return src_reg;
+}
+
+variable_storage *
+ir_to_mesa_visitor::find_variable_storage(ir_variable *var)
+{
+
+ variable_storage *entry;
+
+ foreach_iter(exec_list_iterator, iter, this->variables) {
+ entry = (variable_storage *)iter.get();
+
+ if (entry->var == var)
+ return entry;
+ }
+
+ return NULL;
+}
+
+void
+ir_to_mesa_visitor::visit(ir_variable *ir)
+{
+ if (strcmp(ir->name, "gl_FragCoord") == 0) {
+ struct gl_fragment_program *fp = (struct gl_fragment_program *)this->prog;
+
+ fp->OriginUpperLeft = ir->origin_upper_left;
+ fp->PixelCenterInteger = ir->pixel_center_integer;
+ }
+}
+
+void
+ir_to_mesa_visitor::visit(ir_loop *ir)
+{
+ assert(!ir->from);
+ assert(!ir->to);
+ assert(!ir->increment);
+ assert(!ir->counter);
+
+ ir_to_mesa_emit_op0(NULL, OPCODE_BGNLOOP);
+ visit_exec_list(&ir->body_instructions, this);
+ ir_to_mesa_emit_op0(NULL, OPCODE_ENDLOOP);
+}
+
+void
+ir_to_mesa_visitor::visit(ir_loop_jump *ir)
+{
+ switch (ir->mode) {
+ case ir_loop_jump::jump_break:
+ ir_to_mesa_emit_op0(NULL, OPCODE_BRK);
+ break;
+ case ir_loop_jump::jump_continue:
+ ir_to_mesa_emit_op0(NULL, OPCODE_CONT);
+ break;
+ }
+}
+
+
+void
+ir_to_mesa_visitor::visit(ir_function_signature *ir)
+{
+ assert(0);
+ (void)ir;
+}
+
+void
+ir_to_mesa_visitor::visit(ir_function *ir)
+{
+ /* Ignore function bodies other than main() -- we shouldn't see calls to
+ * them since they should all be inlined before we get to ir_to_mesa.
+ */
+ if (strcmp(ir->name, "main") == 0) {
+ const ir_function_signature *sig;
+ exec_list empty;
+
+ sig = ir->matching_signature(&empty);
+
+ assert(sig);
+
+ foreach_iter(exec_list_iterator, iter, sig->body) {
+ ir_instruction *ir = (ir_instruction *)iter.get();
+
+ ir->accept(this);
+ }
+ }
+}
+
+GLboolean
+ir_to_mesa_visitor::try_emit_mad(ir_expression *ir, int mul_operand)
+{
+ int nonmul_operand = 1 - mul_operand;
+ ir_to_mesa_src_reg a, b, c;
+
+ ir_expression *expr = ir->operands[mul_operand]->as_expression();
+ if (!expr || expr->operation != ir_binop_mul)
+ return false;
+
+ expr->operands[0]->accept(this);
+ a = this->result;
+ expr->operands[1]->accept(this);
+ b = this->result;
+ ir->operands[nonmul_operand]->accept(this);
+ c = this->result;
+
+ this->result = get_temp(ir->type);
+ ir_to_mesa_emit_op3(ir, OPCODE_MAD,
+ ir_to_mesa_dst_reg_from_src(this->result), a, b, c);
+
+ return true;
+}
+
+void
+ir_to_mesa_visitor::reladdr_to_temp(ir_instruction *ir,
+ ir_to_mesa_src_reg *reg, int *num_reladdr)
+{
+ if (!reg->reladdr)
+ return;
+
+ ir_to_mesa_emit_op1(ir, OPCODE_ARL, ir_to_mesa_address_reg, *reg->reladdr);
+
+ if (*num_reladdr != 1) {
+ ir_to_mesa_src_reg temp = get_temp(glsl_type::vec4_type);
+
+ ir_to_mesa_emit_op1(ir, OPCODE_MOV,
+ ir_to_mesa_dst_reg_from_src(temp), *reg);
+ *reg = temp;
+ }
+
+ (*num_reladdr)--;
+}
+
+void
+ir_to_mesa_visitor::visit(ir_expression *ir)
+{
+ unsigned int operand;
+ struct ir_to_mesa_src_reg op[2];
+ struct ir_to_mesa_src_reg result_src;
+ struct ir_to_mesa_dst_reg result_dst;
+ const glsl_type *vec4_type = glsl_type::get_instance(GLSL_TYPE_FLOAT, 4, 1);
+ const glsl_type *vec3_type = glsl_type::get_instance(GLSL_TYPE_FLOAT, 3, 1);
+ const glsl_type *vec2_type = glsl_type::get_instance(GLSL_TYPE_FLOAT, 2, 1);
+
+ /* Quick peephole: Emit OPCODE_MAD(a, b, c) instead of ADD(MUL(a, b), c)
+ */
+ if (ir->operation == ir_binop_add) {
+ if (try_emit_mad(ir, 1))
+ return;
+ if (try_emit_mad(ir, 0))
+ return;
+ }
+
+ for (operand = 0; operand < ir->get_num_operands(); operand++) {
+ this->result.file = PROGRAM_UNDEFINED;
+ ir->operands[operand]->accept(this);
+ if (this->result.file == PROGRAM_UNDEFINED) {
+ ir_print_visitor v;
+ printf("Failed to get tree for expression operand:\n");
+ ir->operands[operand]->accept(&v);
+ exit(1);
+ }
+ op[operand] = this->result;
+
+ /* Matrix expression operands should have been broken down to vector
+ * operations already.
+ */
+ assert(!ir->operands[operand]->type->is_matrix());
+ }
+
+ this->result.file = PROGRAM_UNDEFINED;
+
+ /* Storage for our result. Ideally for an assignment we'd be using
+ * the actual storage for the result here, instead.
+ */
+ result_src = get_temp(ir->type);
+ /* convenience for the emit functions below. */
+ result_dst = ir_to_mesa_dst_reg_from_src(result_src);
+ /* Limit writes to the channels that will be used by result_src later.
+ * This does limit this temp's use as a temporary for multi-instruction
+ * sequences.
+ */
+ result_dst.writemask = (1 << ir->type->vector_elements) - 1;
+
+ switch (ir->operation) {
+ case ir_unop_logic_not:
+ ir_to_mesa_emit_op2(ir, OPCODE_SEQ, result_dst,
+ op[0], src_reg_for_float(0.0));
+ break;
+ case ir_unop_neg:
+ op[0].negate = ~op[0].negate;
+ result_src = op[0];
+ break;
+ case ir_unop_abs:
+ ir_to_mesa_emit_op1(ir, OPCODE_ABS, result_dst, op[0]);
+ break;
+ case ir_unop_sign:
+ ir_to_mesa_emit_op1(ir, OPCODE_SSG, result_dst, op[0]);
+ break;
+ case ir_unop_rcp:
+ ir_to_mesa_emit_scalar_op1(ir, OPCODE_RCP, result_dst, op[0]);
+ break;
+
+ case ir_unop_exp2:
+ ir_to_mesa_emit_scalar_op1(ir, OPCODE_EX2, result_dst, op[0]);
+ break;
+ case ir_unop_exp:
+ case ir_unop_log:
+ assert(!"not reached: should be handled by ir_explog_to_explog2");
+ break;
+ case ir_unop_log2:
+ ir_to_mesa_emit_scalar_op1(ir, OPCODE_LG2, result_dst, op[0]);
+ break;
+ case ir_unop_sin:
+ ir_to_mesa_emit_scalar_op1(ir, OPCODE_SIN, result_dst, op[0]);
+ break;
+ case ir_unop_cos:
+ ir_to_mesa_emit_scalar_op1(ir, OPCODE_COS, result_dst, op[0]);
+ break;
+
+ case ir_unop_dFdx:
+ ir_to_mesa_emit_op1(ir, OPCODE_DDX, result_dst, op[0]);
+ break;
+ case ir_unop_dFdy:
+ ir_to_mesa_emit_op1(ir, OPCODE_DDY, result_dst, op[0]);
+ break;
+
+ case ir_binop_add:
+ ir_to_mesa_emit_op2(ir, OPCODE_ADD, result_dst, op[0], op[1]);
+ break;
+ case ir_binop_sub:
+ ir_to_mesa_emit_op2(ir, OPCODE_SUB, result_dst, op[0], op[1]);
+ break;
+
+ case ir_binop_mul:
+ ir_to_mesa_emit_op2(ir, OPCODE_MUL, result_dst, op[0], op[1]);
+ break;
+ case ir_binop_div:
+ assert(!"not reached: should be handled by ir_div_to_mul_rcp");
+ case ir_binop_mod:
+ assert(!"ir_binop_mod should have been converted to b * fract(a/b)");
+ break;
+
+ case ir_binop_less:
+ ir_to_mesa_emit_op2(ir, OPCODE_SLT, result_dst, op[0], op[1]);
+ break;
+ case ir_binop_greater:
+ ir_to_mesa_emit_op2(ir, OPCODE_SGT, result_dst, op[0], op[1]);
+ break;
+ case ir_binop_lequal:
+ ir_to_mesa_emit_op2(ir, OPCODE_SLE, result_dst, op[0], op[1]);
+ break;
+ case ir_binop_gequal:
+ ir_to_mesa_emit_op2(ir, OPCODE_SGE, result_dst, op[0], op[1]);
+ break;
+ case ir_binop_equal:
+ ir_to_mesa_emit_op2(ir, OPCODE_SEQ, result_dst, op[0], op[1]);
+ break;
+ case ir_binop_logic_xor:
+ case ir_binop_nequal:
+ ir_to_mesa_emit_op2(ir, OPCODE_SNE, result_dst, op[0], op[1]);
+ break;
+
+ case ir_binop_logic_or:
+ /* This could be a saturated add and skip the SNE. */
+ ir_to_mesa_emit_op2(ir, OPCODE_ADD,
+ result_dst,
+ op[0], op[1]);
+
+ ir_to_mesa_emit_op2(ir, OPCODE_SNE,
+ result_dst,
+ result_src, src_reg_for_float(0.0));
+ break;
+
+ case ir_binop_logic_and:
+ /* the bool args are stored as float 0.0 or 1.0, so "mul" gives us "and". */
+ ir_to_mesa_emit_op2(ir, OPCODE_MUL,
+ result_dst,
+ op[0], op[1]);
+ break;
+
+ case ir_binop_dot:
+ if (ir->operands[0]->type == vec4_type) {
+ assert(ir->operands[1]->type == vec4_type);
+ ir_to_mesa_emit_op2(ir, OPCODE_DP4,
+ result_dst,
+ op[0], op[1]);
+ } else if (ir->operands[0]->type == vec3_type) {
+ assert(ir->operands[1]->type == vec3_type);
+ ir_to_mesa_emit_op2(ir, OPCODE_DP3,
+ result_dst,
+ op[0], op[1]);
+ } else if (ir->operands[0]->type == vec2_type) {
+ assert(ir->operands[1]->type == vec2_type);
+ ir_to_mesa_emit_op2(ir, OPCODE_DP2,
+ result_dst,
+ op[0], op[1]);
+ }
+ break;
+
+ case ir_binop_cross:
+ ir_to_mesa_emit_op2(ir, OPCODE_XPD, result_dst, op[0], op[1]);
+ break;
+
+ case ir_unop_sqrt:
+ ir_to_mesa_emit_scalar_op1(ir, OPCODE_RSQ, result_dst, op[0]);
+ ir_to_mesa_emit_scalar_op1(ir, OPCODE_RCP, result_dst, result_src);
+ /* For incoming channels < 0, set the result to 0. */
+ ir_to_mesa_emit_op3(ir, OPCODE_CMP, result_dst,
+ op[0], src_reg_for_float(0.0), result_src);
+ break;
+ case ir_unop_rsq:
+ ir_to_mesa_emit_scalar_op1(ir, OPCODE_RSQ, result_dst, op[0]);
+ break;
+ case ir_unop_i2f:
+ case ir_unop_b2f:
+ case ir_unop_b2i:
+ /* Mesa IR lacks types, ints are stored as truncated floats. */
+ result_src = op[0];
+ break;
+ case ir_unop_f2i:
+ ir_to_mesa_emit_op1(ir, OPCODE_TRUNC, result_dst, op[0]);
+ break;
+ case ir_unop_f2b:
+ case ir_unop_i2b:
+ ir_to_mesa_emit_op2(ir, OPCODE_SNE, result_dst,
+ result_src, src_reg_for_float(0.0));
+ break;
+ case ir_unop_trunc:
+ ir_to_mesa_emit_op1(ir, OPCODE_TRUNC, result_dst, op[0]);
+ break;
+ case ir_unop_ceil:
+ op[0].negate = ~op[0].negate;
+ ir_to_mesa_emit_op1(ir, OPCODE_FLR, result_dst, op[0]);
+ result_src.negate = ~result_src.negate;
+ break;
+ case ir_unop_floor:
+ ir_to_mesa_emit_op1(ir, OPCODE_FLR, result_dst, op[0]);
+ break;
+ case ir_unop_fract:
+ ir_to_mesa_emit_op1(ir, OPCODE_FRC, result_dst, op[0]);
+ break;
+
+ case ir_binop_min:
+ ir_to_mesa_emit_op2(ir, OPCODE_MIN, result_dst, op[0], op[1]);
+ break;
+ case ir_binop_max:
+ ir_to_mesa_emit_op2(ir, OPCODE_MAX, result_dst, op[0], op[1]);
+ break;
+ case ir_binop_pow:
+ ir_to_mesa_emit_scalar_op2(ir, OPCODE_POW, result_dst, op[0], op[1]);
+ break;
+
+ case ir_unop_bit_not:
+ case ir_unop_u2f:
+ case ir_binop_lshift:
+ case ir_binop_rshift:
+ case ir_binop_bit_and:
+ case ir_binop_bit_xor:
+ case ir_binop_bit_or:
+ assert(!"GLSL 1.30 features unsupported");
+ break;
+ }
+
+ this->result = result_src;
+}
+
+
+void
+ir_to_mesa_visitor::visit(ir_swizzle *ir)
+{
+ ir_to_mesa_src_reg src_reg;
+ int i;
+ int swizzle[4];
+
+ /* Note that this is only swizzles in expressions, not those on the left
+ * hand side of an assignment, which do write masking. See ir_assignment
+ * for that.
+ */
+
+ ir->val->accept(this);
+ src_reg = this->result;
+ assert(src_reg.file != PROGRAM_UNDEFINED);
+
+ for (i = 0; i < 4; i++) {
+ if (i < ir->type->vector_elements) {
+ switch (i) {
+ case 0:
+ swizzle[i] = GET_SWZ(src_reg.swizzle, ir->mask.x);
+ break;
+ case 1:
+ swizzle[i] = GET_SWZ(src_reg.swizzle, ir->mask.y);
+ break;
+ case 2:
+ swizzle[i] = GET_SWZ(src_reg.swizzle, ir->mask.z);
+ break;
+ case 3:
+ swizzle[i] = GET_SWZ(src_reg.swizzle, ir->mask.w);
+ break;
+ }
+ } else {
+ /* If the type is smaller than a vec4, replicate the last
+ * channel out.
+ */
+ swizzle[i] = swizzle[ir->type->vector_elements - 1];
+ }
+ }
+
+ src_reg.swizzle = MAKE_SWIZZLE4(swizzle[0],
+ swizzle[1],
+ swizzle[2],
+ swizzle[3]);
+
+ this->result = src_reg;
+}
+
+static const struct {
+ const char *name;
+ const char *field;
+ int tokens[STATE_LENGTH];
+ int swizzle;
+ bool array_indexed;
+} statevars[] = {
+ {"gl_DepthRange", "near",
+ {STATE_DEPTH_RANGE, 0, 0}, SWIZZLE_XXXX},
+ {"gl_DepthRange", "far",
+ {STATE_DEPTH_RANGE, 0, 0}, SWIZZLE_YYYY},
+ {"gl_DepthRange", "diff",
+ {STATE_DEPTH_RANGE, 0, 0}, SWIZZLE_ZZZZ},
+
+ {"gl_ClipPlane", NULL,
+ {STATE_CLIPPLANE, 0, 0}, SWIZZLE_XYZW, true}
+,
+ {"gl_Point", "size",
+ {STATE_POINT_SIZE}, SWIZZLE_XXXX},
+ {"gl_Point", "sizeMin",
+ {STATE_POINT_SIZE}, SWIZZLE_YYYY},
+ {"gl_Point", "sizeMax",
+ {STATE_POINT_SIZE}, SWIZZLE_ZZZZ},
+ {"gl_Point", "fadeThresholdSize",
+ {STATE_POINT_SIZE}, SWIZZLE_WWWW},
+ {"gl_Point", "distanceConstantAttenuation",
+ {STATE_POINT_ATTENUATION}, SWIZZLE_XXXX},
+ {"gl_Point", "distanceLinearAttenuation",
+ {STATE_POINT_ATTENUATION}, SWIZZLE_YYYY},
+ {"gl_Point", "distanceQuadraticAttenuation",
+ {STATE_POINT_ATTENUATION}, SWIZZLE_ZZZZ},
+
+ {"gl_FrontMaterial", "emission",
+ {STATE_MATERIAL, 0, STATE_EMISSION}, SWIZZLE_XYZW},
+ {"gl_FrontMaterial", "ambient",
+ {STATE_MATERIAL, 0, STATE_AMBIENT}, SWIZZLE_XYZW},
+ {"gl_FrontMaterial", "diffuse",
+ {STATE_MATERIAL, 0, STATE_DIFFUSE}, SWIZZLE_XYZW},
+ {"gl_FrontMaterial", "specular",
+ {STATE_MATERIAL, 0, STATE_SPECULAR}, SWIZZLE_XYZW},
+ {"gl_FrontMaterial", "shininess",
+ {STATE_MATERIAL, 0, STATE_SHININESS}, SWIZZLE_XXXX},
+
+ {"gl_BackMaterial", "emission",
+ {STATE_MATERIAL, 1, STATE_EMISSION}, SWIZZLE_XYZW},
+ {"gl_BackMaterial", "ambient",
+ {STATE_MATERIAL, 1, STATE_AMBIENT}, SWIZZLE_XYZW},
+ {"gl_BackMaterial", "diffuse",
+ {STATE_MATERIAL, 1, STATE_DIFFUSE}, SWIZZLE_XYZW},
+ {"gl_BackMaterial", "specular",
+ {STATE_MATERIAL, 1, STATE_SPECULAR}, SWIZZLE_XYZW},
+ {"gl_BackMaterial", "shininess",
+ {STATE_MATERIAL, 1, STATE_SHININESS}, SWIZZLE_XXXX},
+
+ {"gl_LightSource", "ambient",
+ {STATE_LIGHT, 0, STATE_AMBIENT}, SWIZZLE_XYZW, true},
+ {"gl_LightSource", "diffuse",
+ {STATE_LIGHT, 0, STATE_DIFFUSE}, SWIZZLE_XYZW, true},
+ {"gl_LightSource", "specular",
+ {STATE_LIGHT, 0, STATE_SPECULAR}, SWIZZLE_XYZW, true},
+ {"gl_LightSource", "position",
+ {STATE_LIGHT, 0, STATE_POSITION}, SWIZZLE_XYZW, true},
+ {"gl_LightSource", "halfVector",
+ {STATE_LIGHT, 0, STATE_HALF_VECTOR}, SWIZZLE_XYZW, true},
+ {"gl_LightSource", "spotDirection",
+ {STATE_LIGHT, 0, STATE_SPOT_DIRECTION}, SWIZZLE_XYZW, true},
+ {"gl_LightSource", "spotCosCutoff",
+ {STATE_LIGHT, 0, STATE_SPOT_DIRECTION}, SWIZZLE_WWWW, true},
+ {"gl_LightSource", "spotCutoff",
+ {STATE_LIGHT, 0, STATE_SPOT_CUTOFF}, SWIZZLE_XXXX, true},
+ {"gl_LightSource", "spotExponent",
+ {STATE_LIGHT, 0, STATE_ATTENUATION}, SWIZZLE_WWWW, true},
+ {"gl_LightSource", "constantAttenuation",
+ {STATE_LIGHT, 0, STATE_ATTENUATION}, SWIZZLE_XXXX, true},
+ {"gl_LightSource", "linearAttenuation",
+ {STATE_LIGHT, 0, STATE_ATTENUATION}, SWIZZLE_YYYY, true},
+ {"gl_LightSource", "quadraticAttenuation",
+ {STATE_LIGHT, 0, STATE_ATTENUATION}, SWIZZLE_ZZZZ, true},
+
+ {"gl_LightModel", NULL,
+ {STATE_LIGHTMODEL_AMBIENT, 0}, SWIZZLE_XYZW},
+
+ {"gl_FrontLightModelProduct", NULL,
+ {STATE_LIGHTMODEL_SCENECOLOR, 0}, SWIZZLE_XYZW},
+ {"gl_BackLightModelProduct", NULL,
+ {STATE_LIGHTMODEL_SCENECOLOR, 1}, SWIZZLE_XYZW},
+
+ {"gl_FrontLightProduct", "ambient",
+ {STATE_LIGHTPROD, 0, 0, STATE_AMBIENT}, SWIZZLE_XYZW, true},
+ {"gl_FrontLightProduct", "diffuse",
+ {STATE_LIGHTPROD, 0, 0, STATE_DIFFUSE}, SWIZZLE_XYZW, true},
+ {"gl_FrontLightProduct", "specular",
+ {STATE_LIGHTPROD, 0, 0, STATE_SPECULAR}, SWIZZLE_XYZW, true},
+
+ {"gl_BackLightProduct", "ambient",
+ {STATE_LIGHTPROD, 0, 1, STATE_AMBIENT}, SWIZZLE_XYZW, true},
+ {"gl_BackLightProduct", "diffuse",
+ {STATE_LIGHTPROD, 0, 1, STATE_DIFFUSE}, SWIZZLE_XYZW, true},
+ {"gl_BackLightProduct", "specular",
+ {STATE_LIGHTPROD, 0, 1, STATE_SPECULAR}, SWIZZLE_XYZW, true},
+
+ {"gl_TextureEnvColor", "ambient",
+ {STATE_TEXENV_COLOR, 0}, SWIZZLE_XYZW, true},
+
+ {"gl_EyePlaneS", NULL,
+ {STATE_TEXGEN, 0, STATE_TEXGEN_EYE_S}, SWIZZLE_XYZW, true},
+ {"gl_EyePlaneT", NULL,
+ {STATE_TEXGEN, 0, STATE_TEXGEN_EYE_T}, SWIZZLE_XYZW, true},
+ {"gl_EyePlaneR", NULL,
+ {STATE_TEXGEN, 0, STATE_TEXGEN_EYE_R}, SWIZZLE_XYZW, true},
+ {"gl_EyePlaneQ", NULL,
+ {STATE_TEXGEN, 0, STATE_TEXGEN_EYE_Q}, SWIZZLE_XYZW, true},
+
+ {"gl_ObjectPlaneS", NULL,
+ {STATE_TEXGEN, 0, STATE_TEXGEN_OBJECT_S}, SWIZZLE_XYZW, true},
+ {"gl_ObjectPlaneT", NULL,
+ {STATE_TEXGEN, 0, STATE_TEXGEN_OBJECT_T}, SWIZZLE_XYZW, true},
+ {"gl_ObjectPlaneR", NULL,
+ {STATE_TEXGEN, 0, STATE_TEXGEN_OBJECT_R}, SWIZZLE_XYZW, true},
+ {"gl_ObjectPlaneQ", NULL,
+ {STATE_TEXGEN, 0, STATE_TEXGEN_OBJECT_Q}, SWIZZLE_XYZW, true},
+
+ {"gl_Fog", "color",
+ {STATE_FOG_COLOR}, SWIZZLE_XYZW},
+ {"gl_Fog", "density",
+ {STATE_FOG_PARAMS}, SWIZZLE_XXXX},
+ {"gl_Fog", "start",
+ {STATE_FOG_PARAMS}, SWIZZLE_YYYY},
+ {"gl_Fog", "end",
+ {STATE_FOG_PARAMS}, SWIZZLE_ZZZZ},
+ {"gl_Fog", "scale",
+ {STATE_FOG_PARAMS}, SWIZZLE_WWWW},
+};
+
+static ir_to_mesa_src_reg
+get_builtin_uniform_reg(struct gl_program *prog,
+ const char *name, int array_index, const char *field)
+{
+ unsigned int i;
+ ir_to_mesa_src_reg src_reg;
+ int tokens[STATE_LENGTH];
+
+ for (i = 0; i < Elements(statevars); i++) {
+ if (strcmp(statevars[i].name, name) != 0)
+ continue;
+ if (!field && statevars[i].field) {
+ assert(!"FINISHME: whole-structure state var dereference");
+ }
+ if (field && strcmp(statevars[i].field, field) != 0)
+ continue;
+ break;
+ }
+
+ if (i == Elements(statevars)) {
+ printf("builtin uniform %s%s%s not found\n",
+ name,
+ field ? "." : "",
+ field ? field : "");
+ abort();
+ }
+
+ memcpy(&tokens, statevars[i].tokens, sizeof(tokens));
+ if (statevars[i].array_indexed)
+ tokens[1] = array_index;
+
+ src_reg.file = PROGRAM_STATE_VAR;
+ src_reg.index = _mesa_add_state_reference(prog->Parameters,
+ (gl_state_index *)tokens);
+ src_reg.swizzle = statevars[i].swizzle;
+ src_reg.negate = 0;
+ src_reg.reladdr = false;
+
+ return src_reg;
+}
+
+static int
+add_matrix_ref(struct gl_program *prog, int *tokens)
+{
+ int base_pos = -1;
+ int i;
+
+ /* Add a ref for each column. It looks like the reason we do
+ * it this way is that _mesa_add_state_reference doesn't work
+ * for things that aren't vec4s, so the tokens[2]/tokens[3]
+ * range has to be equal.
+ */
+ for (i = 0; i < 4; i++) {
+ tokens[2] = i;
+ tokens[3] = i;
+ int pos = _mesa_add_state_reference(prog->Parameters,
+ (gl_state_index *)tokens);
+ if (base_pos == -1)
+ base_pos = pos;
+ else
+ assert(base_pos + i == pos);
+ }
+
+ return base_pos;
+}
+
+static variable_storage *
+get_builtin_matrix_ref(void *mem_ctx, struct gl_program *prog, ir_variable *var,
+ ir_rvalue *array_index)
+{
+ /*
+ * NOTE: The ARB_vertex_program extension specified that matrices get
+ * loaded in registers in row-major order. With GLSL, we want column-
+ * major order. So, we need to transpose all matrices here...
+ */
+ static const struct {
+ const char *name;
+ int matrix;
+ int modifier;
+ } matrices[] = {
+ { "gl_ModelViewMatrix", STATE_MODELVIEW_MATRIX, STATE_MATRIX_TRANSPOSE },
+ { "gl_ModelViewMatrixInverse", STATE_MODELVIEW_MATRIX, STATE_MATRIX_INVTRANS },
+ { "gl_ModelViewMatrixTranspose", STATE_MODELVIEW_MATRIX, 0 },
+ { "gl_ModelViewMatrixInverseTranspose", STATE_MODELVIEW_MATRIX, STATE_MATRIX_INVERSE },
+
+ { "gl_ProjectionMatrix", STATE_PROJECTION_MATRIX, STATE_MATRIX_TRANSPOSE },
+ { "gl_ProjectionMatrixInverse", STATE_PROJECTION_MATRIX, STATE_MATRIX_INVTRANS },
+ { "gl_ProjectionMatrixTranspose", STATE_PROJECTION_MATRIX, 0 },
+ { "gl_ProjectionMatrixInverseTranspose", STATE_PROJECTION_MATRIX, STATE_MATRIX_INVERSE },
+
+ { "gl_ModelViewProjectionMatrix", STATE_MVP_MATRIX, STATE_MATRIX_TRANSPOSE },
+ { "gl_ModelViewProjectionMatrixInverse", STATE_MVP_MATRIX, STATE_MATRIX_INVTRANS },
+ { "gl_ModelViewProjectionMatrixTranspose", STATE_MVP_MATRIX, 0 },
+ { "gl_ModelViewProjectionMatrixInverseTranspose", STATE_MVP_MATRIX, STATE_MATRIX_INVERSE },
+
+ { "gl_TextureMatrix", STATE_TEXTURE_MATRIX, STATE_MATRIX_TRANSPOSE },
+ { "gl_TextureMatrixInverse", STATE_TEXTURE_MATRIX, STATE_MATRIX_INVTRANS },
+ { "gl_TextureMatrixTranspose", STATE_TEXTURE_MATRIX, 0 },
+ { "gl_TextureMatrixInverseTranspose", STATE_TEXTURE_MATRIX, STATE_MATRIX_INVERSE },
+
+ { "gl_NormalMatrix", STATE_MODELVIEW_MATRIX, STATE_MATRIX_INVERSE },
+
+ };
+ unsigned int i;
+ variable_storage *entry;
+
+ /* C++ gets angry when we try to use an int as a gl_state_index, so we use
+ * ints for gl_state_index. Make sure they're compatible.
+ */
+ assert(sizeof(gl_state_index) == sizeof(int));
+
+ for (i = 0; i < Elements(matrices); i++) {
+ if (strcmp(var->name, matrices[i].name) == 0) {
+ int tokens[STATE_LENGTH];
+ int base_pos = -1;
+
+ tokens[0] = matrices[i].matrix;
+ tokens[4] = matrices[i].modifier;
+ if (matrices[i].matrix == STATE_TEXTURE_MATRIX) {
+ ir_constant *index = array_index->constant_expression_value();
+ if (index) {
+ tokens[1] = index->value.i[0];
+ base_pos = add_matrix_ref(prog, tokens);
+ } else {
+ for (i = 0; i < var->type->length; i++) {
+ tokens[1] = i;
+ int pos = add_matrix_ref(prog, tokens);
+ if (base_pos == -1)
+ base_pos = pos;
+ else
+ assert(base_pos + (int)i * 4 == pos);
+ }
+ }
+ } else {
+ tokens[1] = 0; /* unused array index */
+ base_pos = add_matrix_ref(prog, tokens);
+ }
+ tokens[4] = matrices[i].modifier;
+
+ entry = new(mem_ctx) variable_storage(var,
+ PROGRAM_STATE_VAR,
+ base_pos);
+
+ return entry;
+ }
+ }
+
+ return NULL;
+}
+
+int
+ir_to_mesa_visitor::add_uniform(const char *name,
+ const glsl_type *type,
+ ir_constant *constant)
+{
+ int len;
+
+ if (type->is_vector() ||
+ type->is_scalar()) {
+ len = type->vector_elements;
+ } else {
+ len = type_size(type) * 4;
+ }
+
+ float *values = NULL;
+ if (constant && type->is_array()) {
+ values = (float *)malloc(type->length * 4 * sizeof(float));
+
+ assert(type->fields.array->is_scalar() ||
+ type->fields.array->is_vector() ||
+ !"FINISHME: uniform array initializers for non-vector");
+
+ for (unsigned int i = 0; i < type->length; i++) {
+ ir_constant *element = constant->array_elements[i];
+ unsigned int c;
+
+ for (c = 0; c < type->fields.array->vector_elements; c++) {
+ switch (type->fields.array->base_type) {
+ case GLSL_TYPE_FLOAT:
+ values[4 * i + c] = element->value.f[c];
+ break;
+ case GLSL_TYPE_INT:
+ values[4 * i + c] = element->value.i[c];
+ break;
+ case GLSL_TYPE_UINT:
+ values[4 * i + c] = element->value.u[c];
+ break;
+ case GLSL_TYPE_BOOL:
+ values[4 * i + c] = element->value.b[c];
+ break;
+ default:
+ assert(!"not reached");
+ }
+ }
+ }
+ } else if (constant) {
+ values = (float *)malloc(16 * sizeof(float));
+ for (unsigned int i = 0; i < type->components(); i++) {
+ switch (type->base_type) {
+ case GLSL_TYPE_FLOAT:
+ values[i] = constant->value.f[i];
+ break;
+ case GLSL_TYPE_INT:
+ values[i] = constant->value.i[i];
+ break;
+ case GLSL_TYPE_UINT:
+ values[i] = constant->value.u[i];
+ break;
+ case GLSL_TYPE_BOOL:
+ values[i] = constant->value.b[i];
+ break;
+ default:
+ assert(!"not reached");
+ }
+ }
+ }
+
+ int loc = _mesa_add_uniform(this->prog->Parameters,
+ name,
+ len,
+ type->gl_type,
+ values);
+ free(values);
+
+ return loc;
+}
+
+/* Recursively add all the members of the aggregate uniform as uniform names
+ * to Mesa, moving those uniforms to our structured temporary.
+ */
+void
+ir_to_mesa_visitor::add_aggregate_uniform(ir_instruction *ir,
+ const char *name,
+ const struct glsl_type *type,
+ ir_constant *constant,
+ struct ir_to_mesa_dst_reg temp)
+{
+ int loc;
+
+ if (type->is_record()) {
+ void *mem_ctx = talloc_new(NULL);
+ ir_constant *field_constant = NULL;
+
+ if (constant)
+ field_constant = (ir_constant *)constant->components.get_head();
+
+ for (unsigned int i = 0; i < type->length; i++) {
+ const glsl_type *field_type = type->fields.structure[i].type;
+
+ add_aggregate_uniform(ir,
+ talloc_asprintf(mem_ctx, "%s.%s", name,
+ type->fields.structure[i].name),
+ field_type, field_constant, temp);
+ temp.index += type_size(field_type);
+
+ if (constant)
+ field_constant = (ir_constant *)field_constant->next;
+ }
+
+ talloc_free(mem_ctx);
+
+ return;
+ }
+
+ assert(type->is_vector() || type->is_scalar() || !"FINISHME: other types");
+
+ loc = add_uniform(name, type, constant);
+
+ ir_to_mesa_src_reg uniform(PROGRAM_UNIFORM, loc, type);
+
+ for (int i = 0; i < type_size(type); i++) {
+ ir_to_mesa_emit_op1(ir, OPCODE_MOV, temp, uniform);
+ temp.index++;
+ uniform.index++;
+ }
+}
+
+
+void
+ir_to_mesa_visitor::visit(ir_dereference_variable *ir)
+{
+ variable_storage *entry = find_variable_storage(ir->var);
+ unsigned int loc;
+
+ if (!entry) {
+ switch (ir->var->mode) {
+ case ir_var_uniform:
+ entry = get_builtin_matrix_ref(this->mem_ctx, this->prog, ir->var,
+ NULL);
+ if (entry)
+ break;
+
+ /* FINISHME: Fix up uniform name for arrays and things */
+ if (ir->var->type->base_type == GLSL_TYPE_SAMPLER ||
+ (ir->var->type->base_type == GLSL_TYPE_ARRAY &&
+ ir->var->type->fields.array->base_type == GLSL_TYPE_SAMPLER)) {
+ int array_length;
+
+ if (ir->var->type->base_type == GLSL_TYPE_ARRAY)
+ array_length = ir->var->type->length;
+ else
+ array_length = 1;
+ int sampler = _mesa_add_sampler(this->prog->Parameters,
+ ir->var->name,
+ ir->var->type->gl_type,
+ array_length);
+ set_sampler_location(ir->var, sampler);
+
+ entry = new(mem_ctx) variable_storage(ir->var, PROGRAM_SAMPLER,
+ sampler);
+ this->variables.push_tail(entry);
+ break;
+ }
+
+ assert(ir->var->type->gl_type != 0 &&
+ ir->var->type->gl_type != GL_INVALID_ENUM);
+
+ /* Oh, the joy of aggregate types in Mesa. Like constants,
+ * we can only really do vec4s. So, make a temp, chop the
+ * aggregate up into vec4s, and move those vec4s to the temp.
+ */
+ if (ir->var->type->is_record()) {
+ ir_to_mesa_src_reg temp = get_temp(ir->var->type);
+
+ entry = new(mem_ctx) variable_storage(ir->var,
+ temp.file,
+ temp.index);
+ this->variables.push_tail(entry);
+
+ add_aggregate_uniform(ir->var, ir->var->name, ir->var->type,
+ ir->var->constant_value,
+ ir_to_mesa_dst_reg_from_src(temp));
+ break;
+ }
+
+ loc = add_uniform(ir->var->name,
+ ir->var->type,
+ ir->var->constant_value);
+
+ /* Always mark the uniform used at this point. If it isn't
+ * used, dead code elimination should have nuked the decl already.
+ */
+ this->prog->Parameters->Parameters[loc].Used = GL_TRUE;
+
+ entry = new(mem_ctx) variable_storage(ir->var, PROGRAM_UNIFORM, loc);
+ this->variables.push_tail(entry);
+ break;
+ case ir_var_in:
+ case ir_var_out:
+ case ir_var_inout:
+ /* The linker assigns locations for varyings and attributes,
+ * including deprecated builtins (like gl_Color), user-assign
+ * generic attributes (glBindVertexLocation), and
+ * user-defined varyings.
+ *
+ * FINISHME: We would hit this path for function arguments. Fix!
+ */
+ assert(ir->var->location != -1);
+ if (ir->var->mode == ir_var_in ||
+ ir->var->mode == ir_var_inout) {
+ entry = new(mem_ctx) variable_storage(ir->var,
+ PROGRAM_INPUT,
+ ir->var->location);
+
+ if (this->prog->Target == GL_VERTEX_PROGRAM_ARB &&
+ ir->var->location >= VERT_ATTRIB_GENERIC0) {
+ _mesa_add_attribute(prog->Attributes,
+ ir->var->name,
+ _mesa_sizeof_glsl_type(ir->var->type->gl_type),
+ ir->var->type->gl_type,
+ ir->var->location - VERT_ATTRIB_GENERIC0);
+ }
+ } else {
+ entry = new(mem_ctx) variable_storage(ir->var,
+ PROGRAM_OUTPUT,
+ ir->var->location);
+ }
+
+ break;
+ case ir_var_auto:
+ case ir_var_temporary:
+ entry = new(mem_ctx) variable_storage(ir->var, PROGRAM_TEMPORARY,
+ this->next_temp);
+ this->variables.push_tail(entry);
+
+ next_temp += type_size(ir->var->type);
+ break;
+ }
+
+ if (!entry) {
+ printf("Failed to make storage for %s\n", ir->var->name);
+ exit(1);
+ }
+ }
+
+ this->result = ir_to_mesa_src_reg(entry->file, entry->index, ir->var->type);
+}
+
+void
+ir_to_mesa_visitor::visit(ir_dereference_array *ir)
+{
+ ir_variable *var = ir->variable_referenced();
+ ir_constant *index;
+ ir_to_mesa_src_reg src_reg;
+ ir_dereference_variable *deref_var = ir->array->as_dereference_variable();
+ int element_size = type_size(ir->type);
+
+ index = ir->array_index->constant_expression_value();
+
+ if (deref_var && strncmp(deref_var->var->name,
+ "gl_TextureMatrix",
+ strlen("gl_TextureMatrix")) == 0) {
+ struct variable_storage *entry;
+
+ entry = get_builtin_matrix_ref(this->mem_ctx, this->prog, deref_var->var,
+ ir->array_index);
+ assert(entry);
+
+ ir_to_mesa_src_reg src_reg(entry->file, entry->index, ir->type);
+
+ if (index) {
+ src_reg.reladdr = NULL;
+ } else {
+ ir_to_mesa_src_reg index_reg = get_temp(glsl_type::float_type);
+
+ ir->array_index->accept(this);
+ ir_to_mesa_emit_op2(ir, OPCODE_MUL,
+ ir_to_mesa_dst_reg_from_src(index_reg),
+ this->result, src_reg_for_float(element_size));
+
+ src_reg.reladdr = talloc(mem_ctx, ir_to_mesa_src_reg);
+ memcpy(src_reg.reladdr, &index_reg, sizeof(index_reg));
+ }
+
+ this->result = src_reg;
+ return;
+ }
+
+ if (strncmp(var->name, "gl_", 3) == 0 && var->mode == ir_var_uniform &&
+ !var->type->is_matrix()) {
+ ir_dereference_record *record = NULL;
+ if (ir->array->ir_type == ir_type_dereference_record)
+ record = (ir_dereference_record *)ir->array;
+
+ assert(index || !"FINISHME: variable-indexed builtin uniform access");
+
+ this->result = get_builtin_uniform_reg(prog,
+ var->name,
+ index->value.i[0],
+ record ? record->field : NULL);
+ }
+
+ ir->array->accept(this);
+ src_reg = this->result;
+
+ if (index) {
+ src_reg.index += index->value.i[0] * element_size;
+ } else {
+ ir_to_mesa_src_reg array_base = this->result;
+ /* Variable index array dereference. It eats the "vec4" of the
+ * base of the array and an index that offsets the Mesa register
+ * index.
+ */
+ ir->array_index->accept(this);
+
+ ir_to_mesa_src_reg index_reg;
+
+ if (element_size == 1) {
+ index_reg = this->result;
+ } else {
+ index_reg = get_temp(glsl_type::float_type);
+
+ ir_to_mesa_emit_op2(ir, OPCODE_MUL,
+ ir_to_mesa_dst_reg_from_src(index_reg),
+ this->result, src_reg_for_float(element_size));
+ }
+
+ src_reg.reladdr = talloc(mem_ctx, ir_to_mesa_src_reg);
+ memcpy(src_reg.reladdr, &index_reg, sizeof(index_reg));
+ }
+
+ /* If the type is smaller than a vec4, replicate the last channel out. */
+ if (ir->type->is_scalar() || ir->type->is_vector())
+ src_reg.swizzle = swizzle_for_size(ir->type->vector_elements);
+ else
+ src_reg.swizzle = SWIZZLE_NOOP;
+
+ this->result = src_reg;
+}
+
+void
+ir_to_mesa_visitor::visit(ir_dereference_record *ir)
+{
+ unsigned int i;
+ const glsl_type *struct_type = ir->record->type;
+ int offset = 0;
+ ir_variable *var = ir->record->variable_referenced();
+
+ if (strncmp(var->name, "gl_", 3) == 0 && var->mode == ir_var_uniform) {
+ assert(var);
+
+ this->result = get_builtin_uniform_reg(prog,
+ var->name,
+ 0,
+ ir->field);
+ return;
+ }
+
+ ir->record->accept(this);
+
+ for (i = 0; i < struct_type->length; i++) {
+ if (strcmp(struct_type->fields.structure[i].name, ir->field) == 0)
+ break;
+ offset += type_size(struct_type->fields.structure[i].type);
+ }
+ this->result.swizzle = swizzle_for_size(ir->type->vector_elements);
+ this->result.index += offset;
+}
+
+/**
+ * We want to be careful in assignment setup to hit the actual storage
+ * instead of potentially using a temporary like we might with the
+ * ir_dereference handler.
+ */
+static struct ir_to_mesa_dst_reg
+get_assignment_lhs(ir_dereference *ir, ir_to_mesa_visitor *v,
+ ir_to_mesa_src_reg *r)
+{
+ /* The LHS must be a dereference. If the LHS is a variable indexed array
+ * access of a vector, it must be separated into a series conditional moves
+ * before reaching this point (see ir_vec_index_to_cond_assign).
+ */
+ assert(ir->as_dereference());
+ ir_dereference_array *deref_array = ir->as_dereference_array();
+ if (deref_array) {
+ assert(!deref_array->array->type->is_vector());
+ }
+
+ /* Use the rvalue deref handler for the most part. We'll ignore
+ * swizzles in it and write swizzles using writemask, though.
+ */
+ ir->accept(v);
+ return ir_to_mesa_dst_reg_from_src(v->result);
+}
+
+void
+ir_to_mesa_visitor::visit(ir_assignment *ir)
+{
+ struct ir_to_mesa_dst_reg l;
+ struct ir_to_mesa_src_reg r;
+ int i;
+
+ ir->rhs->accept(this);
+ r = this->result;
+
+ l = get_assignment_lhs(ir->lhs, this, &r);
+
+ /* FINISHME: This should really set to the correct maximal writemask for each
+ * FINISHME: component written (in the loops below). This case can only
+ * FINISHME: occur for matrices, arrays, and structures.
+ */
+ if (ir->write_mask == 0) {
+ assert(!ir->lhs->type->is_scalar() && !ir->lhs->type->is_vector());
+ l.writemask = WRITEMASK_XYZW;
+ } else if (ir->lhs->type->is_scalar()) {
+ /* FINISHME: This hack makes writing to gl_FragData, which lives in the
+ * FINISHME: W component of fragment shader output zero, work correctly.
+ */
+ l.writemask = WRITEMASK_XYZW;
+ } else {
+ assert(ir->lhs->type->is_vector());
+ l.writemask = ir->write_mask;
+ }
+
+ assert(l.file != PROGRAM_UNDEFINED);
+ assert(r.file != PROGRAM_UNDEFINED);
+
+ if (ir->condition) {
+ ir_to_mesa_src_reg condition;
+
+ ir->condition->accept(this);
+ condition = this->result;
+
+ /* We use the OPCODE_CMP (a < 0 ? b : c) for conditional moves,
+ * and the condition we produced is 0.0 or 1.0. By flipping the
+ * sign, we can choose which value OPCODE_CMP produces without
+ * an extra computing the condition.
+ */
+ condition.negate = ~condition.negate;
+ for (i = 0; i < type_size(ir->lhs->type); i++) {
+ ir_to_mesa_emit_op3(ir, OPCODE_CMP, l,
+ condition, r, ir_to_mesa_src_reg_from_dst(l));
+ l.index++;
+ r.index++;
+ }
+ } else {
+ for (i = 0; i < type_size(ir->lhs->type); i++) {
+ ir_to_mesa_emit_op1(ir, OPCODE_MOV, l, r);
+ l.index++;
+ r.index++;
+ }
+ }
+}
+
+
+void
+ir_to_mesa_visitor::visit(ir_constant *ir)
+{
+ ir_to_mesa_src_reg src_reg;
+ GLfloat stack_vals[4];
+ GLfloat *values = stack_vals;
+ unsigned int i;
+
+ /* Unfortunately, 4 floats is all we can get into
+ * _mesa_add_unnamed_constant. So, make a temp to store an
+ * aggregate constant and move each constant value into it. If we
+ * get lucky, copy propagation will eliminate the extra moves.
+ */
+
+ if (ir->type->base_type == GLSL_TYPE_STRUCT) {
+ ir_to_mesa_src_reg temp_base = get_temp(ir->type);
+ ir_to_mesa_dst_reg temp = ir_to_mesa_dst_reg_from_src(temp_base);
+
+ foreach_iter(exec_list_iterator, iter, ir->components) {
+ ir_constant *field_value = (ir_constant *)iter.get();
+ int size = type_size(field_value->type);
+
+ assert(size > 0);
+
+ field_value->accept(this);
+ src_reg = this->result;
+
+ for (i = 0; i < (unsigned int)size; i++) {
+ ir_to_mesa_emit_op1(ir, OPCODE_MOV, temp, src_reg);
+
+ src_reg.index++;
+ temp.index++;
+ }
+ }
+ this->result = temp_base;
+ return;
+ }
+
+ if (ir->type->is_array()) {
+ ir_to_mesa_src_reg temp_base = get_temp(ir->type);
+ ir_to_mesa_dst_reg temp = ir_to_mesa_dst_reg_from_src(temp_base);
+ int size = type_size(ir->type->fields.array);
+
+ assert(size > 0);
+
+ for (i = 0; i < ir->type->length; i++) {
+ ir->array_elements[i]->accept(this);
+ src_reg = this->result;
+ for (int j = 0; j < size; j++) {
+ ir_to_mesa_emit_op1(ir, OPCODE_MOV, temp, src_reg);
+
+ src_reg.index++;
+ temp.index++;
+ }
+ }
+ this->result = temp_base;
+ return;
+ }
+
+ if (ir->type->is_matrix()) {
+ ir_to_mesa_src_reg mat = get_temp(ir->type);
+ ir_to_mesa_dst_reg mat_column = ir_to_mesa_dst_reg_from_src(mat);
+
+ for (i = 0; i < ir->type->matrix_columns; i++) {
+ assert(ir->type->base_type == GLSL_TYPE_FLOAT);
+ values = &ir->value.f[i * ir->type->vector_elements];
+
+ src_reg = ir_to_mesa_src_reg(PROGRAM_CONSTANT, -1, NULL);
+ src_reg.index = _mesa_add_unnamed_constant(this->prog->Parameters,
+ values,
+ ir->type->vector_elements,
+ &src_reg.swizzle);
+ ir_to_mesa_emit_op1(ir, OPCODE_MOV, mat_column, src_reg);
+
+ mat_column.index++;
+ }
+
+ this->result = mat;
+ }
+
+ src_reg.file = PROGRAM_CONSTANT;
+ switch (ir->type->base_type) {
+ case GLSL_TYPE_FLOAT:
+ values = &ir->value.f[0];
+ break;
+ case GLSL_TYPE_UINT:
+ for (i = 0; i < ir->type->vector_elements; i++) {
+ values[i] = ir->value.u[i];
+ }
+ break;
+ case GLSL_TYPE_INT:
+ for (i = 0; i < ir->type->vector_elements; i++) {
+ values[i] = ir->value.i[i];
+ }
+ break;
+ case GLSL_TYPE_BOOL:
+ for (i = 0; i < ir->type->vector_elements; i++) {
+ values[i] = ir->value.b[i];
+ }
+ break;
+ default:
+ assert(!"Non-float/uint/int/bool constant");
+ }
+
+ this->result = ir_to_mesa_src_reg(PROGRAM_CONSTANT, -1, ir->type);
+ this->result.index = _mesa_add_unnamed_constant(this->prog->Parameters,
+ values,
+ ir->type->vector_elements,
+ &this->result.swizzle);
+}
+
+function_entry *
+ir_to_mesa_visitor::get_function_signature(ir_function_signature *sig)
+{
+ function_entry *entry;
+
+ foreach_iter(exec_list_iterator, iter, this->function_signatures) {
+ entry = (function_entry *)iter.get();
+
+ if (entry->sig == sig)
+ return entry;
+ }
+
+ entry = talloc(mem_ctx, function_entry);
+ entry->sig = sig;
+ entry->sig_id = this->next_signature_id++;
+ entry->bgn_inst = NULL;
+
+ /* Allocate storage for all the parameters. */
+ foreach_iter(exec_list_iterator, iter, sig->parameters) {
+ ir_variable *param = (ir_variable *)iter.get();
+ variable_storage *storage;
+
+ storage = find_variable_storage(param);
+ assert(!storage);
+
+ storage = new(mem_ctx) variable_storage(param, PROGRAM_TEMPORARY,
+ this->next_temp);
+ this->variables.push_tail(storage);
+
+ this->next_temp += type_size(param->type);
+ }
+
+ if (!sig->return_type->is_void()) {
+ entry->return_reg = get_temp(sig->return_type);
+ } else {
+ entry->return_reg = ir_to_mesa_undef;
+ }
+
+ this->function_signatures.push_tail(entry);
+ return entry;
+}
+
+void
+ir_to_mesa_visitor::visit(ir_call *ir)
+{
+ ir_to_mesa_instruction *call_inst;
+ ir_function_signature *sig = ir->get_callee();
+ function_entry *entry = get_function_signature(sig);
+ int i;
+
+ /* Process in parameters. */
+ exec_list_iterator sig_iter = sig->parameters.iterator();
+ foreach_iter(exec_list_iterator, iter, *ir) {
+ ir_rvalue *param_rval = (ir_rvalue *)iter.get();
+ ir_variable *param = (ir_variable *)sig_iter.get();
+
+ if (param->mode == ir_var_in ||
+ param->mode == ir_var_inout) {
+ variable_storage *storage = find_variable_storage(param);
+ assert(storage);
+
+ param_rval->accept(this);
+ ir_to_mesa_src_reg r = this->result;
+
+ ir_to_mesa_dst_reg l;
+ l.file = storage->file;
+ l.index = storage->index;
+ l.reladdr = NULL;
+ l.writemask = WRITEMASK_XYZW;
+ l.cond_mask = COND_TR;
+
+ for (i = 0; i < type_size(param->type); i++) {
+ ir_to_mesa_emit_op1(ir, OPCODE_MOV, l, r);
+ l.index++;
+ r.index++;
+ }
+ }
+
+ sig_iter.next();
+ }
+ assert(!sig_iter.has_next());
+
+ /* Emit call instruction */
+ call_inst = ir_to_mesa_emit_op1(ir, OPCODE_CAL,
+ ir_to_mesa_undef_dst, ir_to_mesa_undef);
+ call_inst->function = entry;
+
+ /* Process out parameters. */
+ sig_iter = sig->parameters.iterator();
+ foreach_iter(exec_list_iterator, iter, *ir) {
+ ir_rvalue *param_rval = (ir_rvalue *)iter.get();
+ ir_variable *param = (ir_variable *)sig_iter.get();
+
+ if (param->mode == ir_var_out ||
+ param->mode == ir_var_inout) {
+ variable_storage *storage = find_variable_storage(param);
+ assert(storage);
+
+ ir_to_mesa_src_reg r;
+ r.file = storage->file;
+ r.index = storage->index;
+ r.reladdr = NULL;
+ r.swizzle = SWIZZLE_NOOP;
+ r.negate = 0;
+
+ param_rval->accept(this);
+ ir_to_mesa_dst_reg l = ir_to_mesa_dst_reg_from_src(this->result);
+
+ for (i = 0; i < type_size(param->type); i++) {
+ ir_to_mesa_emit_op1(ir, OPCODE_MOV, l, r);
+ l.index++;
+ r.index++;
+ }
+ }
+
+ sig_iter.next();
+ }
+ assert(!sig_iter.has_next());
+
+ /* Process return value. */
+ this->result = entry->return_reg;
+}
+
+
+void
+ir_to_mesa_visitor::visit(ir_texture *ir)
+{
+ ir_to_mesa_src_reg result_src, coord, lod_info, projector;
+ ir_to_mesa_dst_reg result_dst, coord_dst;
+ ir_to_mesa_instruction *inst = NULL;
+ prog_opcode opcode = OPCODE_NOP;
+
+ ir->coordinate->accept(this);
+
+ /* Put our coords in a temp. We'll need to modify them for shadow,
+ * projection, or LOD, so the only case we'd use it as is is if
+ * we're doing plain old texturing. Mesa IR optimization should
+ * handle cleaning up our mess in that case.
+ */
+ coord = get_temp(glsl_type::vec4_type);
+ coord_dst = ir_to_mesa_dst_reg_from_src(coord);
+ ir_to_mesa_emit_op1(ir, OPCODE_MOV, coord_dst,
+ this->result);
+
+ if (ir->projector) {
+ ir->projector->accept(this);
+ projector = this->result;
+ }
+
+ /* Storage for our result. Ideally for an assignment we'd be using
+ * the actual storage for the result here, instead.
+ */
+ result_src = get_temp(glsl_type::vec4_type);
+ result_dst = ir_to_mesa_dst_reg_from_src(result_src);
+
+ switch (ir->op) {
+ case ir_tex:
+ opcode = OPCODE_TEX;
+ break;
+ case ir_txb:
+ opcode = OPCODE_TXB;
+ ir->lod_info.bias->accept(this);
+ lod_info = this->result;
+ break;
+ case ir_txl:
+ opcode = OPCODE_TXL;
+ ir->lod_info.lod->accept(this);
+ lod_info = this->result;
+ break;
+ case ir_txd:
+ case ir_txf:
+ assert(!"GLSL 1.30 features unsupported");
+ break;
+ }
+
+ if (ir->projector) {
+ if (opcode == OPCODE_TEX) {
+ /* Slot the projector in as the last component of the coord. */
+ coord_dst.writemask = WRITEMASK_W;
+ ir_to_mesa_emit_op1(ir, OPCODE_MOV, coord_dst, projector);
+ coord_dst.writemask = WRITEMASK_XYZW;
+ opcode = OPCODE_TXP;
+ } else {
+ ir_to_mesa_src_reg coord_w = coord;
+ coord_w.swizzle = SWIZZLE_WWWW;
+
+ /* For the other TEX opcodes there's no projective version
+ * since the last slot is taken up by lod info. Do the
+ * projective divide now.
+ */
+ coord_dst.writemask = WRITEMASK_W;
+ ir_to_mesa_emit_op1(ir, OPCODE_RCP, coord_dst, projector);
+
+ coord_dst.writemask = WRITEMASK_XYZ;
+ ir_to_mesa_emit_op2(ir, OPCODE_MUL, coord_dst, coord, coord_w);
+
+ coord_dst.writemask = WRITEMASK_XYZW;
+ coord.swizzle = SWIZZLE_XYZW;
+ }
+ }
+
+ if (ir->shadow_comparitor) {
+ /* Slot the shadow value in as the second to last component of the
+ * coord.
+ */
+ ir->shadow_comparitor->accept(this);
+ coord_dst.writemask = WRITEMASK_Z;
+ ir_to_mesa_emit_op1(ir, OPCODE_MOV, coord_dst, this->result);
+ coord_dst.writemask = WRITEMASK_XYZW;
+ }
+
+ if (opcode == OPCODE_TXL || opcode == OPCODE_TXB) {
+ /* Mesa IR stores lod or lod bias in the last channel of the coords. */
+ coord_dst.writemask = WRITEMASK_W;
+ ir_to_mesa_emit_op1(ir, OPCODE_MOV, coord_dst, lod_info);
+ coord_dst.writemask = WRITEMASK_XYZW;
+ }
+
+ inst = ir_to_mesa_emit_op1(ir, opcode, result_dst, coord);
+
+ if (ir->shadow_comparitor)
+ inst->tex_shadow = GL_TRUE;
+
+ ir_variable *sampler = ir->sampler->variable_referenced();
+
+ /* generate the mapping, remove when we generate storage at
+ * declaration time
+ */
+ ir->sampler->accept(this);
+
+ inst->sampler = get_sampler_location(sampler);
+
+ ir_dereference_array *sampler_array = ir->sampler->as_dereference_array();
+ if (sampler_array) {
+ ir_constant *array_index =
+ sampler_array->array_index->constant_expression_value();
+
+ /* GLSL 1.10 and 1.20 allowed variable sampler array indices,
+ * while GLSL 1.30 requires that the array indices be constant
+ * integer expressions. We don't expect any driver to actually
+ * work with a really variable array index, and in 1.20 all that
+ * would work would be an unrolled loop counter, so assert that
+ * we ended up with a constant at least..
+ */
+ assert(array_index);
+ inst->sampler += array_index->value.i[0];
+ }
+
+ const glsl_type *sampler_type = sampler->type;
+ while (sampler_type->base_type == GLSL_TYPE_ARRAY)
+ sampler_type = sampler_type->fields.array;
+
+ switch (sampler_type->sampler_dimensionality) {
+ case GLSL_SAMPLER_DIM_1D:
+ inst->tex_target = (sampler_type->sampler_array)
+ ? TEXTURE_1D_ARRAY_INDEX : TEXTURE_1D_INDEX;
+ break;
+ case GLSL_SAMPLER_DIM_2D:
+ inst->tex_target = (sampler_type->sampler_array)
+ ? TEXTURE_2D_ARRAY_INDEX : TEXTURE_2D_INDEX;
+ break;
+ case GLSL_SAMPLER_DIM_3D:
+ inst->tex_target = TEXTURE_3D_INDEX;
+ break;
+ case GLSL_SAMPLER_DIM_CUBE:
+ inst->tex_target = TEXTURE_CUBE_INDEX;
+ break;
+ default:
+ assert(!"FINISHME: other texture targets");
+ }
+
+ this->result = result_src;
+}
+
+void
+ir_to_mesa_visitor::visit(ir_return *ir)
+{
+ assert(current_function);
+
+ if (ir->get_value()) {
+ ir_to_mesa_dst_reg l;
+ int i;
+
+ ir->get_value()->accept(this);
+ ir_to_mesa_src_reg r = this->result;
+
+ l = ir_to_mesa_dst_reg_from_src(current_function->return_reg);
+
+ for (i = 0; i < type_size(current_function->sig->return_type); i++) {
+ ir_to_mesa_emit_op1(ir, OPCODE_MOV, l, r);
+ l.index++;
+ r.index++;
+ }
+ }
+
+ ir_to_mesa_emit_op0(ir, OPCODE_RET);
+}
+
+void
+ir_to_mesa_visitor::visit(ir_discard *ir)
+{
+ assert(ir->condition == NULL); /* FINISHME */
+
+ ir_to_mesa_emit_op0(ir, OPCODE_KIL_NV);
+}
+
+void
+ir_to_mesa_visitor::visit(ir_if *ir)
+{
+ ir_to_mesa_instruction *cond_inst, *if_inst, *else_inst = NULL;
+ ir_to_mesa_instruction *prev_inst;
+
+ prev_inst = (ir_to_mesa_instruction *)this->instructions.get_tail();
+
+ ir->condition->accept(this);
+ assert(this->result.file != PROGRAM_UNDEFINED);
+
+ if (ctx->Shader.EmitCondCodes) {
+ cond_inst = (ir_to_mesa_instruction *)this->instructions.get_tail();
+
+ /* See if we actually generated any instruction for generating
+ * the condition. If not, then cook up a move to a temp so we
+ * have something to set cond_update on.
+ */
+ if (cond_inst == prev_inst) {
+ ir_to_mesa_src_reg temp = get_temp(glsl_type::bool_type);
+ cond_inst = ir_to_mesa_emit_op1(ir->condition, OPCODE_MOV,
+ ir_to_mesa_dst_reg_from_src(temp),
+ result);
+ }
+ cond_inst->cond_update = GL_TRUE;
+
+ if_inst = ir_to_mesa_emit_op0(ir->condition, OPCODE_IF);
+ if_inst->dst_reg.cond_mask = COND_NE;
+ } else {
+ if_inst = ir_to_mesa_emit_op1(ir->condition,
+ OPCODE_IF, ir_to_mesa_undef_dst,
+ this->result);
+ }
+
+ this->instructions.push_tail(if_inst);
+
+ visit_exec_list(&ir->then_instructions, this);
+
+ if (!ir->else_instructions.is_empty()) {
+ else_inst = ir_to_mesa_emit_op0(ir->condition, OPCODE_ELSE);
+ visit_exec_list(&ir->else_instructions, this);
+ }
+
+ if_inst = ir_to_mesa_emit_op1(ir->condition, OPCODE_ENDIF,
+ ir_to_mesa_undef_dst, ir_to_mesa_undef);
+}
+
+ir_to_mesa_visitor::ir_to_mesa_visitor()
+{
+ result.file = PROGRAM_UNDEFINED;
+ next_temp = 1;
+ next_signature_id = 1;
+ sampler_map = NULL;
+ current_function = NULL;
+}
+
+ir_to_mesa_visitor::~ir_to_mesa_visitor()
+{
+ if (this->sampler_map)
+ hash_table_dtor(this->sampler_map);
+}
+
+static struct prog_src_register
+mesa_src_reg_from_ir_src_reg(ir_to_mesa_src_reg reg)
+{
+ struct prog_src_register mesa_reg;
+
+ mesa_reg.File = reg.file;
+ assert(reg.index < (1 << INST_INDEX_BITS) - 1);
+ mesa_reg.Index = reg.index;
+ mesa_reg.Swizzle = reg.swizzle;
+ mesa_reg.RelAddr = reg.reladdr != NULL;
+ mesa_reg.Negate = reg.negate;
+ mesa_reg.Abs = 0;
+ mesa_reg.HasIndex2 = GL_FALSE;
+
+ return mesa_reg;
+}
+
+static void
+set_branchtargets(ir_to_mesa_visitor *v,
+ struct prog_instruction *mesa_instructions,
+ int num_instructions)
+{
+ int if_count = 0, loop_count = 0;
+ int *if_stack, *loop_stack;
+ int if_stack_pos = 0, loop_stack_pos = 0;
+ int i, j;
+
+ for (i = 0; i < num_instructions; i++) {
+ switch (mesa_instructions[i].Opcode) {
+ case OPCODE_IF:
+ if_count++;
+ break;
+ case OPCODE_BGNLOOP:
+ loop_count++;
+ break;
+ case OPCODE_BRK:
+ case OPCODE_CONT:
+ mesa_instructions[i].BranchTarget = -1;
+ break;
+ default:
+ break;
+ }
+ }
+
+ if_stack = (int *)calloc(if_count, sizeof(*if_stack));
+ loop_stack = (int *)calloc(loop_count, sizeof(*loop_stack));
+
+ for (i = 0; i < num_instructions; i++) {
+ switch (mesa_instructions[i].Opcode) {
+ case OPCODE_IF:
+ if_stack[if_stack_pos] = i;
+ if_stack_pos++;
+ break;
+ case OPCODE_ELSE:
+ mesa_instructions[if_stack[if_stack_pos - 1]].BranchTarget = i;
+ if_stack[if_stack_pos - 1] = i;
+ break;
+ case OPCODE_ENDIF:
+ mesa_instructions[if_stack[if_stack_pos - 1]].BranchTarget = i;
+ if_stack_pos--;
+ break;
+ case OPCODE_BGNLOOP:
+ loop_stack[loop_stack_pos] = i;
+ loop_stack_pos++;
+ break;
+ case OPCODE_ENDLOOP:
+ loop_stack_pos--;
+ /* Rewrite any breaks/conts at this nesting level (haven't
+ * already had a BranchTarget assigned) to point to the end
+ * of the loop.
+ */
+ for (j = loop_stack[loop_stack_pos]; j < i; j++) {
+ if (mesa_instructions[j].Opcode == OPCODE_BRK ||
+ mesa_instructions[j].Opcode == OPCODE_CONT) {
+ if (mesa_instructions[j].BranchTarget == -1) {
+ mesa_instructions[j].BranchTarget = i;
+ }
+ }
+ }
+ /* The loop ends point at each other. */
+ mesa_instructions[i].BranchTarget = loop_stack[loop_stack_pos];
+ mesa_instructions[loop_stack[loop_stack_pos]].BranchTarget = i;
+ break;
+ case OPCODE_CAL:
+ foreach_iter(exec_list_iterator, iter, v->function_signatures) {
+ function_entry *entry = (function_entry *)iter.get();
+
+ if (entry->sig_id == mesa_instructions[i].BranchTarget) {
+ mesa_instructions[i].BranchTarget = entry->inst;
+ break;
+ }
+ }
+ break;
+ default:
+ break;
+ }
+ }
+
+ free(if_stack);
+}
+
+static void
+print_program(struct prog_instruction *mesa_instructions,
+ ir_instruction **mesa_instruction_annotation,
+ int num_instructions)
+{
+ ir_instruction *last_ir = NULL;
+ int i;
+ int indent = 0;
+
+ for (i = 0; i < num_instructions; i++) {
+ struct prog_instruction *mesa_inst = mesa_instructions + i;
+ ir_instruction *ir = mesa_instruction_annotation[i];
+
+ fprintf(stdout, "%3d: ", i);
+
+ if (last_ir != ir && ir) {
+ int j;
+
+ for (j = 0; j < indent; j++) {
+ fprintf(stdout, " ");
+ }
+ ir->print();
+ printf("\n");
+ last_ir = ir;
+
+ fprintf(stdout, " "); /* line number spacing. */
+ }
+
+ indent = _mesa_fprint_instruction_opt(stdout, mesa_inst, indent,
+ PROG_PRINT_DEBUG, NULL);
+ }
+}
+
+static void
+count_resources(struct gl_program *prog)
+{
+ unsigned int i;
+
+ prog->SamplersUsed = 0;
+
+ for (i = 0; i < prog->NumInstructions; i++) {
+ struct prog_instruction *inst = &prog->Instructions[i];
+
+ /* Instead of just using the uniform's value to map to a
+ * sampler, Mesa first allocates a separate number for the
+ * sampler (_mesa_add_sampler), then we reindex it down to a
+ * small integer (sampler_map[], SamplersUsed), then that gets
+ * mapped to the uniform's value, and we get an actual sampler.
+ */
+ if (_mesa_is_tex_instruction(inst->Opcode)) {
+ prog->SamplerTargets[inst->TexSrcUnit] =
+ (gl_texture_index)inst->TexSrcTarget;
+ prog->SamplersUsed |= 1 << inst->TexSrcUnit;
+ if (inst->TexShadow) {
+ prog->ShadowSamplers |= 1 << inst->TexSrcUnit;
+ }
+ }
+ }
+
+ _mesa_update_shader_textures_used(prog);
+}
+
+/* Each stage has some uniforms in its Parameters list. The Uniforms
+ * list for the linked shader program has a pointer to these uniforms
+ * in each of the stage's Parameters list, so that their values can be
+ * updated when a uniform is set.
+ */
+static void
+link_uniforms_to_shared_uniform_list(struct gl_uniform_list *uniforms,
+ struct gl_program *prog)
+{
+ unsigned int i;
+
+ for (i = 0; i < prog->Parameters->NumParameters; i++) {
+ const struct gl_program_parameter *p = prog->Parameters->Parameters + i;
+
+ if (p->Type == PROGRAM_UNIFORM || p->Type == PROGRAM_SAMPLER) {
+ struct gl_uniform *uniform =
+ _mesa_append_uniform(uniforms, p->Name, prog->Target, i);
+ if (uniform)
+ uniform->Initialized = p->Initialized;
+ }
+ }
+}
+
+struct gl_program *
+get_mesa_program(GLcontext *ctx, struct gl_shader_program *shader_program,
+ struct gl_shader *shader)
+{
+ void *mem_ctx = shader_program;
+ ir_to_mesa_visitor v;
+ struct prog_instruction *mesa_instructions, *mesa_inst;
+ ir_instruction **mesa_instruction_annotation;
+ int i;
+ struct gl_program *prog;
+ GLenum target;
+ const char *target_string;
+ GLboolean progress;
+
+ switch (shader->Type) {
+ case GL_VERTEX_SHADER:
+ target = GL_VERTEX_PROGRAM_ARB;
+ target_string = "vertex";
+ break;
+ case GL_FRAGMENT_SHADER:
+ target = GL_FRAGMENT_PROGRAM_ARB;
+ target_string = "fragment";
+ break;
+ default:
+ assert(!"should not be reached");
+ break;
+ }
+
+ validate_ir_tree(shader->ir);
+
+ prog = ctx->Driver.NewProgram(ctx, target, shader_program->Name);
+ if (!prog)
+ return NULL;
+ prog->Parameters = _mesa_new_parameter_list();
+ prog->Varying = _mesa_new_parameter_list();
+ prog->Attributes = _mesa_new_parameter_list();
+ v.ctx = ctx;
+ v.prog = prog;
+
+ v.mem_ctx = talloc_new(NULL);
+
+ /* Emit Mesa IR for main(). */
+ visit_exec_list(shader->ir, &v);
+ v.ir_to_mesa_emit_op0(NULL, OPCODE_END);
+
+ /* Now emit bodies for any functions that were used. */
+ do {
+ progress = GL_FALSE;
+
+ foreach_iter(exec_list_iterator, iter, v.function_signatures) {
+ function_entry *entry = (function_entry *)iter.get();
+
+ if (!entry->bgn_inst) {
+ v.current_function = entry;
+
+ entry->bgn_inst = v.ir_to_mesa_emit_op0(NULL, OPCODE_BGNSUB);
+ entry->bgn_inst->function = entry;
+
+ visit_exec_list(&entry->sig->body, &v);
+
+ ir_to_mesa_instruction *last;
+ last = (ir_to_mesa_instruction *)v.instructions.get_tail();
+ if (last->op != OPCODE_RET)
+ v.ir_to_mesa_emit_op0(NULL, OPCODE_RET);
+
+ ir_to_mesa_instruction *end;
+ end = v.ir_to_mesa_emit_op0(NULL, OPCODE_ENDSUB);
+ end->function = entry;
+
+ progress = GL_TRUE;
+ }
+ }
+ } while (progress);
+
+ prog->NumTemporaries = v.next_temp;
+
+ int num_instructions = 0;
+ foreach_iter(exec_list_iterator, iter, v.instructions) {
+ num_instructions++;
+ }
+
+ mesa_instructions =
+ (struct prog_instruction *)calloc(num_instructions,
+ sizeof(*mesa_instructions));
+ mesa_instruction_annotation = talloc_array(mem_ctx, ir_instruction *,
+ num_instructions);
+
+ mesa_inst = mesa_instructions;
+ i = 0;
+ foreach_iter(exec_list_iterator, iter, v.instructions) {
+ ir_to_mesa_instruction *inst = (ir_to_mesa_instruction *)iter.get();
+
+ mesa_inst->Opcode = inst->op;
+ mesa_inst->CondUpdate = inst->cond_update;
+ mesa_inst->DstReg.File = inst->dst_reg.file;
+ mesa_inst->DstReg.Index = inst->dst_reg.index;
+ mesa_inst->DstReg.CondMask = inst->dst_reg.cond_mask;
+ mesa_inst->DstReg.WriteMask = inst->dst_reg.writemask;
+ mesa_inst->DstReg.RelAddr = inst->dst_reg.reladdr != NULL;
+ mesa_inst->SrcReg[0] = mesa_src_reg_from_ir_src_reg(inst->src_reg[0]);
+ mesa_inst->SrcReg[1] = mesa_src_reg_from_ir_src_reg(inst->src_reg[1]);
+ mesa_inst->SrcReg[2] = mesa_src_reg_from_ir_src_reg(inst->src_reg[2]);
+ mesa_inst->TexSrcUnit = inst->sampler;
+ mesa_inst->TexSrcTarget = inst->tex_target;
+ mesa_inst->TexShadow = inst->tex_shadow;
+ mesa_instruction_annotation[i] = inst->ir;
+
+ if (ctx->Shader.EmitNoIfs && mesa_inst->Opcode == OPCODE_IF) {
+ shader_program->InfoLog =
+ talloc_asprintf_append(shader_program->InfoLog,
+ "Couldn't flatten if statement\n");
+ shader_program->LinkStatus = false;
+ }
+
+ switch (mesa_inst->Opcode) {
+ case OPCODE_BGNSUB:
+ inst->function->inst = i;
+ mesa_inst->Comment = strdup(inst->function->sig->function_name());
+ break;
+ case OPCODE_ENDSUB:
+ mesa_inst->Comment = strdup(inst->function->sig->function_name());
+ break;
+ case OPCODE_CAL:
+ mesa_inst->BranchTarget = inst->function->sig_id; /* rewritten later */
+ break;
+ case OPCODE_ARL:
+ prog->NumAddressRegs = 1;
+ break;
+ default:
+ break;
+ }
+
+ mesa_inst++;
+ i++;
+ }
+
+ set_branchtargets(&v, mesa_instructions, num_instructions);
+
+ if (ctx->Shader.Flags & GLSL_DUMP) {
+ printf("\n");
+ printf("GLSL IR for linked %s program %d:\n", target_string,
+ shader_program->Name);
+ _mesa_print_ir(shader->ir, NULL);
+ printf("\n");
+ printf("\n");
+ printf("Mesa IR for linked %s program %d:\n", target_string,
+ shader_program->Name);
+ print_program(mesa_instructions, mesa_instruction_annotation,
+ num_instructions);
+ }
+
+ prog->Instructions = mesa_instructions;
+ prog->NumInstructions = num_instructions;
+
+ do_set_program_inouts(shader->ir, prog);
+ count_resources(prog);
+
+ _mesa_reference_program(ctx, &shader->Program, prog);
+
+ if ((ctx->Shader.Flags & GLSL_NO_OPT) == 0) {
+ _mesa_optimize_program(ctx, prog);
+ }
+
+ return prog;
+}
+
+extern "C" {
+GLboolean
+_mesa_ir_compile_shader(GLcontext *ctx, struct gl_shader *shader)
+{
+ assert(shader->CompileStatus);
+
+ return GL_TRUE;
+}
+
+GLboolean
+_mesa_ir_link_shader(GLcontext *ctx, struct gl_shader_program *prog)
+{
+ assert(prog->LinkStatus);
+
+ for (unsigned i = 0; i < prog->_NumLinkedShaders; i++) {
+ bool progress;
+ exec_list *ir = prog->_LinkedShaders[i]->ir;
+
+ do {
+ progress = false;
+
+ /* Lowering */
+ do_mat_op_to_vec(ir);
+ do_mod_to_fract(ir);
+ do_div_to_mul_rcp(ir);
+ do_explog_to_explog2(ir);
+
+ progress = do_common_optimization(ir, true) || progress;
+
+ if (ctx->Shader.EmitNoIfs)
+ progress = do_if_to_cond_assign(ir) || progress;
+
+ progress = do_vec_index_to_cond_assign(ir) || progress;
+ } while (progress);
+
+ validate_ir_tree(ir);
+ }
+
+ for (unsigned i = 0; i < prog->_NumLinkedShaders; i++) {
+ struct gl_program *linked_prog;
+ bool ok = true;
+
+ linked_prog = get_mesa_program(ctx, prog, prog->_LinkedShaders[i]);
+
+ link_uniforms_to_shared_uniform_list(prog->Uniforms, linked_prog);
+
+ switch (prog->_LinkedShaders[i]->Type) {
+ case GL_VERTEX_SHADER:
+ _mesa_reference_vertprog(ctx, &prog->VertexProgram,
+ (struct gl_vertex_program *)linked_prog);
+ ok = ctx->Driver.ProgramStringNotify(ctx, GL_VERTEX_PROGRAM_ARB,
+ linked_prog);
+ break;
+ case GL_FRAGMENT_SHADER:
+ _mesa_reference_fragprog(ctx, &prog->FragmentProgram,
+ (struct gl_fragment_program *)linked_prog);
+ ok = ctx->Driver.ProgramStringNotify(ctx, GL_FRAGMENT_PROGRAM_ARB,
+ linked_prog);
+ break;
+ }
+ if (!ok) {
+ return GL_FALSE;
+ }
+ }
+
+ return GL_TRUE;
+}
+
+void
+_mesa_glsl_compile_shader(GLcontext *ctx, struct gl_shader *shader)
+{
+ struct _mesa_glsl_parse_state *state =
+ new(shader) _mesa_glsl_parse_state(ctx, shader->Type, shader);
+
+ const char *source = shader->Source;
+ state->error = preprocess(state, &source, &state->info_log,
+ &ctx->Extensions);
+
+ if (!state->error) {
+ _mesa_glsl_lexer_ctor(state, source);
+ _mesa_glsl_parse(state);
+ _mesa_glsl_lexer_dtor(state);
+ }
+
+ shader->ir = new(shader) exec_list;
+ if (!state->error && !state->translation_unit.is_empty())
+ _mesa_ast_to_hir(shader->ir, state);
+
+ if (!state->error && !shader->ir->is_empty()) {
+ validate_ir_tree(shader->ir);
+
+ /* Do some optimization at compile time to reduce shader IR size
+ * and reduce later work if the same shader is linked multiple times
+ */
+ while (do_common_optimization(shader->ir, false))
+ ;
+
+ validate_ir_tree(shader->ir);
+ }
+
+ shader->symbols = state->symbols;
+
+ shader->CompileStatus = !state->error;
+ shader->InfoLog = state->info_log;
+ shader->Version = state->language_version;
+ memcpy(shader->builtins_to_link, state->builtins_to_link,
+ sizeof(shader->builtins_to_link[0]) * state->num_builtins_to_link);
+ shader->num_builtins_to_link = state->num_builtins_to_link;
+
+ if (ctx->Shader.Flags & GLSL_LOG) {
+ _mesa_write_shader_to_file(shader);
+ }
+
+ if (ctx->Shader.Flags & GLSL_DUMP) {
+ printf("GLSL source for shader %d:\n", shader->Name);
+ printf("%s\n", shader->Source);
+
+ if (shader->CompileStatus) {
+ printf("GLSL IR for shader %d:\n", shader->Name);
+ _mesa_print_ir(shader->ir, NULL);
+ printf("\n\n");
+ }
+ }
+
+ /* Retain any live IR, but trash the rest. */
+ reparent_ir(shader->ir, shader);
+
+ talloc_free(state);
+
+ if (shader->CompileStatus) {
+ if (!ctx->Driver.CompileShader(ctx, shader))
+ shader->CompileStatus = GL_FALSE;
+ }
+}
+
+void
+_mesa_glsl_link_shader(GLcontext *ctx, struct gl_shader_program *prog)
+{
+ unsigned int i;
+
+ _mesa_clear_shader_program_data(ctx, prog);
+
+ prog->LinkStatus = GL_TRUE;
+
+ for (i = 0; i < prog->NumShaders; i++) {
+ if (!prog->Shaders[i]->CompileStatus) {
+ prog->InfoLog =
+ talloc_asprintf_append(prog->InfoLog,
+ "linking with uncompiled shader");
+ prog->LinkStatus = GL_FALSE;
+ }
+ }
+
+ prog->Varying = _mesa_new_parameter_list();
+ _mesa_reference_vertprog(ctx, &prog->VertexProgram, NULL);
+ _mesa_reference_fragprog(ctx, &prog->FragmentProgram, NULL);
+
+ if (prog->LinkStatus) {
+ link_shaders(prog);
+
+ /* We don't use the linker's uniforms list, and cook up our own at
+ * generate time.
+ */
+ free(prog->Uniforms);
+ prog->Uniforms = _mesa_new_uniform_list();
+ }
+
+ if (prog->LinkStatus) {
+ if (!ctx->Driver.LinkShader(ctx, prog))
+ prog->LinkStatus = GL_FALSE;
+ }
+}
+
+} /* extern "C" */
diff --git a/src/mesa/program/ir_to_mesa.h b/src/mesa/program/ir_to_mesa.h
new file mode 100644
index 00000000000..ecaacde4bb0
--- /dev/null
+++ b/src/mesa/program/ir_to_mesa.h
@@ -0,0 +1,38 @@
+/*
+ * Copyright © 2010 Intel Corporation
+ *
+ * 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 (including the next
+ * paragraph) 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
+ * THE AUTHORS OR COPYRIGHT HOLDERS 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.
+ */
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#include "main/config.h"
+#include "main/mtypes.h"
+
+void _mesa_glsl_compile_shader(GLcontext *ctx, struct gl_shader *sh);
+void _mesa_glsl_link_shader(GLcontext *ctx, struct gl_shader_program *prog);
+GLboolean _mesa_ir_compile_shader(GLcontext *ctx, struct gl_shader *shader);
+GLboolean _mesa_ir_link_shader(GLcontext *ctx, struct gl_shader_program *prog);
+
+#ifdef __cplusplus
+}
+#endif
diff --git a/src/mesa/program/prog_execute.c b/src/mesa/program/prog_execute.c
index 1670c91b6ad..1222a0f4c8c 100644
--- a/src/mesa/program/prog_execute.c
+++ b/src/mesa/program/prog_execute.c
@@ -1842,7 +1842,11 @@ _mesa_execute_program(GLcontext * ctx,
numExec++;
if (numExec > maxExec) {
- _mesa_problem(ctx, "Infinite loop detected in fragment program");
+ static GLboolean reported = GL_FALSE;
+ if (!reported) {
+ _mesa_problem(ctx, "Infinite loop detected in fragment program");
+ reported = GL_TRUE;
+ }
return GL_TRUE;
}
diff --git a/src/mesa/program/prog_instruction.h b/src/mesa/program/prog_instruction.h
index 21ec8137500..1d850c4d5d5 100644
--- a/src/mesa/program/prog_instruction.h
+++ b/src/mesa/program/prog_instruction.h
@@ -401,7 +401,7 @@ struct prog_instruction
/**
* For BRA and CAL instructions, the location to jump to.
* For BGNLOOP, points to ENDLOOP (and vice-versa).
- * For BRK, points to BGNLOOP (which points to ENDLOOP).
+ * For BRK, points to ENDLOOP
* For IF, points to ELSE or ENDIF.
* For ELSE, points to ENDIF.
*/
diff --git a/src/mesa/program/prog_optimize.c b/src/mesa/program/prog_optimize.c
index 2941a17da3f..457ace14c6b 100644
--- a/src/mesa/program/prog_optimize.c
+++ b/src/mesa/program/prog_optimize.c
@@ -34,7 +34,12 @@
#define MAX_LOOP_NESTING 50
-
+/* MAX_PROGRAM_TEMPS is a low number (256), and we want to be able to
+ * register allocate many temporary values into that small number of
+ * temps. So allow large temporary indices coming into the register
+ * allocator.
+ */
+#define REG_ALLOCATE_MAX_PROGRAM_TEMPS ((1 << INST_INDEX_BITS) - 1)
static GLboolean dbg = GL_FALSE;
@@ -154,8 +159,8 @@ replace_regs(struct gl_program *prog, gl_register_file file, const GLint map[])
static void
_mesa_consolidate_registers(struct gl_program *prog)
{
- GLboolean tempUsed[MAX_PROGRAM_TEMPS];
- GLint tempMap[MAX_PROGRAM_TEMPS];
+ GLboolean tempUsed[REG_ALLOCATE_MAX_PROGRAM_TEMPS];
+ GLint tempMap[REG_ALLOCATE_MAX_PROGRAM_TEMPS];
GLuint tempMax = 0, i;
if (dbg) {
@@ -164,7 +169,7 @@ _mesa_consolidate_registers(struct gl_program *prog)
memset(tempUsed, 0, sizeof(tempUsed));
- for (i = 0; i < MAX_PROGRAM_TEMPS; i++) {
+ for (i = 0; i < REG_ALLOCATE_MAX_PROGRAM_TEMPS; i++) {
tempMap[i] = -1;
}
@@ -176,7 +181,7 @@ _mesa_consolidate_registers(struct gl_program *prog)
for (j = 0; j < numSrc; j++) {
if (inst->SrcReg[j].File == PROGRAM_TEMPORARY) {
const GLuint index = inst->SrcReg[j].Index;
- ASSERT(index < MAX_PROGRAM_TEMPS);
+ ASSERT(index < REG_ALLOCATE_MAX_PROGRAM_TEMPS);
tempUsed[index] = GL_TRUE;
tempMax = MAX2(tempMax, index);
break;
@@ -184,7 +189,7 @@ _mesa_consolidate_registers(struct gl_program *prog)
}
if (inst->DstReg.File == PROGRAM_TEMPORARY) {
const GLuint index = inst->DstReg.Index;
- ASSERT(index < MAX_PROGRAM_TEMPS);
+ ASSERT(index < REG_ALLOCATE_MAX_PROGRAM_TEMPS);
tempUsed[index] = GL_TRUE;
tempMax = MAX2(tempMax, index);
}
@@ -225,7 +230,7 @@ _mesa_consolidate_registers(struct gl_program *prog)
static void
_mesa_remove_dead_code(struct gl_program *prog)
{
- GLboolean tempRead[MAX_PROGRAM_TEMPS][4];
+ GLboolean tempRead[REG_ALLOCATE_MAX_PROGRAM_TEMPS][4];
GLboolean *removeInst; /* per-instruction removal flag */
GLuint i, rem = 0, comp;
@@ -250,7 +255,7 @@ _mesa_remove_dead_code(struct gl_program *prog)
if (inst->SrcReg[j].File == PROGRAM_TEMPORARY) {
const GLuint index = inst->SrcReg[j].Index;
GLuint read_mask;
- ASSERT(index < MAX_PROGRAM_TEMPS);
+ ASSERT(index < REG_ALLOCATE_MAX_PROGRAM_TEMPS);
read_mask = get_src_arg_mask(inst, j);
if (inst->SrcReg[j].RelAddr) {
@@ -286,7 +291,7 @@ _mesa_remove_dead_code(struct gl_program *prog)
/* check dst reg */
if (inst->DstReg.File == PROGRAM_TEMPORARY) {
const GLuint index = inst->DstReg.Index;
- ASSERT(index < MAX_PROGRAM_TEMPS);
+ ASSERT(index < REG_ALLOCATE_MAX_PROGRAM_TEMPS);
if (inst->DstReg.RelAddr) {
if (dbg)
@@ -642,7 +647,7 @@ struct interval
struct interval_list
{
GLuint Num;
- struct interval Intervals[MAX_PROGRAM_TEMPS];
+ struct interval Intervals[REG_ALLOCATE_MAX_PROGRAM_TEMPS];
};
@@ -728,15 +733,33 @@ sort_interval_list_by_start(struct interval_list *list)
#endif
}
+struct loop_info
+{
+ GLuint Start, End; /**< Start, end instructions of loop */
+};
/**
* Update the intermediate interval info for register 'index' and
* instruction 'ic'.
*/
static void
-update_interval(GLint intBegin[], GLint intEnd[], GLuint index, GLuint ic)
+update_interval(GLint intBegin[], GLint intEnd[],
+ struct loop_info *loopStack, GLuint loopStackDepth,
+ GLuint index, GLuint ic)
{
- ASSERT(index < MAX_PROGRAM_TEMPS);
+ int i;
+
+ /* If the register is used in a loop, extend its lifetime through the end
+ * of the outermost loop that doesn't contain its definition.
+ */
+ for (i = 0; i < loopStackDepth; i++) {
+ if (intBegin[index] < loopStack[i].Start) {
+ ic = loopStack[i].End;
+ break;
+ }
+ }
+
+ ASSERT(index < REG_ALLOCATE_MAX_PROGRAM_TEMPS);
if (intBegin[index] == -1) {
ASSERT(intEnd[index] == -1);
intBegin[index] = intEnd[index] = ic;
@@ -753,18 +776,14 @@ update_interval(GLint intBegin[], GLint intEnd[], GLuint index, GLuint ic)
GLboolean
_mesa_find_temp_intervals(const struct prog_instruction *instructions,
GLuint numInstructions,
- GLint intBegin[MAX_PROGRAM_TEMPS],
- GLint intEnd[MAX_PROGRAM_TEMPS])
+ GLint intBegin[REG_ALLOCATE_MAX_PROGRAM_TEMPS],
+ GLint intEnd[REG_ALLOCATE_MAX_PROGRAM_TEMPS])
{
- struct loop_info
- {
- GLuint Start, End; /**< Start, end instructions of loop */
- };
struct loop_info loopStack[MAX_LOOP_NESTING];
GLuint loopStackDepth = 0;
GLuint i;
- for (i = 0; i < MAX_PROGRAM_TEMPS; i++){
+ for (i = 0; i < REG_ALLOCATE_MAX_PROGRAM_TEMPS; i++){
intBegin[i] = intEnd[i] = -1;
}
@@ -790,24 +809,16 @@ _mesa_find_temp_intervals(const struct prog_instruction *instructions,
const GLuint index = inst->SrcReg[j].Index;
if (inst->SrcReg[j].RelAddr)
return GL_FALSE;
- update_interval(intBegin, intEnd, index, i);
- if (loopStackDepth > 0) {
- /* extend temp register's interval to end of loop */
- GLuint loopEnd = loopStack[loopStackDepth - 1].End;
- update_interval(intBegin, intEnd, index, loopEnd);
- }
+ update_interval(intBegin, intEnd, loopStack, loopStackDepth,
+ index, i);
}
}
if (inst->DstReg.File == PROGRAM_TEMPORARY) {
const GLuint index = inst->DstReg.Index;
if (inst->DstReg.RelAddr)
return GL_FALSE;
- update_interval(intBegin, intEnd, index, i);
- if (loopStackDepth > 0) {
- /* extend temp register's interval to end of loop */
- GLuint loopEnd = loopStack[loopStackDepth - 1].End;
- update_interval(intBegin, intEnd, index, loopEnd);
- }
+ update_interval(intBegin, intEnd, loopStack, loopStackDepth,
+ index, i);
}
}
}
@@ -827,7 +838,8 @@ static GLboolean
find_live_intervals(struct gl_program *prog,
struct interval_list *liveIntervals)
{
- GLint intBegin[MAX_PROGRAM_TEMPS], intEnd[MAX_PROGRAM_TEMPS];
+ GLint intBegin[REG_ALLOCATE_MAX_PROGRAM_TEMPS];
+ GLint intEnd[REG_ALLOCATE_MAX_PROGRAM_TEMPS];
GLuint i;
/*
@@ -847,7 +859,7 @@ find_live_intervals(struct gl_program *prog,
/* Build live intervals list from intermediate arrays */
liveIntervals->Num = 0;
- for (i = 0; i < MAX_PROGRAM_TEMPS; i++) {
+ for (i = 0; i < REG_ALLOCATE_MAX_PROGRAM_TEMPS; i++) {
if (intBegin[i] >= 0) {
struct interval inv;
inv.Reg = i;
@@ -883,10 +895,10 @@ find_live_intervals(struct gl_program *prog,
/** Scan the array of used register flags to find free entry */
static GLint
-alloc_register(GLboolean usedRegs[MAX_PROGRAM_TEMPS])
+alloc_register(GLboolean usedRegs[REG_ALLOCATE_MAX_PROGRAM_TEMPS])
{
GLuint k;
- for (k = 0; k < MAX_PROGRAM_TEMPS; k++) {
+ for (k = 0; k < REG_ALLOCATE_MAX_PROGRAM_TEMPS; k++) {
if (!usedRegs[k]) {
usedRegs[k] = GL_TRUE;
return k;
@@ -908,8 +920,8 @@ static void
_mesa_reallocate_registers(struct gl_program *prog)
{
struct interval_list liveIntervals;
- GLint registerMap[MAX_PROGRAM_TEMPS];
- GLboolean usedRegs[MAX_PROGRAM_TEMPS];
+ GLint registerMap[REG_ALLOCATE_MAX_PROGRAM_TEMPS];
+ GLboolean usedRegs[REG_ALLOCATE_MAX_PROGRAM_TEMPS];
GLuint i;
GLint maxTemp = -1;
@@ -918,7 +930,7 @@ _mesa_reallocate_registers(struct gl_program *prog)
_mesa_print_program(prog);
}
- for (i = 0; i < MAX_PROGRAM_TEMPS; i++){
+ for (i = 0; i < REG_ALLOCATE_MAX_PROGRAM_TEMPS; i++){
registerMap[i] = -1;
usedRegs[i] = GL_FALSE;
}
diff --git a/src/mesa/program/prog_parameter.c b/src/mesa/program/prog_parameter.c
index aac488c79ab..fa5deaf127d 100644
--- a/src/mesa/program/prog_parameter.c
+++ b/src/mesa/program/prog_parameter.c
@@ -344,18 +344,19 @@ _mesa_use_uniform(struct gl_program_parameter_list *paramList,
*/
GLint
_mesa_add_sampler(struct gl_program_parameter_list *paramList,
- const char *name, GLenum datatype)
+ const char *name, GLenum datatype, int array_length)
{
GLint i = _mesa_lookup_parameter_index(paramList, -1, name);
if (i >= 0 && paramList->Parameters[i].Type == PROGRAM_SAMPLER) {
- ASSERT(paramList->Parameters[i].Size == 1);
+ ASSERT(paramList->Parameters[i].Size == 4 * array_length);
ASSERT(paramList->Parameters[i].DataType == datatype);
/* already in list */
return (GLint) paramList->ParameterValues[i][0];
}
else {
GLuint i;
- const GLint size = 1; /* a sampler is basically a texture unit number */
+ /* One integer texture unit number goes in each parameter location. */
+ const GLint size = 4 * array_length;
GLfloat value[4];
GLint numSamplers = 0;
for (i = 0; i < paramList->NumParameters; i++) {
@@ -591,7 +592,7 @@ _mesa_lookup_parameter_constant(const struct gl_program_parameter_list *list,
if (vSize == 1) {
/* look for v[0] anywhere within float[4] value */
GLuint j;
- for (j = 0; j < 4; j++) {
+ for (j = 0; j < list->Parameters[i].Size; j++) {
if (list->ParameterValues[i][j] == v[0]) {
/* found it */
*posOut = i;
diff --git a/src/mesa/program/prog_parameter.h b/src/mesa/program/prog_parameter.h
index cc3378ae201..1860f312879 100644
--- a/src/mesa/program/prog_parameter.h
+++ b/src/mesa/program/prog_parameter.h
@@ -142,7 +142,7 @@ _mesa_use_uniform(struct gl_program_parameter_list *paramList,
extern GLint
_mesa_add_sampler(struct gl_program_parameter_list *paramList,
- const char *name, GLenum datatype);
+ const char *name, GLenum datatype, int array_length);
extern GLint
_mesa_add_varying(struct gl_program_parameter_list *paramList,
diff --git a/src/mesa/program/prog_print.c b/src/mesa/program/prog_print.c
index 6056c459e4c..00aa6de963b 100644
--- a/src/mesa/program/prog_print.c
+++ b/src/mesa/program/prog_print.c
@@ -540,12 +540,12 @@ fprint_comment(FILE *f, const struct prog_instruction *inst)
}
-static void
-fprint_alu_instruction(FILE *f,
- const struct prog_instruction *inst,
- const char *opcode_string, GLuint numRegs,
- gl_prog_print_mode mode,
- const struct gl_program *prog)
+void
+_mesa_fprint_alu_instruction(FILE *f,
+ const struct prog_instruction *inst,
+ const char *opcode_string, GLuint numRegs,
+ gl_prog_print_mode mode,
+ const struct gl_program *prog)
{
GLuint j;
@@ -582,8 +582,8 @@ void
_mesa_print_alu_instruction(const struct prog_instruction *inst,
const char *opcode_string, GLuint numRegs)
{
- fprint_alu_instruction(stderr, inst, opcode_string,
- numRegs, PROG_PRINT_DEBUG, NULL);
+ _mesa_fprint_alu_instruction(stderr, inst, opcode_string,
+ numRegs, PROG_PRINT_DEBUG, NULL);
}
@@ -791,16 +791,16 @@ _mesa_fprint_instruction_opt(FILE *f,
default:
if (inst->Opcode < MAX_OPCODE) {
/* typical alu instruction */
- fprint_alu_instruction(f, inst,
- _mesa_opcode_string(inst->Opcode),
- _mesa_num_inst_src_regs(inst->Opcode),
- mode, prog);
+ _mesa_fprint_alu_instruction(f, inst,
+ _mesa_opcode_string(inst->Opcode),
+ _mesa_num_inst_src_regs(inst->Opcode),
+ mode, prog);
}
else {
- fprint_alu_instruction(f, inst,
- _mesa_opcode_string(inst->Opcode),
- 3/*_mesa_num_inst_src_regs(inst->Opcode)*/,
- mode, prog);
+ _mesa_fprint_alu_instruction(f, inst,
+ _mesa_opcode_string(inst->Opcode),
+ 3/*_mesa_num_inst_src_regs(inst->Opcode)*/,
+ mode, prog);
}
break;
}
@@ -1033,11 +1033,11 @@ _mesa_write_shader_to_file(const struct gl_shader *shader)
fprintf(f, "/* Compile status: %s */\n",
shader->CompileStatus ? "ok" : "fail");
- if (!shader->CompileStatus) {
- fprintf(f, "/* Log Info: */\n");
+ fprintf(f, "/* Log Info: */\n");
+ if (shader->InfoLog) {
fputs(shader->InfoLog, f);
}
- else {
+ if (shader->CompileStatus && shader->Program) {
fprintf(f, "/* GPU code */\n");
fprintf(f, "/*\n");
_mesa_fprint_program_opt(f, shader->Program, PROG_PRINT_DEBUG, GL_TRUE);
diff --git a/src/mesa/program/prog_print.h b/src/mesa/program/prog_print.h
index 9ab74560169..4ffd5ab96c6 100644
--- a/src/mesa/program/prog_print.h
+++ b/src/mesa/program/prog_print.h
@@ -56,6 +56,13 @@ extern void
_mesa_print_swizzle(GLuint swizzle);
extern void
+_mesa_fprint_alu_instruction(FILE *f,
+ const struct prog_instruction *inst,
+ const char *opcode_string, GLuint numRegs,
+ gl_prog_print_mode mode,
+ const struct gl_program *prog);
+
+extern void
_mesa_print_alu_instruction(const struct prog_instruction *inst,
const char *opcode_string, GLuint numRegs);
diff --git a/src/mesa/program/symbol_table.c b/src/mesa/program/symbol_table.c
index 6a5d6868974..09e7cb44ef3 100644
--- a/src/mesa/program/symbol_table.c
+++ b/src/mesa/program/symbol_table.c
@@ -58,7 +58,9 @@ struct symbol {
*/
int name_space;
-
+ /** Scope depth where this symbol was defined. */
+ unsigned depth;
+
/**
* Arbitrary user supplied data.
*/
@@ -73,7 +75,7 @@ struct symbol_header {
struct symbol_header *next;
/** Symbol name. */
- const char *name;
+ char *name;
/** Linked list of symbols with the same name. */
struct symbol *symbols;
@@ -104,6 +106,9 @@ struct _mesa_symbol_table {
/** List of all symbol headers in the table. */
struct symbol_header *hdr;
+
+ /** Current scope depth. */
+ unsigned depth;
};
@@ -157,6 +162,7 @@ _mesa_symbol_table_pop_scope(struct _mesa_symbol_table *table)
struct symbol *sym = scope->symbols;
table->current_scope = scope->next;
+ table->depth--;
free(scope);
@@ -184,6 +190,7 @@ _mesa_symbol_table_push_scope(struct _mesa_symbol_table *table)
scope->next = table->current_scope;
table->current_scope = scope;
+ table->depth++;
}
@@ -261,6 +268,36 @@ _mesa_symbol_table_iterator_next(struct _mesa_symbol_table_iterator *iter)
}
+/**
+ * Determine the scope "distance" of a symbol from the current scope
+ *
+ * \return
+ * A non-negative number for the number of scopes between the current scope
+ * and the scope where a symbol was defined. A value of zero means the current
+ * scope. A negative number if the symbol does not exist.
+ */
+int
+_mesa_symbol_table_symbol_scope(struct _mesa_symbol_table *table,
+ int name_space, const char *name)
+{
+ struct symbol_header *const hdr = find_symbol(table, name);
+ struct symbol *sym;
+
+ if (hdr != NULL) {
+ for (sym = hdr->symbols; sym != NULL; sym = sym->next_with_same_name) {
+ assert(sym->hdr == hdr);
+
+ if ((name_space == -1) || (sym->name_space == name_space)) {
+ assert(sym->depth <= table->depth);
+ return sym->depth - table->depth;
+ }
+ }
+ }
+
+ return -1;
+}
+
+
void *
_mesa_symbol_table_find_symbol(struct _mesa_symbol_table *table,
int name_space, const char *name)
@@ -300,21 +337,34 @@ _mesa_symbol_table_add_symbol(struct _mesa_symbol_table *table,
if (hdr == NULL) {
hdr = calloc(1, sizeof(*hdr));
- hdr->name = name;
+ hdr->name = strdup(name);
- hash_table_insert(table->ht, hdr, name);
+ hash_table_insert(table->ht, hdr, hdr->name);
hdr->next = table->hdr;
table->hdr = hdr;
}
check_symbol_table(table);
+ /* If the symbol already exists in this namespace at this scope, it cannot
+ * be added to the table.
+ */
+ for (sym = hdr->symbols
+ ; (sym != NULL) && (sym->name_space != name_space)
+ ; sym = sym->next_with_same_name) {
+ /* empty */
+ }
+
+ if (sym && (sym->depth == table->depth))
+ return -1;
+
sym = calloc(1, sizeof(*sym));
sym->next_with_same_name = hdr->symbols;
sym->next_with_same_scope = table->current_scope->symbols;
sym->hdr = hdr;
sym->name_space = name_space;
sym->data = declaration;
+ sym->depth = table->depth;
assert(sym->hdr == hdr);
@@ -354,6 +404,7 @@ _mesa_symbol_table_dtor(struct _mesa_symbol_table *table)
for (hdr = table->hdr; hdr != NULL; hdr = next) {
next = hdr->next;
+ free(hdr->name);
free(hdr);
}
diff --git a/src/mesa/program/symbol_table.h b/src/mesa/program/symbol_table.h
index 0c054ef1396..1d570fc1a09 100644
--- a/src/mesa/program/symbol_table.h
+++ b/src/mesa/program/symbol_table.h
@@ -33,6 +33,9 @@ extern void _mesa_symbol_table_pop_scope(struct _mesa_symbol_table *table);
extern int _mesa_symbol_table_add_symbol(struct _mesa_symbol_table *symtab,
int name_space, const char *name, void *declaration);
+extern int _mesa_symbol_table_symbol_scope(struct _mesa_symbol_table *table,
+ int name_space, const char *name);
+
extern void *_mesa_symbol_table_find_symbol(
struct _mesa_symbol_table *symtab, int name_space, const char *name);
diff --git a/src/mesa/sources.mak b/src/mesa/sources.mak
index f01b60c4fc8..373f1b50d05 100644
--- a/src/mesa/sources.mak
+++ b/src/mesa/sources.mak
@@ -250,6 +250,9 @@ PROGRAM_SOURCES = \
program/programopt.c \
program/symbol_table.c
+SHADER_CXX_SOURCES = \
+ program/ir_to_mesa.cpp
+
SLANG_SOURCES = \
slang/slang_builtin.c \
slang/slang_codegen.c \
@@ -324,8 +327,10 @@ MESA_SOURCES = \
$(SWRAST_SOURCES) \
$(SWRAST_SETUP_SOURCES) \
$(COMMON_DRIVER_SOURCES)\
- $(ASM_C_SOURCES) \
- $(SLANG_SOURCES)
+ $(ASM_C_SOURCES)
+
+MESA_CXX_SOURCES = \
+ $(SHADER_CXX_SOURCES)
# Sources for building Gallium drivers
MESA_GALLIUM_SOURCES = \
@@ -335,12 +340,15 @@ MESA_GALLIUM_SOURCES = \
$(STATETRACKER_SOURCES) \
$(PROGRAM_SOURCES) \
ppc/common_ppc.c \
- x86/common_x86.c \
- $(SLANG_SOURCES)
+ x86/common_x86.c
+
+MESA_GALLIUM_CXX_SOURCES = \
+ $(SHADER_CXX_SOURCES)
# All the core C sources, for dependency checking
ALL_SOURCES = \
$(MESA_SOURCES) \
+ $(MESA_CXX_SOURCES) \
$(MESA_ASM_SOURCES) \
$(STATETRACKER_SOURCES)
@@ -349,10 +357,12 @@ ALL_SOURCES = \
MESA_OBJECTS = \
$(MESA_SOURCES:.c=.o) \
+ $(MESA_CXX_SOURCES:.cpp=.o) \
$(MESA_ASM_SOURCES:.S=.o)
MESA_GALLIUM_OBJECTS = \
$(MESA_GALLIUM_SOURCES:.c=.o) \
+ $(MESA_GALLIUM_CXX_SOURCES:.cpp=.o) \
$(MESA_ASM_SOURCES:.S=.o)
@@ -362,8 +372,7 @@ COMMON_DRIVER_OBJECTS = $(COMMON_DRIVER_SOURCES:.c=.o)
### Other archives/libraries
GLSL_LIBS = \
- $(TOP)/src/glsl/pp/libglslpp.a \
- $(TOP)/src/glsl/cl/libglslcl.a
+ $(TOP)/src/glsl/libglsl.a
### Include directories
diff --git a/src/talloc/SConscript b/src/talloc/SConscript
new file mode 100644
index 00000000000..a4861a932e5
--- /dev/null
+++ b/src/talloc/SConscript
@@ -0,0 +1,20 @@
+Import('*')
+
+if env['platform'] != 'windows':
+ Return()
+
+env = env.Clone()
+
+talloc = env.SharedLibrary(
+ target = 'talloc',
+ source = ['talloc.c', 'talloc.def'],
+)
+
+env.InstallSharedLibrary(talloc)
+
+if env['platform'] != 'windows':
+ talloc = env.FindIxes(talloc, 'LIBPREFIX', 'LIBSUFFIX')
+else:
+ talloc = env.FindIxes(talloc, 'SHLIBPREFIX', 'SHLIBSUFFIX')
+
+Export('talloc')
diff --git a/src/talloc/gpl-3.0.txt b/src/talloc/gpl-3.0.txt
new file mode 100644
index 00000000000..94a9ed024d3
--- /dev/null
+++ b/src/talloc/gpl-3.0.txt
@@ -0,0 +1,674 @@
+ GNU GENERAL PUBLIC LICENSE
+ Version 3, 29 June 2007
+
+ Copyright (C) 2007 Free Software Foundation, Inc. <http://fsf.org/>
+ Everyone is permitted to copy and distribute verbatim copies
+ of this license document, but changing it is not allowed.
+
+ Preamble
+
+ The GNU General Public License is a free, copyleft license for
+software and other kinds of works.
+
+ The licenses for most software and other practical works are designed
+to take away your freedom to share and change the works. By contrast,
+the GNU General Public License is intended to guarantee your freedom to
+share and change all versions of a program--to make sure it remains free
+software for all its users. We, the Free Software Foundation, use the
+GNU General Public License for most of our software; it applies also to
+any other work released this way by its authors. You can apply it to
+your programs, too.
+
+ When we speak of free software, we are referring to freedom, not
+price. Our General Public Licenses are designed to make sure that you
+have the freedom to distribute copies of free software (and charge for
+them if you wish), that you receive source code or can get it if you
+want it, that you can change the software or use pieces of it in new
+free programs, and that you know you can do these things.
+
+ To protect your rights, we need to prevent others from denying you
+these rights or asking you to surrender the rights. Therefore, you have
+certain responsibilities if you distribute copies of the software, or if
+you modify it: responsibilities to respect the freedom of others.
+
+ For example, if you distribute copies of such a program, whether
+gratis or for a fee, you must pass on to the recipients the same
+freedoms that you received. You must make sure that they, too, receive
+or can get the source code. And you must show them these terms so they
+know their rights.
+
+ Developers that use the GNU GPL protect your rights with two steps:
+(1) assert copyright on the software, and (2) offer you this License
+giving you legal permission to copy, distribute and/or modify it.
+
+ For the developers' and authors' protection, the GPL clearly explains
+that there is no warranty for this free software. For both users' and
+authors' sake, the GPL requires that modified versions be marked as
+changed, so that their problems will not be attributed erroneously to
+authors of previous versions.
+
+ Some devices are designed to deny users access to install or run
+modified versions of the software inside them, although the manufacturer
+can do so. This is fundamentally incompatible with the aim of
+protecting users' freedom to change the software. The systematic
+pattern of such abuse occurs in the area of products for individuals to
+use, which is precisely where it is most unacceptable. Therefore, we
+have designed this version of the GPL to prohibit the practice for those
+products. If such problems arise substantially in other domains, we
+stand ready to extend this provision to those domains in future versions
+of the GPL, as needed to protect the freedom of users.
+
+ Finally, every program is threatened constantly by software patents.
+States should not allow patents to restrict development and use of
+software on general-purpose computers, but in those that do, we wish to
+avoid the special danger that patents applied to a free program could
+make it effectively proprietary. To prevent this, the GPL assures that
+patents cannot be used to render the program non-free.
+
+ The precise terms and conditions for copying, distribution and
+modification follow.
+
+ TERMS AND CONDITIONS
+
+ 0. Definitions.
+
+ "This License" refers to version 3 of the GNU General Public License.
+
+ "Copyright" also means copyright-like laws that apply to other kinds of
+works, such as semiconductor masks.
+
+ "The Program" refers to any copyrightable work licensed under this
+License. Each licensee is addressed as "you". "Licensees" and
+"recipients" may be individuals or organizations.
+
+ To "modify" a work means to copy from or adapt all or part of the work
+in a fashion requiring copyright permission, other than the making of an
+exact copy. The resulting work is called a "modified version" of the
+earlier work or a work "based on" the earlier work.
+
+ A "covered work" means either the unmodified Program or a work based
+on the Program.
+
+ To "propagate" a work means to do anything with it that, without
+permission, would make you directly or secondarily liable for
+infringement under applicable copyright law, except executing it on a
+computer or modifying a private copy. Propagation includes copying,
+distribution (with or without modification), making available to the
+public, and in some countries other activities as well.
+
+ To "convey" a work means any kind of propagation that enables other
+parties to make or receive copies. Mere interaction with a user through
+a computer network, with no transfer of a copy, is not conveying.
+
+ An interactive user interface displays "Appropriate Legal Notices"
+to the extent that it includes a convenient and prominently visible
+feature that (1) displays an appropriate copyright notice, and (2)
+tells the user that there is no warranty for the work (except to the
+extent that warranties are provided), that licensees may convey the
+work under this License, and how to view a copy of this License. If
+the interface presents a list of user commands or options, such as a
+menu, a prominent item in the list meets this criterion.
+
+ 1. Source Code.
+
+ The "source code" for a work means the preferred form of the work
+for making modifications to it. "Object code" means any non-source
+form of a work.
+
+ A "Standard Interface" means an interface that either is an official
+standard defined by a recognized standards body, or, in the case of
+interfaces specified for a particular programming language, one that
+is widely used among developers working in that language.
+
+ The "System Libraries" of an executable work include anything, other
+than the work as a whole, that (a) is included in the normal form of
+packaging a Major Component, but which is not part of that Major
+Component, and (b) serves only to enable use of the work with that
+Major Component, or to implement a Standard Interface for which an
+implementation is available to the public in source code form. A
+"Major Component", in this context, means a major essential component
+(kernel, window system, and so on) of the specific operating system
+(if any) on which the executable work runs, or a compiler used to
+produce the work, or an object code interpreter used to run it.
+
+ The "Corresponding Source" for a work in object code form means all
+the source code needed to generate, install, and (for an executable
+work) run the object code and to modify the work, including scripts to
+control those activities. However, it does not include the work's
+System Libraries, or general-purpose tools or generally available free
+programs which are used unmodified in performing those activities but
+which are not part of the work. For example, Corresponding Source
+includes interface definition files associated with source files for
+the work, and the source code for shared libraries and dynamically
+linked subprograms that the work is specifically designed to require,
+such as by intimate data communication or control flow between those
+subprograms and other parts of the work.
+
+ The Corresponding Source need not include anything that users
+can regenerate automatically from other parts of the Corresponding
+Source.
+
+ The Corresponding Source for a work in source code form is that
+same work.
+
+ 2. Basic Permissions.
+
+ All rights granted under this License are granted for the term of
+copyright on the Program, and are irrevocable provided the stated
+conditions are met. This License explicitly affirms your unlimited
+permission to run the unmodified Program. The output from running a
+covered work is covered by this License only if the output, given its
+content, constitutes a covered work. This License acknowledges your
+rights of fair use or other equivalent, as provided by copyright law.
+
+ You may make, run and propagate covered works that you do not
+convey, without conditions so long as your license otherwise remains
+in force. You may convey covered works to others for the sole purpose
+of having them make modifications exclusively for you, or provide you
+with facilities for running those works, provided that you comply with
+the terms of this License in conveying all material for which you do
+not control copyright. Those thus making or running the covered works
+for you must do so exclusively on your behalf, under your direction
+and control, on terms that prohibit them from making any copies of
+your copyrighted material outside their relationship with you.
+
+ Conveying under any other circumstances is permitted solely under
+the conditions stated below. Sublicensing is not allowed; section 10
+makes it unnecessary.
+
+ 3. Protecting Users' Legal Rights From Anti-Circumvention Law.
+
+ No covered work shall be deemed part of an effective technological
+measure under any applicable law fulfilling obligations under article
+11 of the WIPO copyright treaty adopted on 20 December 1996, or
+similar laws prohibiting or restricting circumvention of such
+measures.
+
+ When you convey a covered work, you waive any legal power to forbid
+circumvention of technological measures to the extent such circumvention
+is effected by exercising rights under this License with respect to
+the covered work, and you disclaim any intention to limit operation or
+modification of the work as a means of enforcing, against the work's
+users, your or third parties' legal rights to forbid circumvention of
+technological measures.
+
+ 4. Conveying Verbatim Copies.
+
+ You may convey verbatim copies of the Program's source code as you
+receive it, in any medium, provided that you conspicuously and
+appropriately publish on each copy an appropriate copyright notice;
+keep intact all notices stating that this License and any
+non-permissive terms added in accord with section 7 apply to the code;
+keep intact all notices of the absence of any warranty; and give all
+recipients a copy of this License along with the Program.
+
+ You may charge any price or no price for each copy that you convey,
+and you may offer support or warranty protection for a fee.
+
+ 5. Conveying Modified Source Versions.
+
+ You may convey a work based on the Program, or the modifications to
+produce it from the Program, in the form of source code under the
+terms of section 4, provided that you also meet all of these conditions:
+
+ a) The work must carry prominent notices stating that you modified
+ it, and giving a relevant date.
+
+ b) The work must carry prominent notices stating that it is
+ released under this License and any conditions added under section
+ 7. This requirement modifies the requirement in section 4 to
+ "keep intact all notices".
+
+ c) You must license the entire work, as a whole, under this
+ License to anyone who comes into possession of a copy. This
+ License will therefore apply, along with any applicable section 7
+ additional terms, to the whole of the work, and all its parts,
+ regardless of how they are packaged. This License gives no
+ permission to license the work in any other way, but it does not
+ invalidate such permission if you have separately received it.
+
+ d) If the work has interactive user interfaces, each must display
+ Appropriate Legal Notices; however, if the Program has interactive
+ interfaces that do not display Appropriate Legal Notices, your
+ work need not make them do so.
+
+ A compilation of a covered work with other separate and independent
+works, which are not by their nature extensions of the covered work,
+and which are not combined with it such as to form a larger program,
+in or on a volume of a storage or distribution medium, is called an
+"aggregate" if the compilation and its resulting copyright are not
+used to limit the access or legal rights of the compilation's users
+beyond what the individual works permit. Inclusion of a covered work
+in an aggregate does not cause this License to apply to the other
+parts of the aggregate.
+
+ 6. Conveying Non-Source Forms.
+
+ You may convey a covered work in object code form under the terms
+of sections 4 and 5, provided that you also convey the
+machine-readable Corresponding Source under the terms of this License,
+in one of these ways:
+
+ a) Convey the object code in, or embodied in, a physical product
+ (including a physical distribution medium), accompanied by the
+ Corresponding Source fixed on a durable physical medium
+ customarily used for software interchange.
+
+ b) Convey the object code in, or embodied in, a physical product
+ (including a physical distribution medium), accompanied by a
+ written offer, valid for at least three years and valid for as
+ long as you offer spare parts or customer support for that product
+ model, to give anyone who possesses the object code either (1) a
+ copy of the Corresponding Source for all the software in the
+ product that is covered by this License, on a durable physical
+ medium customarily used for software interchange, for a price no
+ more than your reasonable cost of physically performing this
+ conveying of source, or (2) access to copy the
+ Corresponding Source from a network server at no charge.
+
+ c) Convey individual copies of the object code with a copy of the
+ written offer to provide the Corresponding Source. This
+ alternative is allowed only occasionally and noncommercially, and
+ only if you received the object code with such an offer, in accord
+ with subsection 6b.
+
+ d) Convey the object code by offering access from a designated
+ place (gratis or for a charge), and offer equivalent access to the
+ Corresponding Source in the same way through the same place at no
+ further charge. You need not require recipients to copy the
+ Corresponding Source along with the object code. If the place to
+ copy the object code is a network server, the Corresponding Source
+ may be on a different server (operated by you or a third party)
+ that supports equivalent copying facilities, provided you maintain
+ clear directions next to the object code saying where to find the
+ Corresponding Source. Regardless of what server hosts the
+ Corresponding Source, you remain obligated to ensure that it is
+ available for as long as needed to satisfy these requirements.
+
+ e) Convey the object code using peer-to-peer transmission, provided
+ you inform other peers where the object code and Corresponding
+ Source of the work are being offered to the general public at no
+ charge under subsection 6d.
+
+ A separable portion of the object code, whose source code is excluded
+from the Corresponding Source as a System Library, need not be
+included in conveying the object code work.
+
+ A "User Product" is either (1) a "consumer product", which means any
+tangible personal property which is normally used for personal, family,
+or household purposes, or (2) anything designed or sold for incorporation
+into a dwelling. In determining whether a product is a consumer product,
+doubtful cases shall be resolved in favor of coverage. For a particular
+product received by a particular user, "normally used" refers to a
+typical or common use of that class of product, regardless of the status
+of the particular user or of the way in which the particular user
+actually uses, or expects or is expected to use, the product. A product
+is a consumer product regardless of whether the product has substantial
+commercial, industrial or non-consumer uses, unless such uses represent
+the only significant mode of use of the product.
+
+ "Installation Information" for a User Product means any methods,
+procedures, authorization keys, or other information required to install
+and execute modified versions of a covered work in that User Product from
+a modified version of its Corresponding Source. The information must
+suffice to ensure that the continued functioning of the modified object
+code is in no case prevented or interfered with solely because
+modification has been made.
+
+ If you convey an object code work under this section in, or with, or
+specifically for use in, a User Product, and the conveying occurs as
+part of a transaction in which the right of possession and use of the
+User Product is transferred to the recipient in perpetuity or for a
+fixed term (regardless of how the transaction is characterized), the
+Corresponding Source conveyed under this section must be accompanied
+by the Installation Information. But this requirement does not apply
+if neither you nor any third party retains the ability to install
+modified object code on the User Product (for example, the work has
+been installed in ROM).
+
+ The requirement to provide Installation Information does not include a
+requirement to continue to provide support service, warranty, or updates
+for a work that has been modified or installed by the recipient, or for
+the User Product in which it has been modified or installed. Access to a
+network may be denied when the modification itself materially and
+adversely affects the operation of the network or violates the rules and
+protocols for communication across the network.
+
+ Corresponding Source conveyed, and Installation Information provided,
+in accord with this section must be in a format that is publicly
+documented (and with an implementation available to the public in
+source code form), and must require no special password or key for
+unpacking, reading or copying.
+
+ 7. Additional Terms.
+
+ "Additional permissions" are terms that supplement the terms of this
+License by making exceptions from one or more of its conditions.
+Additional permissions that are applicable to the entire Program shall
+be treated as though they were included in this License, to the extent
+that they are valid under applicable law. If additional permissions
+apply only to part of the Program, that part may be used separately
+under those permissions, but the entire Program remains governed by
+this License without regard to the additional permissions.
+
+ When you convey a copy of a covered work, you may at your option
+remove any additional permissions from that copy, or from any part of
+it. (Additional permissions may be written to require their own
+removal in certain cases when you modify the work.) You may place
+additional permissions on material, added by you to a covered work,
+for which you have or can give appropriate copyright permission.
+
+ Notwithstanding any other provision of this License, for material you
+add to a covered work, you may (if authorized by the copyright holders of
+that material) supplement the terms of this License with terms:
+
+ a) Disclaiming warranty or limiting liability differently from the
+ terms of sections 15 and 16 of this License; or
+
+ b) Requiring preservation of specified reasonable legal notices or
+ author attributions in that material or in the Appropriate Legal
+ Notices displayed by works containing it; or
+
+ c) Prohibiting misrepresentation of the origin of that material, or
+ requiring that modified versions of such material be marked in
+ reasonable ways as different from the original version; or
+
+ d) Limiting the use for publicity purposes of names of licensors or
+ authors of the material; or
+
+ e) Declining to grant rights under trademark law for use of some
+ trade names, trademarks, or service marks; or
+
+ f) Requiring indemnification of licensors and authors of that
+ material by anyone who conveys the material (or modified versions of
+ it) with contractual assumptions of liability to the recipient, for
+ any liability that these contractual assumptions directly impose on
+ those licensors and authors.
+
+ All other non-permissive additional terms are considered "further
+restrictions" within the meaning of section 10. If the Program as you
+received it, or any part of it, contains a notice stating that it is
+governed by this License along with a term that is a further
+restriction, you may remove that term. If a license document contains
+a further restriction but permits relicensing or conveying under this
+License, you may add to a covered work material governed by the terms
+of that license document, provided that the further restriction does
+not survive such relicensing or conveying.
+
+ If you add terms to a covered work in accord with this section, you
+must place, in the relevant source files, a statement of the
+additional terms that apply to those files, or a notice indicating
+where to find the applicable terms.
+
+ Additional terms, permissive or non-permissive, may be stated in the
+form of a separately written license, or stated as exceptions;
+the above requirements apply either way.
+
+ 8. Termination.
+
+ You may not propagate or modify a covered work except as expressly
+provided under this License. Any attempt otherwise to propagate or
+modify it is void, and will automatically terminate your rights under
+this License (including any patent licenses granted under the third
+paragraph of section 11).
+
+ However, if you cease all violation of this License, then your
+license from a particular copyright holder is reinstated (a)
+provisionally, unless and until the copyright holder explicitly and
+finally terminates your license, and (b) permanently, if the copyright
+holder fails to notify you of the violation by some reasonable means
+prior to 60 days after the cessation.
+
+ Moreover, your license from a particular copyright holder is
+reinstated permanently if the copyright holder notifies you of the
+violation by some reasonable means, this is the first time you have
+received notice of violation of this License (for any work) from that
+copyright holder, and you cure the violation prior to 30 days after
+your receipt of the notice.
+
+ Termination of your rights under this section does not terminate the
+licenses of parties who have received copies or rights from you under
+this License. If your rights have been terminated and not permanently
+reinstated, you do not qualify to receive new licenses for the same
+material under section 10.
+
+ 9. Acceptance Not Required for Having Copies.
+
+ You are not required to accept this License in order to receive or
+run a copy of the Program. Ancillary propagation of a covered work
+occurring solely as a consequence of using peer-to-peer transmission
+to receive a copy likewise does not require acceptance. However,
+nothing other than this License grants you permission to propagate or
+modify any covered work. These actions infringe copyright if you do
+not accept this License. Therefore, by modifying or propagating a
+covered work, you indicate your acceptance of this License to do so.
+
+ 10. Automatic Licensing of Downstream Recipients.
+
+ Each time you convey a covered work, the recipient automatically
+receives a license from the original licensors, to run, modify and
+propagate that work, subject to this License. You are not responsible
+for enforcing compliance by third parties with this License.
+
+ An "entity transaction" is a transaction transferring control of an
+organization, or substantially all assets of one, or subdividing an
+organization, or merging organizations. If propagation of a covered
+work results from an entity transaction, each party to that
+transaction who receives a copy of the work also receives whatever
+licenses to the work the party's predecessor in interest had or could
+give under the previous paragraph, plus a right to possession of the
+Corresponding Source of the work from the predecessor in interest, if
+the predecessor has it or can get it with reasonable efforts.
+
+ You may not impose any further restrictions on the exercise of the
+rights granted or affirmed under this License. For example, you may
+not impose a license fee, royalty, or other charge for exercise of
+rights granted under this License, and you may not initiate litigation
+(including a cross-claim or counterclaim in a lawsuit) alleging that
+any patent claim is infringed by making, using, selling, offering for
+sale, or importing the Program or any portion of it.
+
+ 11. Patents.
+
+ A "contributor" is a copyright holder who authorizes use under this
+License of the Program or a work on which the Program is based. The
+work thus licensed is called the contributor's "contributor version".
+
+ A contributor's "essential patent claims" are all patent claims
+owned or controlled by the contributor, whether already acquired or
+hereafter acquired, that would be infringed by some manner, permitted
+by this License, of making, using, or selling its contributor version,
+but do not include claims that would be infringed only as a
+consequence of further modification of the contributor version. For
+purposes of this definition, "control" includes the right to grant
+patent sublicenses in a manner consistent with the requirements of
+this License.
+
+ Each contributor grants you a non-exclusive, worldwide, royalty-free
+patent license under the contributor's essential patent claims, to
+make, use, sell, offer for sale, import and otherwise run, modify and
+propagate the contents of its contributor version.
+
+ In the following three paragraphs, a "patent license" is any express
+agreement or commitment, however denominated, not to enforce a patent
+(such as an express permission to practice a patent or covenant not to
+sue for patent infringement). To "grant" such a patent license to a
+party means to make such an agreement or commitment not to enforce a
+patent against the party.
+
+ If you convey a covered work, knowingly relying on a patent license,
+and the Corresponding Source of the work is not available for anyone
+to copy, free of charge and under the terms of this License, through a
+publicly available network server or other readily accessible means,
+then you must either (1) cause the Corresponding Source to be so
+available, or (2) arrange to deprive yourself of the benefit of the
+patent license for this particular work, or (3) arrange, in a manner
+consistent with the requirements of this License, to extend the patent
+license to downstream recipients. "Knowingly relying" means you have
+actual knowledge that, but for the patent license, your conveying the
+covered work in a country, or your recipient's use of the covered work
+in a country, would infringe one or more identifiable patents in that
+country that you have reason to believe are valid.
+
+ If, pursuant to or in connection with a single transaction or
+arrangement, you convey, or propagate by procuring conveyance of, a
+covered work, and grant a patent license to some of the parties
+receiving the covered work authorizing them to use, propagate, modify
+or convey a specific copy of the covered work, then the patent license
+you grant is automatically extended to all recipients of the covered
+work and works based on it.
+
+ A patent license is "discriminatory" if it does not include within
+the scope of its coverage, prohibits the exercise of, or is
+conditioned on the non-exercise of one or more of the rights that are
+specifically granted under this License. You may not convey a covered
+work if you are a party to an arrangement with a third party that is
+in the business of distributing software, under which you make payment
+to the third party based on the extent of your activity of conveying
+the work, and under which the third party grants, to any of the
+parties who would receive the covered work from you, a discriminatory
+patent license (a) in connection with copies of the covered work
+conveyed by you (or copies made from those copies), or (b) primarily
+for and in connection with specific products or compilations that
+contain the covered work, unless you entered into that arrangement,
+or that patent license was granted, prior to 28 March 2007.
+
+ Nothing in this License shall be construed as excluding or limiting
+any implied license or other defenses to infringement that may
+otherwise be available to you under applicable patent law.
+
+ 12. No Surrender of Others' Freedom.
+
+ If conditions are imposed on you (whether by court order, agreement or
+otherwise) that contradict the conditions of this License, they do not
+excuse you from the conditions of this License. If you cannot convey a
+covered work so as to satisfy simultaneously your obligations under this
+License and any other pertinent obligations, then as a consequence you may
+not convey it at all. For example, if you agree to terms that obligate you
+to collect a royalty for further conveying from those to whom you convey
+the Program, the only way you could satisfy both those terms and this
+License would be to refrain entirely from conveying the Program.
+
+ 13. Use with the GNU Affero General Public License.
+
+ Notwithstanding any other provision of this License, you have
+permission to link or combine any covered work with a work licensed
+under version 3 of the GNU Affero General Public License into a single
+combined work, and to convey the resulting work. The terms of this
+License will continue to apply to the part which is the covered work,
+but the special requirements of the GNU Affero General Public License,
+section 13, concerning interaction through a network will apply to the
+combination as such.
+
+ 14. Revised Versions of this License.
+
+ The Free Software Foundation may publish revised and/or new versions of
+the GNU General Public License from time to time. Such new versions will
+be similar in spirit to the present version, but may differ in detail to
+address new problems or concerns.
+
+ Each version is given a distinguishing version number. If the
+Program specifies that a certain numbered version of the GNU General
+Public License "or any later version" applies to it, you have the
+option of following the terms and conditions either of that numbered
+version or of any later version published by the Free Software
+Foundation. If the Program does not specify a version number of the
+GNU General Public License, you may choose any version ever published
+by the Free Software Foundation.
+
+ If the Program specifies that a proxy can decide which future
+versions of the GNU General Public License can be used, that proxy's
+public statement of acceptance of a version permanently authorizes you
+to choose that version for the Program.
+
+ Later license versions may give you additional or different
+permissions. However, no additional obligations are imposed on any
+author or copyright holder as a result of your choosing to follow a
+later version.
+
+ 15. Disclaimer of Warranty.
+
+ THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY
+APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT
+HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY
+OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO,
+THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM
+IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF
+ALL NECESSARY SERVICING, REPAIR OR CORRECTION.
+
+ 16. Limitation of Liability.
+
+ IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
+WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS
+THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY
+GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE
+USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF
+DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD
+PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS),
+EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF
+SUCH DAMAGES.
+
+ 17. Interpretation of Sections 15 and 16.
+
+ If the disclaimer of warranty and limitation of liability provided
+above cannot be given local legal effect according to their terms,
+reviewing courts shall apply local law that most closely approximates
+an absolute waiver of all civil liability in connection with the
+Program, unless a warranty or assumption of liability accompanies a
+copy of the Program in return for a fee.
+
+ END OF TERMS AND CONDITIONS
+
+ How to Apply These Terms to Your New Programs
+
+ If you develop a new program, and you want it to be of the greatest
+possible use to the public, the best way to achieve this is to make it
+free software which everyone can redistribute and change under these terms.
+
+ To do so, attach the following notices to the program. It is safest
+to attach them to the start of each source file to most effectively
+state the exclusion of warranty; and each file should have at least
+the "copyright" line and a pointer to where the full notice is found.
+
+ <one line to give the program's name and a brief idea of what it does.>
+ Copyright (C) <year> <name of author>
+
+ This program is free software: you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program. If not, see <http://www.gnu.org/licenses/>.
+
+Also add information on how to contact you by electronic and paper mail.
+
+ If the program does terminal interaction, make it output a short
+notice like this when it starts in an interactive mode:
+
+ <program> Copyright (C) <year> <name of author>
+ This program comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
+ This is free software, and you are welcome to redistribute it
+ under certain conditions; type `show c' for details.
+
+The hypothetical commands `show w' and `show c' should show the appropriate
+parts of the General Public License. Of course, your program's commands
+might be different; for a GUI interface, you would use an "about box".
+
+ You should also get your employer (if you work as a programmer) or school,
+if any, to sign a "copyright disclaimer" for the program, if necessary.
+For more information on this, and how to apply and follow the GNU GPL, see
+<http://www.gnu.org/licenses/>.
+
+ The GNU General Public License does not permit incorporating your program
+into proprietary programs. If your program is a subroutine library, you
+may consider it more useful to permit linking proprietary applications with
+the library. If this is what you want to do, use the GNU Lesser General
+Public License instead of this License. But first, please read
+<http://www.gnu.org/philosophy/why-not-lgpl.html>.
diff --git a/src/talloc/lgpl-3.0.txt b/src/talloc/lgpl-3.0.txt
new file mode 100644
index 00000000000..65c5ca88a67
--- /dev/null
+++ b/src/talloc/lgpl-3.0.txt
@@ -0,0 +1,165 @@
+ GNU LESSER GENERAL PUBLIC LICENSE
+ Version 3, 29 June 2007
+
+ Copyright (C) 2007 Free Software Foundation, Inc. <http://fsf.org/>
+ Everyone is permitted to copy and distribute verbatim copies
+ of this license document, but changing it is not allowed.
+
+
+ This version of the GNU Lesser General Public License incorporates
+the terms and conditions of version 3 of the GNU General Public
+License, supplemented by the additional permissions listed below.
+
+ 0. Additional Definitions.
+
+ As used herein, "this License" refers to version 3 of the GNU Lesser
+General Public License, and the "GNU GPL" refers to version 3 of the GNU
+General Public License.
+
+ "The Library" refers to a covered work governed by this License,
+other than an Application or a Combined Work as defined below.
+
+ An "Application" is any work that makes use of an interface provided
+by the Library, but which is not otherwise based on the Library.
+Defining a subclass of a class defined by the Library is deemed a mode
+of using an interface provided by the Library.
+
+ A "Combined Work" is a work produced by combining or linking an
+Application with the Library. The particular version of the Library
+with which the Combined Work was made is also called the "Linked
+Version".
+
+ The "Minimal Corresponding Source" for a Combined Work means the
+Corresponding Source for the Combined Work, excluding any source code
+for portions of the Combined Work that, considered in isolation, are
+based on the Application, and not on the Linked Version.
+
+ The "Corresponding Application Code" for a Combined Work means the
+object code and/or source code for the Application, including any data
+and utility programs needed for reproducing the Combined Work from the
+Application, but excluding the System Libraries of the Combined Work.
+
+ 1. Exception to Section 3 of the GNU GPL.
+
+ You may convey a covered work under sections 3 and 4 of this License
+without being bound by section 3 of the GNU GPL.
+
+ 2. Conveying Modified Versions.
+
+ If you modify a copy of the Library, and, in your modifications, a
+facility refers to a function or data to be supplied by an Application
+that uses the facility (other than as an argument passed when the
+facility is invoked), then you may convey a copy of the modified
+version:
+
+ a) under this License, provided that you make a good faith effort to
+ ensure that, in the event an Application does not supply the
+ function or data, the facility still operates, and performs
+ whatever part of its purpose remains meaningful, or
+
+ b) under the GNU GPL, with none of the additional permissions of
+ this License applicable to that copy.
+
+ 3. Object Code Incorporating Material from Library Header Files.
+
+ The object code form of an Application may incorporate material from
+a header file that is part of the Library. You may convey such object
+code under terms of your choice, provided that, if the incorporated
+material is not limited to numerical parameters, data structure
+layouts and accessors, or small macros, inline functions and templates
+(ten or fewer lines in length), you do both of the following:
+
+ a) Give prominent notice with each copy of the object code that the
+ Library is used in it and that the Library and its use are
+ covered by this License.
+
+ b) Accompany the object code with a copy of the GNU GPL and this license
+ document.
+
+ 4. Combined Works.
+
+ You may convey a Combined Work under terms of your choice that,
+taken together, effectively do not restrict modification of the
+portions of the Library contained in the Combined Work and reverse
+engineering for debugging such modifications, if you also do each of
+the following:
+
+ a) Give prominent notice with each copy of the Combined Work that
+ the Library is used in it and that the Library and its use are
+ covered by this License.
+
+ b) Accompany the Combined Work with a copy of the GNU GPL and this license
+ document.
+
+ c) For a Combined Work that displays copyright notices during
+ execution, include the copyright notice for the Library among
+ these notices, as well as a reference directing the user to the
+ copies of the GNU GPL and this license document.
+
+ d) Do one of the following:
+
+ 0) Convey the Minimal Corresponding Source under the terms of this
+ License, and the Corresponding Application Code in a form
+ suitable for, and under terms that permit, the user to
+ recombine or relink the Application with a modified version of
+ the Linked Version to produce a modified Combined Work, in the
+ manner specified by section 6 of the GNU GPL for conveying
+ Corresponding Source.
+
+ 1) Use a suitable shared library mechanism for linking with the
+ Library. A suitable mechanism is one that (a) uses at run time
+ a copy of the Library already present on the user's computer
+ system, and (b) will operate properly with a modified version
+ of the Library that is interface-compatible with the Linked
+ Version.
+
+ e) Provide Installation Information, but only if you would otherwise
+ be required to provide such information under section 6 of the
+ GNU GPL, and only to the extent that such information is
+ necessary to install and execute a modified version of the
+ Combined Work produced by recombining or relinking the
+ Application with a modified version of the Linked Version. (If
+ you use option 4d0, the Installation Information must accompany
+ the Minimal Corresponding Source and Corresponding Application
+ Code. If you use option 4d1, you must provide the Installation
+ Information in the manner specified by section 6 of the GNU GPL
+ for conveying Corresponding Source.)
+
+ 5. Combined Libraries.
+
+ You may place library facilities that are a work based on the
+Library side by side in a single library together with other library
+facilities that are not Applications and are not covered by this
+License, and convey such a combined library under terms of your
+choice, if you do both of the following:
+
+ a) Accompany the combined library with a copy of the same work based
+ on the Library, uncombined with any other library facilities,
+ conveyed under the terms of this License.
+
+ b) Give prominent notice with the combined library that part of it
+ is a work based on the Library, and explaining where to find the
+ accompanying uncombined form of the same work.
+
+ 6. Revised Versions of the GNU Lesser General Public License.
+
+ The Free Software Foundation may publish revised and/or new versions
+of the GNU Lesser General Public License from time to time. Such new
+versions will be similar in spirit to the present version, but may
+differ in detail to address new problems or concerns.
+
+ Each version is given a distinguishing version number. If the
+Library as you received it specifies that a certain numbered version
+of the GNU Lesser General Public License "or any later version"
+applies to it, you have the option of following the terms and
+conditions either of that published version or of any later version
+published by the Free Software Foundation. If the Library as you
+received it does not specify a version number of the GNU Lesser
+General Public License, you may choose any version of the GNU Lesser
+General Public License ever published by the Free Software Foundation.
+
+ If the Library as you received it specifies that a proxy can decide
+whether future versions of the GNU Lesser General Public License shall
+apply, that proxy's public statement of acceptance of any version is
+permanent authorization for you to choose that version for the
+Library.
diff --git a/src/talloc/talloc.c b/src/talloc/talloc.c
new file mode 100644
index 00000000000..cc01346a7f0
--- /dev/null
+++ b/src/talloc/talloc.c
@@ -0,0 +1,2034 @@
+/*
+ Samba Unix SMB/CIFS implementation.
+
+ Samba trivial allocation library - new interface
+
+ NOTE: Please read talloc_guide.txt for full documentation
+
+ Copyright (C) Andrew Tridgell 2004
+ Copyright (C) Stefan Metzmacher 2006
+
+ ** NOTE! The following LGPL license applies to the talloc
+ ** library. This does NOT imply that all of Samba is released
+ ** under the LGPL
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 3 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with this library; if not, see <http://www.gnu.org/licenses/>.
+*/
+
+/*
+ inspired by http://swapped.cc/halloc/
+*/
+
+#include "talloc.h"
+#include <string.h>
+
+#define TALLOC_MIN(a,b) ((a)<(b)?(a):(b))
+
+/* Visual C++ 2008 compatibility */
+#if defined(_MSC_VER) && !defined(_cplusplus)
+typedef size_t ssize_t;
+#define inline __inline
+#endif
+
+/* Xcode/gcc4.0 compatibility */
+#if defined(__APPLE__) || defined(__MINGW32__)
+static size_t strnlen (const char* s, size_t n)
+{
+ size_t i;
+ for (i = 0; i < n; ++i)
+ {
+ if (s[i] == '\0')
+ break;
+ }
+ return i;
+}
+#endif
+
+/* Visual C++ 2008 & Xcode/gcc4.0 compatibility */
+#if !defined(_cplusplus) && (defined(WIN32) || defined(__APPLE__))
+typedef int bool;
+#define false 0
+#define true 1
+#endif
+
+
+#ifdef TALLOC_BUILD_VERSION_MAJOR
+#if (TALLOC_VERSION_MAJOR != TALLOC_BUILD_VERSION_MAJOR)
+#error "TALLOC_VERSION_MAJOR != TALLOC_BUILD_VERSION_MAJOR"
+#endif
+#endif
+
+#ifdef TALLOC_BUILD_VERSION_MINOR
+#if (TALLOC_VERSION_MINOR != TALLOC_BUILD_VERSION_MINOR)
+#error "TALLOC_VERSION_MINOR != TALLOC_BUILD_VERSION_MINOR"
+#endif
+#endif
+
+/* use this to force every realloc to change the pointer, to stress test
+ code that might not cope */
+#define ALWAYS_REALLOC 0
+
+
+#define MAX_TALLOC_SIZE 0x10000000
+#define TALLOC_MAGIC_BASE 0xe814ec70
+#define TALLOC_MAGIC ( \
+ TALLOC_MAGIC_BASE + \
+ (TALLOC_VERSION_MAJOR << 12) + \
+ (TALLOC_VERSION_MINOR << 4) \
+)
+
+#define TALLOC_FLAG_FREE 0x01
+#define TALLOC_FLAG_LOOP 0x02
+#define TALLOC_FLAG_POOL 0x04 /* This is a talloc pool */
+#define TALLOC_FLAG_POOLMEM 0x08 /* This is allocated in a pool */
+#define TALLOC_MAGIC_REFERENCE ((const char *)1)
+
+/* by default we abort when given a bad pointer (such as when talloc_free() is called
+ on a pointer that came from malloc() */
+#ifndef TALLOC_ABORT
+#define TALLOC_ABORT(reason) abort()
+#endif
+
+#ifndef discard_const_p
+#if defined(__intptr_t_defined) || defined(HAVE_INTPTR_T)
+# define discard_const_p(type, ptr) ((type *)((intptr_t)(ptr)))
+#else
+# define discard_const_p(type, ptr) ((type *)(ptr))
+#endif
+#endif
+
+/* these macros gain us a few percent of speed on gcc */
+#if (__GNUC__ >= 3)
+/* the strange !! is to ensure that __builtin_expect() takes either 0 or 1
+ as its first argument */
+#ifndef likely
+#define likely(x) __builtin_expect(!!(x), 1)
+#endif
+#ifndef unlikely
+#define unlikely(x) __builtin_expect(!!(x), 0)
+#endif
+#else
+#ifndef likely
+#define likely(x) (x)
+#endif
+#ifndef unlikely
+#define unlikely(x) (x)
+#endif
+#endif
+
+/* this null_context is only used if talloc_enable_leak_report() or
+ talloc_enable_leak_report_full() is called, otherwise it remains
+ NULL
+*/
+static void *null_context;
+static void *autofree_context;
+
+struct talloc_reference_handle {
+ struct talloc_reference_handle *next, *prev;
+ void *ptr;
+ const char *location;
+};
+
+typedef int (*talloc_destructor_t)(void *);
+
+struct talloc_chunk {
+ struct talloc_chunk *next, *prev;
+ struct talloc_chunk *parent, *child;
+ struct talloc_reference_handle *refs;
+ talloc_destructor_t destructor;
+ const char *name;
+ size_t size;
+ unsigned flags;
+
+ /*
+ * "pool" has dual use:
+ *
+ * For the talloc pool itself (i.e. TALLOC_FLAG_POOL is set), "pool"
+ * marks the end of the currently allocated area.
+ *
+ * For members of the pool (i.e. TALLOC_FLAG_POOLMEM is set), "pool"
+ * is a pointer to the struct talloc_chunk of the pool that it was
+ * allocated from. This way children can quickly find the pool to chew
+ * from.
+ */
+ void *pool;
+};
+
+/* 16 byte alignment seems to keep everyone happy */
+#define TC_HDR_SIZE ((sizeof(struct talloc_chunk)+15)&~15)
+#define TC_PTR_FROM_CHUNK(tc) ((void *)(TC_HDR_SIZE + (char*)tc))
+
+int talloc_version_major(void)
+{
+ return TALLOC_VERSION_MAJOR;
+}
+
+int talloc_version_minor(void)
+{
+ return TALLOC_VERSION_MINOR;
+}
+
+static void (*talloc_log_fn)(const char *message);
+
+void talloc_set_log_fn(void (*log_fn)(const char *message))
+{
+ talloc_log_fn = log_fn;
+}
+
+static void talloc_log(const char *fmt, ...) PRINTF_ATTRIBUTE(1,2);
+static void talloc_log(const char *fmt, ...)
+{
+ va_list ap;
+ char *message;
+
+ if (!talloc_log_fn) {
+ return;
+ }
+
+ va_start(ap, fmt);
+ message = talloc_vasprintf(NULL, fmt, ap);
+ va_end(ap);
+
+ talloc_log_fn(message);
+ talloc_free(message);
+}
+
+static void talloc_log_stderr(const char *message)
+{
+ fprintf(stderr, "%s", message);
+}
+
+void talloc_set_log_stderr(void)
+{
+ talloc_set_log_fn(talloc_log_stderr);
+}
+
+static void (*talloc_abort_fn)(const char *reason);
+
+void talloc_set_abort_fn(void (*abort_fn)(const char *reason))
+{
+ talloc_abort_fn = abort_fn;
+}
+
+static void talloc_abort(const char *reason)
+{
+ talloc_log("%s\n", reason);
+
+ if (!talloc_abort_fn) {
+ TALLOC_ABORT(reason);
+ }
+
+ talloc_abort_fn(reason);
+}
+
+static void talloc_abort_magic(unsigned magic)
+{
+ unsigned striped = magic - TALLOC_MAGIC_BASE;
+ unsigned major = (striped & 0xFFFFF000) >> 12;
+ unsigned minor = (striped & 0x00000FF0) >> 4;
+ talloc_log("Bad talloc magic[0x%08X/%u/%u] expected[0x%08X/%u/%u]\n",
+ magic, major, minor,
+ TALLOC_MAGIC, TALLOC_VERSION_MAJOR, TALLOC_VERSION_MINOR);
+ talloc_abort("Bad talloc magic value - wrong talloc version used/mixed");
+}
+
+static void talloc_abort_double_free(void)
+{
+ talloc_abort("Bad talloc magic value - double free");
+}
+
+static void talloc_abort_unknown_value(void)
+{
+ talloc_abort("Bad talloc magic value - unknown value");
+}
+
+/* panic if we get a bad magic value */
+static inline struct talloc_chunk *talloc_chunk_from_ptr(const void *ptr)
+{
+ const char *pp = (const char *)ptr;
+ struct talloc_chunk *tc = discard_const_p(struct talloc_chunk, pp - TC_HDR_SIZE);
+ if (unlikely((tc->flags & (TALLOC_FLAG_FREE | ~0xF)) != TALLOC_MAGIC)) {
+ if ((tc->flags & (~0xFFF)) == TALLOC_MAGIC_BASE) {
+ talloc_abort_magic(tc->flags & (~0xF));
+ return NULL;
+ }
+
+ if (tc->flags & TALLOC_FLAG_FREE) {
+ talloc_log("talloc: double free error - first free may be at %s\n", tc->name);
+ talloc_abort_double_free();
+ return NULL;
+ } else {
+ talloc_abort_unknown_value();
+ return NULL;
+ }
+ }
+ return tc;
+}
+
+/* hook into the front of the list */
+#define _TLIST_ADD(list, p) \
+do { \
+ if (!(list)) { \
+ (list) = (p); \
+ (p)->next = (p)->prev = NULL; \
+ } else { \
+ (list)->prev = (p); \
+ (p)->next = (list); \
+ (p)->prev = NULL; \
+ (list) = (p); \
+ }\
+} while (0)
+
+/* remove an element from a list - element doesn't have to be in list. */
+#define _TLIST_REMOVE(list, p) \
+do { \
+ if ((p) == (list)) { \
+ (list) = (p)->next; \
+ if (list) (list)->prev = NULL; \
+ } else { \
+ if ((p)->prev) (p)->prev->next = (p)->next; \
+ if ((p)->next) (p)->next->prev = (p)->prev; \
+ } \
+ if ((p) && ((p) != (list))) (p)->next = (p)->prev = NULL; \
+} while (0)
+
+
+/*
+ return the parent chunk of a pointer
+*/
+static inline struct talloc_chunk *talloc_parent_chunk(const void *ptr)
+{
+ struct talloc_chunk *tc;
+
+ if (unlikely(ptr == NULL)) {
+ return NULL;
+ }
+
+ tc = talloc_chunk_from_ptr(ptr);
+ while (tc->prev) tc=tc->prev;
+
+ return tc->parent;
+}
+
+void *talloc_parent(const void *ptr)
+{
+ struct talloc_chunk *tc = talloc_parent_chunk(ptr);
+ return tc? TC_PTR_FROM_CHUNK(tc) : NULL;
+}
+
+/*
+ find parents name
+*/
+const char *talloc_parent_name(const void *ptr)
+{
+ struct talloc_chunk *tc = talloc_parent_chunk(ptr);
+ return tc? tc->name : NULL;
+}
+
+/*
+ A pool carries an in-pool object count count in the first 16 bytes.
+ bytes. This is done to support talloc_steal() to a parent outside of the
+ pool. The count includes the pool itself, so a talloc_free() on a pool will
+ only destroy the pool if the count has dropped to zero. A talloc_free() of a
+ pool member will reduce the count, and eventually also call free(3) on the
+ pool memory.
+
+ The object count is not put into "struct talloc_chunk" because it is only
+ relevant for talloc pools and the alignment to 16 bytes would increase the
+ memory footprint of each talloc chunk by those 16 bytes.
+*/
+
+#define TALLOC_POOL_HDR_SIZE 16
+
+static unsigned int *talloc_pool_objectcount(struct talloc_chunk *tc)
+{
+ return (unsigned int *)((char *)tc + sizeof(struct talloc_chunk));
+}
+
+/*
+ Allocate from a pool
+*/
+
+static struct talloc_chunk *talloc_alloc_pool(struct talloc_chunk *parent,
+ size_t size)
+{
+ struct talloc_chunk *pool_ctx = NULL;
+ size_t space_left;
+ struct talloc_chunk *result;
+ size_t chunk_size;
+
+ if (parent == NULL) {
+ return NULL;
+ }
+
+ if (parent->flags & TALLOC_FLAG_POOL) {
+ pool_ctx = parent;
+ }
+ else if (parent->flags & TALLOC_FLAG_POOLMEM) {
+ pool_ctx = (struct talloc_chunk *)parent->pool;
+ }
+
+ if (pool_ctx == NULL) {
+ return NULL;
+ }
+
+ space_left = ((char *)pool_ctx + TC_HDR_SIZE + pool_ctx->size)
+ - ((char *)pool_ctx->pool);
+
+ /*
+ * Align size to 16 bytes
+ */
+ chunk_size = ((size + 15) & ~15);
+
+ if (space_left < chunk_size) {
+ return NULL;
+ }
+
+ result = (struct talloc_chunk *)pool_ctx->pool;
+
+#if defined(DEVELOPER) && defined(VALGRIND_MAKE_MEM_UNDEFINED)
+ VALGRIND_MAKE_MEM_UNDEFINED(result, size);
+#endif
+
+ pool_ctx->pool = (void *)((char *)result + chunk_size);
+
+ result->flags = TALLOC_MAGIC | TALLOC_FLAG_POOLMEM;
+ result->pool = pool_ctx;
+
+ *talloc_pool_objectcount(pool_ctx) += 1;
+
+ return result;
+}
+
+/*
+ Allocate a bit of memory as a child of an existing pointer
+*/
+static inline void *__talloc(const void *context, size_t size)
+{
+ struct talloc_chunk *tc = NULL;
+
+ if (unlikely(context == NULL)) {
+ context = null_context;
+ }
+
+ if (unlikely(size >= MAX_TALLOC_SIZE)) {
+ return NULL;
+ }
+
+ if (context != NULL) {
+ tc = talloc_alloc_pool(talloc_chunk_from_ptr(context),
+ TC_HDR_SIZE+size);
+ }
+
+ if (tc == NULL) {
+ tc = (struct talloc_chunk *)malloc(TC_HDR_SIZE+size);
+ if (unlikely(tc == NULL)) return NULL;
+ tc->flags = TALLOC_MAGIC;
+ tc->pool = NULL;
+ }
+
+ tc->size = size;
+ tc->destructor = NULL;
+ tc->child = NULL;
+ tc->name = NULL;
+ tc->refs = NULL;
+
+ if (likely(context)) {
+ struct talloc_chunk *parent = talloc_chunk_from_ptr(context);
+
+ if (parent->child) {
+ parent->child->parent = NULL;
+ tc->next = parent->child;
+ tc->next->prev = tc;
+ } else {
+ tc->next = NULL;
+ }
+ tc->parent = parent;
+ tc->prev = NULL;
+ parent->child = tc;
+ } else {
+ tc->next = tc->prev = tc->parent = NULL;
+ }
+
+ return TC_PTR_FROM_CHUNK(tc);
+}
+
+/*
+ * Create a talloc pool
+ */
+
+void *talloc_pool(const void *context, size_t size)
+{
+ void *result = __talloc(context, size + TALLOC_POOL_HDR_SIZE);
+ struct talloc_chunk *tc;
+
+ if (unlikely(result == NULL)) {
+ return NULL;
+ }
+
+ tc = talloc_chunk_from_ptr(result);
+
+ tc->flags |= TALLOC_FLAG_POOL;
+ tc->pool = (char *)result + TALLOC_POOL_HDR_SIZE;
+
+ *talloc_pool_objectcount(tc) = 1;
+
+#if defined(DEVELOPER) && defined(VALGRIND_MAKE_MEM_NOACCESS)
+ VALGRIND_MAKE_MEM_NOACCESS(tc->pool, size);
+#endif
+
+ return result;
+}
+
+/*
+ setup a destructor to be called on free of a pointer
+ the destructor should return 0 on success, or -1 on failure.
+ if the destructor fails then the free is failed, and the memory can
+ be continued to be used
+*/
+void _talloc_set_destructor(const void *ptr, int (*destructor)(void *))
+{
+ struct talloc_chunk *tc = talloc_chunk_from_ptr(ptr);
+ tc->destructor = destructor;
+}
+
+/*
+ increase the reference count on a piece of memory.
+*/
+int talloc_increase_ref_count(const void *ptr)
+{
+ if (unlikely(!talloc_reference(null_context, ptr))) {
+ return -1;
+ }
+ return 0;
+}
+
+/*
+ helper for talloc_reference()
+
+ this is referenced by a function pointer and should not be inline
+*/
+static int talloc_reference_destructor(struct talloc_reference_handle *handle)
+{
+ struct talloc_chunk *ptr_tc = talloc_chunk_from_ptr(handle->ptr);
+ _TLIST_REMOVE(ptr_tc->refs, handle);
+ return 0;
+}
+
+/*
+ more efficient way to add a name to a pointer - the name must point to a
+ true string constant
+*/
+static inline void _talloc_set_name_const(const void *ptr, const char *name)
+{
+ struct talloc_chunk *tc = talloc_chunk_from_ptr(ptr);
+ tc->name = name;
+}
+
+/*
+ internal talloc_named_const()
+*/
+static inline void *_talloc_named_const(const void *context, size_t size, const char *name)
+{
+ void *ptr;
+
+ ptr = __talloc(context, size);
+ if (unlikely(ptr == NULL)) {
+ return NULL;
+ }
+
+ _talloc_set_name_const(ptr, name);
+
+ return ptr;
+}
+
+/*
+ make a secondary reference to a pointer, hanging off the given context.
+ the pointer remains valid until both the original caller and this given
+ context are freed.
+
+ the major use for this is when two different structures need to reference the
+ same underlying data, and you want to be able to free the two instances separately,
+ and in either order
+*/
+void *_talloc_reference_loc(const void *context, const void *ptr, const char *location)
+{
+ struct talloc_chunk *tc;
+ struct talloc_reference_handle *handle;
+ if (unlikely(ptr == NULL)) return NULL;
+
+ tc = talloc_chunk_from_ptr(ptr);
+ handle = (struct talloc_reference_handle *)_talloc_named_const(context,
+ sizeof(struct talloc_reference_handle),
+ TALLOC_MAGIC_REFERENCE);
+ if (unlikely(handle == NULL)) return NULL;
+
+ /* note that we hang the destructor off the handle, not the
+ main context as that allows the caller to still setup their
+ own destructor on the context if they want to */
+ talloc_set_destructor(handle, talloc_reference_destructor);
+ handle->ptr = discard_const_p(void, ptr);
+ handle->location = location;
+ _TLIST_ADD(tc->refs, handle);
+ return handle->ptr;
+}
+
+static void *_talloc_steal_internal(const void *new_ctx, const void *ptr);
+
+/*
+ internal talloc_free call
+*/
+static inline int _talloc_free_internal(void *ptr, const char *location)
+{
+ struct talloc_chunk *tc;
+
+ if (unlikely(ptr == NULL)) {
+ return -1;
+ }
+
+ tc = talloc_chunk_from_ptr(ptr);
+
+ if (unlikely(tc->refs)) {
+ int is_child;
+ /* check this is a reference from a child or grantchild
+ * back to it's parent or grantparent
+ *
+ * in that case we need to remove the reference and
+ * call another instance of talloc_free() on the current
+ * pointer.
+ */
+ is_child = talloc_is_parent(tc->refs, ptr);
+ _talloc_free_internal(tc->refs, location);
+ if (is_child) {
+ return _talloc_free_internal(ptr, location);
+ }
+ return -1;
+ }
+
+ if (unlikely(tc->flags & TALLOC_FLAG_LOOP)) {
+ /* we have a free loop - stop looping */
+ return 0;
+ }
+
+ if (unlikely(tc->destructor)) {
+ talloc_destructor_t d = tc->destructor;
+ if (d == (talloc_destructor_t)-1) {
+ return -1;
+ }
+ tc->destructor = (talloc_destructor_t)-1;
+ if (d(ptr) == -1) {
+ tc->destructor = d;
+ return -1;
+ }
+ tc->destructor = NULL;
+ }
+
+ if (tc->parent) {
+ _TLIST_REMOVE(tc->parent->child, tc);
+ if (tc->parent->child) {
+ tc->parent->child->parent = tc->parent;
+ }
+ } else {
+ if (tc->prev) tc->prev->next = tc->next;
+ if (tc->next) tc->next->prev = tc->prev;
+ }
+
+ tc->flags |= TALLOC_FLAG_LOOP;
+
+ while (tc->child) {
+ /* we need to work out who will own an abandoned child
+ if it cannot be freed. In priority order, the first
+ choice is owner of any remaining reference to this
+ pointer, the second choice is our parent, and the
+ final choice is the null context. */
+ void *child = TC_PTR_FROM_CHUNK(tc->child);
+ const void *new_parent = null_context;
+ if (unlikely(tc->child->refs)) {
+ struct talloc_chunk *p = talloc_parent_chunk(tc->child->refs);
+ if (p) new_parent = TC_PTR_FROM_CHUNK(p);
+ }
+ if (unlikely(_talloc_free_internal(child, location) == -1)) {
+ if (new_parent == null_context) {
+ struct talloc_chunk *p = talloc_parent_chunk(ptr);
+ if (p) new_parent = TC_PTR_FROM_CHUNK(p);
+ }
+ _talloc_steal_internal(new_parent, child);
+ }
+ }
+
+ tc->flags |= TALLOC_FLAG_FREE;
+
+ /* we mark the freed memory with where we called the free
+ * from. This means on a double free error we can report where
+ * the first free came from
+ */
+ tc->name = location;
+
+ if (tc->flags & (TALLOC_FLAG_POOL|TALLOC_FLAG_POOLMEM)) {
+ struct talloc_chunk *pool;
+ unsigned int *pool_object_count;
+
+ pool = (tc->flags & TALLOC_FLAG_POOL)
+ ? tc : (struct talloc_chunk *)tc->pool;
+
+ pool_object_count = talloc_pool_objectcount(pool);
+
+ if (*pool_object_count == 0) {
+ talloc_abort("Pool object count zero!");
+ return 0;
+ }
+
+ *pool_object_count -= 1;
+
+ if (*pool_object_count == 0) {
+ free(pool);
+ }
+ }
+ else {
+ free(tc);
+ }
+ return 0;
+}
+
+/*
+ move a lump of memory from one talloc context to another return the
+ ptr on success, or NULL if it could not be transferred.
+ passing NULL as ptr will always return NULL with no side effects.
+*/
+static void *_talloc_steal_internal(const void *new_ctx, const void *ptr)
+{
+ struct talloc_chunk *tc, *new_tc;
+
+ if (unlikely(!ptr)) {
+ return NULL;
+ }
+
+ if (unlikely(new_ctx == NULL)) {
+ new_ctx = null_context;
+ }
+
+ tc = talloc_chunk_from_ptr(ptr);
+
+ if (unlikely(new_ctx == NULL)) {
+ if (tc->parent) {
+ _TLIST_REMOVE(tc->parent->child, tc);
+ if (tc->parent->child) {
+ tc->parent->child->parent = tc->parent;
+ }
+ } else {
+ if (tc->prev) tc->prev->next = tc->next;
+ if (tc->next) tc->next->prev = tc->prev;
+ }
+
+ tc->parent = tc->next = tc->prev = NULL;
+ return discard_const_p(void, ptr);
+ }
+
+ new_tc = talloc_chunk_from_ptr(new_ctx);
+
+ if (unlikely(tc == new_tc || tc->parent == new_tc)) {
+ return discard_const_p(void, ptr);
+ }
+
+ if (tc->parent) {
+ _TLIST_REMOVE(tc->parent->child, tc);
+ if (tc->parent->child) {
+ tc->parent->child->parent = tc->parent;
+ }
+ } else {
+ if (tc->prev) tc->prev->next = tc->next;
+ if (tc->next) tc->next->prev = tc->prev;
+ }
+
+ tc->parent = new_tc;
+ if (new_tc->child) new_tc->child->parent = NULL;
+ _TLIST_ADD(new_tc->child, tc);
+
+ return discard_const_p(void, ptr);
+}
+
+/*
+ move a lump of memory from one talloc context to another return the
+ ptr on success, or NULL if it could not be transferred.
+ passing NULL as ptr will always return NULL with no side effects.
+*/
+void *_talloc_steal_loc(const void *new_ctx, const void *ptr, const char *location)
+{
+ struct talloc_chunk *tc;
+
+ if (unlikely(ptr == NULL)) {
+ return NULL;
+ }
+
+ tc = talloc_chunk_from_ptr(ptr);
+
+ if (unlikely(tc->refs != NULL) && talloc_parent(ptr) != new_ctx) {
+ struct talloc_reference_handle *h;
+
+ talloc_log("WARNING: talloc_steal with references at %s\n",
+ location);
+
+ for (h=tc->refs; h; h=h->next) {
+ talloc_log("\treference at %s\n",
+ h->location);
+ }
+ }
+
+ return _talloc_steal_internal(new_ctx, ptr);
+}
+
+/*
+ this is like a talloc_steal(), but you must supply the old
+ parent. This resolves the ambiguity in a talloc_steal() which is
+ called on a context that has more than one parent (via references)
+
+ The old parent can be either a reference or a parent
+*/
+void *talloc_reparent(const void *old_parent, const void *new_parent, const void *ptr)
+{
+ struct talloc_chunk *tc;
+ struct talloc_reference_handle *h;
+
+ if (unlikely(ptr == NULL)) {
+ return NULL;
+ }
+
+ if (old_parent == talloc_parent(ptr)) {
+ return _talloc_steal_internal(new_parent, ptr);
+ }
+
+ tc = talloc_chunk_from_ptr(ptr);
+ for (h=tc->refs;h;h=h->next) {
+ if (talloc_parent(h) == old_parent) {
+ if (_talloc_steal_internal(new_parent, h) != h) {
+ return NULL;
+ }
+ return discard_const_p(void, ptr);
+ }
+ }
+
+ /* it wasn't a parent */
+ return NULL;
+}
+
+/*
+ remove a secondary reference to a pointer. This undo's what
+ talloc_reference() has done. The context and pointer arguments
+ must match those given to a talloc_reference()
+*/
+static inline int talloc_unreference(const void *context, const void *ptr)
+{
+ struct talloc_chunk *tc = talloc_chunk_from_ptr(ptr);
+ struct talloc_reference_handle *h;
+
+ if (unlikely(context == NULL)) {
+ context = null_context;
+ }
+
+ for (h=tc->refs;h;h=h->next) {
+ struct talloc_chunk *p = talloc_parent_chunk(h);
+ if (p == NULL) {
+ if (context == NULL) break;
+ } else if (TC_PTR_FROM_CHUNK(p) == context) {
+ break;
+ }
+ }
+ if (h == NULL) {
+ return -1;
+ }
+
+ return _talloc_free_internal(h, __location__);
+}
+
+/*
+ remove a specific parent context from a pointer. This is a more
+ controlled varient of talloc_free()
+*/
+int talloc_unlink(const void *context, void *ptr)
+{
+ struct talloc_chunk *tc_p, *new_p;
+ void *new_parent;
+
+ if (ptr == NULL) {
+ return -1;
+ }
+
+ if (context == NULL) {
+ context = null_context;
+ }
+
+ if (talloc_unreference(context, ptr) == 0) {
+ return 0;
+ }
+
+ if (context == NULL) {
+ if (talloc_parent_chunk(ptr) != NULL) {
+ return -1;
+ }
+ } else {
+ if (talloc_chunk_from_ptr(context) != talloc_parent_chunk(ptr)) {
+ return -1;
+ }
+ }
+
+ tc_p = talloc_chunk_from_ptr(ptr);
+
+ if (tc_p->refs == NULL) {
+ return _talloc_free_internal(ptr, __location__);
+ }
+
+ new_p = talloc_parent_chunk(tc_p->refs);
+ if (new_p) {
+ new_parent = TC_PTR_FROM_CHUNK(new_p);
+ } else {
+ new_parent = NULL;
+ }
+
+ if (talloc_unreference(new_parent, ptr) != 0) {
+ return -1;
+ }
+
+ _talloc_steal_internal(new_parent, ptr);
+
+ return 0;
+}
+
+/*
+ add a name to an existing pointer - va_list version
+*/
+static inline const char *talloc_set_name_v(const void *ptr, const char *fmt, va_list ap) PRINTF_ATTRIBUTE(2,0);
+
+static inline const char *talloc_set_name_v(const void *ptr, const char *fmt, va_list ap)
+{
+ struct talloc_chunk *tc = talloc_chunk_from_ptr(ptr);
+ tc->name = talloc_vasprintf(ptr, fmt, ap);
+ if (likely(tc->name)) {
+ _talloc_set_name_const(tc->name, ".name");
+ }
+ return tc->name;
+}
+
+/*
+ add a name to an existing pointer
+*/
+const char *talloc_set_name(const void *ptr, const char *fmt, ...)
+{
+ const char *name;
+ va_list ap;
+ va_start(ap, fmt);
+ name = talloc_set_name_v(ptr, fmt, ap);
+ va_end(ap);
+ return name;
+}
+
+
+/*
+ create a named talloc pointer. Any talloc pointer can be named, and
+ talloc_named() operates just like talloc() except that it allows you
+ to name the pointer.
+*/
+void *talloc_named(const void *context, size_t size, const char *fmt, ...)
+{
+ va_list ap;
+ void *ptr;
+ const char *name;
+
+ ptr = __talloc(context, size);
+ if (unlikely(ptr == NULL)) return NULL;
+
+ va_start(ap, fmt);
+ name = talloc_set_name_v(ptr, fmt, ap);
+ va_end(ap);
+
+ if (unlikely(name == NULL)) {
+ _talloc_free_internal(ptr, __location__);
+ return NULL;
+ }
+
+ return ptr;
+}
+
+/*
+ return the name of a talloc ptr, or "UNNAMED"
+*/
+const char *talloc_get_name(const void *ptr)
+{
+ struct talloc_chunk *tc = talloc_chunk_from_ptr(ptr);
+ if (unlikely(tc->name == TALLOC_MAGIC_REFERENCE)) {
+ return ".reference";
+ }
+ if (likely(tc->name)) {
+ return tc->name;
+ }
+ return "UNNAMED";
+}
+
+
+/*
+ check if a pointer has the given name. If it does, return the pointer,
+ otherwise return NULL
+*/
+void *talloc_check_name(const void *ptr, const char *name)
+{
+ const char *pname;
+ if (unlikely(ptr == NULL)) return NULL;
+ pname = talloc_get_name(ptr);
+ if (likely(pname == name || strcmp(pname, name) == 0)) {
+ return discard_const_p(void, ptr);
+ }
+ return NULL;
+}
+
+static void talloc_abort_type_missmatch(const char *location,
+ const char *name,
+ const char *expected)
+{
+ const char *reason;
+
+ reason = talloc_asprintf(NULL,
+ "%s: Type mismatch: name[%s] expected[%s]",
+ location,
+ name?name:"NULL",
+ expected);
+ if (!reason) {
+ reason = "Type mismatch";
+ }
+
+ talloc_abort(reason);
+}
+
+void *_talloc_get_type_abort(const void *ptr, const char *name, const char *location)
+{
+ const char *pname;
+
+ if (unlikely(ptr == NULL)) {
+ talloc_abort_type_missmatch(location, NULL, name);
+ return NULL;
+ }
+
+ pname = talloc_get_name(ptr);
+ if (likely(pname == name || strcmp(pname, name) == 0)) {
+ return discard_const_p(void, ptr);
+ }
+
+ talloc_abort_type_missmatch(location, pname, name);
+ return NULL;
+}
+
+/*
+ this is for compatibility with older versions of talloc
+*/
+void *talloc_init(const char *fmt, ...)
+{
+ va_list ap;
+ void *ptr;
+ const char *name;
+
+ /*
+ * samba3 expects talloc_report_depth_cb(NULL, ...)
+ * reports all talloc'ed memory, so we need to enable
+ * null_tracking
+ */
+ talloc_enable_null_tracking();
+
+ ptr = __talloc(NULL, 0);
+ if (unlikely(ptr == NULL)) return NULL;
+
+ va_start(ap, fmt);
+ name = talloc_set_name_v(ptr, fmt, ap);
+ va_end(ap);
+
+ if (unlikely(name == NULL)) {
+ _talloc_free_internal(ptr, __location__);
+ return NULL;
+ }
+
+ return ptr;
+}
+
+/*
+ this is a replacement for the Samba3 talloc_destroy_pool functionality. It
+ should probably not be used in new code. It's in here to keep the talloc
+ code consistent across Samba 3 and 4.
+*/
+void talloc_free_children(void *ptr)
+{
+ struct talloc_chunk *tc;
+
+ if (unlikely(ptr == NULL)) {
+ return;
+ }
+
+ tc = talloc_chunk_from_ptr(ptr);
+
+ while (tc->child) {
+ /* we need to work out who will own an abandoned child
+ if it cannot be freed. In priority order, the first
+ choice is owner of any remaining reference to this
+ pointer, the second choice is our parent, and the
+ final choice is the null context. */
+ void *child = TC_PTR_FROM_CHUNK(tc->child);
+ const void *new_parent = null_context;
+ if (unlikely(tc->child->refs)) {
+ struct talloc_chunk *p = talloc_parent_chunk(tc->child->refs);
+ if (p) new_parent = TC_PTR_FROM_CHUNK(p);
+ }
+ if (unlikely(talloc_free(child) == -1)) {
+ if (new_parent == null_context) {
+ struct talloc_chunk *p = talloc_parent_chunk(ptr);
+ if (p) new_parent = TC_PTR_FROM_CHUNK(p);
+ }
+ _talloc_steal_internal(new_parent, child);
+ }
+ }
+
+ if ((tc->flags & TALLOC_FLAG_POOL)
+ && (*talloc_pool_objectcount(tc) == 1)) {
+ tc->pool = ((char *)tc + TC_HDR_SIZE + TALLOC_POOL_HDR_SIZE);
+#if defined(DEVELOPER) && defined(VALGRIND_MAKE_MEM_NOACCESS)
+ VALGRIND_MAKE_MEM_NOACCESS(
+ tc->pool, tc->size - TALLOC_POOL_HDR_SIZE);
+#endif
+ }
+}
+
+/*
+ Allocate a bit of memory as a child of an existing pointer
+*/
+void *_talloc(const void *context, size_t size)
+{
+ return __talloc(context, size);
+}
+
+/*
+ externally callable talloc_set_name_const()
+*/
+void talloc_set_name_const(const void *ptr, const char *name)
+{
+ _talloc_set_name_const(ptr, name);
+}
+
+/*
+ create a named talloc pointer. Any talloc pointer can be named, and
+ talloc_named() operates just like talloc() except that it allows you
+ to name the pointer.
+*/
+void *talloc_named_const(const void *context, size_t size, const char *name)
+{
+ return _talloc_named_const(context, size, name);
+}
+
+/*
+ free a talloc pointer. This also frees all child pointers of this
+ pointer recursively
+
+ return 0 if the memory is actually freed, otherwise -1. The memory
+ will not be freed if the ref_count is > 1 or the destructor (if
+ any) returns non-zero
+*/
+int _talloc_free(void *ptr, const char *location)
+{
+ struct talloc_chunk *tc;
+
+ if (unlikely(ptr == NULL)) {
+ return -1;
+ }
+
+ tc = talloc_chunk_from_ptr(ptr);
+
+ if (unlikely(tc->refs != NULL)) {
+ struct talloc_reference_handle *h;
+
+ talloc_log("ERROR: talloc_free with references at %s\n",
+ location);
+
+ for (h=tc->refs; h; h=h->next) {
+ talloc_log("\treference at %s\n",
+ h->location);
+ }
+ return -1;
+ }
+
+ return _talloc_free_internal(ptr, location);
+}
+
+
+
+/*
+ A talloc version of realloc. The context argument is only used if
+ ptr is NULL
+*/
+void *_talloc_realloc(const void *context, void *ptr, size_t size, const char *name)
+{
+ struct talloc_chunk *tc;
+ void *new_ptr;
+ bool malloced = false;
+
+ /* size zero is equivalent to free() */
+ if (unlikely(size == 0)) {
+ talloc_unlink(context, ptr);
+ return NULL;
+ }
+
+ if (unlikely(size >= MAX_TALLOC_SIZE)) {
+ return NULL;
+ }
+
+ /* realloc(NULL) is equivalent to malloc() */
+ if (ptr == NULL) {
+ return _talloc_named_const(context, size, name);
+ }
+
+ tc = talloc_chunk_from_ptr(ptr);
+
+ /* don't allow realloc on referenced pointers */
+ if (unlikely(tc->refs)) {
+ return NULL;
+ }
+
+ /* don't let anybody try to realloc a talloc_pool */
+ if (unlikely(tc->flags & TALLOC_FLAG_POOL)) {
+ return NULL;
+ }
+
+ /* don't shrink if we have less than 1k to gain */
+ if ((size < tc->size) && ((tc->size - size) < 1024)) {
+ tc->size = size;
+ return ptr;
+ }
+
+ /* by resetting magic we catch users of the old memory */
+ tc->flags |= TALLOC_FLAG_FREE;
+
+#if ALWAYS_REALLOC
+ new_ptr = malloc(size + TC_HDR_SIZE);
+ if (new_ptr) {
+ memcpy(new_ptr, tc, tc->size + TC_HDR_SIZE);
+ free(tc);
+ }
+#else
+ if (tc->flags & TALLOC_FLAG_POOLMEM) {
+
+ new_ptr = talloc_alloc_pool(tc, size + TC_HDR_SIZE);
+ *talloc_pool_objectcount((struct talloc_chunk *)
+ (tc->pool)) -= 1;
+
+ if (new_ptr == NULL) {
+ new_ptr = malloc(TC_HDR_SIZE+size);
+ malloced = true;
+ }
+
+ if (new_ptr) {
+ memcpy(new_ptr, tc, TALLOC_MIN(tc->size,size) + TC_HDR_SIZE);
+ }
+ }
+ else {
+ new_ptr = realloc(tc, size + TC_HDR_SIZE);
+ }
+#endif
+ if (unlikely(!new_ptr)) {
+ tc->flags &= ~TALLOC_FLAG_FREE;
+ return NULL;
+ }
+
+ tc = (struct talloc_chunk *)new_ptr;
+ tc->flags &= ~TALLOC_FLAG_FREE;
+ if (malloced) {
+ tc->flags &= ~TALLOC_FLAG_POOLMEM;
+ }
+ if (tc->parent) {
+ tc->parent->child = tc;
+ }
+ if (tc->child) {
+ tc->child->parent = tc;
+ }
+
+ if (tc->prev) {
+ tc->prev->next = tc;
+ }
+ if (tc->next) {
+ tc->next->prev = tc;
+ }
+
+ tc->size = size;
+ _talloc_set_name_const(TC_PTR_FROM_CHUNK(tc), name);
+
+ return TC_PTR_FROM_CHUNK(tc);
+}
+
+/*
+ a wrapper around talloc_steal() for situations where you are moving a pointer
+ between two structures, and want the old pointer to be set to NULL
+*/
+void *_talloc_move(const void *new_ctx, const void *_pptr)
+{
+ const void **pptr = discard_const_p(const void *,_pptr);
+ void *ret = talloc_steal(new_ctx, discard_const_p(void, *pptr));
+ (*pptr) = NULL;
+ return ret;
+}
+
+/*
+ return the total size of a talloc pool (subtree)
+*/
+size_t talloc_total_size(const void *ptr)
+{
+ size_t total = 0;
+ struct talloc_chunk *c, *tc;
+
+ if (ptr == NULL) {
+ ptr = null_context;
+ }
+ if (ptr == NULL) {
+ return 0;
+ }
+
+ tc = talloc_chunk_from_ptr(ptr);
+
+ if (tc->flags & TALLOC_FLAG_LOOP) {
+ return 0;
+ }
+
+ tc->flags |= TALLOC_FLAG_LOOP;
+
+ if (likely(tc->name != TALLOC_MAGIC_REFERENCE)) {
+ total = tc->size;
+ }
+ for (c=tc->child;c;c=c->next) {
+ total += talloc_total_size(TC_PTR_FROM_CHUNK(c));
+ }
+
+ tc->flags &= ~TALLOC_FLAG_LOOP;
+
+ return total;
+}
+
+/*
+ return the total number of blocks in a talloc pool (subtree)
+*/
+size_t talloc_total_blocks(const void *ptr)
+{
+ size_t total = 0;
+ struct talloc_chunk *c, *tc;
+
+ if (ptr == NULL) {
+ ptr = null_context;
+ }
+ if (ptr == NULL) {
+ return 0;
+ }
+
+ tc = talloc_chunk_from_ptr(ptr);
+
+ if (tc->flags & TALLOC_FLAG_LOOP) {
+ return 0;
+ }
+
+ tc->flags |= TALLOC_FLAG_LOOP;
+
+ total++;
+ for (c=tc->child;c;c=c->next) {
+ total += talloc_total_blocks(TC_PTR_FROM_CHUNK(c));
+ }
+
+ tc->flags &= ~TALLOC_FLAG_LOOP;
+
+ return total;
+}
+
+/*
+ return the number of external references to a pointer
+*/
+size_t talloc_reference_count(const void *ptr)
+{
+ struct talloc_chunk *tc = talloc_chunk_from_ptr(ptr);
+ struct talloc_reference_handle *h;
+ size_t ret = 0;
+
+ for (h=tc->refs;h;h=h->next) {
+ ret++;
+ }
+ return ret;
+}
+
+/*
+ report on memory usage by all children of a pointer, giving a full tree view
+*/
+void talloc_report_depth_cb(const void *ptr, int depth, int max_depth,
+ void (*callback)(const void *ptr,
+ int depth, int max_depth,
+ int is_ref,
+ void *private_data),
+ void *private_data)
+{
+ struct talloc_chunk *c, *tc;
+
+ if (ptr == NULL) {
+ ptr = null_context;
+ }
+ if (ptr == NULL) return;
+
+ tc = talloc_chunk_from_ptr(ptr);
+
+ if (tc->flags & TALLOC_FLAG_LOOP) {
+ return;
+ }
+
+ callback(ptr, depth, max_depth, 0, private_data);
+
+ if (max_depth >= 0 && depth >= max_depth) {
+ return;
+ }
+
+ tc->flags |= TALLOC_FLAG_LOOP;
+ for (c=tc->child;c;c=c->next) {
+ if (c->name == TALLOC_MAGIC_REFERENCE) {
+ struct talloc_reference_handle *h = (struct talloc_reference_handle *)TC_PTR_FROM_CHUNK(c);
+ callback(h->ptr, depth + 1, max_depth, 1, private_data);
+ } else {
+ talloc_report_depth_cb(TC_PTR_FROM_CHUNK(c), depth + 1, max_depth, callback, private_data);
+ }
+ }
+ tc->flags &= ~TALLOC_FLAG_LOOP;
+}
+
+static void talloc_report_depth_FILE_helper(const void *ptr, int depth, int max_depth, int is_ref, void *_f)
+{
+ const char *name = talloc_get_name(ptr);
+ FILE *f = (FILE *)_f;
+
+ if (is_ref) {
+ fprintf(f, "%*sreference to: %s\n", depth*4, "", name);
+ return;
+ }
+
+ if (depth == 0) {
+ fprintf(f,"%stalloc report on '%s' (total %6lu bytes in %3lu blocks)\n",
+ (max_depth < 0 ? "full " :""), name,
+ (unsigned long)talloc_total_size(ptr),
+ (unsigned long)talloc_total_blocks(ptr));
+ return;
+ }
+
+ fprintf(f, "%*s%-30s contains %6lu bytes in %3lu blocks (ref %d) %p\n",
+ depth*4, "",
+ name,
+ (unsigned long)talloc_total_size(ptr),
+ (unsigned long)talloc_total_blocks(ptr),
+ (int)talloc_reference_count(ptr), ptr);
+
+#if 0
+ fprintf(f, "content: ");
+ if (talloc_total_size(ptr)) {
+ int tot = talloc_total_size(ptr);
+ int i;
+
+ for (i = 0; i < tot; i++) {
+ if ((((char *)ptr)[i] > 31) && (((char *)ptr)[i] < 126)) {
+ fprintf(f, "%c", ((char *)ptr)[i]);
+ } else {
+ fprintf(f, "~%02x", ((char *)ptr)[i]);
+ }
+ }
+ }
+ fprintf(f, "\n");
+#endif
+}
+
+/*
+ report on memory usage by all children of a pointer, giving a full tree view
+*/
+void talloc_report_depth_file(const void *ptr, int depth, int max_depth, FILE *f)
+{
+ if (f) {
+ talloc_report_depth_cb(ptr, depth, max_depth, talloc_report_depth_FILE_helper, f);
+ fflush(f);
+ }
+}
+
+/*
+ report on memory usage by all children of a pointer, giving a full tree view
+*/
+void talloc_report_full(const void *ptr, FILE *f)
+{
+ talloc_report_depth_file(ptr, 0, -1, f);
+}
+
+/*
+ report on memory usage by all children of a pointer
+*/
+void talloc_report(const void *ptr, FILE *f)
+{
+ talloc_report_depth_file(ptr, 0, 1, f);
+}
+
+/*
+ report on any memory hanging off the null context
+*/
+static void talloc_report_null(void)
+{
+ if (talloc_total_size(null_context) != 0) {
+ talloc_report(null_context, stderr);
+ }
+}
+
+/*
+ report on any memory hanging off the null context
+*/
+static void talloc_report_null_full(void)
+{
+ if (talloc_total_size(null_context) != 0) {
+ talloc_report_full(null_context, stderr);
+ }
+}
+
+/*
+ enable tracking of the NULL context
+*/
+void talloc_enable_null_tracking(void)
+{
+ if (null_context == NULL) {
+ null_context = _talloc_named_const(NULL, 0, "null_context");
+ if (autofree_context != NULL) {
+ talloc_reparent(NULL, null_context, autofree_context);
+ }
+ }
+}
+
+/*
+ enable tracking of the NULL context, not moving the autofree context
+ into the NULL context. This is needed for the talloc testsuite
+*/
+void talloc_enable_null_tracking_no_autofree(void)
+{
+ if (null_context == NULL) {
+ null_context = _talloc_named_const(NULL, 0, "null_context");
+ }
+}
+
+/*
+ disable tracking of the NULL context
+*/
+void talloc_disable_null_tracking(void)
+{
+ if (null_context != NULL) {
+ /* we have to move any children onto the real NULL
+ context */
+ struct talloc_chunk *tc, *tc2;
+ tc = talloc_chunk_from_ptr(null_context);
+ for (tc2 = tc->child; tc2; tc2=tc2->next) {
+ if (tc2->parent == tc) tc2->parent = NULL;
+ if (tc2->prev == tc) tc2->prev = NULL;
+ }
+ for (tc2 = tc->next; tc2; tc2=tc2->next) {
+ if (tc2->parent == tc) tc2->parent = NULL;
+ if (tc2->prev == tc) tc2->prev = NULL;
+ }
+ tc->child = NULL;
+ tc->next = NULL;
+ }
+ talloc_free(null_context);
+ null_context = NULL;
+}
+
+/*
+ enable leak reporting on exit
+*/
+void talloc_enable_leak_report(void)
+{
+ talloc_enable_null_tracking();
+ atexit(talloc_report_null);
+}
+
+/*
+ enable full leak reporting on exit
+*/
+void talloc_enable_leak_report_full(void)
+{
+ talloc_enable_null_tracking();
+ atexit(talloc_report_null_full);
+}
+
+/*
+ talloc and zero memory.
+*/
+void *_talloc_zero(const void *ctx, size_t size, const char *name)
+{
+ void *p = _talloc_named_const(ctx, size, name);
+
+ if (p) {
+ memset(p, '\0', size);
+ }
+
+ return p;
+}
+
+/*
+ memdup with a talloc.
+*/
+void *_talloc_memdup(const void *t, const void *p, size_t size, const char *name)
+{
+ void *newp = _talloc_named_const(t, size, name);
+
+ if (likely(newp)) {
+ memcpy(newp, p, size);
+ }
+
+ return newp;
+}
+
+static inline char *__talloc_strlendup(const void *t, const char *p, size_t len)
+{
+ char *ret;
+
+ ret = (char *)__talloc(t, len + 1);
+ if (unlikely(!ret)) return NULL;
+
+ memcpy(ret, p, len);
+ ret[len] = 0;
+
+ _talloc_set_name_const(ret, ret);
+ return ret;
+}
+
+/*
+ strdup with a talloc
+*/
+char *talloc_strdup(const void *t, const char *p)
+{
+ if (unlikely(!p)) return NULL;
+ return __talloc_strlendup(t, p, strlen(p));
+}
+
+/*
+ strndup with a talloc
+*/
+char *talloc_strndup(const void *t, const char *p, size_t n)
+{
+ if (unlikely(!p)) return NULL;
+ return __talloc_strlendup(t, p, strnlen(p, n));
+}
+
+static inline char *__talloc_strlendup_append(char *s, size_t slen,
+ const char *a, size_t alen)
+{
+ char *ret;
+
+ ret = talloc_realloc(NULL, s, char, slen + alen + 1);
+ if (unlikely(!ret)) return NULL;
+
+ /* append the string and the trailing \0 */
+ memcpy(&ret[slen], a, alen);
+ ret[slen+alen] = 0;
+
+ _talloc_set_name_const(ret, ret);
+ return ret;
+}
+
+/*
+ * Appends at the end of the string.
+ */
+char *talloc_strdup_append(char *s, const char *a)
+{
+ if (unlikely(!s)) {
+ return talloc_strdup(NULL, a);
+ }
+
+ if (unlikely(!a)) {
+ return s;
+ }
+
+ return __talloc_strlendup_append(s, strlen(s), a, strlen(a));
+}
+
+/*
+ * Appends at the end of the talloc'ed buffer,
+ * not the end of the string.
+ */
+char *talloc_strdup_append_buffer(char *s, const char *a)
+{
+ size_t slen;
+
+ if (unlikely(!s)) {
+ return talloc_strdup(NULL, a);
+ }
+
+ if (unlikely(!a)) {
+ return s;
+ }
+
+ slen = talloc_get_size(s);
+ if (likely(slen > 0)) {
+ slen--;
+ }
+
+ return __talloc_strlendup_append(s, slen, a, strlen(a));
+}
+
+/*
+ * Appends at the end of the string.
+ */
+char *talloc_strndup_append(char *s, const char *a, size_t n)
+{
+ if (unlikely(!s)) {
+ return talloc_strdup(NULL, a);
+ }
+
+ if (unlikely(!a)) {
+ return s;
+ }
+
+ return __talloc_strlendup_append(s, strlen(s), a, strnlen(a, n));
+}
+
+/*
+ * Appends at the end of the talloc'ed buffer,
+ * not the end of the string.
+ */
+char *talloc_strndup_append_buffer(char *s, const char *a, size_t n)
+{
+ size_t slen;
+
+ if (unlikely(!s)) {
+ return talloc_strdup(NULL, a);
+ }
+
+ if (unlikely(!a)) {
+ return s;
+ }
+
+ slen = talloc_get_size(s);
+ if (likely(slen > 0)) {
+ slen--;
+ }
+
+ return __talloc_strlendup_append(s, slen, a, strnlen(a, n));
+}
+
+#ifndef va_copy
+#ifdef HAVE___VA_COPY
+#define va_copy(dest, src) __va_copy(dest, src)
+#else
+#define va_copy(dest, src) (dest) = (src)
+#endif
+#endif
+
+char *talloc_vasprintf(const void *t, const char *fmt, va_list ap)
+{
+ int len;
+ char *ret;
+ va_list ap2;
+ char c;
+
+ /* this call looks strange, but it makes it work on older solaris boxes */
+ va_copy(ap2, ap);
+ #ifdef _MSC_VER
+ /* MSVC runtime needs to use _vcsprintf to return buffer size; vsnprintf would return -1 */
+ len = _vscprintf(fmt, ap2);
+ #else
+ len = vsnprintf(&c, 1, fmt, ap2);
+ #endif
+ va_end(ap2);
+ if (unlikely(len < 0)) {
+ return NULL;
+ }
+
+ ret = (char *)__talloc(t, len+1);
+ if (unlikely(!ret)) return NULL;
+
+ va_copy(ap2, ap);
+ vsnprintf(ret, len+1, fmt, ap2);
+ va_end(ap2);
+
+ _talloc_set_name_const(ret, ret);
+ return ret;
+}
+
+
+/*
+ Perform string formatting, and return a pointer to newly allocated
+ memory holding the result, inside a memory pool.
+ */
+char *talloc_asprintf(const void *t, const char *fmt, ...)
+{
+ va_list ap;
+ char *ret;
+
+ va_start(ap, fmt);
+ ret = talloc_vasprintf(t, fmt, ap);
+ va_end(ap);
+ return ret;
+}
+
+static inline char *__talloc_vaslenprintf_append(char *s, size_t slen,
+ const char *fmt, va_list ap)
+ PRINTF_ATTRIBUTE(3,0);
+
+static inline char *__talloc_vaslenprintf_append(char *s, size_t slen,
+ const char *fmt, va_list ap)
+{
+ ssize_t alen;
+ va_list ap2;
+ char c;
+
+ va_copy(ap2, ap);
+ #ifdef _MSC_VER
+ /* MSVC runtime needs to use _vcsprintf to return buffer size; vsnprintf would return -1 */
+ alen = _vscprintf(fmt, ap2);
+ #else
+ alen = vsnprintf(&c, 1, fmt, ap2);
+ #endif
+ va_end(ap2);
+
+ if (alen <= 0) {
+ /* Either the vsnprintf failed or the format resulted in
+ * no characters being formatted. In the former case, we
+ * ought to return NULL, in the latter we ought to return
+ * the original string. Most current callers of this
+ * function expect it to never return NULL.
+ */
+ return s;
+ }
+
+ s = talloc_realloc(NULL, s, char, slen + alen + 1);
+ if (!s) return NULL;
+
+ va_copy(ap2, ap);
+ vsnprintf(s + slen, alen + 1, fmt, ap2);
+ va_end(ap2);
+
+ _talloc_set_name_const(s, s);
+ return s;
+}
+
+/**
+ * Realloc @p s to append the formatted result of @p fmt and @p ap,
+ * and return @p s, which may have moved. Good for gradually
+ * accumulating output into a string buffer. Appends at the end
+ * of the string.
+ **/
+char *talloc_vasprintf_append(char *s, const char *fmt, va_list ap)
+{
+ if (unlikely(!s)) {
+ return talloc_vasprintf(NULL, fmt, ap);
+ }
+
+ return __talloc_vaslenprintf_append(s, strlen(s), fmt, ap);
+}
+
+/**
+ * Realloc @p s to append the formatted result of @p fmt and @p ap,
+ * and return @p s, which may have moved. Always appends at the
+ * end of the talloc'ed buffer, not the end of the string.
+ **/
+char *talloc_vasprintf_append_buffer(char *s, const char *fmt, va_list ap)
+{
+ size_t slen;
+
+ if (unlikely(!s)) {
+ return talloc_vasprintf(NULL, fmt, ap);
+ }
+
+ slen = talloc_get_size(s);
+ if (likely(slen > 0)) {
+ slen--;
+ }
+
+ return __talloc_vaslenprintf_append(s, slen, fmt, ap);
+}
+
+/*
+ Realloc @p s to append the formatted result of @p fmt and return @p
+ s, which may have moved. Good for gradually accumulating output
+ into a string buffer.
+ */
+char *talloc_asprintf_append(char *s, const char *fmt, ...)
+{
+ va_list ap;
+
+ va_start(ap, fmt);
+ s = talloc_vasprintf_append(s, fmt, ap);
+ va_end(ap);
+ return s;
+}
+
+/*
+ Realloc @p s to append the formatted result of @p fmt and return @p
+ s, which may have moved. Good for gradually accumulating output
+ into a buffer.
+ */
+char *talloc_asprintf_append_buffer(char *s, const char *fmt, ...)
+{
+ va_list ap;
+
+ va_start(ap, fmt);
+ s = talloc_vasprintf_append_buffer(s, fmt, ap);
+ va_end(ap);
+ return s;
+}
+
+/*
+ alloc an array, checking for integer overflow in the array size
+*/
+void *_talloc_array(const void *ctx, size_t el_size, unsigned count, const char *name)
+{
+ if (count >= MAX_TALLOC_SIZE/el_size) {
+ return NULL;
+ }
+ return _talloc_named_const(ctx, el_size * count, name);
+}
+
+/*
+ alloc an zero array, checking for integer overflow in the array size
+*/
+void *_talloc_zero_array(const void *ctx, size_t el_size, unsigned count, const char *name)
+{
+ if (count >= MAX_TALLOC_SIZE/el_size) {
+ return NULL;
+ }
+ return _talloc_zero(ctx, el_size * count, name);
+}
+
+/*
+ realloc an array, checking for integer overflow in the array size
+*/
+void *_talloc_realloc_array(const void *ctx, void *ptr, size_t el_size, unsigned count, const char *name)
+{
+ if (count >= MAX_TALLOC_SIZE/el_size) {
+ return NULL;
+ }
+ return _talloc_realloc(ctx, ptr, el_size * count, name);
+}
+
+/*
+ a function version of talloc_realloc(), so it can be passed as a function pointer
+ to libraries that want a realloc function (a realloc function encapsulates
+ all the basic capabilities of an allocation library, which is why this is useful)
+*/
+void *talloc_realloc_fn(const void *context, void *ptr, size_t size)
+{
+ return _talloc_realloc(context, ptr, size, NULL);
+}
+
+
+static int talloc_autofree_destructor(void *ptr)
+{
+ autofree_context = NULL;
+ return 0;
+}
+
+static void talloc_autofree(void)
+{
+ talloc_free(autofree_context);
+}
+
+/*
+ return a context which will be auto-freed on exit
+ this is useful for reducing the noise in leak reports
+*/
+void *talloc_autofree_context(void)
+{
+ if (autofree_context == NULL) {
+ autofree_context = _talloc_named_const(NULL, 0, "autofree_context");
+ talloc_set_destructor(autofree_context, talloc_autofree_destructor);
+ atexit(talloc_autofree);
+ }
+ return autofree_context;
+}
+
+size_t talloc_get_size(const void *context)
+{
+ struct talloc_chunk *tc;
+
+ if (context == NULL) {
+ context = null_context;
+ }
+ if (context == NULL) {
+ return 0;
+ }
+
+ tc = talloc_chunk_from_ptr(context);
+
+ return tc->size;
+}
+
+/*
+ find a parent of this context that has the given name, if any
+*/
+void *talloc_find_parent_byname(const void *context, const char *name)
+{
+ struct talloc_chunk *tc;
+
+ if (context == NULL) {
+ return NULL;
+ }
+
+ tc = talloc_chunk_from_ptr(context);
+ while (tc) {
+ if (tc->name && strcmp(tc->name, name) == 0) {
+ return TC_PTR_FROM_CHUNK(tc);
+ }
+ while (tc && tc->prev) tc = tc->prev;
+ if (tc) {
+ tc = tc->parent;
+ }
+ }
+ return NULL;
+}
+
+/*
+ show the parentage of a context
+*/
+void talloc_show_parents(const void *context, FILE *file)
+{
+ struct talloc_chunk *tc;
+
+ if (context == NULL) {
+ fprintf(file, "talloc no parents for NULL\n");
+ return;
+ }
+
+ tc = talloc_chunk_from_ptr(context);
+ fprintf(file, "talloc parents of '%s'\n", talloc_get_name(context));
+ while (tc) {
+ fprintf(file, "\t'%s'\n", talloc_get_name(TC_PTR_FROM_CHUNK(tc)));
+ while (tc && tc->prev) tc = tc->prev;
+ if (tc) {
+ tc = tc->parent;
+ }
+ }
+ fflush(file);
+}
+
+/*
+ return 1 if ptr is a parent of context
+*/
+int talloc_is_parent(const void *context, const void *ptr)
+{
+ struct talloc_chunk *tc;
+
+ if (context == NULL) {
+ return 0;
+ }
+
+ tc = talloc_chunk_from_ptr(context);
+ while (tc) {
+ if (TC_PTR_FROM_CHUNK(tc) == ptr) return 1;
+ while (tc && tc->prev) tc = tc->prev;
+ if (tc) {
+ tc = tc->parent;
+ }
+ }
+ return 0;
+}
diff --git a/src/talloc/talloc.def b/src/talloc/talloc.def
new file mode 100644
index 00000000000..13d7a159cef
--- /dev/null
+++ b/src/talloc/talloc.def
@@ -0,0 +1,63 @@
+EXPORTS
+ _talloc
+ _talloc_array
+ _talloc_free
+ _talloc_get_type_abort
+ _talloc_memdup
+ _talloc_move
+ _talloc_realloc
+ _talloc_realloc_array
+ _talloc_reference_loc
+ _talloc_set_destructor
+ _talloc_steal_loc
+ _talloc_zero
+ _talloc_zero_array
+ talloc_asprintf
+ talloc_asprintf_append
+ talloc_asprintf_append_buffer
+ talloc_autofree_context
+ talloc_check_name
+ talloc_disable_null_tracking
+ talloc_enable_leak_report
+ talloc_enable_leak_report_full
+ talloc_enable_null_tracking
+ talloc_enable_null_tracking_no_autofree
+ talloc_find_parent_byname
+ talloc_free_children
+ talloc_get_name
+ talloc_get_size
+ talloc_increase_ref_count
+ talloc_init
+ talloc_is_parent
+ talloc_named
+ talloc_named_const
+ talloc_parent
+ talloc_parent_name
+ talloc_pool
+ talloc_realloc_fn
+ talloc_reference_count
+ talloc_reparent
+ talloc_report
+ talloc_report_depth_cb
+ talloc_report_depth_file
+ talloc_report_full
+ talloc_set_abort_fn
+ talloc_set_log_fn
+ talloc_set_log_stderr
+ talloc_set_name
+ talloc_set_name_const
+ talloc_show_parents
+ talloc_strdup
+ talloc_strdup_append
+ talloc_strdup_append_buffer
+ talloc_strndup
+ talloc_strndup_append
+ talloc_strndup_append_buffer
+ talloc_total_blocks
+ talloc_total_size
+ talloc_unlink
+ talloc_vasprintf
+ talloc_vasprintf_append
+ talloc_vasprintf_append_buffer
+ talloc_version_major
+ talloc_version_minor
diff --git a/src/talloc/talloc.h b/src/talloc/talloc.h
new file mode 100644
index 00000000000..f549a17fba2
--- /dev/null
+++ b/src/talloc/talloc.h
@@ -0,0 +1,202 @@
+#ifndef _TALLOC_H_
+#define _TALLOC_H_
+/*
+ Unix SMB/CIFS implementation.
+ Samba temporary memory allocation functions
+
+ Copyright (C) Andrew Tridgell 2004-2005
+ Copyright (C) Stefan Metzmacher 2006
+
+ ** NOTE! The following LGPL license applies to the talloc
+ ** library. This does NOT imply that all of Samba is released
+ ** under the LGPL
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 3 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with this library; if not, see <http://www.gnu.org/licenses/>.
+*/
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <stdarg.h>
+
+#define TALLOC_VERSION_MAJOR 2
+#define TALLOC_VERSION_MINOR 0
+
+int talloc_version_major(void);
+int talloc_version_minor(void);
+
+/* this is only needed for compatibility with the old talloc */
+typedef void TALLOC_CTX;
+
+/*
+ this uses a little trick to allow __LINE__ to be stringified
+*/
+#ifndef __location__
+#define __TALLOC_STRING_LINE1__(s) #s
+#define __TALLOC_STRING_LINE2__(s) __TALLOC_STRING_LINE1__(s)
+#define __TALLOC_STRING_LINE3__ __TALLOC_STRING_LINE2__(__LINE__)
+#define __location__ __FILE__ ":" __TALLOC_STRING_LINE3__
+#endif
+
+#ifndef TALLOC_DEPRECATED
+#define TALLOC_DEPRECATED 0
+#endif
+
+#ifndef PRINTF_ATTRIBUTE
+#if (__GNUC__ >= 3)
+/** Use gcc attribute to check printf fns. a1 is the 1-based index of
+ * the parameter containing the format, and a2 the index of the first
+ * argument. Note that some gcc 2.x versions don't handle this
+ * properly **/
+#define PRINTF_ATTRIBUTE(a1, a2) __attribute__ ((format (__printf__, a1, a2)))
+#else
+#define PRINTF_ATTRIBUTE(a1, a2)
+#endif
+#endif
+
+/* try to make talloc_set_destructor() and talloc_steal() type safe,
+ if we have a recent gcc */
+#if (__GNUC__ >= 3)
+#define _TALLOC_TYPEOF(ptr) __typeof__(ptr)
+#define talloc_set_destructor(ptr, function) \
+ do { \
+ int (*_talloc_destructor_fn)(_TALLOC_TYPEOF(ptr)) = (function); \
+ _talloc_set_destructor((ptr), (int (*)(void *))_talloc_destructor_fn); \
+ } while(0)
+/* this extremely strange macro is to avoid some braindamaged warning
+ stupidity in gcc 4.1.x */
+#define talloc_steal(ctx, ptr) ({ _TALLOC_TYPEOF(ptr) __talloc_steal_ret = (_TALLOC_TYPEOF(ptr))_talloc_steal_loc((ctx),(ptr), __location__); __talloc_steal_ret; })
+#else
+#define talloc_set_destructor(ptr, function) \
+ _talloc_set_destructor((ptr), (int (*)(void *))(function))
+#define _TALLOC_TYPEOF(ptr) void *
+#define talloc_steal(ctx, ptr) (_TALLOC_TYPEOF(ptr))_talloc_steal_loc((ctx),(ptr), __location__)
+#endif
+
+#define talloc_reference(ctx, ptr) (_TALLOC_TYPEOF(ptr))_talloc_reference_loc((ctx),(ptr), __location__)
+#define talloc_move(ctx, ptr) (_TALLOC_TYPEOF(*(ptr)))_talloc_move((ctx),(void *)(ptr))
+
+/* useful macros for creating type checked pointers */
+#define talloc(ctx, type) (type *)talloc_named_const(ctx, sizeof(type), #type)
+#define talloc_size(ctx, size) talloc_named_const(ctx, size, __location__)
+#define talloc_ptrtype(ctx, ptr) (_TALLOC_TYPEOF(ptr))talloc_size(ctx, sizeof(*(ptr)))
+
+#define talloc_new(ctx) talloc_named_const(ctx, 0, "talloc_new: " __location__)
+
+#define talloc_zero(ctx, type) (type *)_talloc_zero(ctx, sizeof(type), #type)
+#define talloc_zero_size(ctx, size) _talloc_zero(ctx, size, __location__)
+
+#define talloc_zero_array(ctx, type, count) (type *)_talloc_zero_array(ctx, sizeof(type), count, #type)
+#define talloc_array(ctx, type, count) (type *)_talloc_array(ctx, sizeof(type), count, #type)
+#define talloc_array_size(ctx, size, count) _talloc_array(ctx, size, count, __location__)
+#define talloc_array_ptrtype(ctx, ptr, count) (_TALLOC_TYPEOF(ptr))talloc_array_size(ctx, sizeof(*(ptr)), count)
+#define talloc_array_length(ctx) (talloc_get_size(ctx)/sizeof(*ctx))
+
+#define talloc_realloc(ctx, p, type, count) (type *)_talloc_realloc_array(ctx, p, sizeof(type), count, #type)
+#define talloc_realloc_size(ctx, ptr, size) _talloc_realloc(ctx, ptr, size, __location__)
+
+#define talloc_memdup(t, p, size) _talloc_memdup(t, p, size, __location__)
+
+#define talloc_set_type(ptr, type) talloc_set_name_const(ptr, #type)
+#define talloc_get_type(ptr, type) (type *)talloc_check_name(ptr, #type)
+#define talloc_get_type_abort(ptr, type) (type *)_talloc_get_type_abort(ptr, #type, __location__)
+
+#define talloc_find_parent_bytype(ptr, type) (type *)talloc_find_parent_byname(ptr, #type)
+#define talloc_free(ctx) _talloc_free(ctx, __location__)
+
+
+#if TALLOC_DEPRECATED
+#define talloc_zero_p(ctx, type) talloc_zero(ctx, type)
+#define talloc_p(ctx, type) talloc(ctx, type)
+#define talloc_array_p(ctx, type, count) talloc_array(ctx, type, count)
+#define talloc_realloc_p(ctx, p, type, count) talloc_realloc(ctx, p, type, count)
+#define talloc_destroy(ctx) talloc_free(ctx)
+#define talloc_append_string(c, s, a) (s?talloc_strdup_append(s,a):talloc_strdup(c, a))
+#endif
+
+#define TALLOC_FREE(ctx) do { talloc_free(ctx); ctx=NULL; } while(0)
+
+/* The following definitions come from talloc.c */
+void *_talloc(const void *context, size_t size);
+void *talloc_pool(const void *context, size_t size);
+void _talloc_set_destructor(const void *ptr, int (*_destructor)(void *));
+int talloc_increase_ref_count(const void *ptr);
+size_t talloc_reference_count(const void *ptr);
+void *_talloc_reference_loc(const void *context, const void *ptr, const char *location);
+int talloc_unlink(const void *context, void *ptr);
+const char *talloc_set_name(const void *ptr, const char *fmt, ...) PRINTF_ATTRIBUTE(2,3);
+void talloc_set_name_const(const void *ptr, const char *name);
+void *talloc_named(const void *context, size_t size,
+ const char *fmt, ...) PRINTF_ATTRIBUTE(3,4);
+void *talloc_named_const(const void *context, size_t size, const char *name);
+const char *talloc_get_name(const void *ptr);
+void *talloc_check_name(const void *ptr, const char *name);
+void *_talloc_get_type_abort(const void *ptr, const char *name, const char *location);
+void *talloc_parent(const void *ptr);
+const char *talloc_parent_name(const void *ptr);
+void *talloc_init(const char *fmt, ...) PRINTF_ATTRIBUTE(1,2);
+int _talloc_free(void *ptr, const char *location);
+void talloc_free_children(void *ptr);
+void *_talloc_realloc(const void *context, void *ptr, size_t size, const char *name);
+void *_talloc_steal_loc(const void *new_ctx, const void *ptr, const char *location);
+void *talloc_reparent(const void *old_parent, const void *new_parent, const void *ptr);
+void *_talloc_move(const void *new_ctx, const void *pptr);
+size_t talloc_total_size(const void *ptr);
+size_t talloc_total_blocks(const void *ptr);
+void talloc_report_depth_cb(const void *ptr, int depth, int max_depth,
+ void (*callback)(const void *ptr,
+ int depth, int max_depth,
+ int is_ref,
+ void *private_data),
+ void *private_data);
+void talloc_report_depth_file(const void *ptr, int depth, int max_depth, FILE *f);
+void talloc_report_full(const void *ptr, FILE *f);
+void talloc_report(const void *ptr, FILE *f);
+void talloc_enable_null_tracking(void);
+void talloc_enable_null_tracking_no_autofree(void);
+void talloc_disable_null_tracking(void);
+void talloc_enable_leak_report(void);
+void talloc_enable_leak_report_full(void);
+void *_talloc_zero(const void *ctx, size_t size, const char *name);
+void *_talloc_memdup(const void *t, const void *p, size_t size, const char *name);
+void *_talloc_array(const void *ctx, size_t el_size, unsigned count, const char *name);
+void *_talloc_zero_array(const void *ctx, size_t el_size, unsigned count, const char *name);
+void *_talloc_realloc_array(const void *ctx, void *ptr, size_t el_size, unsigned count, const char *name);
+void *talloc_realloc_fn(const void *context, void *ptr, size_t size);
+void *talloc_autofree_context(void);
+size_t talloc_get_size(const void *ctx);
+void *talloc_find_parent_byname(const void *ctx, const char *name);
+void talloc_show_parents(const void *context, FILE *file);
+int talloc_is_parent(const void *context, const void *ptr);
+
+char *talloc_strdup(const void *t, const char *p);
+char *talloc_strdup_append(char *s, const char *a);
+char *talloc_strdup_append_buffer(char *s, const char *a);
+
+char *talloc_strndup(const void *t, const char *p, size_t n);
+char *talloc_strndup_append(char *s, const char *a, size_t n);
+char *talloc_strndup_append_buffer(char *s, const char *a, size_t n);
+
+char *talloc_vasprintf(const void *t, const char *fmt, va_list ap) PRINTF_ATTRIBUTE(2,0);
+char *talloc_vasprintf_append(char *s, const char *fmt, va_list ap) PRINTF_ATTRIBUTE(2,0);
+char *talloc_vasprintf_append_buffer(char *s, const char *fmt, va_list ap) PRINTF_ATTRIBUTE(2,0);
+
+char *talloc_asprintf(const void *t, const char *fmt, ...) PRINTF_ATTRIBUTE(2,3);
+char *talloc_asprintf_append(char *s, const char *fmt, ...) PRINTF_ATTRIBUTE(2,3);
+char *talloc_asprintf_append_buffer(char *s, const char *fmt, ...) PRINTF_ATTRIBUTE(2,3);
+
+void talloc_set_abort_fn(void (*abort_fn)(const char *reason));
+void talloc_set_log_fn(void (*log_fn)(const char *message));
+void talloc_set_log_stderr(void);
+
+#endif
diff --git a/src/talloc/talloc_guide.txt b/src/talloc/talloc_guide.txt
new file mode 100644
index 00000000000..01de806662d
--- /dev/null
+++ b/src/talloc/talloc_guide.txt
@@ -0,0 +1,757 @@
+Using talloc in Samba4
+======================
+
+.. contents::
+
+Andrew Tridgell
+August 2009
+
+The most current version of this document is available at
+ http://samba.org/ftp/unpacked/talloc/talloc_guide.txt
+
+If you are used to the "old" talloc from Samba3 before 3.0.20 then please read
+this carefully, as talloc has changed a lot. With 3.0.20 (or 3.0.14?) the
+Samba4 talloc has been ported back to Samba3, so this guide applies to both.
+
+The new talloc is a hierarchical, reference counted memory pool system
+with destructors. Quite a mouthful really, but not too bad once you
+get used to it.
+
+Perhaps the biggest change from Samba3 is that there is no distinction
+between a "talloc context" and a "talloc pointer". Any pointer
+returned from talloc() is itself a valid talloc context. This means
+you can do this::
+
+ struct foo *X = talloc(mem_ctx, struct foo);
+ X->name = talloc_strdup(X, "foo");
+
+and the pointer X->name would be a "child" of the talloc context "X"
+which is itself a child of mem_ctx. So if you do talloc_free(mem_ctx)
+then it is all destroyed, whereas if you do talloc_free(X) then just X
+and X->name are destroyed, and if you do talloc_free(X->name) then
+just the name element of X is destroyed.
+
+If you think about this, then what this effectively gives you is an
+n-ary tree, where you can free any part of the tree with
+talloc_free().
+
+If you find this confusing, then I suggest you run the testsuite to
+watch talloc in action. You may also like to add your own tests to
+testsuite.c to clarify how some particular situation is handled.
+
+
+Performance
+-----------
+
+All the additional features of talloc() over malloc() do come at a
+price. We have a simple performance test in Samba4 that measures
+talloc() versus malloc() performance, and it seems that talloc() is
+about 4% slower than malloc() on my x86 Debian Linux box. For Samba,
+the great reduction in code complexity that we get by using talloc
+makes this worthwhile, especially as the total overhead of
+talloc/malloc in Samba is already quite small.
+
+
+talloc API
+----------
+
+The following is a complete guide to the talloc API. Read it all at
+least twice.
+
+Multi-threading
+---------------
+
+talloc itself does not deal with threads. It is thread-safe (assuming
+the underlying "malloc" is), as long as each thread uses different
+memory contexts.
+If two threads uses the same context then they need to synchronize in
+order to be safe. In particular:
+- when using talloc_enable_leak_report(), giving directly NULL as a
+parent context implicitly refers to a hidden "null context" global
+variable, so this should not be used in a multi-threaded environment
+without proper synchronization ;
+- the context returned by talloc_autofree_context() is also global so
+shouldn't be used by several threads simultaneously without
+synchronization.
+
+
+=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
+(type *)talloc(const void *context, type);
+
+The talloc() macro is the core of the talloc library. It takes a
+memory context and a type, and returns a pointer to a new area of
+memory of the given type.
+
+The returned pointer is itself a talloc context, so you can use it as
+the context argument to more calls to talloc if you wish.
+
+The returned pointer is a "child" of the supplied context. This means
+that if you talloc_free() the context then the new child disappears as
+well. Alternatively you can free just the child.
+
+The context argument to talloc() can be NULL, in which case a new top
+level context is created.
+
+
+=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
+void *talloc_size(const void *context, size_t size);
+
+The function talloc_size() should be used when you don't have a
+convenient type to pass to talloc(). Unlike talloc(), it is not type
+safe (as it returns a void *), so you are on your own for type checking.
+
+=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
+(typeof(ptr)) talloc_ptrtype(const void *ctx, ptr);
+
+The talloc_ptrtype() macro should be used when you have a pointer and
+want to allocate memory to point at with this pointer. When compiling
+with gcc >= 3 it is typesafe. Note this is a wrapper of talloc_size()
+and talloc_get_name() will return the current location in the source file.
+and not the type.
+
+=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
+int talloc_free(void *ptr);
+
+The talloc_free() function frees a piece of talloc memory, and all its
+children. You can call talloc_free() on any pointer returned by
+talloc().
+
+The return value of talloc_free() indicates success or failure, with 0
+returned for success and -1 for failure. The only possible failure
+condition is if the pointer had a destructor attached to it and the
+destructor returned -1. See talloc_set_destructor() for details on
+destructors.
+
+If this pointer has an additional parent when talloc_free() is called
+then the memory is not actually released, but instead the most
+recently established parent is destroyed. See talloc_reference() for
+details on establishing additional parents.
+
+For more control on which parent is removed, see talloc_unlink()
+
+talloc_free() operates recursively on its children.
+
+From the 2.0 version of talloc, as a special case, talloc_free() is
+refused on pointers that have more than one parent, as talloc would
+have no way of knowing which parent should be removed. To free a
+pointer that has more than one parent please use talloc_unlink().
+
+To help you find problems in your code caused by this behaviour, if
+you do try and free a pointer with more than one parent then the
+talloc logging function will be called to give output like this:
+
+ ERROR: talloc_free with references at some_dir/source/foo.c:123
+ reference at some_dir/source/other.c:325
+ reference at some_dir/source/third.c:121
+
+Please see the documentation for talloc_set_log_fn() and
+talloc_set_log_stderr() for more information on talloc logging
+functions.
+
+=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
+int talloc_free_children(void *ptr);
+
+The talloc_free_children() walks along the list of all children of a
+talloc context and talloc_free()s only the children, not the context
+itself.
+
+
+=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
+void *talloc_reference(const void *context, const void *ptr);
+
+The talloc_reference() function makes "context" an additional parent
+of "ptr".
+
+The return value of talloc_reference() is always the original pointer
+"ptr", unless talloc ran out of memory in creating the reference in
+which case it will return NULL (each additional reference consumes
+around 48 bytes of memory on intel x86 platforms).
+
+If "ptr" is NULL, then the function is a no-op, and simply returns NULL.
+
+After creating a reference you can free it in one of the following
+ways:
+
+ - you can talloc_free() any parent of the original pointer. That
+ will reduce the number of parents of this pointer by 1, and will
+ cause this pointer to be freed if it runs out of parents.
+
+ - you can talloc_free() the pointer itself. That will destroy the
+ most recently established parent to the pointer and leave the
+ pointer as a child of its current parent.
+
+For more control on which parent to remove, see talloc_unlink()
+
+
+=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
+int talloc_unlink(const void *context, const void *ptr);
+
+The talloc_unlink() function removes a specific parent from ptr. The
+context passed must either be a context used in talloc_reference()
+with this pointer, or must be a direct parent of ptr.
+
+Note that if the parent has already been removed using talloc_free()
+then this function will fail and will return -1. Likewise, if "ptr"
+is NULL, then the function will make no modifications and return -1.
+
+Usually you can just use talloc_free() instead of talloc_unlink(), but
+sometimes it is useful to have the additional control on which parent
+is removed.
+
+
+=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
+void talloc_set_destructor(const void *ptr, int (*destructor)(void *));
+
+The function talloc_set_destructor() sets the "destructor" for the
+pointer "ptr". A destructor is a function that is called when the
+memory used by a pointer is about to be released. The destructor
+receives the pointer as an argument, and should return 0 for success
+and -1 for failure.
+
+The destructor can do anything it wants to, including freeing other
+pieces of memory. A common use for destructors is to clean up
+operating system resources (such as open file descriptors) contained
+in the structure the destructor is placed on.
+
+You can only place one destructor on a pointer. If you need more than
+one destructor then you can create a zero-length child of the pointer
+and place an additional destructor on that.
+
+To remove a destructor call talloc_set_destructor() with NULL for the
+destructor.
+
+If your destructor attempts to talloc_free() the pointer that it is
+the destructor for then talloc_free() will return -1 and the free will
+be ignored. This would be a pointless operation anyway, as the
+destructor is only called when the memory is just about to go away.
+
+
+=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
+int talloc_increase_ref_count(const void *ptr);
+
+The talloc_increase_ref_count(ptr) function is exactly equivalent to:
+
+ talloc_reference(NULL, ptr);
+
+You can use either syntax, depending on which you think is clearer in
+your code.
+
+It returns 0 on success and -1 on failure.
+
+=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
+size_t talloc_reference_count(const void *ptr);
+
+Return the number of references to the pointer.
+
+=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
+void talloc_set_name(const void *ptr, const char *fmt, ...);
+
+Each talloc pointer has a "name". The name is used principally for
+debugging purposes, although it is also possible to set and get the
+name on a pointer in as a way of "marking" pointers in your code.
+
+The main use for names on pointer is for "talloc reports". See
+talloc_report() and talloc_report_full() for details. Also see
+talloc_enable_leak_report() and talloc_enable_leak_report_full().
+
+The talloc_set_name() function allocates memory as a child of the
+pointer. It is logically equivalent to:
+ talloc_set_name_const(ptr, talloc_asprintf(ptr, fmt, ...));
+
+Note that multiple calls to talloc_set_name() will allocate more
+memory without releasing the name. All of the memory is released when
+the ptr is freed using talloc_free().
+
+
+=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
+void talloc_set_name_const(const void *ptr, const char *name);
+
+The function talloc_set_name_const() is just like talloc_set_name(),
+but it takes a string constant, and is much faster. It is extensively
+used by the "auto naming" macros, such as talloc_p().
+
+This function does not allocate any memory. It just copies the
+supplied pointer into the internal representation of the talloc
+ptr. This means you must not pass a name pointer to memory that will
+disappear before the ptr is freed with talloc_free().
+
+
+=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
+void *talloc_named(const void *context, size_t size, const char *fmt, ...);
+
+The talloc_named() function creates a named talloc pointer. It is
+equivalent to:
+
+ ptr = talloc_size(context, size);
+ talloc_set_name(ptr, fmt, ....);
+
+
+=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
+void *talloc_named_const(const void *context, size_t size, const char *name);
+
+This is equivalent to::
+
+ ptr = talloc_size(context, size);
+ talloc_set_name_const(ptr, name);
+
+
+=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
+const char *talloc_get_name(const void *ptr);
+
+This returns the current name for the given talloc pointer. See
+talloc_set_name() for details.
+
+
+=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
+void *talloc_init(const char *fmt, ...);
+
+This function creates a zero length named talloc context as a top
+level context. It is equivalent to::
+
+ talloc_named(NULL, 0, fmt, ...);
+
+
+=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
+void *talloc_new(void *ctx);
+
+This is a utility macro that creates a new memory context hanging
+off an exiting context, automatically naming it "talloc_new: __location__"
+where __location__ is the source line it is called from. It is
+particularly useful for creating a new temporary working context.
+
+
+=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
+(type *)talloc_realloc(const void *context, void *ptr, type, count);
+
+The talloc_realloc() macro changes the size of a talloc
+pointer. The "count" argument is the number of elements of type "type"
+that you want the resulting pointer to hold.
+
+talloc_realloc() has the following equivalences::
+
+ talloc_realloc(context, NULL, type, 1) ==> talloc(context, type);
+ talloc_realloc(context, NULL, type, N) ==> talloc_array(context, type, N);
+ talloc_realloc(context, ptr, type, 0) ==> talloc_free(ptr);
+
+The "context" argument is only used if "ptr" is NULL, otherwise it is
+ignored.
+
+talloc_realloc() returns the new pointer, or NULL on failure. The call
+will fail either due to a lack of memory, or because the pointer has
+more than one parent (see talloc_reference()).
+
+
+=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
+void *talloc_realloc_size(const void *context, void *ptr, size_t size);
+
+the talloc_realloc_size() function is useful when the type is not
+known so the typesafe talloc_realloc() cannot be used.
+
+
+=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
+void *talloc_steal(const void *new_ctx, const void *ptr);
+
+The talloc_steal() function changes the parent context of a talloc
+pointer. It is typically used when the context that the pointer is
+currently a child of is going to be freed and you wish to keep the
+memory for a longer time.
+
+The talloc_steal() function returns the pointer that you pass it. It
+does not have any failure modes.
+
+NOTE: It is possible to produce loops in the parent/child relationship
+if you are not careful with talloc_steal(). No guarantees are provided
+as to your sanity or the safety of your data if you do this.
+
+talloc_steal (new_ctx, NULL) will return NULL with no sideeffects.
+
+Note that if you try and call talloc_steal() on a pointer that has
+more than one parent then the result is ambiguous. Talloc will choose
+to remove the parent that is currently indicated by talloc_parent()
+and replace it with the chosen parent. You will also get a message
+like this via the talloc logging functions:
+
+ WARNING: talloc_steal with references at some_dir/source/foo.c:123
+ reference at some_dir/source/other.c:325
+ reference at some_dir/source/third.c:121
+
+To unambiguously change the parent of a pointer please see the
+function talloc_reparent(). See the talloc_set_log_fn() documentation
+for more information on talloc logging.
+
+=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
+void *talloc_reparent(const void *old_parent, const void *new_parent, const void *ptr);
+
+The talloc_reparent() function changes the parent context of a talloc
+pointer. It is typically used when the context that the pointer is
+currently a child of is going to be freed and you wish to keep the
+memory for a longer time.
+
+The talloc_reparent() function returns the pointer that you pass it. It
+does not have any failure modes.
+
+The difference between talloc_reparent() and talloc_steal() is that
+talloc_reparent() can specify which parent you wish to change. This is
+useful when a pointer has multiple parents via references.
+
+=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
+void *talloc_parent(const void *ptr);
+
+The talloc_parent() function returns the current talloc parent. This
+is usually the pointer under which this memory was originally created,
+but it may have changed due to a talloc_steal() or talloc_reparent()
+
+=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
+size_t talloc_total_size(const void *ptr);
+
+The talloc_total_size() function returns the total size in bytes used
+by this pointer and all child pointers. Mostly useful for debugging.
+
+Passing NULL is allowed, but it will only give a meaningful result if
+talloc_enable_leak_report() or talloc_enable_leak_report_full() has
+been called.
+
+
+=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
+size_t talloc_total_blocks(const void *ptr);
+
+The talloc_total_blocks() function returns the total memory block
+count used by this pointer and all child pointers. Mostly useful for
+debugging.
+
+Passing NULL is allowed, but it will only give a meaningful result if
+talloc_enable_leak_report() or talloc_enable_leak_report_full() has
+been called.
+
+=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
+void talloc_report_depth_cb(const void *ptr, int depth, int max_depth,
+ void (*callback)(const void *ptr,
+ int depth, int max_depth,
+ int is_ref,
+ void *priv),
+ void *priv);
+
+This provides a more flexible reports than talloc_report(). It
+will recursively call the callback for the entire tree of memory
+referenced by the pointer. References in the tree are passed with
+is_ref = 1 and the pointer that is referenced.
+
+You can pass NULL for the pointer, in which case a report is
+printed for the top level memory context, but only if
+talloc_enable_leak_report() or talloc_enable_leak_report_full()
+has been called.
+
+The recursion is stopped when depth >= max_depth.
+max_depth = -1 means only stop at leaf nodes.
+
+
+=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
+void talloc_report_depth_file(const void *ptr, int depth, int max_depth, FILE *f);
+
+This provides a more flexible reports than talloc_report(). It
+will let you specify the depth and max_depth.
+
+
+=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
+void talloc_report(const void *ptr, FILE *f);
+
+The talloc_report() function prints a summary report of all memory
+used by ptr. One line of report is printed for each immediate child of
+ptr, showing the total memory and number of blocks used by that child.
+
+You can pass NULL for the pointer, in which case a report is printed
+for the top level memory context, but only if
+talloc_enable_leak_report() or talloc_enable_leak_report_full() has
+been called.
+
+
+=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
+void talloc_report_full(const void *ptr, FILE *f);
+
+This provides a more detailed report than talloc_report(). It will
+recursively print the ensire tree of memory referenced by the
+pointer. References in the tree are shown by giving the name of the
+pointer that is referenced.
+
+You can pass NULL for the pointer, in which case a report is printed
+for the top level memory context, but only if
+talloc_enable_leak_report() or talloc_enable_leak_report_full() has
+been called.
+
+
+=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
+void talloc_enable_leak_report(void);
+
+This enables calling of talloc_report(NULL, stderr) when the program
+exits. In Samba4 this is enabled by using the --leak-report command
+line option.
+
+For it to be useful, this function must be called before any other
+talloc function as it establishes a "null context" that acts as the
+top of the tree. If you don't call this function first then passing
+NULL to talloc_report() or talloc_report_full() won't give you the
+full tree printout.
+
+Here is a typical talloc report:
+
+talloc report on 'null_context' (total 267 bytes in 15 blocks)
+ libcli/auth/spnego_parse.c:55 contains 31 bytes in 2 blocks
+ libcli/auth/spnego_parse.c:55 contains 31 bytes in 2 blocks
+ iconv(UTF8,CP850) contains 42 bytes in 2 blocks
+ libcli/auth/spnego_parse.c:55 contains 31 bytes in 2 blocks
+ iconv(CP850,UTF8) contains 42 bytes in 2 blocks
+ iconv(UTF8,UTF-16LE) contains 45 bytes in 2 blocks
+ iconv(UTF-16LE,UTF8) contains 45 bytes in 2 blocks
+
+
+=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
+void talloc_enable_leak_report_full(void);
+
+This enables calling of talloc_report_full(NULL, stderr) when the
+program exits. In Samba4 this is enabled by using the
+--leak-report-full command line option.
+
+For it to be useful, this function must be called before any other
+talloc function as it establishes a "null context" that acts as the
+top of the tree. If you don't call this function first then passing
+NULL to talloc_report() or talloc_report_full() won't give you the
+full tree printout.
+
+Here is a typical full report:
+
+full talloc report on 'root' (total 18 bytes in 8 blocks)
+ p1 contains 18 bytes in 7 blocks (ref 0)
+ r1 contains 13 bytes in 2 blocks (ref 0)
+ reference to: p2
+ p2 contains 1 bytes in 1 blocks (ref 1)
+ x3 contains 1 bytes in 1 blocks (ref 0)
+ x2 contains 1 bytes in 1 blocks (ref 0)
+ x1 contains 1 bytes in 1 blocks (ref 0)
+
+
+=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
+void talloc_enable_null_tracking(void);
+
+This enables tracking of the NULL memory context without enabling leak
+reporting on exit. Useful for when you want to do your own leak
+reporting call via talloc_report_null_full();
+
+=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
+void talloc_disable_null_tracking(void);
+
+This disables tracking of the NULL memory context.
+
+=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
+(type *)talloc_zero(const void *ctx, type);
+
+The talloc_zero() macro is equivalent to::
+
+ ptr = talloc(ctx, type);
+ if (ptr) memset(ptr, 0, sizeof(type));
+
+
+=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
+void *talloc_zero_size(const void *ctx, size_t size)
+
+The talloc_zero_size() function is useful when you don't have a known type
+
+
+=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
+void *talloc_memdup(const void *ctx, const void *p, size_t size);
+
+The talloc_memdup() function is equivalent to::
+
+ ptr = talloc_size(ctx, size);
+ if (ptr) memcpy(ptr, p, size);
+
+
+=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
+char *talloc_strdup(const void *ctx, const char *p);
+
+The talloc_strdup() function is equivalent to::
+
+ ptr = talloc_size(ctx, strlen(p)+1);
+ if (ptr) memcpy(ptr, p, strlen(p)+1);
+
+This functions sets the name of the new pointer to the passed
+string. This is equivalent to::
+
+ talloc_set_name_const(ptr, ptr)
+
+=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
+char *talloc_strndup(const void *t, const char *p, size_t n);
+
+The talloc_strndup() function is the talloc equivalent of the C
+library function strndup()
+
+This functions sets the name of the new pointer to the passed
+string. This is equivalent to:
+ talloc_set_name_const(ptr, ptr)
+
+=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
+char *talloc_append_string(const void *t, char *orig, const char *append);
+
+The talloc_append_string() function appends the given formatted
+string to the given string.
+
+This function sets the name of the new pointer to the new
+string. This is equivalent to::
+
+ talloc_set_name_const(ptr, ptr)
+
+=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
+char *talloc_vasprintf(const void *t, const char *fmt, va_list ap);
+
+The talloc_vasprintf() function is the talloc equivalent of the C
+library function vasprintf()
+
+This functions sets the name of the new pointer to the new
+string. This is equivalent to::
+
+ talloc_set_name_const(ptr, ptr)
+
+
+=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
+char *talloc_asprintf(const void *t, const char *fmt, ...);
+
+The talloc_asprintf() function is the talloc equivalent of the C
+library function asprintf()
+
+This functions sets the name of the new pointer to the new
+string. This is equivalent to::
+
+ talloc_set_name_const(ptr, ptr)
+
+
+=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
+char *talloc_asprintf_append(char *s, const char *fmt, ...);
+
+The talloc_asprintf_append() function appends the given formatted
+string to the given string.
+Use this varient when the string in the current talloc buffer may
+have been truncated in length.
+
+This functions sets the name of the new pointer to the new
+string. This is equivalent to::
+
+ talloc_set_name_const(ptr, ptr)
+
+
+=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
+char *talloc_asprintf_append_buffer(char *s, const char *fmt, ...);
+
+The talloc_asprintf_append() function appends the given formatted
+string to the end of the currently allocated talloc buffer.
+Use this varient when the string in the current talloc buffer has
+not been changed.
+
+This functions sets the name of the new pointer to the new
+string. This is equivalent to::
+
+ talloc_set_name_const(ptr, ptr)
+
+
+=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
+((type *)talloc_array(const void *ctx, type, uint_t count);
+
+The talloc_array() macro is equivalent to::
+
+ (type *)talloc_size(ctx, sizeof(type) * count);
+
+except that it provides integer overflow protection for the multiply,
+returning NULL if the multiply overflows.
+
+
+=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
+void *talloc_array_size(const void *ctx, size_t size, uint_t count);
+
+The talloc_array_size() function is useful when the type is not
+known. It operates in the same way as talloc_array(), but takes a size
+instead of a type.
+
+=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
+(typeof(ptr)) talloc_array_ptrtype(const void *ctx, ptr, uint_t count);
+
+The talloc_ptrtype() macro should be used when you have a pointer to an array
+and want to allocate memory of an array to point at with this pointer. When compiling
+with gcc >= 3 it is typesafe. Note this is a wrapper of talloc_array_size()
+and talloc_get_name() will return the current location in the source file.
+and not the type.
+
+=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
+void *talloc_realloc_fn(const void *ctx, void *ptr, size_t size);
+
+This is a non-macro version of talloc_realloc(), which is useful
+as libraries sometimes want a ralloc function pointer. A realloc()
+implementation encapsulates the functionality of malloc(), free() and
+realloc() in one call, which is why it is useful to be able to pass
+around a single function pointer.
+
+
+=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
+void *talloc_autofree_context(void);
+
+This is a handy utility function that returns a talloc context
+which will be automatically freed on program exit. This can be used
+to reduce the noise in memory leak reports.
+
+
+=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
+void *talloc_check_name(const void *ptr, const char *name);
+
+This function checks if a pointer has the specified name. If it does
+then the pointer is returned. It it doesn't then NULL is returned.
+
+
+=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
+(type *)talloc_get_type(const void *ptr, type);
+
+This macro allows you to do type checking on talloc pointers. It is
+particularly useful for void* private pointers. It is equivalent to
+this::
+
+ (type *)talloc_check_name(ptr, #type)
+
+
+=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
+talloc_set_type(const void *ptr, type);
+
+This macro allows you to force the name of a pointer to be a
+particular type. This can be used in conjunction with
+talloc_get_type() to do type checking on void* pointers.
+
+It is equivalent to this::
+
+ talloc_set_name_const(ptr, #type)
+
+=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
+talloc_get_size(const void *ctx);
+
+This function lets you know the amount of memory alloced so far by
+this context. It does NOT account for subcontext memory.
+This can be used to calculate the size of an array.
+
+=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
+void *talloc_find_parent_byname(const void *ctx, const char *name);
+
+Find a parent memory context of the current context that has the given
+name. This can be very useful in complex programs where it may be
+difficult to pass all information down to the level you need, but you
+know the structure you want is a parent of another context.
+
+=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
+(type *)talloc_find_parent_bytype(ctx, type);
+
+Like talloc_find_parent_byname() but takes a type, making it typesafe.
+
+=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
+void talloc_set_log_fn(void (*log_fn)(const char *message));
+
+This function sets a logging function that talloc will use for
+warnings and errors. By default talloc will not print any warnings or
+errors.
+
+=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
+void talloc_set_log_stderr(void)
+
+This sets the talloc log function to write log messages to stderr