aboutsummaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorEric Anholt <[email protected]>2010-06-24 15:47:38 -0700
committerEric Anholt <[email protected]>2010-06-24 15:47:40 -0700
commitbcc13b74443137043e8a34f8cb64a5add0d8af93 (patch)
tree5f4e003dceb61c091ce0fcb8c5cf9d91bec033c0 /src
parent84341f4b2014810b2964230384fe76338be1d78e (diff)
parente5cf3aadb8d57dcc70b597092ecac276042f73cb (diff)
Merge branch 'glsl2-head' into glsl2
This brings in the standalone GLSL compiler that we are planning on replacing the existing Mesa GLSL compiler. It currently targets GLSL 1.20 and the Mesa IR.
Diffstat (limited to 'src')
-rw-r--r--src/glsl/.dir-locals.el3
-rw-r--r--src/glsl/.gitignore25
-rw-r--r--src/glsl/Makefile.am79
-rw-r--r--src/glsl/README153
-rw-r--r--src/glsl/TODO84
-rw-r--r--src/glsl/ast.h651
-rw-r--r--src/glsl/ast_expr.cpp96
-rw-r--r--src/glsl/ast_function.cpp751
-rw-r--r--src/glsl/ast_to_hir.cpp2453
-rw-r--r--src/glsl/ast_type.cpp110
-rwxr-xr-xsrc/glsl/autogen.sh12
-rw-r--r--src/glsl/builtin_function.cpp5080
-rw-r--r--src/glsl/builtin_types.h268
-rw-r--r--src/glsl/builtin_variables.h93
-rw-r--r--src/glsl/builtins/110/abs21
-rw-r--r--src/glsl/builtins/110/all16
-rw-r--r--src/glsl/builtins/110/any16
-rw-r--r--src/glsl/builtins/110/asin112
-rw-r--r--src/glsl/builtins/110/atan154
-rw-r--r--src/glsl/builtins/110/ceil21
-rw-r--r--src/glsl/builtins/110/clamp62
-rw-r--r--src/glsl/builtins/110/cos21
-rw-r--r--src/glsl/builtins/110/cross17
-rw-r--r--src/glsl/builtins/110/degrees21
-rw-r--r--src/glsl/builtins/110/distance33
-rw-r--r--src/glsl/builtins/110/dot25
-rw-r--r--src/glsl/builtins/110/equal61
-rw-r--r--src/glsl/builtins/110/exp21
-rw-r--r--src/glsl/builtins/110/exp221
-rw-r--r--src/glsl/builtins/110/faceforward37
-rw-r--r--src/glsl/builtins/110/floor21
-rw-r--r--src/glsl/builtins/110/fract34
-rw-r--r--src/glsl/builtins/110/greaterThan61
-rw-r--r--src/glsl/builtins/110/greaterThanEqual61
-rw-r--r--src/glsl/builtins/110/inversesqrt21
-rw-r--r--src/glsl/builtins/110/length21
-rw-r--r--src/glsl/builtins/110/lessThan61
-rw-r--r--src/glsl/builtins/110/lessThanEqual61
-rw-r--r--src/glsl/builtins/110/log21
-rw-r--r--src/glsl/builtins/110/log221
-rw-r--r--src/glsl/builtins/110/matrixCompMult32
-rw-r--r--src/glsl/builtins/110/max64
-rw-r--r--src/glsl/builtins/110/min64
-rw-r--r--src/glsl/builtins/110/mix50
-rw-r--r--src/glsl/builtins/110/mod64
-rw-r--r--src/glsl/builtins/110/noise_fake76
-rw-r--r--src/glsl/builtins/110/normalize21
-rw-r--r--src/glsl/builtins/110/not16
-rw-r--r--src/glsl/builtins/110/notEqual61
-rw-r--r--src/glsl/builtins/110/pow25
-rw-r--r--src/glsl/builtins/110/radians21
-rw-r--r--src/glsl/builtins/110/reflect58
-rw-r--r--src/glsl/builtins/110/refract102
-rw-r--r--src/glsl/builtins/110/sign34
-rw-r--r--src/glsl/builtins/110/sin21
-rw-r--r--src/glsl/builtins/110/smoothstep224
-rw-r--r--src/glsl/builtins/110/sqrt21
-rw-r--r--src/glsl/builtins/110/step68
-rw-r--r--src/glsl/builtins/110/tan21
-rw-r--r--src/glsl/builtins/110/textures213
-rw-r--r--src/glsl/builtins/110_fs/derivatives73
-rw-r--r--src/glsl/builtins/110_fs/textures113
-rw-r--r--src/glsl/builtins/110_vs/ftransform7
-rw-r--r--src/glsl/builtins/120/matrixCompMult61
-rw-r--r--src/glsl/builtins/120/outerProduct92
-rw-r--r--src/glsl/builtins/120/transpose139
-rw-r--r--src/glsl/builtins/130/clamp123
-rw-r--r--src/glsl/builtins/130/cosh30
-rw-r--r--src/glsl/builtins/130/equal31
-rw-r--r--src/glsl/builtins/130/greaterThan31
-rw-r--r--src/glsl/builtins/130/greaterThanEqual31
-rw-r--r--src/glsl/builtins/130/lessThan31
-rw-r--r--src/glsl/builtins/130/lessThanEqual31
-rw-r--r--src/glsl/builtins/130/max127
-rw-r--r--src/glsl/builtins/130/min127
-rw-r--r--src/glsl/builtins/130/notEqual31
-rw-r--r--src/glsl/builtins/130/sign34
-rw-r--r--src/glsl/builtins/130/sinh30
-rw-r--r--src/glsl/builtins/130/tanh42
-rw-r--r--src/glsl/builtins/130/texelFetch107
-rw-r--r--src/glsl/builtins/130/texture110
-rw-r--r--src/glsl/builtins/130/textureGrad147
-rw-r--r--src/glsl/builtins/130/textureLod128
-rw-r--r--src/glsl/builtins/130/textureProj92
-rw-r--r--src/glsl/builtins/130/textureProjGrad122
-rw-r--r--src/glsl/builtins/130/textureProjLod107
-rw-r--r--src/glsl/builtins/130_fs/texture128
-rw-r--r--src/glsl/builtins/130_fs/textureProj107
-rw-r--r--src/glsl/builtins/ARB_texture_rectangle/textures16
-rw-r--r--src/glsl/builtins/EXT_texture_array/textures59
-rw-r--r--src/glsl/builtins/EXT_texture_array_fs/textures27
-rwxr-xr-xsrc/glsl/builtins/tools/generate_builtins.pl123
-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.py298
-rw-r--r--src/glsl/configure.ac69
-rw-r--r--src/glsl/glcpp/.gitignore11
-rw-r--r--src/glsl/glcpp/Makefile.am46
-rw-r--r--src/glsl/glcpp/README30
-rw-r--r--src/glsl/glcpp/glcpp-lex.l257
-rw-r--r--src/glsl/glcpp/glcpp-parse.y1611
-rw-r--r--src/glsl/glcpp/glcpp.c88
-rw-r--r--src/glsl/glcpp/glcpp.h224
-rw-r--r--src/glsl/glcpp/hash_table.c159
-rw-r--r--src/glsl/glcpp/hash_table.h125
-rw-r--r--src/glsl/glcpp/main/imports.h6
-rw-r--r--src/glsl/glcpp/main/simple_list.h235
-rw-r--r--src/glsl/glcpp/pp.c155
-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.expected3
-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/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/099-c99-example.c17
-rw-r--r--src/glsl/glcpp/tests/099-c99-example.c.expected17
-rwxr-xr-xsrc/glsl/glcpp/tests/glcpp-test7
-rw-r--r--src/glsl/glcpp/xtalloc.c99
-rw-r--r--src/glsl/glsl_lexer.lpp336
-rw-r--r--src/glsl/glsl_parser.ypp1444
-rw-r--r--src/glsl/glsl_parser_extras.cpp621
-rw-r--r--src/glsl/glsl_parser_extras.h139
-rw-r--r--src/glsl/glsl_symbol_table.h163
-rw-r--r--src/glsl/glsl_types.cpp773
-rw-r--r--src/glsl/glsl_types.h445
-rw-r--r--src/glsl/hash_table.c159
-rw-r--r--src/glsl/hash_table.h125
-rw-r--r--src/glsl/hir_field_selection.cpp81
-rw-r--r--src/glsl/ir.cpp818
-rw-r--r--src/glsl/ir.h1178
-rw-r--r--src/glsl/ir_basic_block.cpp144
-rw-r--r--src/glsl/ir_basic_block.h28
-rw-r--r--src/glsl/ir_clone.cpp287
-rw-r--r--src/glsl/ir_constant_expression.cpp671
-rw-r--r--src/glsl/ir_constant_folding.cpp229
-rw-r--r--src/glsl/ir_constant_variable.cpp156
-rw-r--r--src/glsl/ir_copy_propagation.cpp256
-rw-r--r--src/glsl/ir_dead_code.cpp219
-rw-r--r--src/glsl/ir_dead_code_local.cpp223
-rw-r--r--src/glsl/ir_expression_flattening.cpp172
-rw-r--r--src/glsl/ir_expression_flattening.h38
-rw-r--r--src/glsl/ir_function.cpp225
-rw-r--r--src/glsl/ir_function_can_inline.cpp71
-rw-r--r--src/glsl/ir_function_inlining.cpp272
-rw-r--r--src/glsl/ir_function_inlining.h30
-rw-r--r--src/glsl/ir_hierarchical_visitor.cpp284
-rw-r--r--src/glsl/ir_hierarchical_visitor.h162
-rw-r--r--src/glsl/ir_hv_accept.cpp348
-rw-r--r--src/glsl/ir_if_simplification.cpp84
-rw-r--r--src/glsl/ir_optimization.h41
-rw-r--r--src/glsl/ir_print_visitor.cpp373
-rw-r--r--src/glsl/ir_print_visitor.h81
-rw-r--r--src/glsl/ir_reader.cpp1053
-rw-r--r--src/glsl/ir_reader.h34
-rw-r--r--src/glsl/ir_swizzle_swizzle.cpp93
-rw-r--r--src/glsl/ir_to_mesa.cpp1211
-rw-r--r--src/glsl/ir_validate.cpp104
-rw-r--r--src/glsl/ir_variable.cpp345
-rw-r--r--src/glsl/ir_vec_index_to_swizzle.cpp158
-rw-r--r--src/glsl/ir_visitor.h66
-rw-r--r--src/glsl/linker.cpp871
-rw-r--r--src/glsl/list.h403
-rw-r--r--src/glsl/main.cpp256
-rw-r--r--src/glsl/main/imports.h6
-rw-r--r--src/glsl/main/mtypes.h270
-rw-r--r--src/glsl/main/simple_list.h235
-rw-r--r--src/glsl/mesa/shader/prog_instruction.c363
-rw-r--r--src/glsl/mesa/shader/prog_instruction.h437
-rw-r--r--src/glsl/mesa/shader/prog_print.c1089
-rw-r--r--src/glsl/mesa/shader/prog_print.h98
-rw-r--r--src/glsl/program.h155
-rw-r--r--src/glsl/s_expression.cpp131
-rw-r--r--src/glsl/s_expression.h142
-rw-r--r--src/glsl/symbol_table.c413
-rw-r--r--src/glsl/symbol_table.h66
-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
376 files changed, 38300 insertions, 0 deletions
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..376aaeda13a
--- /dev/null
+++ b/src/glsl/.gitignore
@@ -0,0 +1,25 @@
+.deps
+COPYING
+INSTALL
+Makefile.in
+aclocal.m4
+autom4te.cache
+config.*
+configure
+depcomp
+ylwrap
+install-sh
+missing
+stamp-h1
+libtool
+ltmain.sh
+Makefile
+*.o
+*~
+glsl_lexer.cpp
+glsl_parser.output
+glsl_parser.cpp
+glsl_parser.h
+glsl
+mesa_codegen.cpp
+mesa_codegen.h
diff --git a/src/glsl/Makefile.am b/src/glsl/Makefile.am
new file mode 100644
index 00000000000..c34f7d8abfb
--- /dev/null
+++ b/src/glsl/Makefile.am
@@ -0,0 +1,79 @@
+# 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 \
+ symbol_table.c hash_table.c 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 \
+ mesa/shader/prog_instruction.c \
+ mesa/shader/prog_instruction.h \
+ mesa/shader/prog_print.c \
+ mesa/shader/prog_print.h
+
+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..8b6162ab672
--- /dev/null
+++ b/src/glsl/README
@@ -0,0 +1,153 @@
+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 --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.
diff --git a/src/glsl/TODO b/src/glsl/TODO
new file mode 100644
index 00000000000..193cfc767d8
--- /dev/null
+++ b/src/glsl/TODO
@@ -0,0 +1,84 @@
+- Implement AST-to-HIR conversion of discard instructions.
+
+- Handle constant expressions of (matrix {+,-,*,/} scalar)
+
+- Handle constant expressions of (vector {+,-,*,/} scalar)
+
+- Handle constant expressions of (matrix * vector)
+
+- Handle constant expressions of (matrix * matrix)
+
+- Handle currently unsupported constant expression types
+ - ir_unop_sign
+ - ir_unop_exp2
+ - ir_unop_log2
+ - ir_unop_u2f
+ - ir_unop_trunc
+ - ir_unop_ceil
+ - ir_unop_floor
+ - ir_unop_sin
+ - ir_unop_cos
+ - ir_binop_dot
+ - ir_binop_min
+ - ir_binop_max
+ - ir_binop_pow
+
+- Handle constant expressions of (struct == struct)
+
+- Handle constant expressions of (struct != struct)
+
+- Add support to ir_constant for array constants Arrays can only be
+ - declared 'const' in GLSL 1.20+. This is because there are no
+ array constructors in GLSL 1.10, and any variable declared as
+ 'const' must have an initializer.
+
+- Handle constant expressions of (array == array)
+
+- Handle constant expressions of (array != array)
+
+- 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 non-void functions that lack a return statement
+
+- Detect return statements with a type not matching the funciton's
+ return type.
+
+- 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
diff --git a/src/glsl/ast.h b/src/glsl/ast.h
new file mode 100644
index 00000000000..de300e719c4
--- /dev/null
+++ b/src/glsl/ast.h
@@ -0,0 +1,651 @@
+/* -*- 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 ir_instruction;
+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_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;
+};
+
+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;
+
+ 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:
+ 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 struct ir_rvalue *
+_mesa_ast_field_selection_to_hir(const struct 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..761af00b95e
--- /dev/null
+++ b/src/glsl/ast_function.cpp
@@ -0,0 +1,751 @@
+/*
+ * 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"
+
+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;
+}
+
+
+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 = talloc_parent(state);
+
+ const 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");
+ }
+ }
+
+ actual_iter.next();
+ formal_iter.next();
+ }
+
+ /* FINISHME: The list of actual parameters needs to be modified to
+ * FINISHME: include any necessary conversions.
+ */
+ return new(ctx) ir_call(sig, actual_parameters);
+ } else {
+ /* FINISHME: Log a better error message here. G++ will show the types
+ * FINISHME: of the actual parameters and the set of candidate
+ * FINISHME: functions. A different error should also be logged when
+ * FINISHME: multiple functions match.
+ */
+ _mesa_glsl_error(loc, state, "no matching function for call to `%s'",
+ f->name);
+ 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 = talloc_parent(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
+ */
+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: {
+ ir_constant *zero = NULL;
+
+ switch (b) {
+ case GLSL_TYPE_UINT: zero = new(ctx) ir_constant(unsigned(0)); break;
+ case GLSL_TYPE_INT: zero = new(ctx) ir_constant(int(0)); break;
+ case GLSL_TYPE_FLOAT: zero = new(ctx) ir_constant(0.0f); break;
+ }
+
+ result = new(ctx) ir_expression(ir_binop_nequal, desired_type, src, zero);
+ }
+ }
+
+ assert(result != NULL);
+
+ 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 = talloc_parent(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(state,
+ constructor_type->element_type(),
+ parameter_count);
+ assert(constructor_type != NULL);
+ assert(constructor_type->length == parameter_count);
+ }
+
+ ir_function *f = state->symbols->get_function(constructor_type->name);
+
+ /* If the constructor for this type of array does not exist, generate the
+ * prototype and add it to the symbol table.
+ */
+ if (f == NULL) {
+ f = constructor_type->generate_constructor(state->symbols);
+ }
+
+ ir_rvalue *const r =
+ process_call(instructions, f, loc, &actual_parameters, state);
+
+ assert(r != NULL);
+ assert(r->type->is_error() || (r->type == constructor_type));
+
+ return r;
+}
+
+
+/**
+ * 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 = talloc_parent(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_sentinal()) {
+ _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;
+ }
+}
+
+
+ir_rvalue *
+ast_function_expression::hir(exec_list *instructions,
+ struct _mesa_glsl_parse_state *state)
+{
+ void *ctx = talloc_parent(state);
+ /* There are three sorts of function calls.
+ *
+ * 1. contstructors - 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()) {
+ /* Constructing a numeric type has a couple steps. First all values
+ * passed to the constructor are broken into individual parameters
+ * and type converted to the base type of the thing being constructed.
+ *
+ * At that point we have some number of values that match the base
+ * type of the thing being constructed. Now the constructor can be
+ * treated like a function call. Each numeric type has a small set
+ * of constructor functions. The set of new parameters will either
+ * match one of those functions or the original constructor is
+ * invalid.
+ */
+ const glsl_type *const base_type = constructor_type->get_base_type();
+
+ /* 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;
+
+ bool all_parameters_are_constant = true;
+
+ /* This handles invalid constructor calls such as 'vec4 v = vec4();'
+ */
+ if (this->expressions.is_empty()) {
+ _mesa_glsl_error(& loc, state, "too few components to construct "
+ "`%s'",
+ constructor_type->name);
+ return ir_call::get_error_instruction(ctx);
+ }
+
+ foreach_list (n, &this->expressions) {
+ ast_node *ast = exec_node_data(ast_node, n, link);
+ ir_rvalue *result =
+ ast->hir(instructions, state)->as_rvalue();
+ ir_variable *result_var = NULL;
+
+ /* 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;
+
+ /* 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++;
+
+ /* We can't use the same instruction node in the multiple
+ * swizzle dereferences that happen, so assign it to a
+ * variable and deref that. Plus it saves computation for
+ * complicated expressions and handles
+ * glsl-vs-constructor-call.shader_test.
+ */
+ if (result->type->components() >= 1 && !result->as_constant()) {
+ result_var = new(ctx) ir_variable(result->type,
+ "constructor_tmp");
+ ir_dereference_variable *lhs;
+
+ lhs = new(ctx) ir_dereference_variable(result_var);
+ instructions->push_tail(new(ctx) ir_assignment(lhs,
+ result, NULL));
+ }
+
+ /* Process each of the components of the parameter. Dereference
+ * each component individually, perform any type conversions, and
+ * add it to the parameter list for the constructor.
+ */
+ for (unsigned i = 0; i < result->type->components(); i++) {
+ if (components_used >= type_components)
+ break;
+
+ ir_rvalue *component;
+
+ if (result_var) {
+ ir_dereference *d = new(ctx) ir_dereference_variable(result_var);
+ component = dereference_component(d, i);
+ } else {
+ component = dereference_component(result, i);
+ }
+ component = convert_component(component, base_type);
+
+ /* All cases that could result in component->type being the
+ * error type should have already been caught above.
+ */
+ assert(component->type == base_type);
+
+ if (component->as_constant() == NULL)
+ all_parameters_are_constant = false;
+
+ /* Don't actually generate constructor calls for scalars.
+ * Instead, do the usual component selection and conversion,
+ * and return the single component.
+ */
+ if (constructor_type->is_scalar())
+ return component;
+
+ actual_parameters.push_tail(component);
+ components_used++;
+ }
+ }
+
+ /* 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);
+ }
+
+ ir_function *f = state->symbols->get_function(constructor_type->name);
+ if (f == NULL) {
+ _mesa_glsl_error(& loc, state, "no constructor for type `%s'",
+ constructor_type->name);
+ return ir_call::get_error_instruction(ctx);
+ }
+
+ const ir_function_signature *sig =
+ f->matching_signature(& actual_parameters);
+ if (sig != NULL) {
+ /* 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(sig->return_type,
+ & actual_parameters);
+
+ assert(sig->return_type->is_vector()
+ || sig->return_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 (sig->return_type->is_matrix())
+ generate_constructor_matrix(sig->return_type, initializer,
+ &data);
+ else
+ generate_constructor_vector(sig->return_type, initializer,
+ &data);
+
+ return new(ctx) ir_constant(sig->return_type, &data);
+ } else
+ return new(ctx) ir_call(sig, & actual_parameters);
+ } else {
+ /* FINISHME: Log a better error message here. G++ will show the
+ * FINSIHME: types of the actual parameters and the set of
+ * FINSIHME: candidate functions. A different error should also be
+ * FINSIHME: logged when multiple functions match.
+ */
+ _mesa_glsl_error(& loc, state, "no matching constructor for `%s'",
+ constructor_type->name);
+ return ir_call::get_error_instruction(ctx);
+ }
+ }
+
+ return ir_call::get_error_instruction(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..33eb27533fd
--- /dev/null
+++ b/src/glsl/ast_to_hir.cpp
@@ -0,0 +1,2453 @@
+/*
+ * 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 "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_constructors(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 = talloc_parent(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;
+
+ 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)
+ return type_b;
+ } 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())
+ return type_a;
+ }
+
+ _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 = talloc_parent(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(state,
+ lhs->type->element_type(),
+ rhs->type->array_size());
+ }
+ }
+
+ /* 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_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);
+
+ instructions->push_tail(new(ctx) ir_assignment(lhs,
+ deref_var,
+ NULL));
+
+ return new(ctx) ir_dereference_variable(var);
+}
+
+
+/**
+ * Generate a new temporary and add its declaration to the instruction stream
+ */
+static ir_variable *
+generate_temporary(const glsl_type *type, exec_list *instructions,
+ struct _mesa_glsl_parse_state *state)
+{
+ void *ctx = talloc_parent(state);
+ char *name = (char *) malloc(sizeof(char) * 13);
+
+ snprintf(name, 13, "tmp_%08X", state->temp_index);
+ state->temp_index++;
+
+ ir_variable *const var = new(ctx) ir_variable(type, name);
+ instructions->push_tail(var);
+
+ return 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");
+ 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 = talloc_parent(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[2];
+ 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);
+
+ error_emitted = op[0]->type->is_error();
+ if (type->is_error())
+ op[0]->type = type;
+
+ 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_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_variable *const tmp = generate_temporary(glsl_type::bool_type,
+ instructions, state);
+
+ 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_if *const stmt = new(ctx) ir_if(op[0]);
+ instructions->push_tail(stmt);
+
+ ir_variable *const tmp = generate_temporary(glsl_type::bool_type,
+ instructions, state);
+
+ 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, 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,
+ (ir_rvalue *)op[0]->clone(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);
+
+ struct ir_rvalue *temp_rhs;
+ temp_rhs = new(ctx) ir_expression(operations[this->oper], type,
+ op[0], op[1]);
+
+ result = do_assignment(instructions, state,
+ (ir_rvalue *)op[0]->clone(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 = generate_temporary(type,
+ instructions, state);
+
+ 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);
+
+ struct ir_rvalue *temp_rhs;
+ temp_rhs = new(ctx) ir_expression(operations[this->oper], type,
+ op[0], op[1]);
+
+ result = do_assignment(instructions, state,
+ (ir_rvalue *)op[0]->clone(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);
+
+ struct 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, (ir_rvalue *)op[0]->clone(NULL));
+
+ (void)do_assignment(instructions, state,
+ (ir_rvalue *)op[0]->clone(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;
+ }
+ }
+
+ 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(state, 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,
+ struct 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 (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;
+ else
+ var->mode = ir_var_auto;
+
+ if (qual->uniform)
+ var->shader_in = true;
+
+ /* Any 'in' or 'inout' variables at global scope must be marked as being
+ * shader inputs. Likewise, any 'out' or 'inout' variables at global scope
+ * must be marked as being shader outputs.
+ */
+ if (state->current_function == NULL) {
+ switch (var->mode) {
+ case ir_var_in:
+ case ir_var_uniform:
+ var->shader_in = true;
+ break;
+ case ir_var_out:
+ var->shader_out = true;
+ break;
+ case ir_var_inout:
+ var->shader_in = true;
+ var->shader_out = true;
+ break;
+ default:
+ break;
+ }
+ }
+
+ if (qual->flat)
+ var->interpolation = ir_var_flat;
+ else if (qual->noperspective)
+ var->interpolation = ir_var_noperspective;
+ else
+ var->interpolation = ir_var_smooth;
+
+ 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 = talloc_parent(state);
+ const struct glsl_type *decl_type;
+ const char *type_name = NULL;
+ ir_rvalue *result = NULL;
+ YYLTYPE loc = this->get_location();
+
+ /* The type specifier may contain a structure definition. Process that
+ * before any of the variable declarations.
+ */
+ (void) this->type->specifier->hir(instructions, state);
+
+ /* FINISHME: Handle vertex shader "invariant" declarations that do not
+ * FINISHME: include a type. These re-declare built-in variables to be
+ * FINISHME: invariant.
+ */
+
+ decl_type = this->type->specifier->glsl_type(& type_name, state);
+ if (this->declarations.is_empty()) {
+ /* There are only two valid cases where the declaration list can be
+ * empty.
+ *
+ * 1. The declaration is setting the default precision of a built-in
+ * type (e.g., 'precision highp vec4;').
+ *
+ * 2. Adding 'invariant' to an existing vertex shader output.
+ */
+
+ if (this->type->qualifier.invariant) {
+ } else 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;
+ struct 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);
+
+ /* 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);
+
+ /* 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.
+ */
+
+ if (var->type->array_size() <= (int)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 {
+ 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);
+ }
+
+ instructions->push_tail(var);
+
+ 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;
+ }
+ }
+ }
+
+ 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(instructions, state);
+
+ /* Calculate the constant value if this is a const or uniform
+ * declaration.
+ */
+ if (this->type->qualifier.constant || this->type->qualifier.uniform) {
+ 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(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");
+ }
+
+ /* Add the vairable 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(decl->identifier, 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 = talloc_parent(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);
+
+ /* 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);
+ if (var->mode == ir_var_auto)
+ var->mode = ir_var_in;
+
+ 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 = talloc_parent(state);
+ ir_function *f = NULL;
+ ir_function_signature *sig = NULL;
+ exec_list hir_parameters;
+
+
+ /* 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);
+
+ /* 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.
+ */
+ const char *const name = identifier;
+ f = state->symbols->get_function(name);
+ if (f != NULL) {
+ ir_function_signature *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;
+
+ /* 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;
+
+ /* 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 = talloc_parent(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);
+
+ /* FINISHME: Make sure the type of the return value matches the return
+ * FINISHME: type of the enclosing function.
+ */
+
+ 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;
+ }
+
+ instructions->push_tail(inst);
+ break;
+ }
+
+ case ast_discard:
+ /* FINISHME: discard support */
+ if (state->target != fragment_shader) {
+ YYLTYPE loc = this->get_location();
+
+ _mesa_glsl_error(& loc, state,
+ "`discard' may only appear in a fragment shader");
+ }
+ 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();
+
+ 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 = talloc_parent(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 = talloc_parent(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 = talloc_parent(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;
+ state->loop_or_switch_nesting = stmt;
+
+ 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;
+
+ /* 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)
+{
+ void *ctx = talloc_parent(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 = (glsl_struct_field *)
+ malloc(sizeof(*fields) * 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;
+ }
+
+ glsl_type *t = new(ctx) glsl_type(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..cb0852bb773
--- /dev/null
+++ b/src/glsl/ast_type.cpp
@@ -0,0 +1,110 @@
+/*
+ * 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"
+#include "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];
+}
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..d248388a1ab
--- /dev/null
+++ b/src/glsl/builtin_function.cpp
@@ -0,0 +1,5080 @@
+/* DO NOT MODIFY - automatically generated by generate_builtins.pl */
+/*
+ * 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"
+#include "ir_reader.h"
+
+void
+read_builtins(_mesa_glsl_parse_state *st, exec_list *instructions,
+ const char **functions, unsigned count)
+{
+ if (st->error)
+ return;
+
+ for (unsigned i = 0; i < count; i++) {
+ _mesa_glsl_read_ir(st, instructions, functions[i]);
+
+ if (st->error) {
+ printf("error reading builtin: %.35s ...\n", functions[i]);
+ return;
+ }
+ }
+}
+
+/* 110 builtins */
+
+static const char *builtins_110_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 *builtins_110_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 *builtins_110_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 *builtins_110_asin = {
+ "((function asin\n"
+ " (signature float\n"
+ " (parameters\n"
+ " (declare (in) float x))\n"
+ " ((return (expression float *\n"
+ " (expression float -\n"
+ " (expression float *\n"
+ " (constant float (3.1415926))\n"
+ " (constant float (0.5)))\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 float -\n"
+ " (expression float *\n"
+ " (constant float (3.1415926))\n"
+ " (constant float (0.5)))\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 -\n"
+ " (expression float *\n"
+ " (constant float (3.1415926))\n"
+ " (constant float (0.5)))\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 -\n"
+ " (expression float *\n"
+ " (constant float (3.1415926))\n"
+ " (constant float (0.5)))\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"
+ "\n"
+ " (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 *builtins_110_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"
+ " ((declare () float r)\n"
+ " (if (expression bool >\n"
+ " (expression float abs (var_ref x))\n"
+ " (constant float (.0001)))\n"
+ " ((assign (constant bool (1))\n"
+ " (var_ref r) (call atan ((expression float /\n"
+ " (var_ref y)\n"
+ " (var_ref x)))))\n"
+ " (if (expression bool <\n"
+ " (var_ref x)\n"
+ " (constant float (0.0)))\n"
+ " ((assign (constant bool (1))\n"
+ " (var_ref r)\n"
+ " (expression float +\n"
+ " (var_ref r)\n"
+ " (expression float *\n"
+ " (expression int sign (var_ref y))\n"
+ " (constant float (3.1415926))))))\n"
+ " ()))\n"
+ " ())\n"
+ " (return (var_ref r))))\n"
+ "\n"
+ " (signature vec2\n"
+ " (parameters\n"
+ " (declare (in) vec2 y)\n"
+ " (declare (in) vec2 x))\n"
+ " ((declare () vec2 r)\n"
+ " (if (expression bool >\n"
+ " (expression vec2 abs (var_ref x))\n"
+ " (constant float (.0001)))\n"
+ " ((assign (constant bool (1))\n"
+ " (var_ref r) (call atan ((expression vec2 /\n"
+ " (var_ref y)\n"
+ " (var_ref x)))))\n"
+ " (if (expression bool <\n"
+ " (var_ref x)\n"
+ " (constant float (0.0)))\n"
+ " ((assign (constant bool (1))\n"
+ " (var_ref r)\n"
+ " (expression vec2 +\n"
+ " (var_ref r)\n"
+ " (expression vec2 *\n"
+ " (expression int sign (var_ref y))\n"
+ " (constant float (3.1415926))))))\n"
+ " ()))\n"
+ " ())\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"
+ " (if (expression bool >\n"
+ " (expression vec3 abs (var_ref x))\n"
+ " (constant float (.0001)))\n"
+ " ((assign (constant bool (1))\n"
+ " (var_ref r) (call atan ((expression vec3 /\n"
+ " (var_ref y)\n"
+ " (var_ref x)))))\n"
+ " (if (expression bool <\n"
+ " (var_ref x)\n"
+ " (constant float (0.0)))\n"
+ " ((assign (constant bool (1))\n"
+ " (var_ref r)\n"
+ " (expression vec3 +\n"
+ " (var_ref r)\n"
+ " (expression vec3 *\n"
+ " (expression int sign (var_ref y))\n"
+ " (constant float (3.1415926))))))\n"
+ " ()))\n"
+ " ())\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"
+ " (if (expression bool >\n"
+ " (expression vec4 abs (var_ref x))\n"
+ " (constant float (.0001)))\n"
+ " ((assign (constant bool (1))\n"
+ " (var_ref r) (call atan ((expression vec4 /\n"
+ " (var_ref y)\n"
+ " (var_ref x)))))\n"
+ " (if (expression bool <\n"
+ " (var_ref x)\n"
+ " (constant float (0.0)))\n"
+ " ((assign (constant bool (1))\n"
+ " (var_ref r)\n"
+ " (expression vec4 +\n"
+ " (var_ref r)\n"
+ " (expression vec4 *\n"
+ " (expression int sign (var_ref y))\n"
+ " (constant float (3.1415926))))))\n"
+ " ()))\n"
+ " ())\n"
+ " (return (var_ref r))))\n"
+ "\n"
+ "))\n"
+};
+
+static const char *builtins_110_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 *builtins_110_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"
+ " ((declare () vec2 result)\n"
+ " (assign (constant bool (1)) (swiz x (var_ref result)) (expression vec4 max (expression vec4 min (swiz x (var_ref arg0)) (var_ref arg2)) (var_ref arg1)))\n"
+ " (assign (constant bool (1)) (swiz y (var_ref result)) (expression vec4 max (expression vec4 min (swiz y (var_ref arg0)) (var_ref arg2)) (var_ref arg1)))\n"
+ " (return (var_ref result))))\n"
+ "\n"
+ " (signature vec3\n"
+ " (parameters\n"
+ " (declare (in) vec3 arg0)\n"
+ " (declare (in) float arg1)\n"
+ " (declare (in) float arg2))\n"
+ " ((declare () vec3 result)\n"
+ " (assign (constant bool (1)) (swiz x (var_ref result)) (expression vec4 max (expression vec4 min (swiz x (var_ref arg0)) (var_ref arg2)) (var_ref arg1)))\n"
+ " (assign (constant bool (1)) (swiz y (var_ref result)) (expression vec4 max (expression vec4 min (swiz y (var_ref arg0)) (var_ref arg2)) (var_ref arg1)))\n"
+ " (assign (constant bool (1)) (swiz z (var_ref result)) (expression vec4 max (expression vec4 min (swiz z (var_ref arg0)) (var_ref arg2)) (var_ref arg1)))\n"
+ " (return (var_ref result))))\n"
+ "\n"
+ " (signature vec4\n"
+ " (parameters\n"
+ " (declare (in) vec4 arg0)\n"
+ " (declare (in) float arg1)\n"
+ " (declare (in) float arg2))\n"
+ " ((declare () vec4 result)\n"
+ " (assign (constant bool (1)) (swiz x (var_ref result)) (expression vec4 max (expression vec4 min (swiz x (var_ref arg0)) (var_ref arg2)) (var_ref arg1)))\n"
+ " (assign (constant bool (1)) (swiz y (var_ref result)) (expression vec4 max (expression vec4 min (swiz y (var_ref arg0)) (var_ref arg2)) (var_ref arg1)))\n"
+ " (assign (constant bool (1)) (swiz z (var_ref result)) (expression vec4 max (expression vec4 min (swiz z (var_ref arg0)) (var_ref arg2)) (var_ref arg1)))\n"
+ " (assign (constant bool (1)) (swiz w (var_ref result)) (expression vec4 max (expression vec4 min (swiz w (var_ref arg0)) (var_ref arg2)) (var_ref arg1)))\n"
+ " (return (var_ref result))))\n"
+ "))\n"
+};
+
+static const char *builtins_110_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 *builtins_110_cross = {
+ "((function cross\n"
+ " (signature vec3\n"
+ " (parameters\n"
+ " (declare (in) vec3 arg0)\n"
+ " (declare (in) vec3 arg1))\n"
+ " ((declare () vec3 t)\n"
+ " (assign (constant bool (1)) (swiz x (var_ref t))\n"
+ " (expression float - (expression float * (swiz y (var_ref arg0)) (swiz z (var_ref arg1)))\n"
+ " (expression float * (swiz y (var_ref arg1)) (swiz z (var_ref arg0)))))\n"
+ " (assign (constant bool (1)) (swiz y (var_ref t))\n"
+ " (expression float - (expression float * (swiz z (var_ref arg0)) (swiz x (var_ref arg1)))\n"
+ " (expression float * (swiz z (var_ref arg1)) (swiz x (var_ref arg0)))))\n"
+ " (assign (constant bool (1)) (swiz z (var_ref t))\n"
+ " (expression float - (expression float * (swiz x (var_ref arg0)) (swiz y (var_ref arg1)))\n"
+ " (expression float * (swiz x (var_ref arg1)) (swiz y (var_ref arg0)))))\n"
+ " (return (var_ref t))))\n"
+ "))\n"
+};
+
+static const char *builtins_110_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 *builtins_110_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 *builtins_110_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 *builtins_110_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"
+};
+
+static const char *builtins_110_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 *builtins_110_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 *builtins_110_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 *builtins_110_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 *builtins_110_fract = {
+ "((function fract\n"
+ " (signature float\n"
+ " (parameters\n"
+ " (declare (in) float x))\n"
+ " ((return (expression float - (var_ref x) (expression float floor (var_ref x))))))\n"
+ "\n"
+ " (signature vec2\n"
+ " (parameters\n"
+ " (declare (in) vec2 x))\n"
+ " ((declare () vec2 t)\n"
+ " (assign (constant bool (1)) (swiz x (var_ref t)) (expression float - (swiz x (var_ref x)) (expression float floor (swiz x (var_ref x)))))\n"
+ " (assign (constant bool (1)) (swiz y (var_ref t)) (expression float - (swiz y (var_ref x)) (expression float floor (swiz y (var_ref x)))))\n"
+ " (return (var_ref t))))\n"
+ "\n"
+ " (signature vec3\n"
+ " (parameters\n"
+ " (declare (in) vec3 x))\n"
+ " ((declare () vec3 t)\n"
+ " (assign (constant bool (1)) (swiz x (var_ref t)) (expression float - (swiz x (var_ref x)) (expression float floor (swiz x (var_ref x)))))\n"
+ " (assign (constant bool (1)) (swiz y (var_ref t)) (expression float - (swiz y (var_ref x)) (expression float floor (swiz y (var_ref x)))))\n"
+ " (assign (constant bool (1)) (swiz z (var_ref t)) (expression float - (swiz z (var_ref x)) (expression float floor (swiz z (var_ref x)))))\n"
+ " (return (var_ref t))))\n"
+ "\n"
+ " (signature vec4\n"
+ " (parameters\n"
+ " (declare (in) vec4 x))\n"
+ " ((declare () vec4 t)\n"
+ " (assign (constant bool (1)) (swiz x (var_ref t)) (expression float - (swiz x (var_ref x)) (expression float floor (swiz x (var_ref x)))))\n"
+ " (assign (constant bool (1)) (swiz y (var_ref t)) (expression float - (swiz y (var_ref x)) (expression float floor (swiz y (var_ref x)))))\n"
+ " (assign (constant bool (1)) (swiz z (var_ref t)) (expression float - (swiz z (var_ref x)) (expression float floor (swiz z (var_ref x)))))\n"
+ " (assign (constant bool (1)) (swiz w (var_ref t)) (expression float - (swiz w (var_ref x)) (expression float floor (swiz w (var_ref x)))))\n"
+ " (return (var_ref t))))\n"
+ "))\n"
+ "\n"
+};
+
+static const char *builtins_110_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"
+};
+
+static const char *builtins_110_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"
+};
+
+static const char *builtins_110_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 *builtins_110_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 *builtins_110_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"
+};
+
+static const char *builtins_110_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"
+};
+
+static const char *builtins_110_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 *builtins_110_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 *builtins_110_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"
+ "\n"
+};
+
+static const char *builtins_110_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"
+ " ((declare () vec2 result)\n"
+ " (assign (constant bool (1)) (swiz x (var_ref result))\n"
+ " (expression float max (swiz x (var_ref arg0)) (var_ref arg1)))\n"
+ " (assign (constant bool (1)) (swiz y (var_ref result))\n"
+ " (expression float max (swiz y (var_ref arg0)) (var_ref arg1)))\n"
+ " (return (var_ref result))))\n"
+ "\n"
+ " (signature vec3\n"
+ " (parameters\n"
+ " (declare (in) vec3 arg0)\n"
+ " (declare (in) float arg1))\n"
+ " ((declare () vec3 result)\n"
+ " (assign (constant bool (1)) (swiz x (var_ref result))\n"
+ " (expression float max (swiz x (var_ref arg0)) (var_ref arg1)))\n"
+ " (assign (constant bool (1)) (swiz y (var_ref result))\n"
+ " (expression float max (swiz y (var_ref arg0)) (var_ref arg1)))\n"
+ " (assign (constant bool (1)) (swiz z (var_ref result))\n"
+ " (expression float max (swiz z (var_ref arg0)) (var_ref arg1)))\n"
+ " (return (var_ref result))))\n"
+ "\n"
+ " (signature vec4\n"
+ " (parameters\n"
+ " (declare (in) vec4 arg0)\n"
+ " (declare (in) float arg1))\n"
+ " ((declare () vec4 result)\n"
+ " (assign (constant bool (1)) (swiz x (var_ref result))\n"
+ " (expression float max (swiz x (var_ref arg0)) (var_ref arg1)))\n"
+ " (assign (constant bool (1)) (swiz y (var_ref result))\n"
+ " (expression float max (swiz y (var_ref arg0)) (var_ref arg1)))\n"
+ " (assign (constant bool (1)) (swiz z (var_ref result))\n"
+ " (expression float max (swiz z (var_ref arg0)) (var_ref arg1)))\n"
+ " (assign (constant bool (1)) (swiz w (var_ref result))\n"
+ " (expression float max (swiz w (var_ref arg0)) (var_ref arg1)))\n"
+ " (return (var_ref result))))\n"
+ "))\n"
+};
+
+static const char *builtins_110_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"
+ " ((declare () vec2 result)\n"
+ " (assign (constant bool (1)) (swiz x (var_ref result))\n"
+ " (expression float min (swiz x (var_ref arg0)) (var_ref arg1)))\n"
+ " (assign (constant bool (1)) (swiz y (var_ref result))\n"
+ " (expression float min (swiz y (var_ref arg0)) (var_ref arg1)))\n"
+ " (return (var_ref result))))\n"
+ "\n"
+ " (signature vec3\n"
+ " (parameters\n"
+ " (declare (in) vec3 arg0)\n"
+ " (declare (in) float arg1))\n"
+ " ((declare () vec3 result)\n"
+ " (assign (constant bool (1)) (swiz x (var_ref result))\n"
+ " (expression float min (swiz x (var_ref arg0)) (var_ref arg1)))\n"
+ " (assign (constant bool (1)) (swiz y (var_ref result))\n"
+ " (expression float min (swiz y (var_ref arg0)) (var_ref arg1)))\n"
+ " (assign (constant bool (1)) (swiz z (var_ref result))\n"
+ " (expression float min (swiz z (var_ref arg0)) (var_ref arg1)))\n"
+ " (return (var_ref result))))\n"
+ "\n"
+ " (signature vec4\n"
+ " (parameters\n"
+ " (declare (in) vec4 arg0)\n"
+ " (declare (in) float arg1))\n"
+ " ((declare () vec4 result)\n"
+ " (assign (constant bool (1)) (swiz x (var_ref result))\n"
+ " (expression float min (swiz x (var_ref arg0)) (var_ref arg1)))\n"
+ " (assign (constant bool (1)) (swiz y (var_ref result))\n"
+ " (expression float min (swiz y (var_ref arg0)) (var_ref arg1)))\n"
+ " (assign (constant bool (1)) (swiz z (var_ref result))\n"
+ " (expression float min (swiz z (var_ref arg0)) (var_ref arg1)))\n"
+ " (assign (constant bool (1)) (swiz w (var_ref result))\n"
+ " (expression float min (swiz w (var_ref arg0)) (var_ref arg1)))\n"
+ " (return (var_ref result))))\n"
+ "))\n"
+};
+
+static const char *builtins_110_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 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) float 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) float 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"
+};
+
+static const char *builtins_110_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"
+ " ((declare () vec2 result)\n"
+ " (assign (constant bool (1)) (swiz x (var_ref result))\n"
+ " (expression float % (swiz x (var_ref arg0)) (var_ref arg1)))\n"
+ " (assign (constant bool (1)) (swiz y (var_ref result))\n"
+ " (expression float % (swiz y (var_ref arg0)) (var_ref arg1)))\n"
+ " (return (var_ref result))))\n"
+ "\n"
+ " (signature vec3\n"
+ " (parameters\n"
+ " (declare (in) vec3 arg0)\n"
+ " (declare (in) float arg1))\n"
+ " ((declare () vec3 result)\n"
+ " (assign (constant bool (1)) (swiz x (var_ref result))\n"
+ " (expression float % (swiz x (var_ref arg0)) (var_ref arg1)))\n"
+ " (assign (constant bool (1)) (swiz y (var_ref result))\n"
+ " (expression float % (swiz y (var_ref arg0)) (var_ref arg1)))\n"
+ " (assign (constant bool (1)) (swiz z (var_ref result))\n"
+ " (expression float % (swiz z (var_ref arg0)) (var_ref arg1)))\n"
+ " (return (var_ref result))))\n"
+ "\n"
+ " (signature vec4\n"
+ " (parameters\n"
+ " (declare (in) vec4 arg0)\n"
+ " (declare (in) float arg1))\n"
+ " ((declare () vec4 result)\n"
+ " (assign (constant bool (1)) (swiz x (var_ref result))\n"
+ " (expression float % (swiz x (var_ref arg0)) (var_ref arg1)))\n"
+ " (assign (constant bool (1)) (swiz y (var_ref result))\n"
+ " (expression float % (swiz y (var_ref arg0)) (var_ref arg1)))\n"
+ " (assign (constant bool (1)) (swiz z (var_ref result))\n"
+ " (expression float % (swiz z (var_ref arg0)) (var_ref arg1)))\n"
+ " (assign (constant bool (1)) (swiz w (var_ref result))\n"
+ " (expression float % (swiz w (var_ref arg0)) (var_ref arg1)))\n"
+ " (return (var_ref result))))\n"
+ "))\n"
+};
+
+static const char *builtins_110_noise_fake = {
+ "((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"
+ "\n"
+ " (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"
+ "\n"
+ " (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"
+ "\n"
+ " (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"
+ ")\n"
+};
+
+static const char *builtins_110_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 *builtins_110_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 *builtins_110_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 float != (swiz x (var_ref arg0))(swiz x (var_ref arg1)))) \n"
+ " (assign (constant bool (1)) (swiz y (var_ref temp)) (expression float != (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 float != (swiz x (var_ref arg0))(swiz x (var_ref arg1)))) \n"
+ " (assign (constant bool (1)) (swiz y (var_ref temp)) (expression float != (swiz y (var_ref arg0))(swiz y (var_ref arg1)))) \n"
+ " (assign (constant bool (1)) (swiz z (var_ref temp)) (expression float != (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 float != (swiz x (var_ref arg0))(swiz x (var_ref arg1)))) \n"
+ " (assign (constant bool (1)) (swiz y (var_ref temp)) (expression float != (swiz y (var_ref arg0))(swiz y (var_ref arg1)))) \n"
+ " (assign (constant bool (1)) (swiz z (var_ref temp)) (expression float != (swiz z (var_ref arg0))(swiz z (var_ref arg1)))) \n"
+ " (assign (constant bool (1)) (swiz w (var_ref temp)) (expression float != (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 int != (swiz x (var_ref arg0))(swiz x (var_ref arg1)))) \n"
+ " (assign (constant bool (1)) (swiz y (var_ref temp)) (expression int != (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 int != (swiz x (var_ref arg0))(swiz x (var_ref arg1)))) \n"
+ " (assign (constant bool (1)) (swiz y (var_ref temp)) (expression int != (swiz y (var_ref arg0))(swiz y (var_ref arg1)))) \n"
+ " (assign (constant bool (1)) (swiz z (var_ref temp)) (expression int != (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 int != (swiz x (var_ref arg0))(swiz x (var_ref arg1)))) \n"
+ " (assign (constant bool (1)) (swiz y (var_ref temp)) (expression int != (swiz y (var_ref arg0))(swiz y (var_ref arg1)))) \n"
+ " (assign (constant bool (1)) (swiz z (var_ref temp)) (expression int != (swiz z (var_ref arg0))(swiz z (var_ref arg1)))) \n"
+ " (assign (constant bool (1)) (swiz w (var_ref temp)) (expression int != (swiz w (var_ref arg0))(swiz w (var_ref arg1)))) \n"
+ " (return (var_ref temp))))\n"
+ "))\n"
+};
+
+static const char *builtins_110_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 *builtins_110_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 *builtins_110_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 *builtins_110_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))))\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))))\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 *builtins_110_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"
+ " ((declare () vec2 t)\n"
+ " (assign (constant bool (1)) (swiz x (var_ref t)) (expression float sign (swiz x (var_ref x))))\n"
+ " (assign (constant bool (1)) (swiz y (var_ref t)) (expression float sign (swiz y (var_ref x))))\n"
+ " (return (var_ref t))))\n"
+ "\n"
+ " (signature vec3\n"
+ " (parameters\n"
+ " (declare (in) vec3 x))\n"
+ " ((declare () vec3 t)\n"
+ " (assign (constant bool (1)) (swiz x (var_ref t)) (expression float sign (swiz x (var_ref x))))\n"
+ " (assign (constant bool (1)) (swiz y (var_ref t)) (expression float sign (swiz y (var_ref x))))\n"
+ " (assign (constant bool (1)) (swiz z (var_ref t)) (expression float sign (swiz z (var_ref x))))\n"
+ " (return (var_ref t))))\n"
+ "\n"
+ " (signature vec4\n"
+ " (parameters\n"
+ " (declare (in) vec4 x))\n"
+ " ((declare () vec4 t)\n"
+ " (assign (constant bool (1)) (swiz x (var_ref t)) (expression float sign (swiz x (var_ref x))))\n"
+ " (assign (constant bool (1)) (swiz y (var_ref t)) (expression float sign (swiz y (var_ref x))))\n"
+ " (assign (constant bool (1)) (swiz z (var_ref t)) (expression float sign (swiz z (var_ref x))))\n"
+ " (assign (constant bool (1)) (swiz w (var_ref t)) (expression float sign (swiz w (var_ref x))))\n"
+ " (return (var_ref t))))\n"
+ "))\n"
+ "\n"
+};
+
+static const char *builtins_110_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 *builtins_110_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"
+ " ((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)) (swiz x (var_ref edge0))) (expression float - (swiz x (var_ref edge1)) (swiz x (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)) (swiz y (var_ref edge0))) (expression float - (swiz y (var_ref edge1)) (swiz y (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) vec3 edge0)\n"
+ " (declare (in) vec3 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)) (swiz x (var_ref edge0))) (expression float - (swiz x (var_ref edge1)) (swiz x (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)) (swiz y (var_ref edge0))) (expression float - (swiz y (var_ref edge1)) (swiz y (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)) (swiz z (var_ref edge0))) (expression float - (swiz z (var_ref edge1)) (swiz z (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) vec4 edge0)\n"
+ " (declare (in) vec4 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)) (swiz x (var_ref edge0))) (expression float - (swiz x (var_ref edge1)) (swiz x (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)) (swiz y (var_ref edge0))) (expression float - (swiz y (var_ref edge1)) (swiz y (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)) (swiz z (var_ref edge0))) (expression float - (swiz z (var_ref edge1)) (swiz z (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)) (swiz w (var_ref edge0))) (expression float - (swiz w (var_ref edge1)) (swiz w (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"
+ "))\n"
+ "\n"
+};
+
+static const char *builtins_110_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 *builtins_110_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 *builtins_110_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 float / (expression float sin (var_ref angle)) (expression vec2 cos (var_ref angle))))))\n"
+ "\n"
+ " (signature vec3\n"
+ " (parameters\n"
+ " (declare (in) vec3 angle))\n"
+ " ((return (expression float / (expression float sin (var_ref angle)) (expression vec3 cos (var_ref angle))))))\n"
+ "\n"
+ " (signature vec4\n"
+ " (parameters\n"
+ " (declare (in) vec4 angle))\n"
+ " ((return (expression float / (expression float sin (var_ref angle)) (expression vec4 cos (var_ref angle))))))\n"
+ "))\n"
+};
+
+static const char *builtins_110_textures = {
+ "((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"
+ ")\n"
+ " (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"
+ " (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"
+ ")\n"
+ " (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"
+ " (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"
+ ")\n"
+ "(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"
+ " (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"
+ ")\n"
+ " (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"
+ " (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"
+ ")\n"
+ " (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"
+ " (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"
+ ")\n"
+ " (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"
+ " (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"
+ ")\n"
+ " (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"
+ " (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"
+ ")\n"
+ " (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"
+ " (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"
+ ")\n"
+ " (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"
+ " (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"
+ ")\n"
+ " (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"
+ " (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"
+ ")\n"
+ " (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 *functions_for_110 [] = {
+ builtins_110_abs,
+ builtins_110_all,
+ builtins_110_any,
+ builtins_110_asin,
+ builtins_110_atan,
+ builtins_110_ceil,
+ builtins_110_clamp,
+ builtins_110_cos,
+ builtins_110_cross,
+ builtins_110_degrees,
+ builtins_110_distance,
+ builtins_110_dot,
+ builtins_110_equal,
+ builtins_110_exp,
+ builtins_110_exp2,
+ builtins_110_faceforward,
+ builtins_110_floor,
+ builtins_110_fract,
+ builtins_110_greaterThan,
+ builtins_110_greaterThanEqual,
+ builtins_110_inversesqrt,
+ builtins_110_length,
+ builtins_110_lessThan,
+ builtins_110_lessThanEqual,
+ builtins_110_log,
+ builtins_110_log2,
+ builtins_110_matrixCompMult,
+ builtins_110_max,
+ builtins_110_min,
+ builtins_110_mix,
+ builtins_110_mod,
+ builtins_110_noise_fake,
+ builtins_110_normalize,
+ builtins_110_not,
+ builtins_110_notEqual,
+ builtins_110_pow,
+ builtins_110_radians,
+ builtins_110_reflect,
+ builtins_110_refract,
+ builtins_110_sign,
+ builtins_110_sin,
+ builtins_110_smoothstep,
+ builtins_110_sqrt,
+ builtins_110_step,
+ builtins_110_tan,
+ builtins_110_textures,
+};
+
+/* 110_fs builtins */
+
+static const char *builtins_110_fs_derivatives = {
+ "((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"
+ "\n"
+ " (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"
+ "\n"
+ " (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 *builtins_110_fs_textures = {
+ "((function texture1D\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"
+ " (function texture1DProj\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"
+ " (function texture2D\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"
+ " (function texture2DProj\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"
+ " (function texture3D\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"
+ " (function texture3DProj\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"
+ " (function textureCube\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"
+ " (function shadow1D\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"
+ " (function shadow1DProj\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"
+ " (function shadow2D\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"
+ " (function shadow2DProj\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 *functions_for_110_fs [] = {
+ builtins_110_fs_derivatives,
+ builtins_110_fs_textures,
+};
+
+/* 110_vs builtins */
+
+static const char *builtins_110_vs_ftransform = {
+ "((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 *functions_for_110_vs [] = {
+ builtins_110_vs_ftransform,
+};
+
+/* 120 builtins */
+
+static const char *builtins_120_matrixCompMult = {
+ "((function matrixCompMult\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 *builtins_120_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 v) (swiz x (var_ref u)))) \n"
+ " (assign (constant bool (1)) (array_ref (var_ref m) (constant int (1))) (expression vec2 * (var_ref v) (swiz y (var_ref u)))) \n"
+ "(return (var_ref m))))\n"
+ "\n"
+ " (signature mat2x3\n"
+ " (parameters\n"
+ " (declare (in) vec2 u)\n"
+ " (declare (in) vec3 v))\n"
+ " ((declare () mat2x3 m)\n"
+ " (assign (constant bool (1)) (array_ref (var_ref m) (constant int (0))) (expression vec3 * (var_ref v) (swiz x (var_ref u)))) \n"
+ " (assign (constant bool (1)) (array_ref (var_ref m) (constant int (1))) (expression vec3 * (var_ref v) (swiz y (var_ref u)))) \n"
+ "(return (var_ref m))))\n"
+ "\n"
+ " (signature mat2x4\n"
+ " (parameters\n"
+ " (declare (in) vec2 u)\n"
+ " (declare (in) vec4 v))\n"
+ " ((declare () mat2x4 m)\n"
+ " (assign (constant bool (1)) (array_ref (var_ref m) (constant int (0))) (expression vec4 * (var_ref v) (swiz x (var_ref u)))) \n"
+ " (assign (constant bool (1)) (array_ref (var_ref m) (constant int (1))) (expression vec4 * (var_ref v) (swiz y (var_ref u)))) \n"
+ "(return (var_ref m))))\n"
+ "\n"
+ " (signature mat3x2\n"
+ " (parameters\n"
+ " (declare (in) vec3 u)\n"
+ " (declare (in) vec2 v))\n"
+ " ((declare () mat3x2 m)\n"
+ " (assign (constant bool (1)) (array_ref (var_ref m) (constant int (0))) (expression vec2 * (var_ref v) (swiz x (var_ref u)))) \n"
+ " (assign (constant bool (1)) (array_ref (var_ref m) (constant int (1))) (expression vec2 * (var_ref v) (swiz y (var_ref u)))) \n"
+ " (assign (constant bool (1)) (array_ref (var_ref m) (constant int (2))) (expression vec2 * (var_ref v) (swiz z (var_ref u)))) \n"
+ "(return (var_ref m))))\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 v) (swiz x (var_ref u)))) \n"
+ " (assign (constant bool (1)) (array_ref (var_ref m) (constant int (1))) (expression vec3 * (var_ref v) (swiz y (var_ref u)))) \n"
+ " (assign (constant bool (1)) (array_ref (var_ref m) (constant int (2))) (expression vec3 * (var_ref v) (swiz z (var_ref u)))) \n"
+ "(return (var_ref m))))\n"
+ "\n"
+ " (signature mat3x4\n"
+ " (parameters\n"
+ " (declare (in) vec3 u)\n"
+ " (declare (in) vec4 v))\n"
+ " ((declare () mat3x4 m)\n"
+ " (assign (constant bool (1)) (array_ref (var_ref m) (constant int (0))) (expression vec4 * (var_ref v) (swiz x (var_ref u)))) \n"
+ " (assign (constant bool (1)) (array_ref (var_ref m) (constant int (1))) (expression vec4 * (var_ref v) (swiz y (var_ref u)))) \n"
+ " (assign (constant bool (1)) (array_ref (var_ref m) (constant int (2))) (expression vec4 * (var_ref v) (swiz z (var_ref u)))) \n"
+ "(return (var_ref m))))\n"
+ "\n"
+ " (signature mat4x2\n"
+ " (parameters\n"
+ " (declare (in) vec4 u)\n"
+ " (declare (in) vec2 v))\n"
+ " ((declare () mat4x2 m)\n"
+ " (assign (constant bool (1)) (array_ref (var_ref m) (constant int (0))) (expression vec2 * (var_ref v) (swiz x (var_ref u)))) \n"
+ " (assign (constant bool (1)) (array_ref (var_ref m) (constant int (1))) (expression vec2 * (var_ref v) (swiz y (var_ref u)))) \n"
+ " (assign (constant bool (1)) (array_ref (var_ref m) (constant int (2))) (expression vec2 * (var_ref v) (swiz z (var_ref u)))) \n"
+ " (assign (constant bool (1)) (array_ref (var_ref m) (constant int (3))) (expression vec2 * (var_ref v) (swiz w (var_ref u)))) \n"
+ "(return (var_ref m))))\n"
+ "\n"
+ " (signature mat4x3\n"
+ " (parameters\n"
+ " (declare (in) vec4 u)\n"
+ " (declare (in) vec3 v))\n"
+ " ((declare () mat4x3 m)\n"
+ " (assign (constant bool (1)) (array_ref (var_ref m) (constant int (0))) (expression vec3 * (var_ref v) (swiz x (var_ref u)))) \n"
+ " (assign (constant bool (1)) (array_ref (var_ref m) (constant int (1))) (expression vec3 * (var_ref v) (swiz y (var_ref u)))) \n"
+ " (assign (constant bool (1)) (array_ref (var_ref m) (constant int (2))) (expression vec3 * (var_ref v) (swiz z (var_ref u)))) \n"
+ " (assign (constant bool (1)) (array_ref (var_ref m) (constant int (3))) (expression vec3 * (var_ref v) (swiz w (var_ref u)))) \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 v) (swiz x (var_ref u)))) \n"
+ " (assign (constant bool (1)) (array_ref (var_ref m) (constant int (1))) (expression vec4 * (var_ref v) (swiz y (var_ref u)))) \n"
+ " (assign (constant bool (1)) (array_ref (var_ref m) (constant int (2))) (expression vec4 * (var_ref v) (swiz z (var_ref u)))) \n"
+ " (assign (constant bool (1)) (array_ref (var_ref m) (constant int (3))) (expression vec4 * (var_ref v) (swiz w (var_ref u)))) \n"
+ "(return (var_ref m))))\n"
+ "))\n"
+ "\n"
+};
+
+static const char *builtins_120_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 *functions_for_120 [] = {
+ builtins_120_matrixCompMult,
+ builtins_120_outerProduct,
+ builtins_120_transpose,
+};
+
+/* 130 builtins */
+
+static const char *builtins_130_clamp = {
+ "((function clamp\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"
+ " ((declare () ivec2 result)\n"
+ " (assign (constant bool (1)) (swiz x (var_ref result)) (expression ivec4 max (expression ivec4 min (swiz x (var_ref arg0)) (var_ref arg2)) (var_ref arg1)))\n"
+ " (assign (constant bool (1)) (swiz y (var_ref result)) (expression ivec4 max (expression ivec4 min (swiz y (var_ref arg0)) (var_ref arg2)) (var_ref arg1)))\n"
+ " (return (var_ref result))))\n"
+ "\n"
+ " (signature ivec3\n"
+ " (parameters\n"
+ " (declare (in) ivec3 arg0)\n"
+ " (declare (in) int arg1)\n"
+ " (declare (in) int arg2))\n"
+ " ((declare () ivec3 result)\n"
+ " (assign (constant bool (1)) (swiz x (var_ref result)) (expression ivec4 max (expression ivec4 min (swiz x (var_ref arg0)) (var_ref arg2)) (var_ref arg1)))\n"
+ " (assign (constant bool (1)) (swiz y (var_ref result)) (expression ivec4 max (expression ivec4 min (swiz y (var_ref arg0)) (var_ref arg2)) (var_ref arg1)))\n"
+ " (assign (constant bool (1)) (swiz z (var_ref result)) (expression ivec4 max (expression ivec4 min (swiz z (var_ref arg0)) (var_ref arg2)) (var_ref arg1)))\n"
+ " (return (var_ref result))))\n"
+ "\n"
+ " (signature ivec4\n"
+ " (parameters\n"
+ " (declare (in) ivec4 arg0)\n"
+ " (declare (in) int arg1)\n"
+ " (declare (in) int arg2))\n"
+ " ((declare () ivec4 result)\n"
+ " (assign (constant bool (1)) (swiz x (var_ref result)) (expression ivec4 max (expression ivec4 min (swiz x (var_ref arg0)) (var_ref arg2)) (var_ref arg1)))\n"
+ " (assign (constant bool (1)) (swiz y (var_ref result)) (expression ivec4 max (expression ivec4 min (swiz y (var_ref arg0)) (var_ref arg2)) (var_ref arg1)))\n"
+ " (assign (constant bool (1)) (swiz z (var_ref result)) (expression ivec4 max (expression ivec4 min (swiz z (var_ref arg0)) (var_ref arg2)) (var_ref arg1)))\n"
+ " (assign (constant bool (1)) (swiz w (var_ref result)) (expression ivec4 max (expression ivec4 min (swiz w (var_ref arg0)) (var_ref arg2)) (var_ref arg1)))\n"
+ " (return (var_ref result))))\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"
+ " ((declare () uvec2 result)\n"
+ " (assign (constant bool (1)) (swiz x (var_ref result)) (expression uvec4 max (expression uvec4 min (swiz x (var_ref arg0)) (var_ref arg2)) (var_ref arg1)))\n"
+ " (assign (constant bool (1)) (swiz y (var_ref result)) (expression uvec4 max (expression uvec4 min (swiz y (var_ref arg0)) (var_ref arg2)) (var_ref arg1)))\n"
+ " (return (var_ref result))))\n"
+ "\n"
+ " (signature uvec3\n"
+ " (parameters\n"
+ " (declare (in) uvec3 arg0)\n"
+ " (declare (in) uint arg1)\n"
+ " (declare (in) uint arg2))\n"
+ " ((declare () uvec3 result)\n"
+ " (assign (constant bool (1)) (swiz x (var_ref result)) (expression uvec4 max (expression uvec4 min (swiz x (var_ref arg0)) (var_ref arg2)) (var_ref arg1)))\n"
+ " (assign (constant bool (1)) (swiz y (var_ref result)) (expression uvec4 max (expression uvec4 min (swiz y (var_ref arg0)) (var_ref arg2)) (var_ref arg1)))\n"
+ " (assign (constant bool (1)) (swiz z (var_ref result)) (expression uvec4 max (expression uvec4 min (swiz z (var_ref arg0)) (var_ref arg2)) (var_ref arg1)))\n"
+ " (return (var_ref result))))\n"
+ "\n"
+ " (signature uvec4\n"
+ " (parameters\n"
+ " (declare (in) uvec4 arg0)\n"
+ " (declare (in) uint arg1)\n"
+ " (declare (in) uint arg2))\n"
+ " ((declare () uvec4 result)\n"
+ " (assign (constant bool (1)) (swiz x (var_ref result)) (expression uvec4 max (expression uvec4 min (swiz x (var_ref arg0)) (var_ref arg2)) (var_ref arg1)))\n"
+ " (assign (constant bool (1)) (swiz y (var_ref result)) (expression uvec4 max (expression uvec4 min (swiz y (var_ref arg0)) (var_ref arg2)) (var_ref arg1)))\n"
+ " (assign (constant bool (1)) (swiz z (var_ref result)) (expression uvec4 max (expression uvec4 min (swiz z (var_ref arg0)) (var_ref arg2)) (var_ref arg1)))\n"
+ " (assign (constant bool (1)) (swiz w (var_ref result)) (expression uvec4 max (expression uvec4 min (swiz w (var_ref arg0)) (var_ref arg2)) (var_ref arg1)))\n"
+ " (return (var_ref result))))\n"
+ "))\n"
+};
+
+static const char *builtins_130_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 *builtins_130_equal = {
+ "((function equal\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 *builtins_130_greaterThan = {
+ "((function greaterThan\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 *builtins_130_greaterThanEqual = {
+ "((function greaterThanEqual\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 *builtins_130_lessThan = {
+ "((function lessThan\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 *builtins_130_lessThanEqual = {
+ "((function lessThanEqual\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 *builtins_130_max = {
+ "((function max\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"
+ " ((declare () ivec2 result)\n"
+ " (assign (constant bool (1)) (swiz x (var_ref result))\n"
+ " (expression int max (swiz x (var_ref arg0)) (var_ref arg1)))\n"
+ " (assign (constant bool (1)) (swiz y (var_ref result))\n"
+ " (expression int max (swiz y (var_ref arg0)) (var_ref arg1)))\n"
+ " (return (var_ref result))))\n"
+ "\n"
+ " (signature ivec3\n"
+ " (parameters\n"
+ " (declare (in) ivec3 arg0)\n"
+ " (declare (in) int arg1))\n"
+ " ((declare () ivec3 result)\n"
+ " (assign (constant bool (1)) (swiz x (var_ref result))\n"
+ " (expression int max (swiz x (var_ref arg0)) (var_ref arg1)))\n"
+ " (assign (constant bool (1)) (swiz y (var_ref result))\n"
+ " (expression int max (swiz y (var_ref arg0)) (var_ref arg1)))\n"
+ " (assign (constant bool (1)) (swiz z (var_ref result))\n"
+ " (expression int max (swiz z (var_ref arg0)) (var_ref arg1)))\n"
+ " (return (var_ref result))))\n"
+ "\n"
+ " (signature ivec4\n"
+ " (parameters\n"
+ " (declare (in) ivec4 arg0)\n"
+ " (declare (in) int arg1))\n"
+ " ((declare () ivec4 result)\n"
+ " (assign (constant bool (1)) (swiz x (var_ref result))\n"
+ " (expression int max (swiz x (var_ref arg0)) (var_ref arg1)))\n"
+ " (assign (constant bool (1)) (swiz y (var_ref result))\n"
+ " (expression int max (swiz y (var_ref arg0)) (var_ref arg1)))\n"
+ " (assign (constant bool (1)) (swiz z (var_ref result))\n"
+ " (expression int max (swiz z (var_ref arg0)) (var_ref arg1)))\n"
+ " (assign (constant bool (1)) (swiz w (var_ref result))\n"
+ " (expression int max (swiz w (var_ref arg0)) (var_ref arg1)))\n"
+ " (return (var_ref result))))\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"
+ " ((declare () uvec2 result)\n"
+ " (assign (constant bool (1)) (swiz x (var_ref result))\n"
+ " (expression uint max (swiz x (var_ref arg0)) (var_ref arg1)))\n"
+ " (assign (constant bool (1)) (swiz y (var_ref result))\n"
+ " (expression uint max (swiz y (var_ref arg0)) (var_ref arg1)))\n"
+ " (return (var_ref result))))\n"
+ "\n"
+ " (signature uvec3\n"
+ " (parameters\n"
+ " (declare (in) uvec3 arg0)\n"
+ " (declare (in) uint arg1))\n"
+ " ((declare () uvec3 result)\n"
+ " (assign (constant bool (1)) (swiz x (var_ref result))\n"
+ " (expression uint max (swiz x (var_ref arg0)) (var_ref arg1)))\n"
+ " (assign (constant bool (1)) (swiz y (var_ref result))\n"
+ " (expression uint max (swiz y (var_ref arg0)) (var_ref arg1)))\n"
+ " (assign (constant bool (1)) (swiz z (var_ref result))\n"
+ " (expression uint max (swiz z (var_ref arg0)) (var_ref arg1)))\n"
+ " (return (var_ref result))))\n"
+ "\n"
+ " (signature uvec4\n"
+ " (parameters\n"
+ " (declare (in) uvec4 arg0)\n"
+ " (declare (in) uint arg1))\n"
+ " ((declare () uvec4 result)\n"
+ " (assign (constant bool (1)) (swiz x (var_ref result))\n"
+ " (expression uint max (swiz x (var_ref arg0)) (var_ref arg1)))\n"
+ " (assign (constant bool (1)) (swiz y (var_ref result))\n"
+ " (expression uint max (swiz y (var_ref arg0)) (var_ref arg1)))\n"
+ " (assign (constant bool (1)) (swiz z (var_ref result))\n"
+ " (expression uint max (swiz z (var_ref arg0)) (var_ref arg1)))\n"
+ " (assign (constant bool (1)) (swiz w (var_ref result))\n"
+ " (expression uint max (swiz w (var_ref arg0)) (var_ref arg1)))\n"
+ " (return (var_ref result))))\n"
+ "))\n"
+};
+
+static const char *builtins_130_min = {
+ "((function min\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"
+ " ((declare () ivec2 result)\n"
+ " (assign (constant bool (1)) (swiz x (var_ref result))\n"
+ " (expression int min (swiz x (var_ref arg0)) (var_ref arg1)))\n"
+ " (assign (constant bool (1)) (swiz y (var_ref result))\n"
+ " (expression int min (swiz y (var_ref arg0)) (var_ref arg1)))\n"
+ " (return (var_ref result))))\n"
+ "\n"
+ " (signature ivec3\n"
+ " (parameters\n"
+ " (declare (in) ivec3 arg0)\n"
+ " (declare (in) int arg1))\n"
+ " ((declare () ivec3 result)\n"
+ " (assign (constant bool (1)) (swiz x (var_ref result))\n"
+ " (expression int min (swiz x (var_ref arg0)) (var_ref arg1)))\n"
+ " (assign (constant bool (1)) (swiz y (var_ref result))\n"
+ " (expression int min (swiz y (var_ref arg0)) (var_ref arg1)))\n"
+ " (assign (constant bool (1)) (swiz z (var_ref result))\n"
+ " (expression int min (swiz z (var_ref arg0)) (var_ref arg1)))\n"
+ " (return (var_ref result))))\n"
+ "\n"
+ " (signature ivec4\n"
+ " (parameters\n"
+ " (declare (in) ivec4 arg0)\n"
+ " (declare (in) int arg1))\n"
+ " ((declare () ivec4 result)\n"
+ " (assign (constant bool (1)) (swiz x (var_ref result))\n"
+ " (expression int min (swiz x (var_ref arg0)) (var_ref arg1)))\n"
+ " (assign (constant bool (1)) (swiz y (var_ref result))\n"
+ " (expression int min (swiz y (var_ref arg0)) (var_ref arg1)))\n"
+ " (assign (constant bool (1)) (swiz z (var_ref result))\n"
+ " (expression int min (swiz z (var_ref arg0)) (var_ref arg1)))\n"
+ " (assign (constant bool (1)) (swiz w (var_ref result))\n"
+ " (expression int min (swiz w (var_ref arg0)) (var_ref arg1)))\n"
+ " (return (var_ref result))))\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"
+ " ((declare () uvec2 result)\n"
+ " (assign (constant bool (1)) (swiz x (var_ref result))\n"
+ " (expression uint min (swiz x (var_ref arg0)) (var_ref arg1)))\n"
+ " (assign (constant bool (1)) (swiz y (var_ref result))\n"
+ " (expression uint min (swiz y (var_ref arg0)) (var_ref arg1)))\n"
+ " (return (var_ref result))))\n"
+ "\n"
+ " (signature uvec3\n"
+ " (parameters\n"
+ " (declare (in) uvec3 arg0)\n"
+ " (declare (in) uint arg1))\n"
+ " ((declare () uvec3 result)\n"
+ " (assign (constant bool (1)) (swiz x (var_ref result))\n"
+ " (expression uint min (swiz x (var_ref arg0)) (var_ref arg1)))\n"
+ " (assign (constant bool (1)) (swiz y (var_ref result))\n"
+ " (expression uint min (swiz y (var_ref arg0)) (var_ref arg1)))\n"
+ " (assign (constant bool (1)) (swiz z (var_ref result))\n"
+ " (expression uint min (swiz z (var_ref arg0)) (var_ref arg1)))\n"
+ " (return (var_ref result))))\n"
+ "\n"
+ " (signature uvec4\n"
+ " (parameters\n"
+ " (declare (in) uvec4 arg0)\n"
+ " (declare (in) uint arg1))\n"
+ " ((declare () uvec4 result)\n"
+ " (assign (constant bool (1)) (swiz x (var_ref result))\n"
+ " (expression uint min (swiz x (var_ref arg0)) (var_ref arg1)))\n"
+ " (assign (constant bool (1)) (swiz y (var_ref result))\n"
+ " (expression uint min (swiz y (var_ref arg0)) (var_ref arg1)))\n"
+ " (assign (constant bool (1)) (swiz z (var_ref result))\n"
+ " (expression uint min (swiz z (var_ref arg0)) (var_ref arg1)))\n"
+ " (assign (constant bool (1)) (swiz w (var_ref result))\n"
+ " (expression uint min (swiz w (var_ref arg0)) (var_ref arg1)))\n"
+ " (return (var_ref result))))\n"
+ "))\n"
+};
+
+static const char *builtins_130_notEqual = {
+ "((function notEqual\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 *builtins_130_sign = {
+ "((function sign\n"
+ " (signature int\n"
+ " (parameters\n"
+ " (declare (in) int x))\n"
+ " ((return (expression int / (var_ref x) (expression int abs (var_ref x))))))\n"
+ "\n"
+ " (signature ivec2\n"
+ " (parameters\n"
+ " (declare (in) ivec2 x))\n"
+ " ((declare () ivec2 t)\n"
+ " (assign (constant bool (1)) (swiz x (var_ref t)) (expression int sign (swiz x (var_ref x))))\n"
+ " (assign (constant bool (1)) (swiz y (var_ref t)) (expression int sign (swiz y (var_ref x))))\n"
+ " (return (var_ref t))))\n"
+ "\n"
+ " (signature ivec3\n"
+ " (parameters\n"
+ " (declare (in) ivec3 x))\n"
+ " ((declare () ivec3 t)\n"
+ " (assign (constant bool (1)) (swiz x (var_ref t)) (expression int sign (swiz x (var_ref x))))\n"
+ " (assign (constant bool (1)) (swiz y (var_ref t)) (expression int sign (swiz y (var_ref x))))\n"
+ " (assign (constant bool (1)) (swiz z (var_ref t)) (expression int sign (swiz z (var_ref x))))\n"
+ " (return (var_ref t))))\n"
+ "\n"
+ " (signature ivec4\n"
+ " (parameters\n"
+ " (declare (in) ivec4 x))\n"
+ " ((declare () ivec4 t)\n"
+ " (assign (constant bool (1)) (swiz x (var_ref t)) (expression int sign (swiz x (var_ref x))))\n"
+ " (assign (constant bool (1)) (swiz y (var_ref t)) (expression int sign (swiz y (var_ref x))))\n"
+ " (assign (constant bool (1)) (swiz z (var_ref t)) (expression int sign (swiz z (var_ref x))))\n"
+ " (assign (constant bool (1)) (swiz w (var_ref t)) (expression int sign (swiz w (var_ref x))))\n"
+ " (return (var_ref t))))\n"
+ "))\n"
+ "\n"
+};
+
+static const char *builtins_130_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 *builtins_130_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 *builtins_130_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 *builtins_130_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"
+ "))\n"
+};
+
+static const char *builtins_130_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"
+ ")\n"
+};
+
+static const char *builtins_130_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 *builtins_130_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"
+ "))\n"
+};
+
+static const char *builtins_130_textureProjGrad = {
+ "((function textureLod\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 *builtins_130_textureProjLod = {
+ "((function textureLod\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 *functions_for_130 [] = {
+ builtins_130_clamp,
+ builtins_130_cosh,
+ builtins_130_equal,
+ builtins_130_greaterThan,
+ builtins_130_greaterThanEqual,
+ builtins_130_lessThan,
+ builtins_130_lessThanEqual,
+ builtins_130_max,
+ builtins_130_min,
+ builtins_130_notEqual,
+ builtins_130_sign,
+ builtins_130_sinh,
+ builtins_130_tanh,
+ builtins_130_texelFetch,
+ builtins_130_texture,
+ builtins_130_textureGrad,
+ builtins_130_textureLod,
+ builtins_130_textureProj,
+ builtins_130_textureProjGrad,
+ builtins_130_textureProjLod,
+};
+
+/* 130_fs builtins */
+
+static const char *builtins_130_fs_texture = {
+ "((function texture\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 *builtins_130_fs_textureProj = {
+ "((function textureProj\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 *functions_for_130_fs [] = {
+ builtins_130_fs_texture,
+ builtins_130_fs_textureProj,
+};
+
+/* ARB_texture_rectangle builtins */
+
+static const char *builtins_ARB_texture_rectangle_textures = {
+ "((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"
+ " (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 *functions_for_ARB_texture_rectangle [] = {
+ builtins_ARB_texture_rectangle_textures,
+};
+
+/* EXT_texture_array builtins */
+
+static const char *builtins_EXT_texture_array_textures = {
+ "((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"
+ ")\n"
+ " (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"
+ " (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"
+ ")\n"
+ " (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"
+ " (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"
+ ")\n"
+ " (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"
+ " (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 *functions_for_EXT_texture_array [] = {
+ builtins_EXT_texture_array_textures,
+};
+
+/* EXT_texture_array_fs builtins */
+
+static const char *builtins_EXT_texture_array_fs_textures = {
+ "((function texture1DArray\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"
+ " (function texture2DArray\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"
+ " (function shadow1DArray\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 *functions_for_EXT_texture_array_fs [] = {
+ builtins_EXT_texture_array_fs_textures,
+};
+
+void
+_mesa_glsl_initialize_functions(exec_list *instructions,
+ struct _mesa_glsl_parse_state *state)
+{
+ if (state->language_version >= 110)
+ read_builtins(state, instructions,
+ functions_for_110,
+ sizeof(functions_for_110) / sizeof(const char *));
+
+ if (state->target == fragment_shader && state->language_version >= 110)
+ read_builtins(state, instructions,
+ functions_for_110_fs,
+ sizeof(functions_for_110_fs) / sizeof(const char *));
+
+ if (state->target == vertex_shader && state->language_version >= 110)
+ read_builtins(state, instructions,
+ functions_for_110_vs,
+ sizeof(functions_for_110_vs) / sizeof(const char *));
+
+ if (state->language_version >= 120)
+ read_builtins(state, instructions,
+ functions_for_120,
+ sizeof(functions_for_120) / sizeof(const char *));
+
+ if (state->language_version >= 130)
+ read_builtins(state, instructions,
+ functions_for_130,
+ sizeof(functions_for_130) / sizeof(const char *));
+
+ if (state->target == fragment_shader && state->language_version >= 130)
+ read_builtins(state, instructions,
+ functions_for_130_fs,
+ sizeof(functions_for_130_fs) / sizeof(const char *));
+
+ if (state->ARB_texture_rectangle_enable)
+ read_builtins(state, instructions,
+ functions_for_ARB_texture_rectangle,
+ sizeof(functions_for_ARB_texture_rectangle) / sizeof(const char *));
+
+ if (state->EXT_texture_array_enable)
+ read_builtins(state, instructions,
+ functions_for_EXT_texture_array,
+ sizeof(functions_for_EXT_texture_array) / sizeof(const char *));
+
+ if (state->target == fragment_shader && state->EXT_texture_array_enable)
+ read_builtins(state, instructions,
+ functions_for_EXT_texture_array_fs,
+ sizeof(functions_for_EXT_texture_array_fs) / sizeof(const char *));
+
+}
diff --git a/src/glsl/builtin_types.h b/src/glsl/builtin_types.h
new file mode 100644
index 00000000000..48202f56454
--- /dev/null
+++ b/src/glsl/builtin_types.h
@@ -0,0 +1,268 @@
+/*
+ * 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.
+ */
+
+#ifndef Elements
+#define Elements(x) (sizeof(x)/sizeof(*(x)))
+#endif
+
+static const struct glsl_type _error_type =
+ glsl_type(GLSL_TYPE_ERROR, 0, 0, "");
+
+static const struct glsl_type void_type =
+ glsl_type(GLSL_TYPE_VOID, 0, 0, "void");
+
+const glsl_type *const glsl_type::error_type = & _error_type;
+
+/** \name Core built-in types
+ *
+ * These types exist in all versions of GLSL.
+ */
+/*@{*/
+
+static const struct glsl_type builtin_core_types[] = {
+ glsl_type( GLSL_TYPE_BOOL, 1, 1, "bool"),
+ glsl_type( GLSL_TYPE_BOOL, 2, 1, "bvec2"),
+ glsl_type( GLSL_TYPE_BOOL, 3, 1, "bvec3"),
+ glsl_type( GLSL_TYPE_BOOL, 4, 1, "bvec4"),
+ glsl_type( GLSL_TYPE_INT, 1, 1, "int"),
+ glsl_type( GLSL_TYPE_INT, 2, 1, "ivec2"),
+ glsl_type( GLSL_TYPE_INT, 3, 1, "ivec3"),
+ glsl_type( GLSL_TYPE_INT, 4, 1, "ivec4"),
+ glsl_type( GLSL_TYPE_FLOAT, 1, 1, "float"),
+ glsl_type( GLSL_TYPE_FLOAT, 2, 1, "vec2"),
+ glsl_type( GLSL_TYPE_FLOAT, 3, 1, "vec3"),
+ glsl_type( GLSL_TYPE_FLOAT, 4, 1, "vec4"),
+ glsl_type( GLSL_TYPE_FLOAT, 2, 2, "mat2"),
+ glsl_type( GLSL_TYPE_FLOAT, 3, 3, "mat3"),
+ glsl_type( GLSL_TYPE_FLOAT, 4, 4, "mat4"),
+ glsl_type( GLSL_SAMPLER_DIM_1D, 0, 0, GLSL_TYPE_FLOAT, "sampler1D"),
+ glsl_type( GLSL_SAMPLER_DIM_1D, 1, 0, GLSL_TYPE_FLOAT, "sampler1DShadow"),
+ glsl_type( GLSL_SAMPLER_DIM_2D, 0, 0, GLSL_TYPE_FLOAT, "sampler2D"),
+ glsl_type( GLSL_SAMPLER_DIM_2D, 1, 0, GLSL_TYPE_FLOAT, "sampler2DShadow"),
+ glsl_type( GLSL_SAMPLER_DIM_3D, 0, 0, GLSL_TYPE_FLOAT, "sampler3D"),
+ glsl_type(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" },
+};
+
+static const struct 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" },
+};
+
+static const struct 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
+ */
+/*@{*/
+
+static const struct glsl_type builtin_120_types[] = {
+ glsl_type( GLSL_TYPE_FLOAT, 3, 2, "mat2x3"),
+ glsl_type( GLSL_TYPE_FLOAT, 4, 2, "mat2x4"),
+ glsl_type( GLSL_TYPE_FLOAT, 2, 3, "mat3x2"),
+ glsl_type( GLSL_TYPE_FLOAT, 4, 3, "mat3x4"),
+ glsl_type( GLSL_TYPE_FLOAT, 2, 4, "mat4x2"),
+ glsl_type( 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
+ */
+/*@{*/
+
+static const struct glsl_type builtin_130_types[] = {
+ glsl_type( GLSL_TYPE_UINT, 1, 1, "uint"),
+ glsl_type( GLSL_TYPE_UINT, 2, 1, "uvec2"),
+ glsl_type( GLSL_TYPE_UINT, 3, 1, "uvec3"),
+ glsl_type( GLSL_TYPE_UINT, 4, 1, "uvec4"),
+
+ /* 1D and 2D texture arrays */
+ glsl_type( GLSL_SAMPLER_DIM_1D, 0, 1, GLSL_TYPE_FLOAT, "sampler1DArray"),
+ glsl_type( GLSL_SAMPLER_DIM_1D, 0, 1, GLSL_TYPE_INT, "isampler1DArray"),
+ glsl_type( GLSL_SAMPLER_DIM_1D, 0, 1, GLSL_TYPE_UINT, "usampler1DArray"),
+ glsl_type( GLSL_SAMPLER_DIM_1D, 1, 1, GLSL_TYPE_FLOAT, "sampler1DArrayShadow"),
+ glsl_type( GLSL_SAMPLER_DIM_2D, 0, 1, GLSL_TYPE_FLOAT, "sampler2DArray"),
+ glsl_type( GLSL_SAMPLER_DIM_2D, 0, 1, GLSL_TYPE_INT, "isampler2DArray"),
+ glsl_type( GLSL_SAMPLER_DIM_2D, 0, 1, GLSL_TYPE_UINT, "usampler2DArray"),
+ glsl_type( GLSL_SAMPLER_DIM_2D, 1, 1, GLSL_TYPE_FLOAT, "sampler2DArrayShadow"),
+
+ /* cube shadow samplers */
+ glsl_type(GLSL_SAMPLER_DIM_CUBE, 1, 0, GLSL_TYPE_FLOAT, "samplerCubeShadow"),
+
+ /* signed and unsigned integer samplers */
+ glsl_type( GLSL_SAMPLER_DIM_1D, 0, 0, GLSL_TYPE_INT, "isampler1D"),
+ glsl_type( GLSL_SAMPLER_DIM_1D, 0, 0, GLSL_TYPE_UINT, "usampler1D"),
+ glsl_type( GLSL_SAMPLER_DIM_2D, 0, 0, GLSL_TYPE_INT, "isampler2D"),
+ glsl_type( GLSL_SAMPLER_DIM_2D, 0, 0, GLSL_TYPE_UINT, "usampler2D"),
+ glsl_type( GLSL_SAMPLER_DIM_3D, 0, 0, GLSL_TYPE_INT, "isampler3D"),
+ glsl_type( GLSL_SAMPLER_DIM_3D, 0, 0, GLSL_TYPE_UINT, "usampler3D"),
+ glsl_type(GLSL_SAMPLER_DIM_CUBE, 0, 0, GLSL_TYPE_INT, "isamplerCube"),
+ glsl_type(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
+ */
+/*@{*/
+
+static const struct glsl_type builtin_ARB_texture_rectangle_types[] = {
+ glsl_type(GLSL_SAMPLER_DIM_RECT, 0, 0, GLSL_TYPE_FLOAT, "sampler2DRect"),
+ glsl_type(GLSL_SAMPLER_DIM_RECT, 1, 0, GLSL_TYPE_FLOAT, "sampler2DRectShadow"),
+};
+/*@}*/
+
+/** \name Sampler types added by GL_EXT_texture_array
+ */
+/*@{*/
+
+static const struct glsl_type builtin_EXT_texture_array_types[] = {
+ glsl_type( GLSL_SAMPLER_DIM_1D, 0, 1, GLSL_TYPE_FLOAT, "sampler1DArray"),
+ glsl_type( GLSL_SAMPLER_DIM_2D, 0, 1, GLSL_TYPE_FLOAT, "sampler2DArray"),
+ glsl_type( GLSL_SAMPLER_DIM_1D, 1, 1, GLSL_TYPE_FLOAT, "sampler1DArrayShadow"),
+ glsl_type( GLSL_SAMPLER_DIM_2D, 1, 1, GLSL_TYPE_FLOAT, "sampler2DArrayShadow"),
+};
+/*@}*/
+
+/** \name Sampler types added by GL_EXT_texture_buffer_object
+ */
+/*@{*/
+
+static const struct glsl_type builtin_EXT_texture_buffer_object_types[] = {
+ glsl_type( GLSL_SAMPLER_DIM_BUF, 0, 0, GLSL_TYPE_FLOAT, "samplerBuffer"),
+ glsl_type( GLSL_SAMPLER_DIM_BUF, 0, 0, GLSL_TYPE_INT, "isamplerBuffer"),
+ glsl_type( 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..77f2fe55023
--- /dev/null
+++ b/src/glsl/builtin_variables.h
@@ -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.
+ */
+
+#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_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" },
+};
+
diff --git a/src/glsl/builtins/110/abs b/src/glsl/builtins/110/abs
new file mode 100644
index 00000000000..904845307c4
--- /dev/null
+++ b/src/glsl/builtins/110/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/110/all b/src/glsl/builtins/110/all
new file mode 100644
index 00000000000..2cac0dfb684
--- /dev/null
+++ b/src/glsl/builtins/110/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/110/any b/src/glsl/builtins/110/any
new file mode 100644
index 00000000000..f10e8a7b478
--- /dev/null
+++ b/src/glsl/builtins/110/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/110/asin b/src/glsl/builtins/110/asin
new file mode 100644
index 00000000000..fe93337bffc
--- /dev/null
+++ b/src/glsl/builtins/110/asin
@@ -0,0 +1,112 @@
+((function asin
+ (signature float
+ (parameters
+ (declare (in) float x))
+ ((return (expression float *
+ (expression float -
+ (expression float *
+ (constant float (3.1415926))
+ (constant float (0.5)))
+ (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 float -
+ (expression float *
+ (constant float (3.1415926))
+ (constant float (0.5)))
+ (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 -
+ (expression float *
+ (constant float (3.1415926))
+ (constant float (0.5)))
+ (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 -
+ (expression float *
+ (constant float (3.1415926))
+ (constant float (0.5)))
+ (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))))))))))
+)
+
+ (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/110/atan b/src/glsl/builtins/110/atan
new file mode 100644
index 00000000000..e5542350b51
--- /dev/null
+++ b/src/glsl/builtins/110/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)
+ (if (expression bool >
+ (expression float abs (var_ref x))
+ (constant float (.0001)))
+ ((assign (constant bool (1))
+ (var_ref r) (call atan ((expression float /
+ (var_ref y)
+ (var_ref x)))))
+ (if (expression bool <
+ (var_ref x)
+ (constant float (0.0)))
+ ((assign (constant bool (1))
+ (var_ref r)
+ (expression float +
+ (var_ref r)
+ (expression float *
+ (expression int sign (var_ref y))
+ (constant float (3.1415926))))))
+ ()))
+ ())
+ (return (var_ref r))))
+
+ (signature vec2
+ (parameters
+ (declare (in) vec2 y)
+ (declare (in) vec2 x))
+ ((declare () vec2 r)
+ (if (expression bool >
+ (expression vec2 abs (var_ref x))
+ (constant float (.0001)))
+ ((assign (constant bool (1))
+ (var_ref r) (call atan ((expression vec2 /
+ (var_ref y)
+ (var_ref x)))))
+ (if (expression bool <
+ (var_ref x)
+ (constant float (0.0)))
+ ((assign (constant bool (1))
+ (var_ref r)
+ (expression vec2 +
+ (var_ref r)
+ (expression vec2 *
+ (expression int sign (var_ref y))
+ (constant float (3.1415926))))))
+ ()))
+ ())
+ (return (var_ref r))))
+
+ (signature vec3
+ (parameters
+ (declare (in) vec3 y)
+ (declare (in) vec3 x))
+ ((declare () vec3 r)
+ (if (expression bool >
+ (expression vec3 abs (var_ref x))
+ (constant float (.0001)))
+ ((assign (constant bool (1))
+ (var_ref r) (call atan ((expression vec3 /
+ (var_ref y)
+ (var_ref x)))))
+ (if (expression bool <
+ (var_ref x)
+ (constant float (0.0)))
+ ((assign (constant bool (1))
+ (var_ref r)
+ (expression vec3 +
+ (var_ref r)
+ (expression vec3 *
+ (expression int sign (var_ref y))
+ (constant float (3.1415926))))))
+ ()))
+ ())
+ (return (var_ref r))))
+
+ (signature vec4
+ (parameters
+ (declare (in) vec4 y)
+ (declare (in) vec4 x))
+ ((declare () vec4 r)
+ (if (expression bool >
+ (expression vec4 abs (var_ref x))
+ (constant float (.0001)))
+ ((assign (constant bool (1))
+ (var_ref r) (call atan ((expression vec4 /
+ (var_ref y)
+ (var_ref x)))))
+ (if (expression bool <
+ (var_ref x)
+ (constant float (0.0)))
+ ((assign (constant bool (1))
+ (var_ref r)
+ (expression vec4 +
+ (var_ref r)
+ (expression vec4 *
+ (expression int sign (var_ref y))
+ (constant float (3.1415926))))))
+ ()))
+ ())
+ (return (var_ref r))))
+
+))
diff --git a/src/glsl/builtins/110/ceil b/src/glsl/builtins/110/ceil
new file mode 100644
index 00000000000..a26a7750493
--- /dev/null
+++ b/src/glsl/builtins/110/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/110/clamp b/src/glsl/builtins/110/clamp
new file mode 100644
index 00000000000..94c8e5ed168
--- /dev/null
+++ b/src/glsl/builtins/110/clamp
@@ -0,0 +1,62 @@
+((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))
+ ((declare () vec2 result)
+ (assign (constant bool (1)) (swiz x (var_ref result)) (expression vec4 max (expression vec4 min (swiz x (var_ref arg0)) (var_ref arg2)) (var_ref arg1)))
+ (assign (constant bool (1)) (swiz y (var_ref result)) (expression vec4 max (expression vec4 min (swiz y (var_ref arg0)) (var_ref arg2)) (var_ref arg1)))
+ (return (var_ref result))))
+
+ (signature vec3
+ (parameters
+ (declare (in) vec3 arg0)
+ (declare (in) float arg1)
+ (declare (in) float arg2))
+ ((declare () vec3 result)
+ (assign (constant bool (1)) (swiz x (var_ref result)) (expression vec4 max (expression vec4 min (swiz x (var_ref arg0)) (var_ref arg2)) (var_ref arg1)))
+ (assign (constant bool (1)) (swiz y (var_ref result)) (expression vec4 max (expression vec4 min (swiz y (var_ref arg0)) (var_ref arg2)) (var_ref arg1)))
+ (assign (constant bool (1)) (swiz z (var_ref result)) (expression vec4 max (expression vec4 min (swiz z (var_ref arg0)) (var_ref arg2)) (var_ref arg1)))
+ (return (var_ref result))))
+
+ (signature vec4
+ (parameters
+ (declare (in) vec4 arg0)
+ (declare (in) float arg1)
+ (declare (in) float arg2))
+ ((declare () vec4 result)
+ (assign (constant bool (1)) (swiz x (var_ref result)) (expression vec4 max (expression vec4 min (swiz x (var_ref arg0)) (var_ref arg2)) (var_ref arg1)))
+ (assign (constant bool (1)) (swiz y (var_ref result)) (expression vec4 max (expression vec4 min (swiz y (var_ref arg0)) (var_ref arg2)) (var_ref arg1)))
+ (assign (constant bool (1)) (swiz z (var_ref result)) (expression vec4 max (expression vec4 min (swiz z (var_ref arg0)) (var_ref arg2)) (var_ref arg1)))
+ (assign (constant bool (1)) (swiz w (var_ref result)) (expression vec4 max (expression vec4 min (swiz w (var_ref arg0)) (var_ref arg2)) (var_ref arg1)))
+ (return (var_ref result))))
+))
diff --git a/src/glsl/builtins/110/cos b/src/glsl/builtins/110/cos
new file mode 100644
index 00000000000..88f266eccbe
--- /dev/null
+++ b/src/glsl/builtins/110/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/110/cross b/src/glsl/builtins/110/cross
new file mode 100644
index 00000000000..deb2f952bfc
--- /dev/null
+++ b/src/glsl/builtins/110/cross
@@ -0,0 +1,17 @@
+((function cross
+ (signature vec3
+ (parameters
+ (declare (in) vec3 arg0)
+ (declare (in) vec3 arg1))
+ ((declare () vec3 t)
+ (assign (constant bool (1)) (swiz x (var_ref t))
+ (expression float - (expression float * (swiz y (var_ref arg0)) (swiz z (var_ref arg1)))
+ (expression float * (swiz y (var_ref arg1)) (swiz z (var_ref arg0)))))
+ (assign (constant bool (1)) (swiz y (var_ref t))
+ (expression float - (expression float * (swiz z (var_ref arg0)) (swiz x (var_ref arg1)))
+ (expression float * (swiz z (var_ref arg1)) (swiz x (var_ref arg0)))))
+ (assign (constant bool (1)) (swiz z (var_ref t))
+ (expression float - (expression float * (swiz x (var_ref arg0)) (swiz y (var_ref arg1)))
+ (expression float * (swiz x (var_ref arg1)) (swiz y (var_ref arg0)))))
+ (return (var_ref t))))
+))
diff --git a/src/glsl/builtins/110/degrees b/src/glsl/builtins/110/degrees
new file mode 100644
index 00000000000..dc0d7b9e20d
--- /dev/null
+++ b/src/glsl/builtins/110/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/110/distance b/src/glsl/builtins/110/distance
new file mode 100644
index 00000000000..a2309c484f9
--- /dev/null
+++ b/src/glsl/builtins/110/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/110/dot b/src/glsl/builtins/110/dot
new file mode 100644
index 00000000000..a91a6d2c56d
--- /dev/null
+++ b/src/glsl/builtins/110/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/110/equal b/src/glsl/builtins/110/equal
new file mode 100644
index 00000000000..ae7ddc53bdc
--- /dev/null
+++ b/src/glsl/builtins/110/equal
@@ -0,0 +1,61 @@
+((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))))
+))
diff --git a/src/glsl/builtins/110/exp b/src/glsl/builtins/110/exp
new file mode 100644
index 00000000000..a73bd6a7f84
--- /dev/null
+++ b/src/glsl/builtins/110/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/110/exp2 b/src/glsl/builtins/110/exp2
new file mode 100644
index 00000000000..a842d3fe65b
--- /dev/null
+++ b/src/glsl/builtins/110/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/110/faceforward b/src/glsl/builtins/110/faceforward
new file mode 100644
index 00000000000..d1703972388
--- /dev/null
+++ b/src/glsl/builtins/110/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/110/floor b/src/glsl/builtins/110/floor
new file mode 100644
index 00000000000..8dd8052799b
--- /dev/null
+++ b/src/glsl/builtins/110/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/110/fract b/src/glsl/builtins/110/fract
new file mode 100644
index 00000000000..3995bfaf3f9
--- /dev/null
+++ b/src/glsl/builtins/110/fract
@@ -0,0 +1,34 @@
+((function fract
+ (signature float
+ (parameters
+ (declare (in) float x))
+ ((return (expression float - (var_ref x) (expression float floor (var_ref x))))))
+
+ (signature vec2
+ (parameters
+ (declare (in) vec2 x))
+ ((declare () vec2 t)
+ (assign (constant bool (1)) (swiz x (var_ref t)) (expression float - (swiz x (var_ref x)) (expression float floor (swiz x (var_ref x)))))
+ (assign (constant bool (1)) (swiz y (var_ref t)) (expression float - (swiz y (var_ref x)) (expression float floor (swiz y (var_ref x)))))
+ (return (var_ref t))))
+
+ (signature vec3
+ (parameters
+ (declare (in) vec3 x))
+ ((declare () vec3 t)
+ (assign (constant bool (1)) (swiz x (var_ref t)) (expression float - (swiz x (var_ref x)) (expression float floor (swiz x (var_ref x)))))
+ (assign (constant bool (1)) (swiz y (var_ref t)) (expression float - (swiz y (var_ref x)) (expression float floor (swiz y (var_ref x)))))
+ (assign (constant bool (1)) (swiz z (var_ref t)) (expression float - (swiz z (var_ref x)) (expression float floor (swiz z (var_ref x)))))
+ (return (var_ref t))))
+
+ (signature vec4
+ (parameters
+ (declare (in) vec4 x))
+ ((declare () vec4 t)
+ (assign (constant bool (1)) (swiz x (var_ref t)) (expression float - (swiz x (var_ref x)) (expression float floor (swiz x (var_ref x)))))
+ (assign (constant bool (1)) (swiz y (var_ref t)) (expression float - (swiz y (var_ref x)) (expression float floor (swiz y (var_ref x)))))
+ (assign (constant bool (1)) (swiz z (var_ref t)) (expression float - (swiz z (var_ref x)) (expression float floor (swiz z (var_ref x)))))
+ (assign (constant bool (1)) (swiz w (var_ref t)) (expression float - (swiz w (var_ref x)) (expression float floor (swiz w (var_ref x)))))
+ (return (var_ref t))))
+))
+
diff --git a/src/glsl/builtins/110/greaterThan b/src/glsl/builtins/110/greaterThan
new file mode 100644
index 00000000000..ae03030e495
--- /dev/null
+++ b/src/glsl/builtins/110/greaterThan
@@ -0,0 +1,61 @@
+((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))))
+))
diff --git a/src/glsl/builtins/110/greaterThanEqual b/src/glsl/builtins/110/greaterThanEqual
new file mode 100644
index 00000000000..204d5fd1439
--- /dev/null
+++ b/src/glsl/builtins/110/greaterThanEqual
@@ -0,0 +1,61 @@
+((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))))
+))
diff --git a/src/glsl/builtins/110/inversesqrt b/src/glsl/builtins/110/inversesqrt
new file mode 100644
index 00000000000..5b66d2b3695
--- /dev/null
+++ b/src/glsl/builtins/110/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/110/length b/src/glsl/builtins/110/length
new file mode 100644
index 00000000000..89ff7f3ef12
--- /dev/null
+++ b/src/glsl/builtins/110/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/110/lessThan b/src/glsl/builtins/110/lessThan
new file mode 100644
index 00000000000..5c4254165c7
--- /dev/null
+++ b/src/glsl/builtins/110/lessThan
@@ -0,0 +1,61 @@
+((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))))
+))
diff --git a/src/glsl/builtins/110/lessThanEqual b/src/glsl/builtins/110/lessThanEqual
new file mode 100644
index 00000000000..ccb955b8a76
--- /dev/null
+++ b/src/glsl/builtins/110/lessThanEqual
@@ -0,0 +1,61 @@
+((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))))
+))
diff --git a/src/glsl/builtins/110/log b/src/glsl/builtins/110/log
new file mode 100644
index 00000000000..d168abb5a73
--- /dev/null
+++ b/src/glsl/builtins/110/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/110/log2 b/src/glsl/builtins/110/log2
new file mode 100644
index 00000000000..b96c6276f0a
--- /dev/null
+++ b/src/glsl/builtins/110/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/110/matrixCompMult b/src/glsl/builtins/110/matrixCompMult
new file mode 100644
index 00000000000..cb5a2cb1f7b
--- /dev/null
+++ b/src/glsl/builtins/110/matrixCompMult
@@ -0,0 +1,32 @@
+((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))))
+))
+
diff --git a/src/glsl/builtins/110/max b/src/glsl/builtins/110/max
new file mode 100644
index 00000000000..c05545f3d93
--- /dev/null
+++ b/src/glsl/builtins/110/max
@@ -0,0 +1,64 @@
+((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))
+ ((declare () vec2 result)
+ (assign (constant bool (1)) (swiz x (var_ref result))
+ (expression float max (swiz x (var_ref arg0)) (var_ref arg1)))
+ (assign (constant bool (1)) (swiz y (var_ref result))
+ (expression float max (swiz y (var_ref arg0)) (var_ref arg1)))
+ (return (var_ref result))))
+
+ (signature vec3
+ (parameters
+ (declare (in) vec3 arg0)
+ (declare (in) float arg1))
+ ((declare () vec3 result)
+ (assign (constant bool (1)) (swiz x (var_ref result))
+ (expression float max (swiz x (var_ref arg0)) (var_ref arg1)))
+ (assign (constant bool (1)) (swiz y (var_ref result))
+ (expression float max (swiz y (var_ref arg0)) (var_ref arg1)))
+ (assign (constant bool (1)) (swiz z (var_ref result))
+ (expression float max (swiz z (var_ref arg0)) (var_ref arg1)))
+ (return (var_ref result))))
+
+ (signature vec4
+ (parameters
+ (declare (in) vec4 arg0)
+ (declare (in) float arg1))
+ ((declare () vec4 result)
+ (assign (constant bool (1)) (swiz x (var_ref result))
+ (expression float max (swiz x (var_ref arg0)) (var_ref arg1)))
+ (assign (constant bool (1)) (swiz y (var_ref result))
+ (expression float max (swiz y (var_ref arg0)) (var_ref arg1)))
+ (assign (constant bool (1)) (swiz z (var_ref result))
+ (expression float max (swiz z (var_ref arg0)) (var_ref arg1)))
+ (assign (constant bool (1)) (swiz w (var_ref result))
+ (expression float max (swiz w (var_ref arg0)) (var_ref arg1)))
+ (return (var_ref result))))
+))
diff --git a/src/glsl/builtins/110/min b/src/glsl/builtins/110/min
new file mode 100644
index 00000000000..31e79489405
--- /dev/null
+++ b/src/glsl/builtins/110/min
@@ -0,0 +1,64 @@
+((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))
+ ((declare () vec2 result)
+ (assign (constant bool (1)) (swiz x (var_ref result))
+ (expression float min (swiz x (var_ref arg0)) (var_ref arg1)))
+ (assign (constant bool (1)) (swiz y (var_ref result))
+ (expression float min (swiz y (var_ref arg0)) (var_ref arg1)))
+ (return (var_ref result))))
+
+ (signature vec3
+ (parameters
+ (declare (in) vec3 arg0)
+ (declare (in) float arg1))
+ ((declare () vec3 result)
+ (assign (constant bool (1)) (swiz x (var_ref result))
+ (expression float min (swiz x (var_ref arg0)) (var_ref arg1)))
+ (assign (constant bool (1)) (swiz y (var_ref result))
+ (expression float min (swiz y (var_ref arg0)) (var_ref arg1)))
+ (assign (constant bool (1)) (swiz z (var_ref result))
+ (expression float min (swiz z (var_ref arg0)) (var_ref arg1)))
+ (return (var_ref result))))
+
+ (signature vec4
+ (parameters
+ (declare (in) vec4 arg0)
+ (declare (in) float arg1))
+ ((declare () vec4 result)
+ (assign (constant bool (1)) (swiz x (var_ref result))
+ (expression float min (swiz x (var_ref arg0)) (var_ref arg1)))
+ (assign (constant bool (1)) (swiz y (var_ref result))
+ (expression float min (swiz y (var_ref arg0)) (var_ref arg1)))
+ (assign (constant bool (1)) (swiz z (var_ref result))
+ (expression float min (swiz z (var_ref arg0)) (var_ref arg1)))
+ (assign (constant bool (1)) (swiz w (var_ref result))
+ (expression float min (swiz w (var_ref arg0)) (var_ref arg1)))
+ (return (var_ref result))))
+))
diff --git a/src/glsl/builtins/110/mix b/src/glsl/builtins/110/mix
new file mode 100644
index 00000000000..032f29e5fa8
--- /dev/null
+++ b/src/glsl/builtins/110/mix
@@ -0,0 +1,50 @@
+((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 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) float 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) float 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))))))
+))
diff --git a/src/glsl/builtins/110/mod b/src/glsl/builtins/110/mod
new file mode 100644
index 00000000000..9e08bbc7ef4
--- /dev/null
+++ b/src/glsl/builtins/110/mod
@@ -0,0 +1,64 @@
+((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))
+ ((declare () vec2 result)
+ (assign (constant bool (1)) (swiz x (var_ref result))
+ (expression float % (swiz x (var_ref arg0)) (var_ref arg1)))
+ (assign (constant bool (1)) (swiz y (var_ref result))
+ (expression float % (swiz y (var_ref arg0)) (var_ref arg1)))
+ (return (var_ref result))))
+
+ (signature vec3
+ (parameters
+ (declare (in) vec3 arg0)
+ (declare (in) float arg1))
+ ((declare () vec3 result)
+ (assign (constant bool (1)) (swiz x (var_ref result))
+ (expression float % (swiz x (var_ref arg0)) (var_ref arg1)))
+ (assign (constant bool (1)) (swiz y (var_ref result))
+ (expression float % (swiz y (var_ref arg0)) (var_ref arg1)))
+ (assign (constant bool (1)) (swiz z (var_ref result))
+ (expression float % (swiz z (var_ref arg0)) (var_ref arg1)))
+ (return (var_ref result))))
+
+ (signature vec4
+ (parameters
+ (declare (in) vec4 arg0)
+ (declare (in) float arg1))
+ ((declare () vec4 result)
+ (assign (constant bool (1)) (swiz x (var_ref result))
+ (expression float % (swiz x (var_ref arg0)) (var_ref arg1)))
+ (assign (constant bool (1)) (swiz y (var_ref result))
+ (expression float % (swiz y (var_ref arg0)) (var_ref arg1)))
+ (assign (constant bool (1)) (swiz z (var_ref result))
+ (expression float % (swiz z (var_ref arg0)) (var_ref arg1)))
+ (assign (constant bool (1)) (swiz w (var_ref result))
+ (expression float % (swiz w (var_ref arg0)) (var_ref arg1)))
+ (return (var_ref result))))
+))
diff --git a/src/glsl/builtins/110/noise_fake b/src/glsl/builtins/110/noise_fake
new file mode 100644
index 00000000000..bcfb17b04b8
--- /dev/null
+++ b/src/glsl/builtins/110/noise_fake
@@ -0,0 +1,76 @@
+((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)))))
+ )
+
+ (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)))))
+ )
+
+ (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)))))
+ )
+
+ (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/110/normalize b/src/glsl/builtins/110/normalize
new file mode 100644
index 00000000000..be88a9830d1
--- /dev/null
+++ b/src/glsl/builtins/110/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/110/not b/src/glsl/builtins/110/not
new file mode 100644
index 00000000000..b696b06557f
--- /dev/null
+++ b/src/glsl/builtins/110/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/110/notEqual b/src/glsl/builtins/110/notEqual
new file mode 100644
index 00000000000..c87efa317f7
--- /dev/null
+++ b/src/glsl/builtins/110/notEqual
@@ -0,0 +1,61 @@
+((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 float != (swiz x (var_ref arg0))(swiz x (var_ref arg1))))
+ (assign (constant bool (1)) (swiz y (var_ref temp)) (expression float != (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 float != (swiz x (var_ref arg0))(swiz x (var_ref arg1))))
+ (assign (constant bool (1)) (swiz y (var_ref temp)) (expression float != (swiz y (var_ref arg0))(swiz y (var_ref arg1))))
+ (assign (constant bool (1)) (swiz z (var_ref temp)) (expression float != (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 float != (swiz x (var_ref arg0))(swiz x (var_ref arg1))))
+ (assign (constant bool (1)) (swiz y (var_ref temp)) (expression float != (swiz y (var_ref arg0))(swiz y (var_ref arg1))))
+ (assign (constant bool (1)) (swiz z (var_ref temp)) (expression float != (swiz z (var_ref arg0))(swiz z (var_ref arg1))))
+ (assign (constant bool (1)) (swiz w (var_ref temp)) (expression float != (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 int != (swiz x (var_ref arg0))(swiz x (var_ref arg1))))
+ (assign (constant bool (1)) (swiz y (var_ref temp)) (expression int != (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 int != (swiz x (var_ref arg0))(swiz x (var_ref arg1))))
+ (assign (constant bool (1)) (swiz y (var_ref temp)) (expression int != (swiz y (var_ref arg0))(swiz y (var_ref arg1))))
+ (assign (constant bool (1)) (swiz z (var_ref temp)) (expression int != (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 int != (swiz x (var_ref arg0))(swiz x (var_ref arg1))))
+ (assign (constant bool (1)) (swiz y (var_ref temp)) (expression int != (swiz y (var_ref arg0))(swiz y (var_ref arg1))))
+ (assign (constant bool (1)) (swiz z (var_ref temp)) (expression int != (swiz z (var_ref arg0))(swiz z (var_ref arg1))))
+ (assign (constant bool (1)) (swiz w (var_ref temp)) (expression int != (swiz w (var_ref arg0))(swiz w (var_ref arg1))))
+ (return (var_ref temp))))
+))
diff --git a/src/glsl/builtins/110/pow b/src/glsl/builtins/110/pow
new file mode 100644
index 00000000000..a61bc4418e3
--- /dev/null
+++ b/src/glsl/builtins/110/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/110/radians b/src/glsl/builtins/110/radians
new file mode 100644
index 00000000000..6a0f5d2e219
--- /dev/null
+++ b/src/glsl/builtins/110/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/110/reflect b/src/glsl/builtins/110/reflect
new file mode 100644
index 00000000000..8238fdc93fd
--- /dev/null
+++ b/src/glsl/builtins/110/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/110/refract b/src/glsl/builtins/110/refract
new file mode 100644
index 00000000000..e9b1475294a
--- /dev/null
+++ b/src/glsl/builtins/110/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))))
+ ((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))))
+ ((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/110/sign b/src/glsl/builtins/110/sign
new file mode 100644
index 00000000000..7d540de405b
--- /dev/null
+++ b/src/glsl/builtins/110/sign
@@ -0,0 +1,34 @@
+((function sign
+ (signature float
+ (parameters
+ (declare (in) float x))
+ ((return (expression float sign (var_ref x)))))
+
+ (signature vec2
+ (parameters
+ (declare (in) vec2 x))
+ ((declare () vec2 t)
+ (assign (constant bool (1)) (swiz x (var_ref t)) (expression float sign (swiz x (var_ref x))))
+ (assign (constant bool (1)) (swiz y (var_ref t)) (expression float sign (swiz y (var_ref x))))
+ (return (var_ref t))))
+
+ (signature vec3
+ (parameters
+ (declare (in) vec3 x))
+ ((declare () vec3 t)
+ (assign (constant bool (1)) (swiz x (var_ref t)) (expression float sign (swiz x (var_ref x))))
+ (assign (constant bool (1)) (swiz y (var_ref t)) (expression float sign (swiz y (var_ref x))))
+ (assign (constant bool (1)) (swiz z (var_ref t)) (expression float sign (swiz z (var_ref x))))
+ (return (var_ref t))))
+
+ (signature vec4
+ (parameters
+ (declare (in) vec4 x))
+ ((declare () vec4 t)
+ (assign (constant bool (1)) (swiz x (var_ref t)) (expression float sign (swiz x (var_ref x))))
+ (assign (constant bool (1)) (swiz y (var_ref t)) (expression float sign (swiz y (var_ref x))))
+ (assign (constant bool (1)) (swiz z (var_ref t)) (expression float sign (swiz z (var_ref x))))
+ (assign (constant bool (1)) (swiz w (var_ref t)) (expression float sign (swiz w (var_ref x))))
+ (return (var_ref t))))
+))
+
diff --git a/src/glsl/builtins/110/sin b/src/glsl/builtins/110/sin
new file mode 100644
index 00000000000..e6009d8ef12
--- /dev/null
+++ b/src/glsl/builtins/110/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/110/smoothstep b/src/glsl/builtins/110/smoothstep
new file mode 100644
index 00000000000..b4255ba78f1
--- /dev/null
+++ b/src/glsl/builtins/110/smoothstep
@@ -0,0 +1,224 @@
+((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))
+ ((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)) (swiz x (var_ref edge0))) (expression float - (swiz x (var_ref edge1)) (swiz x (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)) (swiz y (var_ref edge0))) (expression float - (swiz y (var_ref edge1)) (swiz y (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) vec3 edge0)
+ (declare (in) vec3 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)) (swiz x (var_ref edge0))) (expression float - (swiz x (var_ref edge1)) (swiz x (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)) (swiz y (var_ref edge0))) (expression float - (swiz y (var_ref edge1)) (swiz y (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)) (swiz z (var_ref edge0))) (expression float - (swiz z (var_ref edge1)) (swiz z (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) vec4 edge0)
+ (declare (in) vec4 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)) (swiz x (var_ref edge0))) (expression float - (swiz x (var_ref edge1)) (swiz x (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)) (swiz y (var_ref edge0))) (expression float - (swiz y (var_ref edge1)) (swiz y (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)) (swiz z (var_ref edge0))) (expression float - (swiz z (var_ref edge1)) (swiz z (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)) (swiz w (var_ref edge0))) (expression float - (swiz w (var_ref edge1)) (swiz w (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))
+ ))
+
+))
+
diff --git a/src/glsl/builtins/110/sqrt b/src/glsl/builtins/110/sqrt
new file mode 100644
index 00000000000..0302d164ae5
--- /dev/null
+++ b/src/glsl/builtins/110/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/110/step b/src/glsl/builtins/110/step
new file mode 100644
index 00000000000..1cc2b51f8fb
--- /dev/null
+++ b/src/glsl/builtins/110/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/110/tan b/src/glsl/builtins/110/tan
new file mode 100644
index 00000000000..3e04892a76c
--- /dev/null
+++ b/src/glsl/builtins/110/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 float / (expression float sin (var_ref angle)) (expression vec2 cos (var_ref angle))))))
+
+ (signature vec3
+ (parameters
+ (declare (in) vec3 angle))
+ ((return (expression float / (expression float sin (var_ref angle)) (expression vec3 cos (var_ref angle))))))
+
+ (signature vec4
+ (parameters
+ (declare (in) vec4 angle))
+ ((return (expression float / (expression float sin (var_ref angle)) (expression vec4 cos (var_ref angle))))))
+))
diff --git a/src/glsl/builtins/110/textures b/src/glsl/builtins/110/textures
new file mode 100644
index 00000000000..c81b7e8ad49
--- /dev/null
+++ b/src/glsl/builtins/110/textures
@@ -0,0 +1,213 @@
+((function texture1D
+ (signature vec4
+ (parameters
+ (declare (in) sampler1D sampler)
+ (declare (in) float P) )
+ ((return (tex (var_ref sampler) (var_ref P) (0 0 0) 1 () ))))
+
+)
+ (function texture1DLod
+ (signature vec4
+ (parameters
+ (declare (in) sampler1D sampler)
+ (declare (in) float P)
+ (declare (in) float lod) )
+ ((return (txl (var_ref sampler) (var_ref P) (0 0 0) 1 () (var_ref lod) ))))
+
+)
+ (function texture1DProj
+ (signature vec4
+ (parameters
+ (declare (in) sampler1D sampler)
+ (declare (in) vec2 P) )
+ ((return (tex (var_ref sampler) (swiz x (var_ref P)) (0 0 0) (swiz y (var_ref P)) () ))))
+
+ (signature vec4
+ (parameters
+ (declare (in) sampler1D sampler)
+ (declare (in) vec4 P) )
+ ((return (tex (var_ref sampler) (swiz x (var_ref P)) (0 0 0) (swiz w (var_ref P)) () ))))
+
+)
+ (function texture1DProjLod
+ (signature vec4
+ (parameters
+ (declare (in) sampler1D sampler)
+ (declare (in) vec2 P)
+ (declare (in) float lod) )
+ ((return (txl (var_ref sampler) (swiz x (var_ref P)) (0 0 0) (swiz y (var_ref P)) () (var_ref lod) ))))
+
+ (signature vec4
+ (parameters
+ (declare (in) sampler1D sampler)
+ (declare (in) vec4 P)
+ (declare (in) float lod) )
+ ((return (txl (var_ref sampler) (swiz x (var_ref P)) (0 0 0) (swiz w (var_ref P)) () (var_ref lod) ))))
+
+)
+ (function texture2D
+ (signature vec4
+ (parameters
+ (declare (in) sampler2D sampler)
+ (declare (in) vec2 P) )
+ ((return (tex (var_ref sampler) (var_ref P) (0 0 0) 1 () ))))
+
+)
+(function texture2DLod
+ (signature vec4
+ (parameters
+ (declare (in) sampler2D sampler)
+ (declare (in) vec2 P)
+ (declare (in) float lod) )
+ ((return (txl (var_ref sampler) (var_ref P) (0 0 0) 1 () (var_ref lod) ))))
+
+)
+ (function texture2DProj
+ (signature vec4
+ (parameters
+ (declare (in) sampler2D sampler)
+ (declare (in) vec3 P) )
+ ((return (tex (var_ref sampler) (swiz xy (var_ref P)) (0 0 0) (swiz z (var_ref P)) () ))))
+
+ (signature vec4
+ (parameters
+ (declare (in) sampler2D sampler)
+ (declare (in) vec4 P) )
+ ((return (tex (var_ref sampler) (swiz xy (var_ref P)) (0 0 0) (swiz w (var_ref P)) () ))))
+
+)
+ (function texture2DProjLod
+ (signature vec4
+ (parameters
+ (declare (in) sampler2D sampler)
+ (declare (in) vec3 P)
+ (declare (in) float lod) )
+ ((return (txl (var_ref sampler) (swiz xy (var_ref P)) (0 0 0) (swiz z (var_ref P)) () (var_ref lod) ))))
+
+ (signature vec4
+ (parameters
+ (declare (in) sampler2D sampler)
+ (declare (in) vec4 P)
+ (declare (in) float lod) )
+ ((return (txl (var_ref sampler) (swiz xy (var_ref P)) (0 0 0) (swiz w (var_ref P)) () (var_ref lod) ))))
+
+)
+ (function texture3D
+ (signature vec4
+ (parameters
+ (declare (in) sampler3D sampler)
+ (declare (in) vec3 P) )
+ ((return (tex (var_ref sampler) (var_ref P) (0 0 0) 1 () ))))
+
+)
+ (function texture3DLod
+ (signature vec4
+ (parameters
+ (declare (in) sampler3D sampler)
+ (declare (in) vec3 P)
+ (declare (in) float lod) )
+ ((return (txl (var_ref sampler) (var_ref P) (0 0 0) 1 () (var_ref lod) ))))
+
+)
+ (function texture3DProj
+ (signature vec4
+ (parameters
+ (declare (in) sampler3D sampler)
+ (declare (in) vec4 P) )
+ ((return (tex (var_ref sampler) (swiz xyz (var_ref P)) (0 0 0) (swiz w (var_ref P)) () ))))
+
+)
+ (function texture3DProjLod
+ (signature vec4
+ (parameters
+ (declare (in) sampler3D sampler)
+ (declare (in) vec4 P)
+ (declare (in) float lod) )
+ ((return (txl (var_ref sampler) (swiz xyz (var_ref P)) (0 0 0) (swiz w (var_ref P)) () (var_ref lod) ))))
+
+)
+ (function textureCube
+ (signature vec4
+ (parameters
+ (declare (in) samplerCube sampler)
+ (declare (in) vec3 P) )
+ ((return (tex (var_ref sampler) (var_ref P) (0 0 0) 1 () ))))
+
+)
+ (function textureCubeLod
+ (signature vec4
+ (parameters
+ (declare (in) samplerCube sampler)
+ (declare (in) vec3 P)
+ (declare (in) float lod) )
+ ((return (txl (var_ref sampler) (var_ref P) (0 0 0) 1 () (var_ref lod) ))))
+
+)
+ (function shadow1D
+ (signature vec4
+ (parameters
+ (declare (in) sampler1DShadow sampler)
+ (declare (in) vec3 P) )
+ ((return (tex (var_ref sampler) (swiz x (var_ref P)) (0 0 0) 1 (swiz z (var_ref P)) ))))
+
+)
+ (function shadow1DLod
+ (signature vec4
+ (parameters
+ (declare (in) sampler1DShadow sampler)
+ (declare (in) vec3 P)
+ (declare (in) float lod) )
+ ((return (txl (var_ref sampler) (swiz x (var_ref P)) (0 0 0) 1 (swiz z (var_ref P)) (var_ref lod) ))))
+
+)
+ (function shadow1DProj
+ (signature vec4
+ (parameters
+ (declare (in) sampler1DShadow sampler)
+ (declare (in) vec4 P) )
+ ((return (tex (var_ref sampler) (swiz x (var_ref P)) (0 0 0) (swiz w (var_ref P)) (swiz z (var_ref P)) ))))
+
+)
+ (function shadow1DProjLod
+ (signature vec4
+ (parameters
+ (declare (in) sampler1DShadow sampler)
+ (declare (in) vec4 P)
+ (declare (in) float lod) )
+ ((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) ))))
+
+)
+ (function shadow2D
+ (signature vec4
+ (parameters
+ (declare (in) sampler2DShadow sampler)
+ (declare (in) vec3 P) )
+ ((return (tex (var_ref sampler) (swiz xy (var_ref P)) (0 0 0) 1 (swiz z (var_ref P)) ))))
+
+)
+ (function shadow2DLod
+ (signature vec4
+ (parameters
+ (declare (in) sampler2DShadow sampler)
+ (declare (in) vec3 P)
+ (declare (in) float lod) )
+ ((return (txl (var_ref sampler) (swiz xy (var_ref P)) (0 0 0) 1 (swiz z (var_ref P)) (var_ref lod) ))))
+
+)
+ (function shadow2DProj
+ (signature vec4
+ (parameters
+ (declare (in) sampler2DShadow sampler)
+ (declare (in) vec4 P) )
+ ((return (tex (var_ref sampler) (swiz xy (var_ref P)) (0 0 0) (swiz w (var_ref P)) (swiz z (var_ref P)) ))))
+
+)
+ (function shadow2DProjLod
+ (signature vec4
+ (parameters
+ (declare (in) sampler2DShadow sampler)
+ (declare (in) vec4 P)
+ (declare (in) float lod) )
+ ((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) ))))
+
+))
diff --git a/src/glsl/builtins/110_fs/derivatives b/src/glsl/builtins/110_fs/derivatives
new file mode 100644
index 00000000000..b79852ee1ff
--- /dev/null
+++ b/src/glsl/builtins/110_fs/derivatives
@@ -0,0 +1,73 @@
+((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)))))
+ )
+
+ (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)))))
+ )
+
+ (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/110_fs/textures b/src/glsl/builtins/110_fs/textures
new file mode 100644
index 00000000000..38f3787e9ef
--- /dev/null
+++ b/src/glsl/builtins/110_fs/textures
@@ -0,0 +1,113 @@
+((function texture1D
+ (signature vec4
+ (parameters
+ (declare (in) sampler1D sampler)
+ (declare (in) float P)
+ (declare (in) float bias) )
+ ((return (txb (var_ref sampler) (var_ref P) (0 0 0) 1 () (var_ref bias) ))))
+
+)
+ (function texture1DProj
+ (signature vec4
+ (parameters
+ (declare (in) sampler1D sampler)
+ (declare (in) vec2 P)
+ (declare (in) float bias) )
+ ((return (txb (var_ref sampler) (swiz x (var_ref P)) (0 0 0) (swiz y (var_ref P)) () (var_ref bias) ))))
+
+ (signature vec4
+ (parameters
+ (declare (in) sampler1D sampler)
+ (declare (in) vec4 P)
+ (declare (in) float bias) )
+ ((return (txb (var_ref sampler) (swiz x (var_ref P)) (0 0 0) (swiz w (var_ref P)) () (var_ref bias) ))))
+
+)
+ (function texture2D
+ (signature vec4
+ (parameters
+ (declare (in) sampler2D sampler)
+ (declare (in) vec2 P)
+ (declare (in) float bias) )
+ ((return (txb (var_ref sampler) (var_ref P) (0 0 0) 1 () (var_ref bias) ))))
+
+)
+ (function texture2DProj
+ (signature vec4
+ (parameters
+ (declare (in) sampler2D sampler)
+ (declare (in) vec3 P)
+ (declare (in) float bias) )
+ ((return (txb (var_ref sampler) (swiz xy (var_ref P)) (0 0 0) (swiz z (var_ref P)) () (var_ref bias) ))))
+
+ (signature vec4
+ (parameters
+ (declare (in) sampler2D sampler)
+ (declare (in) vec4 P)
+ (declare (in) float bias) )
+ ((return (txb (var_ref sampler) (swiz xy (var_ref P)) (0 0 0) (swiz w (var_ref P)) () (var_ref bias) ))))
+
+)
+ (function texture3D
+ (signature vec4
+ (parameters
+ (declare (in) sampler3D sampler)
+ (declare (in) vec3 P)
+ (declare (in) float bias) )
+ ((return (txb (var_ref sampler) (var_ref P) (0 0 0) 1 () (var_ref bias) ))))
+
+)
+ (function texture3DProj
+ (signature vec4
+ (parameters
+ (declare (in) sampler3D sampler)
+ (declare (in) vec4 P)
+ (declare (in) float bias) )
+ ((return (txb (var_ref sampler) (swiz xyz (var_ref P)) (0 0 0) (swiz w (var_ref P)) () (var_ref bias) ))))
+
+)
+ (function textureCube
+ (signature vec4
+ (parameters
+ (declare (in) samplerCube sampler)
+ (declare (in) vec3 P)
+ (declare (in) float bias) )
+ ((return (txb (var_ref sampler) (var_ref P) (0 0 0) 1 () (var_ref bias) ))))
+
+)
+ (function shadow1D
+ (signature vec4
+ (parameters
+ (declare (in) sampler1DShadow sampler)
+ (declare (in) vec3 P)
+ (declare (in) float bias) )
+ ((return (txb (var_ref sampler) (swiz x (var_ref P)) (0 0 0) 1 (swiz z (var_ref P)) (var_ref bias) ))))
+
+)
+ (function shadow1DProj
+ (signature vec4
+ (parameters
+ (declare (in) sampler1DShadow sampler)
+ (declare (in) vec4 P)
+ (declare (in) float bias) )
+ ((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) ))))
+
+)
+ (function shadow2D
+ (signature vec4
+ (parameters
+ (declare (in) sampler2DShadow sampler)
+ (declare (in) vec3 P)
+ (declare (in) float bias) )
+ ((return (txb (var_ref sampler) (swiz xy (var_ref P)) (0 0 0) 1 (swiz z (var_ref P)) (var_ref bias) ))))
+
+)
+ (function shadow2DProj
+ (signature vec4
+ (parameters
+ (declare (in) sampler2DShadow sampler)
+ (declare (in) vec4 P)
+ (declare (in) float bias) )
+ ((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) ))))
+
+))
diff --git a/src/glsl/builtins/110_vs/ftransform b/src/glsl/builtins/110_vs/ftransform
new file mode 100644
index 00000000000..3a5e8ccecfc
--- /dev/null
+++ b/src/glsl/builtins/110_vs/ftransform
@@ -0,0 +1,7 @@
+((function ftransform
+ (signature vec4
+ (parameters)
+ ((return (expression vec4 *
+ (var_ref gl_ModelViewProjectionMatrix)
+ (var_ref gl_Vertex)))))
+))
diff --git a/src/glsl/builtins/120/matrixCompMult b/src/glsl/builtins/120/matrixCompMult
new file mode 100644
index 00000000000..69331e26525
--- /dev/null
+++ b/src/glsl/builtins/120/matrixCompMult
@@ -0,0 +1,61 @@
+((function matrixCompMult
+ (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/120/outerProduct b/src/glsl/builtins/120/outerProduct
new file mode 100644
index 00000000000..b401ba02337
--- /dev/null
+++ b/src/glsl/builtins/120/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 v) (swiz x (var_ref u))))
+ (assign (constant bool (1)) (array_ref (var_ref m) (constant int (1))) (expression vec2 * (var_ref v) (swiz y (var_ref u))))
+(return (var_ref m))))
+
+ (signature mat2x3
+ (parameters
+ (declare (in) vec2 u)
+ (declare (in) vec3 v))
+ ((declare () mat2x3 m)
+ (assign (constant bool (1)) (array_ref (var_ref m) (constant int (0))) (expression vec3 * (var_ref v) (swiz x (var_ref u))))
+ (assign (constant bool (1)) (array_ref (var_ref m) (constant int (1))) (expression vec3 * (var_ref v) (swiz y (var_ref u))))
+(return (var_ref m))))
+
+ (signature mat2x4
+ (parameters
+ (declare (in) vec2 u)
+ (declare (in) vec4 v))
+ ((declare () mat2x4 m)
+ (assign (constant bool (1)) (array_ref (var_ref m) (constant int (0))) (expression vec4 * (var_ref v) (swiz x (var_ref u))))
+ (assign (constant bool (1)) (array_ref (var_ref m) (constant int (1))) (expression vec4 * (var_ref v) (swiz y (var_ref u))))
+(return (var_ref m))))
+
+ (signature mat3x2
+ (parameters
+ (declare (in) vec3 u)
+ (declare (in) vec2 v))
+ ((declare () mat3x2 m)
+ (assign (constant bool (1)) (array_ref (var_ref m) (constant int (0))) (expression vec2 * (var_ref v) (swiz x (var_ref u))))
+ (assign (constant bool (1)) (array_ref (var_ref m) (constant int (1))) (expression vec2 * (var_ref v) (swiz y (var_ref u))))
+ (assign (constant bool (1)) (array_ref (var_ref m) (constant int (2))) (expression vec2 * (var_ref v) (swiz z (var_ref u))))
+(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 v) (swiz x (var_ref u))))
+ (assign (constant bool (1)) (array_ref (var_ref m) (constant int (1))) (expression vec3 * (var_ref v) (swiz y (var_ref u))))
+ (assign (constant bool (1)) (array_ref (var_ref m) (constant int (2))) (expression vec3 * (var_ref v) (swiz z (var_ref u))))
+(return (var_ref m))))
+
+ (signature mat3x4
+ (parameters
+ (declare (in) vec3 u)
+ (declare (in) vec4 v))
+ ((declare () mat3x4 m)
+ (assign (constant bool (1)) (array_ref (var_ref m) (constant int (0))) (expression vec4 * (var_ref v) (swiz x (var_ref u))))
+ (assign (constant bool (1)) (array_ref (var_ref m) (constant int (1))) (expression vec4 * (var_ref v) (swiz y (var_ref u))))
+ (assign (constant bool (1)) (array_ref (var_ref m) (constant int (2))) (expression vec4 * (var_ref v) (swiz z (var_ref u))))
+(return (var_ref m))))
+
+ (signature mat4x2
+ (parameters
+ (declare (in) vec4 u)
+ (declare (in) vec2 v))
+ ((declare () mat4x2 m)
+ (assign (constant bool (1)) (array_ref (var_ref m) (constant int (0))) (expression vec2 * (var_ref v) (swiz x (var_ref u))))
+ (assign (constant bool (1)) (array_ref (var_ref m) (constant int (1))) (expression vec2 * (var_ref v) (swiz y (var_ref u))))
+ (assign (constant bool (1)) (array_ref (var_ref m) (constant int (2))) (expression vec2 * (var_ref v) (swiz z (var_ref u))))
+ (assign (constant bool (1)) (array_ref (var_ref m) (constant int (3))) (expression vec2 * (var_ref v) (swiz w (var_ref u))))
+(return (var_ref m))))
+
+ (signature mat4x3
+ (parameters
+ (declare (in) vec4 u)
+ (declare (in) vec3 v))
+ ((declare () mat4x3 m)
+ (assign (constant bool (1)) (array_ref (var_ref m) (constant int (0))) (expression vec3 * (var_ref v) (swiz x (var_ref u))))
+ (assign (constant bool (1)) (array_ref (var_ref m) (constant int (1))) (expression vec3 * (var_ref v) (swiz y (var_ref u))))
+ (assign (constant bool (1)) (array_ref (var_ref m) (constant int (2))) (expression vec3 * (var_ref v) (swiz z (var_ref u))))
+ (assign (constant bool (1)) (array_ref (var_ref m) (constant int (3))) (expression vec3 * (var_ref v) (swiz w (var_ref u))))
+(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 v) (swiz x (var_ref u))))
+ (assign (constant bool (1)) (array_ref (var_ref m) (constant int (1))) (expression vec4 * (var_ref v) (swiz y (var_ref u))))
+ (assign (constant bool (1)) (array_ref (var_ref m) (constant int (2))) (expression vec4 * (var_ref v) (swiz z (var_ref u))))
+ (assign (constant bool (1)) (array_ref (var_ref m) (constant int (3))) (expression vec4 * (var_ref v) (swiz w (var_ref u))))
+(return (var_ref m))))
+))
+
diff --git a/src/glsl/builtins/120/transpose b/src/glsl/builtins/120/transpose
new file mode 100644
index 00000000000..416a0ee4677
--- /dev/null
+++ b/src/glsl/builtins/120/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/130/clamp b/src/glsl/builtins/130/clamp
new file mode 100644
index 00000000000..3aed22c20df
--- /dev/null
+++ b/src/glsl/builtins/130/clamp
@@ -0,0 +1,123 @@
+((function clamp
+ (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))
+ ((declare () ivec2 result)
+ (assign (constant bool (1)) (swiz x (var_ref result)) (expression ivec4 max (expression ivec4 min (swiz x (var_ref arg0)) (var_ref arg2)) (var_ref arg1)))
+ (assign (constant bool (1)) (swiz y (var_ref result)) (expression ivec4 max (expression ivec4 min (swiz y (var_ref arg0)) (var_ref arg2)) (var_ref arg1)))
+ (return (var_ref result))))
+
+ (signature ivec3
+ (parameters
+ (declare (in) ivec3 arg0)
+ (declare (in) int arg1)
+ (declare (in) int arg2))
+ ((declare () ivec3 result)
+ (assign (constant bool (1)) (swiz x (var_ref result)) (expression ivec4 max (expression ivec4 min (swiz x (var_ref arg0)) (var_ref arg2)) (var_ref arg1)))
+ (assign (constant bool (1)) (swiz y (var_ref result)) (expression ivec4 max (expression ivec4 min (swiz y (var_ref arg0)) (var_ref arg2)) (var_ref arg1)))
+ (assign (constant bool (1)) (swiz z (var_ref result)) (expression ivec4 max (expression ivec4 min (swiz z (var_ref arg0)) (var_ref arg2)) (var_ref arg1)))
+ (return (var_ref result))))
+
+ (signature ivec4
+ (parameters
+ (declare (in) ivec4 arg0)
+ (declare (in) int arg1)
+ (declare (in) int arg2))
+ ((declare () ivec4 result)
+ (assign (constant bool (1)) (swiz x (var_ref result)) (expression ivec4 max (expression ivec4 min (swiz x (var_ref arg0)) (var_ref arg2)) (var_ref arg1)))
+ (assign (constant bool (1)) (swiz y (var_ref result)) (expression ivec4 max (expression ivec4 min (swiz y (var_ref arg0)) (var_ref arg2)) (var_ref arg1)))
+ (assign (constant bool (1)) (swiz z (var_ref result)) (expression ivec4 max (expression ivec4 min (swiz z (var_ref arg0)) (var_ref arg2)) (var_ref arg1)))
+ (assign (constant bool (1)) (swiz w (var_ref result)) (expression ivec4 max (expression ivec4 min (swiz w (var_ref arg0)) (var_ref arg2)) (var_ref arg1)))
+ (return (var_ref result))))
+
+ (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))
+ ((declare () uvec2 result)
+ (assign (constant bool (1)) (swiz x (var_ref result)) (expression uvec4 max (expression uvec4 min (swiz x (var_ref arg0)) (var_ref arg2)) (var_ref arg1)))
+ (assign (constant bool (1)) (swiz y (var_ref result)) (expression uvec4 max (expression uvec4 min (swiz y (var_ref arg0)) (var_ref arg2)) (var_ref arg1)))
+ (return (var_ref result))))
+
+ (signature uvec3
+ (parameters
+ (declare (in) uvec3 arg0)
+ (declare (in) uint arg1)
+ (declare (in) uint arg2))
+ ((declare () uvec3 result)
+ (assign (constant bool (1)) (swiz x (var_ref result)) (expression uvec4 max (expression uvec4 min (swiz x (var_ref arg0)) (var_ref arg2)) (var_ref arg1)))
+ (assign (constant bool (1)) (swiz y (var_ref result)) (expression uvec4 max (expression uvec4 min (swiz y (var_ref arg0)) (var_ref arg2)) (var_ref arg1)))
+ (assign (constant bool (1)) (swiz z (var_ref result)) (expression uvec4 max (expression uvec4 min (swiz z (var_ref arg0)) (var_ref arg2)) (var_ref arg1)))
+ (return (var_ref result))))
+
+ (signature uvec4
+ (parameters
+ (declare (in) uvec4 arg0)
+ (declare (in) uint arg1)
+ (declare (in) uint arg2))
+ ((declare () uvec4 result)
+ (assign (constant bool (1)) (swiz x (var_ref result)) (expression uvec4 max (expression uvec4 min (swiz x (var_ref arg0)) (var_ref arg2)) (var_ref arg1)))
+ (assign (constant bool (1)) (swiz y (var_ref result)) (expression uvec4 max (expression uvec4 min (swiz y (var_ref arg0)) (var_ref arg2)) (var_ref arg1)))
+ (assign (constant bool (1)) (swiz z (var_ref result)) (expression uvec4 max (expression uvec4 min (swiz z (var_ref arg0)) (var_ref arg2)) (var_ref arg1)))
+ (assign (constant bool (1)) (swiz w (var_ref result)) (expression uvec4 max (expression uvec4 min (swiz w (var_ref arg0)) (var_ref arg2)) (var_ref arg1)))
+ (return (var_ref result))))
+))
diff --git a/src/glsl/builtins/130/cosh b/src/glsl/builtins/130/cosh
new file mode 100644
index 00000000000..45e0ae427d6
--- /dev/null
+++ b/src/glsl/builtins/130/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/130/equal b/src/glsl/builtins/130/equal
new file mode 100644
index 00000000000..079c3e97fb2
--- /dev/null
+++ b/src/glsl/builtins/130/equal
@@ -0,0 +1,31 @@
+((function equal
+ (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/130/greaterThan b/src/glsl/builtins/130/greaterThan
new file mode 100644
index 00000000000..a9fb7b3a43e
--- /dev/null
+++ b/src/glsl/builtins/130/greaterThan
@@ -0,0 +1,31 @@
+((function greaterThan
+ (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/130/greaterThanEqual b/src/glsl/builtins/130/greaterThanEqual
new file mode 100644
index 00000000000..293c93c7cca
--- /dev/null
+++ b/src/glsl/builtins/130/greaterThanEqual
@@ -0,0 +1,31 @@
+((function greaterThanEqual
+ (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/130/lessThan b/src/glsl/builtins/130/lessThan
new file mode 100644
index 00000000000..d9f693fd63f
--- /dev/null
+++ b/src/glsl/builtins/130/lessThan
@@ -0,0 +1,31 @@
+((function lessThan
+ (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/130/lessThanEqual b/src/glsl/builtins/130/lessThanEqual
new file mode 100644
index 00000000000..494411b869a
--- /dev/null
+++ b/src/glsl/builtins/130/lessThanEqual
@@ -0,0 +1,31 @@
+((function lessThanEqual
+ (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/130/max b/src/glsl/builtins/130/max
new file mode 100644
index 00000000000..45a6089c9f2
--- /dev/null
+++ b/src/glsl/builtins/130/max
@@ -0,0 +1,127 @@
+((function max
+ (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))
+ ((declare () ivec2 result)
+ (assign (constant bool (1)) (swiz x (var_ref result))
+ (expression int max (swiz x (var_ref arg0)) (var_ref arg1)))
+ (assign (constant bool (1)) (swiz y (var_ref result))
+ (expression int max (swiz y (var_ref arg0)) (var_ref arg1)))
+ (return (var_ref result))))
+
+ (signature ivec3
+ (parameters
+ (declare (in) ivec3 arg0)
+ (declare (in) int arg1))
+ ((declare () ivec3 result)
+ (assign (constant bool (1)) (swiz x (var_ref result))
+ (expression int max (swiz x (var_ref arg0)) (var_ref arg1)))
+ (assign (constant bool (1)) (swiz y (var_ref result))
+ (expression int max (swiz y (var_ref arg0)) (var_ref arg1)))
+ (assign (constant bool (1)) (swiz z (var_ref result))
+ (expression int max (swiz z (var_ref arg0)) (var_ref arg1)))
+ (return (var_ref result))))
+
+ (signature ivec4
+ (parameters
+ (declare (in) ivec4 arg0)
+ (declare (in) int arg1))
+ ((declare () ivec4 result)
+ (assign (constant bool (1)) (swiz x (var_ref result))
+ (expression int max (swiz x (var_ref arg0)) (var_ref arg1)))
+ (assign (constant bool (1)) (swiz y (var_ref result))
+ (expression int max (swiz y (var_ref arg0)) (var_ref arg1)))
+ (assign (constant bool (1)) (swiz z (var_ref result))
+ (expression int max (swiz z (var_ref arg0)) (var_ref arg1)))
+ (assign (constant bool (1)) (swiz w (var_ref result))
+ (expression int max (swiz w (var_ref arg0)) (var_ref arg1)))
+ (return (var_ref result))))
+
+ (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))
+ ((declare () uvec2 result)
+ (assign (constant bool (1)) (swiz x (var_ref result))
+ (expression uint max (swiz x (var_ref arg0)) (var_ref arg1)))
+ (assign (constant bool (1)) (swiz y (var_ref result))
+ (expression uint max (swiz y (var_ref arg0)) (var_ref arg1)))
+ (return (var_ref result))))
+
+ (signature uvec3
+ (parameters
+ (declare (in) uvec3 arg0)
+ (declare (in) uint arg1))
+ ((declare () uvec3 result)
+ (assign (constant bool (1)) (swiz x (var_ref result))
+ (expression uint max (swiz x (var_ref arg0)) (var_ref arg1)))
+ (assign (constant bool (1)) (swiz y (var_ref result))
+ (expression uint max (swiz y (var_ref arg0)) (var_ref arg1)))
+ (assign (constant bool (1)) (swiz z (var_ref result))
+ (expression uint max (swiz z (var_ref arg0)) (var_ref arg1)))
+ (return (var_ref result))))
+
+ (signature uvec4
+ (parameters
+ (declare (in) uvec4 arg0)
+ (declare (in) uint arg1))
+ ((declare () uvec4 result)
+ (assign (constant bool (1)) (swiz x (var_ref result))
+ (expression uint max (swiz x (var_ref arg0)) (var_ref arg1)))
+ (assign (constant bool (1)) (swiz y (var_ref result))
+ (expression uint max (swiz y (var_ref arg0)) (var_ref arg1)))
+ (assign (constant bool (1)) (swiz z (var_ref result))
+ (expression uint max (swiz z (var_ref arg0)) (var_ref arg1)))
+ (assign (constant bool (1)) (swiz w (var_ref result))
+ (expression uint max (swiz w (var_ref arg0)) (var_ref arg1)))
+ (return (var_ref result))))
+))
diff --git a/src/glsl/builtins/130/min b/src/glsl/builtins/130/min
new file mode 100644
index 00000000000..d98ec1e79da
--- /dev/null
+++ b/src/glsl/builtins/130/min
@@ -0,0 +1,127 @@
+((function min
+ (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))
+ ((declare () ivec2 result)
+ (assign (constant bool (1)) (swiz x (var_ref result))
+ (expression int min (swiz x (var_ref arg0)) (var_ref arg1)))
+ (assign (constant bool (1)) (swiz y (var_ref result))
+ (expression int min (swiz y (var_ref arg0)) (var_ref arg1)))
+ (return (var_ref result))))
+
+ (signature ivec3
+ (parameters
+ (declare (in) ivec3 arg0)
+ (declare (in) int arg1))
+ ((declare () ivec3 result)
+ (assign (constant bool (1)) (swiz x (var_ref result))
+ (expression int min (swiz x (var_ref arg0)) (var_ref arg1)))
+ (assign (constant bool (1)) (swiz y (var_ref result))
+ (expression int min (swiz y (var_ref arg0)) (var_ref arg1)))
+ (assign (constant bool (1)) (swiz z (var_ref result))
+ (expression int min (swiz z (var_ref arg0)) (var_ref arg1)))
+ (return (var_ref result))))
+
+ (signature ivec4
+ (parameters
+ (declare (in) ivec4 arg0)
+ (declare (in) int arg1))
+ ((declare () ivec4 result)
+ (assign (constant bool (1)) (swiz x (var_ref result))
+ (expression int min (swiz x (var_ref arg0)) (var_ref arg1)))
+ (assign (constant bool (1)) (swiz y (var_ref result))
+ (expression int min (swiz y (var_ref arg0)) (var_ref arg1)))
+ (assign (constant bool (1)) (swiz z (var_ref result))
+ (expression int min (swiz z (var_ref arg0)) (var_ref arg1)))
+ (assign (constant bool (1)) (swiz w (var_ref result))
+ (expression int min (swiz w (var_ref arg0)) (var_ref arg1)))
+ (return (var_ref result))))
+
+ (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))
+ ((declare () uvec2 result)
+ (assign (constant bool (1)) (swiz x (var_ref result))
+ (expression uint min (swiz x (var_ref arg0)) (var_ref arg1)))
+ (assign (constant bool (1)) (swiz y (var_ref result))
+ (expression uint min (swiz y (var_ref arg0)) (var_ref arg1)))
+ (return (var_ref result))))
+
+ (signature uvec3
+ (parameters
+ (declare (in) uvec3 arg0)
+ (declare (in) uint arg1))
+ ((declare () uvec3 result)
+ (assign (constant bool (1)) (swiz x (var_ref result))
+ (expression uint min (swiz x (var_ref arg0)) (var_ref arg1)))
+ (assign (constant bool (1)) (swiz y (var_ref result))
+ (expression uint min (swiz y (var_ref arg0)) (var_ref arg1)))
+ (assign (constant bool (1)) (swiz z (var_ref result))
+ (expression uint min (swiz z (var_ref arg0)) (var_ref arg1)))
+ (return (var_ref result))))
+
+ (signature uvec4
+ (parameters
+ (declare (in) uvec4 arg0)
+ (declare (in) uint arg1))
+ ((declare () uvec4 result)
+ (assign (constant bool (1)) (swiz x (var_ref result))
+ (expression uint min (swiz x (var_ref arg0)) (var_ref arg1)))
+ (assign (constant bool (1)) (swiz y (var_ref result))
+ (expression uint min (swiz y (var_ref arg0)) (var_ref arg1)))
+ (assign (constant bool (1)) (swiz z (var_ref result))
+ (expression uint min (swiz z (var_ref arg0)) (var_ref arg1)))
+ (assign (constant bool (1)) (swiz w (var_ref result))
+ (expression uint min (swiz w (var_ref arg0)) (var_ref arg1)))
+ (return (var_ref result))))
+))
diff --git a/src/glsl/builtins/130/notEqual b/src/glsl/builtins/130/notEqual
new file mode 100644
index 00000000000..81e6376bd9c
--- /dev/null
+++ b/src/glsl/builtins/130/notEqual
@@ -0,0 +1,31 @@
+((function notEqual
+ (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/130/sign b/src/glsl/builtins/130/sign
new file mode 100644
index 00000000000..0bdc0e09d25
--- /dev/null
+++ b/src/glsl/builtins/130/sign
@@ -0,0 +1,34 @@
+((function sign
+ (signature int
+ (parameters
+ (declare (in) int x))
+ ((return (expression int / (var_ref x) (expression int abs (var_ref x))))))
+
+ (signature ivec2
+ (parameters
+ (declare (in) ivec2 x))
+ ((declare () ivec2 t)
+ (assign (constant bool (1)) (swiz x (var_ref t)) (expression int sign (swiz x (var_ref x))))
+ (assign (constant bool (1)) (swiz y (var_ref t)) (expression int sign (swiz y (var_ref x))))
+ (return (var_ref t))))
+
+ (signature ivec3
+ (parameters
+ (declare (in) ivec3 x))
+ ((declare () ivec3 t)
+ (assign (constant bool (1)) (swiz x (var_ref t)) (expression int sign (swiz x (var_ref x))))
+ (assign (constant bool (1)) (swiz y (var_ref t)) (expression int sign (swiz y (var_ref x))))
+ (assign (constant bool (1)) (swiz z (var_ref t)) (expression int sign (swiz z (var_ref x))))
+ (return (var_ref t))))
+
+ (signature ivec4
+ (parameters
+ (declare (in) ivec4 x))
+ ((declare () ivec4 t)
+ (assign (constant bool (1)) (swiz x (var_ref t)) (expression int sign (swiz x (var_ref x))))
+ (assign (constant bool (1)) (swiz y (var_ref t)) (expression int sign (swiz y (var_ref x))))
+ (assign (constant bool (1)) (swiz z (var_ref t)) (expression int sign (swiz z (var_ref x))))
+ (assign (constant bool (1)) (swiz w (var_ref t)) (expression int sign (swiz w (var_ref x))))
+ (return (var_ref t))))
+))
+
diff --git a/src/glsl/builtins/130/sinh b/src/glsl/builtins/130/sinh
new file mode 100644
index 00000000000..7ad4f58e204
--- /dev/null
+++ b/src/glsl/builtins/130/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/130/tanh b/src/glsl/builtins/130/tanh
new file mode 100644
index 00000000000..3b7271bf779
--- /dev/null
+++ b/src/glsl/builtins/130/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/130/texelFetch b/src/glsl/builtins/130/texelFetch
new file mode 100644
index 00000000000..d51ce65a897
--- /dev/null
+++ b/src/glsl/builtins/130/texelFetch
@@ -0,0 +1,107 @@
+((function texelFetch
+ (signature vec4
+ (parameters
+ (declare (in) sampler1D sampler)
+ (declare (in) int P)
+ (declare (in) int lod) )
+ ((return (txf (var_ref sampler) (var_ref P) (0 0 0) (var_ref lod) ))))
+
+ (signature ivec4
+ (parameters
+ (declare (in) isampler1D sampler)
+ (declare (in) int P)
+ (declare (in) int lod) )
+ ((return (txf (var_ref sampler) (var_ref P) (0 0 0) (var_ref lod) ))))
+
+ (signature uvec4
+ (parameters
+ (declare (in) usampler1D sampler)
+ (declare (in) int P)
+ (declare (in) int lod) )
+ ((return (txf (var_ref sampler) (var_ref P) (0 0 0) (var_ref lod) ))))
+
+ (signature vec4
+ (parameters
+ (declare (in) sampler2D sampler)
+ (declare (in) ivec2 P)
+ (declare (in) int lod) )
+ ((return (txf (var_ref sampler) (var_ref P) (0 0 0) (var_ref lod) ))))
+
+ (signature ivec4
+ (parameters
+ (declare (in) isampler2D sampler)
+ (declare (in) ivec2 P)
+ (declare (in) int lod) )
+ ((return (txf (var_ref sampler) (var_ref P) (0 0 0) (var_ref lod) ))))
+
+ (signature uvec4
+ (parameters
+ (declare (in) usampler2D sampler)
+ (declare (in) ivec2 P)
+ (declare (in) int lod) )
+ ((return (txf (var_ref sampler) (var_ref P) (0 0 0) (var_ref lod) ))))
+
+ (signature vec4
+ (parameters
+ (declare (in) sampler3D sampler)
+ (declare (in) ivec3 P)
+ (declare (in) int lod) )
+ ((return (txf (var_ref sampler) (var_ref P) (0 0 0) (var_ref lod) ))))
+
+ (signature ivec4
+ (parameters
+ (declare (in) isampler3D sampler)
+ (declare (in) ivec3 P)
+ (declare (in) int lod) )
+ ((return (txf (var_ref sampler) (var_ref P) (0 0 0) (var_ref lod) ))))
+
+ (signature uvec4
+ (parameters
+ (declare (in) usampler3D sampler)
+ (declare (in) ivec3 P)
+ (declare (in) int lod) )
+ ((return (txf (var_ref sampler) (var_ref P) (0 0 0) (var_ref lod) ))))
+
+ (signature vec4
+ (parameters
+ (declare (in) sampler1DArray sampler)
+ (declare (in) ivec2 P)
+ (declare (in) int lod) )
+ ((return (txf (var_ref sampler) (var_ref P) (0 0 0) (var_ref lod) ))))
+
+ (signature ivec4
+ (parameters
+ (declare (in) isampler1DArray sampler)
+ (declare (in) ivec2 P)
+ (declare (in) int lod) )
+ ((return (txf (var_ref sampler) (var_ref P) (0 0 0) (var_ref lod) ))))
+
+ (signature uvec4
+ (parameters
+ (declare (in) usampler1DArray sampler)
+ (declare (in) ivec2 P)
+ (declare (in) int lod) )
+ ((return (txf (var_ref sampler) (var_ref P) (0 0 0) (var_ref lod) ))))
+
+ (signature vec4
+ (parameters
+ (declare (in) sampler2DArray sampler)
+ (declare (in) ivec3 P)
+ (declare (in) int lod) )
+ ((return (txf (var_ref sampler) (var_ref P) (0 0 0) (var_ref lod) ))))
+
+ (signature ivec4
+ (parameters
+ (declare (in) isampler2DArray sampler)
+ (declare (in) ivec3 P)
+ (declare (in) int lod) )
+ ((return (txf (var_ref sampler) (var_ref P) (0 0 0) (var_ref lod) ))))
+
+ (signature uvec4
+ (parameters
+ (declare (in) usampler2DArray sampler)
+ (declare (in) ivec3 P)
+ (declare (in) int lod) )
+ ((return (txf (var_ref sampler) (var_ref P) (0 0 0) (var_ref lod) ))))
+
+))
diff --git a/src/glsl/builtins/130/texture b/src/glsl/builtins/130/texture
new file mode 100644
index 00000000000..b170b583094
--- /dev/null
+++ b/src/glsl/builtins/130/texture
@@ -0,0 +1,110 @@
+((function texture
+ (signature vec4
+ (parameters
+ (declare (in) sampler1D sampler)
+ (declare (in) float P) )
+ ((return (tex (var_ref sampler) (var_ref P) (0 0 0) 1 () ))))
+
+ (signature ivec4
+ (parameters
+ (declare (in) isampler1D sampler)
+ (declare (in) float P) )
+ ((return (tex (var_ref sampler) (var_ref P) (0 0 0) 1 () ))))
+
+ (signature uvec4
+ (parameters
+ (declare (in) usampler1D sampler)
+ (declare (in) float P) )
+ ((return (tex (var_ref sampler) (var_ref P) (0 0 0) 1 () ))))
+
+ (signature vec4
+ (parameters
+ (declare (in) sampler2D sampler)
+ (declare (in) vec2 P) )
+ ((return (tex (var_ref sampler) (var_ref P) (0 0 0) 1 () ))))
+
+ (signature ivec4
+ (parameters
+ (declare (in) isampler2D sampler)
+ (declare (in) vec2 P) )
+ ((return (tex (var_ref sampler) (var_ref P) (0 0 0) 1 () ))))
+
+ (signature uvec4
+ (parameters
+ (declare (in) usampler2D sampler)
+ (declare (in) vec2 P) )
+ ((return (tex (var_ref sampler) (var_ref P) (0 0 0) 1 () ))))
+
+ (signature vec4
+ (parameters
+ (declare (in) sampler3D sampler)
+ (declare (in) vec3 P) )
+ ((return (tex (var_ref sampler) (var_ref P) (0 0 0) 1 () ))))
+
+ (signature ivec4
+ (parameters
+ (declare (in) isampler3D sampler)
+ (declare (in) vec3 P) )
+ ((return (tex (var_ref sampler) (var_ref P) (0 0 0) 1 () ))))
+
+ (signature uvec4
+ (parameters
+ (declare (in) usampler3D sampler)
+ (declare (in) vec3 P) )
+ ((return (tex (var_ref sampler) (var_ref P) (0 0 0) 1 () ))))
+
+ (signature vec4
+ (parameters
+ (declare (in) samplerCube sampler)
+ (declare (in) vec3 P) )
+ ((return (tex (var_ref sampler) (var_ref P) (0 0 0) 1 () ))))
+
+ (signature ivec4
+ (parameters
+ (declare (in) isamplerCube sampler)
+ (declare (in) vec3 P) )
+ ((return (tex (var_ref sampler) (var_ref P) (0 0 0) 1 () ))))
+
+ (signature uvec4
+ (parameters
+ (declare (in) usamplerCube sampler)
+ (declare (in) vec3 P) )
+ ((return (tex (var_ref sampler) (var_ref P) (0 0 0) 1 () ))))
+
+ (signature vec4
+ (parameters
+ (declare (in) sampler1DArray sampler)
+ (declare (in) vec2 P) )
+ ((return (tex (var_ref sampler) (var_ref P) (0 0 0) 1 () ))))
+
+ (signature ivec4
+ (parameters
+ (declare (in) isampler1DArray sampler)
+ (declare (in) vec2 P) )
+ ((return (tex (var_ref sampler) (var_ref P) (0 0 0) 1 () ))))
+
+ (signature uvec4
+ (parameters
+ (declare (in) usampler1DArray sampler)
+ (declare (in) vec2 P) )
+ ((return (tex (var_ref sampler) (var_ref P) (0 0 0) 1 () ))))
+
+ (signature vec4
+ (parameters
+ (declare (in) sampler2DArray sampler)
+ (declare (in) vec3 P) )
+ ((return (tex (var_ref sampler) (var_ref P) (0 0 0) 1 () ))))
+
+ (signature ivec4
+ (parameters
+ (declare (in) isampler2DArray sampler)
+ (declare (in) vec3 P) )
+ ((return (tex (var_ref sampler) (var_ref P) (0 0 0) 1 () ))))
+
+ (signature uvec4
+ (parameters
+ (declare (in) usampler2DArray sampler)
+ (declare (in) vec3 P) )
+ ((return (tex (var_ref sampler) (var_ref P) (0 0 0) 1 () ))))
+
+))
diff --git a/src/glsl/builtins/130/textureGrad b/src/glsl/builtins/130/textureGrad
new file mode 100644
index 00000000000..0ef428c224a
--- /dev/null
+++ b/src/glsl/builtins/130/textureGrad
@@ -0,0 +1,147 @@
+((function textureGrad
+ (signature vec4
+ (parameters
+ (declare (in) sampler1D sampler)
+ (declare (in) float P)
+ (declare (in) float dPdx)
+ (declare (in) float dPdy) )
+ ((return (txd (var_ref sampler) (var_ref P) (0 0 0) 1 () ((var_ref dPdx) (var_ref dPdy)) ))))
+
+ (signature ivec4
+ (parameters
+ (declare (in) isampler1D sampler)
+ (declare (in) float P)
+ (declare (in) float dPdx)
+ (declare (in) float dPdy) )
+ ((return (txd (var_ref sampler) (var_ref P) (0 0 0) 1 () ((var_ref dPdx) (var_ref dPdy)) ))))
+
+ (signature uvec4
+ (parameters
+ (declare (in) usampler1D sampler)
+ (declare (in) float P)
+ (declare (in) float dPdx)
+ (declare (in) float dPdy) )
+ ((return (txd (var_ref sampler) (var_ref P) (0 0 0) 1 () ((var_ref dPdx) (var_ref dPdy)) ))))
+
+ (signature vec4
+ (parameters
+ (declare (in) sampler2D sampler)
+ (declare (in) vec2 P)
+ (declare (in) vec2 dPdx)
+ (declare (in) vec2 dPdy) )
+ ((return (txd (var_ref sampler) (var_ref P) (0 0 0) 1 () ((var_ref dPdx) (var_ref dPdy)) ))))
+
+ (signature ivec4
+ (parameters
+ (declare (in) isampler2D sampler)
+ (declare (in) vec2 P)
+ (declare (in) vec2 dPdx)
+ (declare (in) vec2 dPdy) )
+ ((return (txd (var_ref sampler) (var_ref P) (0 0 0) 1 () ((var_ref dPdx) (var_ref dPdy)) ))))
+
+ (signature uvec4
+ (parameters
+ (declare (in) usampler2D sampler)
+ (declare (in) vec2 P)
+ (declare (in) vec2 dPdx)
+ (declare (in) vec2 dPdy) )
+ ((return (txd (var_ref sampler) (var_ref P) (0 0 0) 1 () ((var_ref dPdx) (var_ref dPdy)) ))))
+
+ (signature vec4
+ (parameters
+ (declare (in) sampler3D sampler)
+ (declare (in) vec3 P)
+ (declare (in) vec3 dPdx)
+ (declare (in) vec3 dPdy) )
+ ((return (txd (var_ref sampler) (var_ref P) (0 0 0) 1 () ((var_ref dPdx) (var_ref dPdy)) ))))
+
+ (signature ivec4
+ (parameters
+ (declare (in) isampler3D sampler)
+ (declare (in) vec3 P)
+ (declare (in) vec3 dPdx)
+ (declare (in) vec3 dPdy) )
+ ((return (txd (var_ref sampler) (var_ref P) (0 0 0) 1 () ((var_ref dPdx) (var_ref dPdy)) ))))
+
+ (signature uvec4
+ (parameters
+ (declare (in) usampler3D sampler)
+ (declare (in) vec3 P)
+ (declare (in) vec3 dPdx)
+ (declare (in) vec3 dPdy) )
+ ((return (txd (var_ref sampler) (var_ref P) (0 0 0) 1 () ((var_ref dPdx) (var_ref dPdy)) ))))
+
+ (signature vec4
+ (parameters
+ (declare (in) samplerCube sampler)
+ (declare (in) vec3 P)
+ (declare (in) vec3 dPdx)
+ (declare (in) vec3 dPdy) )
+ ((return (txd (var_ref sampler) (var_ref P) (0 0 0) 1 () ((var_ref dPdx) (var_ref dPdy)) ))))
+
+ (signature ivec4
+ (parameters
+ (declare (in) isamplerCube sampler)
+ (declare (in) vec3 P)
+ (declare (in) vec3 dPdx)
+ (declare (in) vec3 dPdy) )
+ ((return (txd (var_ref sampler) (var_ref P) (0 0 0) 1 () ((var_ref dPdx) (var_ref dPdy)) ))))
+
+ (signature uvec4
+ (parameters
+ (declare (in) usamplerCube sampler)
+ (declare (in) vec3 P)
+ (declare (in) vec3 dPdx)
+ (declare (in) vec3 dPdy) )
+ ((return (txd (var_ref sampler) (var_ref P) (0 0 0) 1 () ((var_ref dPdx) (var_ref dPdy)) ))))
+
+ (signature vec4
+ (parameters
+ (declare (in) sampler1DArray sampler)
+ (declare (in) vec2 P)
+ (declare (in) vec2 dPdx)
+ (declare (in) vec2 dPdy) )
+ ((return (txd (var_ref sampler) (var_ref P) (0 0 0) 1 () ((var_ref dPdx) (var_ref dPdy)) ))))
+
+ (signature ivec4
+ (parameters
+ (declare (in) isampler1DArray sampler)
+ (declare (in) vec2 P)
+ (declare (in) vec2 dPdx)
+ (declare (in) vec2 dPdy) )
+ ((return (txd (var_ref sampler) (var_ref P) (0 0 0) 1 () ((var_ref dPdx) (var_ref dPdy)) ))))
+
+ (signature uvec4
+ (parameters
+ (declare (in) usampler1DArray sampler)
+ (declare (in) vec2 P)
+ (declare (in) vec2 dPdx)
+ (declare (in) vec2 dPdy) )
+ ((return (txd (var_ref sampler) (var_ref P) (0 0 0) 1 () ((var_ref dPdx) (var_ref dPdy)) ))))
+
+ (signature vec4
+ (parameters
+ (declare (in) sampler2DArray sampler)
+ (declare (in) vec3 P)
+ (declare (in) vec3 dPdx)
+ (declare (in) vec3 dPdy) )
+ ((return (txd (var_ref sampler) (var_ref P) (0 0 0) 1 () ((var_ref dPdx) (var_ref dPdy)) ))))
+
+ (signature ivec4
+ (parameters
+ (declare (in) isampler2DArray sampler)
+ (declare (in) vec3 P)
+ (declare (in) vec3 dPdx)
+ (declare (in) vec3 dPdy) )
+ ((return (txd (var_ref sampler) (var_ref P) (0 0 0) 1 () ((var_ref dPdx) (var_ref dPdy)) ))))
+
+ (signature uvec4
+ (parameters
+ (declare (in) usampler2DArray sampler)
+ (declare (in) vec3 P)
+ (declare (in) vec3 dPdx)
+ (declare (in) vec3 dPdy) )
+ ((return (txd (var_ref sampler) (var_ref P) (0 0 0) 1 () ((var_ref dPdx) (var_ref dPdy)) ))))
+
+)
+)
diff --git a/src/glsl/builtins/130/textureLod b/src/glsl/builtins/130/textureLod
new file mode 100644
index 00000000000..7d7059d848c
--- /dev/null
+++ b/src/glsl/builtins/130/textureLod
@@ -0,0 +1,128 @@
+((function textureLod
+ (signature vec4
+ (parameters
+ (declare (in) sampler1D sampler)
+ (declare (in) float P)
+ (declare (in) float lod) )
+ ((return (txl (var_ref sampler) (var_ref P) (0 0 0) 1 () (var_ref lod) ))))
+
+ (signature ivec4
+ (parameters
+ (declare (in) isampler1D sampler)
+ (declare (in) float P)
+ (declare (in) float lod) )
+ ((return (txl (var_ref sampler) (var_ref P) (0 0 0) 1 () (var_ref lod) ))))
+
+ (signature uvec4
+ (parameters
+ (declare (in) usampler1D sampler)
+ (declare (in) float P)
+ (declare (in) float lod) )
+ ((return (txl (var_ref sampler) (var_ref P) (0 0 0) 1 () (var_ref lod) ))))
+
+ (signature vec4
+ (parameters
+ (declare (in) sampler2D sampler)
+ (declare (in) vec2 P)
+ (declare (in) float lod) )
+ ((return (txl (var_ref sampler) (var_ref P) (0 0 0) 1 () (var_ref lod) ))))
+
+ (signature ivec4
+ (parameters
+ (declare (in) isampler2D sampler)
+ (declare (in) vec2 P)
+ (declare (in) float lod) )
+ ((return (txl (var_ref sampler) (var_ref P) (0 0 0) 1 () (var_ref lod) ))))
+
+ (signature uvec4
+ (parameters
+ (declare (in) usampler2D sampler)
+ (declare (in) vec2 P)
+ (declare (in) float lod) )
+ ((return (txl (var_ref sampler) (var_ref P) (0 0 0) 1 () (var_ref lod) ))))
+
+ (signature vec4
+ (parameters
+ (declare (in) sampler3D sampler)
+ (declare (in) vec3 P)
+ (declare (in) float lod) )
+ ((return (txl (var_ref sampler) (var_ref P) (0 0 0) 1 () (var_ref lod) ))))
+
+ (signature ivec4
+ (parameters
+ (declare (in) isampler3D sampler)
+ (declare (in) vec3 P)
+ (declare (in) float lod) )
+ ((return (txl (var_ref sampler) (var_ref P) (0 0 0) 1 () (var_ref lod) ))))
+
+ (signature uvec4
+ (parameters
+ (declare (in) usampler3D sampler)
+ (declare (in) vec3 P)
+ (declare (in) float lod) )
+ ((return (txl (var_ref sampler) (var_ref P) (0 0 0) 1 () (var_ref lod) ))))
+
+ (signature vec4
+ (parameters
+ (declare (in) samplerCube sampler)
+ (declare (in) vec3 P)
+ (declare (in) float lod) )
+ ((return (txl (var_ref sampler) (var_ref P) (0 0 0) 1 () (var_ref lod) ))))
+
+ (signature ivec4
+ (parameters
+ (declare (in) isamplerCube sampler)
+ (declare (in) vec3 P)
+ (declare (in) float lod) )
+ ((return (txl (var_ref sampler) (var_ref P) (0 0 0) 1 () (var_ref lod) ))))
+
+ (signature uvec4
+ (parameters
+ (declare (in) usamplerCube sampler)
+ (declare (in) vec3 P)
+ (declare (in) float lod) )
+ ((return (txl (var_ref sampler) (var_ref P) (0 0 0) 1 () (var_ref lod) ))))
+
+ (signature vec4
+ (parameters
+ (declare (in) sampler1DArray sampler)
+ (declare (in) vec2 P)
+ (declare (in) float lod) )
+ ((return (txl (var_ref sampler) (var_ref P) (0 0 0) 1 () (var_ref lod) ))))
+
+ (signature ivec4
+ (parameters
+ (declare (in) isampler1DArray sampler)
+ (declare (in) vec2 P)
+ (declare (in) float lod) )
+ ((return (txl (var_ref sampler) (var_ref P) (0 0 0) 1 () (var_ref lod) ))))
+
+ (signature uvec4
+ (parameters
+ (declare (in) usampler1DArray sampler)
+ (declare (in) vec2 P)
+ (declare (in) float lod) )
+ ((return (txl (var_ref sampler) (var_ref P) (0 0 0) 1 () (var_ref lod) ))))
+
+ (signature vec4
+ (parameters
+ (declare (in) sampler2DArray sampler)
+ (declare (in) vec3 P)
+ (declare (in) float lod) )
+ ((return (txl (var_ref sampler) (var_ref P) (0 0 0) 1 () (var_ref lod) ))))
+
+ (signature ivec4
+ (parameters
+ (declare (in) isampler2DArray sampler)
+ (declare (in) vec3 P)
+ (declare (in) float lod) )
+ ((return (txl (var_ref sampler) (var_ref P) (0 0 0) 1 () (var_ref lod) ))))
+
+ (signature uvec4
+ (parameters
+ (declare (in) usampler2DArray sampler)
+ (declare (in) vec3 P)
+ (declare (in) float lod) )
+ ((return (txl (var_ref sampler) (var_ref P) (0 0 0) 1 () (var_ref lod) ))))
+
+))
diff --git a/src/glsl/builtins/130/textureProj b/src/glsl/builtins/130/textureProj
new file mode 100644
index 00000000000..40ea1c2af68
--- /dev/null
+++ b/src/glsl/builtins/130/textureProj
@@ -0,0 +1,92 @@
+((function textureProj
+ (signature vec4
+ (parameters
+ (declare (in) sampler1D sampler)
+ (declare (in) vec2 P) )
+ ((return (tex (var_ref sampler) (swiz x (var_ref P)) (0 0 0) (swiz y (var_ref P)) () ))))
+
+ (signature ivec4
+ (parameters
+ (declare (in) isampler1D sampler)
+ (declare (in) vec2 P) )
+ ((return (tex (var_ref sampler) (swiz x (var_ref P)) (0 0 0) (swiz y (var_ref P)) () ))))
+
+ (signature uvec4
+ (parameters
+ (declare (in) usampler1D sampler)
+ (declare (in) vec2 P) )
+ ((return (tex (var_ref sampler) (swiz x (var_ref P)) (0 0 0) (swiz y (var_ref P)) () ))))
+
+ (signature vec4
+ (parameters
+ (declare (in) sampler1D sampler)
+ (declare (in) vec4 P) )
+ ((return (tex (var_ref sampler) (swiz x (var_ref P)) (0 0 0) (swiz w (var_ref P)) () ))))
+
+ (signature ivec4
+ (parameters
+ (declare (in) isampler1D sampler)
+ (declare (in) vec4 P) )
+ ((return (tex (var_ref sampler) (swiz x (var_ref P)) (0 0 0) (swiz w (var_ref P)) () ))))
+
+ (signature uvec4
+ (parameters
+ (declare (in) usampler1D sampler)
+ (declare (in) vec4 P) )
+ ((return (tex (var_ref sampler) (swiz x (var_ref P)) (0 0 0) (swiz w (var_ref P)) () ))))
+
+ (signature vec4
+ (parameters
+ (declare (in) sampler2D sampler)
+ (declare (in) vec3 P) )
+ ((return (tex (var_ref sampler) (swiz xy (var_ref P)) (0 0 0) (swiz z (var_ref P)) () ))))
+
+ (signature ivec4
+ (parameters
+ (declare (in) isampler2D sampler)
+ (declare (in) vec3 P) )
+ ((return (tex (var_ref sampler) (swiz xy (var_ref P)) (0 0 0) (swiz z (var_ref P)) () ))))
+
+ (signature uvec4
+ (parameters
+ (declare (in) usampler2D sampler)
+ (declare (in) vec3 P) )
+ ((return (tex (var_ref sampler) (swiz xy (var_ref P)) (0 0 0) (swiz z (var_ref P)) () ))))
+
+ (signature vec4
+ (parameters
+ (declare (in) sampler2D sampler)
+ (declare (in) vec4 P) )
+ ((return (tex (var_ref sampler) (swiz xy (var_ref P)) (0 0 0) (swiz w (var_ref P)) () ))))
+
+ (signature ivec4
+ (parameters
+ (declare (in) isampler2D sampler)
+ (declare (in) vec4 P) )
+ ((return (tex (var_ref sampler) (swiz xy (var_ref P)) (0 0 0) (swiz w (var_ref P)) () ))))
+
+ (signature uvec4
+ (parameters
+ (declare (in) usampler2D sampler)
+ (declare (in) vec4 P) )
+ ((return (tex (var_ref sampler) (swiz xy (var_ref P)) (0 0 0) (swiz w (var_ref P)) () ))))
+
+ (signature vec4
+ (parameters
+ (declare (in) sampler3D sampler)
+ (declare (in) vec4 P) )
+ ((return (tex (var_ref sampler) (swiz xyz (var_ref P)) (0 0 0) (swiz w (var_ref P)) () ))))
+
+ (signature ivec4
+ (parameters
+ (declare (in) isampler3D sampler)
+ (declare (in) vec4 P) )
+ ((return (tex (var_ref sampler) (swiz xyz (var_ref P)) (0 0 0) (swiz w (var_ref P)) () ))))
+
+ (signature uvec4
+ (parameters
+ (declare (in) usampler3D sampler)
+ (declare (in) vec4 P) )
+ ((return (tex (var_ref sampler) (swiz xyz (var_ref P)) (0 0 0) (swiz w (var_ref P)) () ))))
+
+))
diff --git a/src/glsl/builtins/130/textureProjGrad b/src/glsl/builtins/130/textureProjGrad
new file mode 100644
index 00000000000..a0142c5e683
--- /dev/null
+++ b/src/glsl/builtins/130/textureProjGrad
@@ -0,0 +1,122 @@
+((function textureLod
+ (signature vec4
+ (parameters
+ (declare (in) sampler1D sampler)
+ (declare (in) vec2 P)
+ (declare (in) float dPdx)
+ (declare (in) float dPdy) )
+ ((return (txd (var_ref sampler) (swiz x (var_ref P)) (0 0 0) (swiz y (var_ref P)) () ((var_ref dPdx) (var_ref dPdy)) ))))
+
+ (signature ivec4
+ (parameters
+ (declare (in) isampler1D sampler)
+ (declare (in) vec2 P)
+ (declare (in) float dPdx)
+ (declare (in) float dPdy) )
+ ((return (txd (var_ref sampler) (swiz x (var_ref P)) (0 0 0) (swiz y (var_ref P)) () ((var_ref dPdx) (var_ref dPdy)) ))))
+
+ (signature uvec4
+ (parameters
+ (declare (in) usampler1D sampler)
+ (declare (in) vec2 P)
+ (declare (in) float dPdx)
+ (declare (in) float dPdy) )
+ ((return (txd (var_ref sampler) (swiz x (var_ref P)) (0 0 0) (swiz y (var_ref P)) () ((var_ref dPdx) (var_ref dPdy)) ))))
+
+ (signature vec4
+ (parameters
+ (declare (in) sampler1D sampler)
+ (declare (in) vec4 P)
+ (declare (in) float dPdx)
+ (declare (in) float dPdy) )
+ ((return (txd (var_ref sampler) (swiz x (var_ref P)) (0 0 0) (swiz w (var_ref P)) () ((var_ref dPdx) (var_ref dPdy)) ))))
+
+ (signature ivec4
+ (parameters
+ (declare (in) isampler1D sampler)
+ (declare (in) vec4 P)
+ (declare (in) float dPdx)
+ (declare (in) float dPdy) )
+ ((return (txd (var_ref sampler) (swiz x (var_ref P)) (0 0 0) (swiz w (var_ref P)) () ((var_ref dPdx) (var_ref dPdy)) ))))
+
+ (signature uvec4
+ (parameters
+ (declare (in) usampler1D sampler)
+ (declare (in) vec4 P)
+ (declare (in) float dPdx)
+ (declare (in) float dPdy) )
+ ((return (txd (var_ref sampler) (swiz x (var_ref P)) (0 0 0) (swiz w (var_ref P)) () ((var_ref dPdx) (var_ref dPdy)) ))))
+
+ (signature vec4
+ (parameters
+ (declare (in) sampler2D sampler)
+ (declare (in) vec3 P)
+ (declare (in) vec2 dPdx)
+ (declare (in) vec2 dPdy) )
+ ((return (txd (var_ref sampler) (swiz xy (var_ref P)) (0 0 0) (swiz z (var_ref P)) () ((var_ref dPdx) (var_ref dPdy)) ))))
+
+ (signature ivec4
+ (parameters
+ (declare (in) isampler2D sampler)
+ (declare (in) vec3 P)
+ (declare (in) vec2 dPdx)
+ (declare (in) vec2 dPdy) )
+ ((return (txd (var_ref sampler) (swiz xy (var_ref P)) (0 0 0) (swiz z (var_ref P)) () ((var_ref dPdx) (var_ref dPdy)) ))))
+
+ (signature uvec4
+ (parameters
+ (declare (in) usampler2D sampler)
+ (declare (in) vec3 P)
+ (declare (in) vec2 dPdx)
+ (declare (in) vec2 dPdy) )
+ ((return (txd (var_ref sampler) (swiz xy (var_ref P)) (0 0 0) (swiz z (var_ref P)) () ((var_ref dPdx) (var_ref dPdy)) ))))
+
+ (signature vec4
+ (parameters
+ (declare (in) sampler2D sampler)
+ (declare (in) vec4 P)
+ (declare (in) vec2 dPdx)
+ (declare (in) vec2 dPdy) )
+ ((return (txd (var_ref sampler) (swiz xy (var_ref P)) (0 0 0) (swiz w (var_ref P)) () ((var_ref dPdx) (var_ref dPdy)) ))))
+
+ (signature ivec4
+ (parameters
+ (declare (in) isampler2D sampler)
+ (declare (in) vec4 P)
+ (declare (in) vec2 dPdx)
+ (declare (in) vec2 dPdy) )
+ ((return (txd (var_ref sampler) (swiz xy (var_ref P)) (0 0 0) (swiz w (var_ref P)) () ((var_ref dPdx) (var_ref dPdy)) ))))
+
+ (signature uvec4
+ (parameters
+ (declare (in) usampler2D sampler)
+ (declare (in) vec4 P)
+ (declare (in) vec2 dPdx)
+ (declare (in) vec2 dPdy) )
+ ((return (txd (var_ref sampler) (swiz xy (var_ref P)) (0 0 0) (swiz w (var_ref P)) () ((var_ref dPdx) (var_ref dPdy)) ))))
+
+ (signature vec4
+ (parameters
+ (declare (in) sampler3D sampler)
+ (declare (in) vec4 P)
+ (declare (in) vec3 dPdx)
+ (declare (in) vec3 dPdy) )
+ ((return (txd (var_ref sampler) (swiz xyz (var_ref P)) (0 0 0) (swiz w (var_ref P)) () ((var_ref dPdx) (var_ref dPdy)) ))))
+
+ (signature ivec4
+ (parameters
+ (declare (in) isampler3D sampler)
+ (declare (in) vec4 P)
+ (declare (in) vec3 dPdx)
+ (declare (in) vec3 dPdy) )
+ ((return (txd (var_ref sampler) (swiz xyz (var_ref P)) (0 0 0) (swiz w (var_ref P)) () ((var_ref dPdx) (var_ref dPdy)) ))))
+
+ (signature uvec4
+ (parameters
+ (declare (in) usampler3D sampler)
+ (declare (in) vec4 P)
+ (declare (in) vec3 dPdx)
+ (declare (in) vec3 dPdy) )
+ ((return (txd (var_ref sampler) (swiz xyz (var_ref P)) (0 0 0) (swiz w (var_ref P)) () ((var_ref dPdx) (var_ref dPdy)) ))))
+
+))
diff --git a/src/glsl/builtins/130/textureProjLod b/src/glsl/builtins/130/textureProjLod
new file mode 100644
index 00000000000..9f4ce1b493d
--- /dev/null
+++ b/src/glsl/builtins/130/textureProjLod
@@ -0,0 +1,107 @@
+((function textureLod
+ (signature vec4
+ (parameters
+ (declare (in) sampler1D sampler)
+ (declare (in) vec2 P)
+ (declare (in) float lod) )
+ ((return (txl (var_ref sampler) (swiz x (var_ref P)) (0 0 0) (swiz y (var_ref P)) () (var_ref lod) ))))
+
+ (signature ivec4
+ (parameters
+ (declare (in) isampler1D sampler)
+ (declare (in) vec2 P)
+ (declare (in) float lod) )
+ ((return (txl (var_ref sampler) (swiz x (var_ref P)) (0 0 0) (swiz y (var_ref P)) () (var_ref lod) ))))
+
+ (signature uvec4
+ (parameters
+ (declare (in) usampler1D sampler)
+ (declare (in) vec2 P)
+ (declare (in) float lod) )
+ ((return (txl (var_ref sampler) (swiz x (var_ref P)) (0 0 0) (swiz y (var_ref P)) () (var_ref lod) ))))
+
+ (signature vec4
+ (parameters
+ (declare (in) sampler1D sampler)
+ (declare (in) vec4 P)
+ (declare (in) float lod) )
+ ((return (txl (var_ref sampler) (swiz x (var_ref P)) (0 0 0) (swiz w (var_ref P)) () (var_ref lod) ))))
+
+ (signature ivec4
+ (parameters
+ (declare (in) isampler1D sampler)
+ (declare (in) vec4 P)
+ (declare (in) float lod) )
+ ((return (txl (var_ref sampler) (swiz x (var_ref P)) (0 0 0) (swiz w (var_ref P)) () (var_ref lod) ))))
+
+ (signature uvec4
+ (parameters
+ (declare (in) usampler1D sampler)
+ (declare (in) vec4 P)
+ (declare (in) float lod) )
+ ((return (txl (var_ref sampler) (swiz x (var_ref P)) (0 0 0) (swiz w (var_ref P)) () (var_ref lod) ))))
+
+ (signature vec4
+ (parameters
+ (declare (in) sampler2D sampler)
+ (declare (in) vec3 P)
+ (declare (in) float lod) )
+ ((return (txl (var_ref sampler) (swiz xy (var_ref P)) (0 0 0) (swiz z (var_ref P)) () (var_ref lod) ))))
+
+ (signature ivec4
+ (parameters
+ (declare (in) isampler2D sampler)
+ (declare (in) vec3 P)
+ (declare (in) float lod) )
+ ((return (txl (var_ref sampler) (swiz xy (var_ref P)) (0 0 0) (swiz z (var_ref P)) () (var_ref lod) ))))
+
+ (signature uvec4
+ (parameters
+ (declare (in) usampler2D sampler)
+ (declare (in) vec3 P)
+ (declare (in) float lod) )
+ ((return (txl (var_ref sampler) (swiz xy (var_ref P)) (0 0 0) (swiz z (var_ref P)) () (var_ref lod) ))))
+
+ (signature vec4
+ (parameters
+ (declare (in) sampler2D sampler)
+ (declare (in) vec4 P)
+ (declare (in) float lod) )
+ ((return (txl (var_ref sampler) (swiz xy (var_ref P)) (0 0 0) (swiz w (var_ref P)) () (var_ref lod) ))))
+
+ (signature ivec4
+ (parameters
+ (declare (in) isampler2D sampler)
+ (declare (in) vec4 P)
+ (declare (in) float lod) )
+ ((return (txl (var_ref sampler) (swiz xy (var_ref P)) (0 0 0) (swiz w (var_ref P)) () (var_ref lod) ))))
+
+ (signature uvec4
+ (parameters
+ (declare (in) usampler2D sampler)
+ (declare (in) vec4 P)
+ (declare (in) float lod) )
+ ((return (txl (var_ref sampler) (swiz xy (var_ref P)) (0 0 0) (swiz w (var_ref P)) () (var_ref lod) ))))
+
+ (signature vec4
+ (parameters
+ (declare (in) sampler3D sampler)
+ (declare (in) vec4 P)
+ (declare (in) float lod) )
+ ((return (txl (var_ref sampler) (swiz xyz (var_ref P)) (0 0 0) (swiz w (var_ref P)) () (var_ref lod) ))))
+
+ (signature ivec4
+ (parameters
+ (declare (in) isampler3D sampler)
+ (declare (in) vec4 P)
+ (declare (in) float lod) )
+ ((return (txl (var_ref sampler) (swiz xyz (var_ref P)) (0 0 0) (swiz w (var_ref P)) () (var_ref lod) ))))
+
+ (signature uvec4
+ (parameters
+ (declare (in) usampler3D sampler)
+ (declare (in) vec4 P)
+ (declare (in) float lod) )
+ ((return (txl (var_ref sampler) (swiz xyz (var_ref P)) (0 0 0) (swiz w (var_ref P)) () (var_ref lod) ))))
+
+))
diff --git a/src/glsl/builtins/130_fs/texture b/src/glsl/builtins/130_fs/texture
new file mode 100644
index 00000000000..0de981397f0
--- /dev/null
+++ b/src/glsl/builtins/130_fs/texture
@@ -0,0 +1,128 @@
+((function texture
+ (signature vec4
+ (parameters
+ (declare (in) sampler1D sampler)
+ (declare (in) float P)
+ (declare (in) float bias) )
+ ((return (txb (var_ref sampler) (var_ref P) (0 0 0) 1 () (var_ref bias) ))))
+
+ (signature ivec4
+ (parameters
+ (declare (in) isampler1D sampler)
+ (declare (in) float P)
+ (declare (in) float bias) )
+ ((return (txb (var_ref sampler) (var_ref P) (0 0 0) 1 () (var_ref bias) ))))
+
+ (signature uvec4
+ (parameters
+ (declare (in) usampler1D sampler)
+ (declare (in) float P)
+ (declare (in) float bias) )
+ ((return (txb (var_ref sampler) (var_ref P) (0 0 0) 1 () (var_ref bias) ))))
+
+ (signature vec4
+ (parameters
+ (declare (in) sampler2D sampler)
+ (declare (in) vec2 P)
+ (declare (in) float bias) )
+ ((return (txb (var_ref sampler) (var_ref P) (0 0 0) 1 () (var_ref bias) ))))
+
+ (signature ivec4
+ (parameters
+ (declare (in) isampler2D sampler)
+ (declare (in) vec2 P)
+ (declare (in) float bias) )
+ ((return (txb (var_ref sampler) (var_ref P) (0 0 0) 1 () (var_ref bias) ))))
+
+ (signature uvec4
+ (parameters
+ (declare (in) usampler2D sampler)
+ (declare (in) vec2 P)
+ (declare (in) float bias) )
+ ((return (txb (var_ref sampler) (var_ref P) (0 0 0) 1 () (var_ref bias) ))))
+
+ (signature vec4
+ (parameters
+ (declare (in) sampler3D sampler)
+ (declare (in) vec3 P)
+ (declare (in) float bias) )
+ ((return (txb (var_ref sampler) (var_ref P) (0 0 0) 1 () (var_ref bias) ))))
+
+ (signature ivec4
+ (parameters
+ (declare (in) isampler3D sampler)
+ (declare (in) vec3 P)
+ (declare (in) float bias) )
+ ((return (txb (var_ref sampler) (var_ref P) (0 0 0) 1 () (var_ref bias) ))))
+
+ (signature uvec4
+ (parameters
+ (declare (in) usampler3D sampler)
+ (declare (in) vec3 P)
+ (declare (in) float bias) )
+ ((return (txb (var_ref sampler) (var_ref P) (0 0 0) 1 () (var_ref bias) ))))
+
+ (signature vec4
+ (parameters
+ (declare (in) samplerCube sampler)
+ (declare (in) vec3 P)
+ (declare (in) float bias) )
+ ((return (txb (var_ref sampler) (var_ref P) (0 0 0) 1 () (var_ref bias) ))))
+
+ (signature ivec4
+ (parameters
+ (declare (in) isamplerCube sampler)
+ (declare (in) vec3 P)
+ (declare (in) float bias) )
+ ((return (txb (var_ref sampler) (var_ref P) (0 0 0) 1 () (var_ref bias) ))))
+
+ (signature uvec4
+ (parameters
+ (declare (in) usamplerCube sampler)
+ (declare (in) vec3 P)
+ (declare (in) float bias) )
+ ((return (txb (var_ref sampler) (var_ref P) (0 0 0) 1 () (var_ref bias) ))))
+
+ (signature vec4
+ (parameters
+ (declare (in) sampler1DArray sampler)
+ (declare (in) vec2 P)
+ (declare (in) float bias) )
+ ((return (txb (var_ref sampler) (var_ref P) (0 0 0) 1 () (var_ref bias) ))))
+
+ (signature ivec4
+ (parameters
+ (declare (in) isampler1DArray sampler)
+ (declare (in) vec2 P)
+ (declare (in) float bias) )
+ ((return (txb (var_ref sampler) (var_ref P) (0 0 0) 1 () (var_ref bias) ))))
+
+ (signature uvec4
+ (parameters
+ (declare (in) usampler1DArray sampler)
+ (declare (in) vec2 P)
+ (declare (in) float bias) )
+ ((return (txb (var_ref sampler) (var_ref P) (0 0 0) 1 () (var_ref bias) ))))
+
+ (signature vec4
+ (parameters
+ (declare (in) sampler2DArray sampler)
+ (declare (in) vec3 P)
+ (declare (in) float bias) )
+ ((return (txb (var_ref sampler) (var_ref P) (0 0 0) 1 () (var_ref bias) ))))
+
+ (signature ivec4
+ (parameters
+ (declare (in) isampler2DArray sampler)
+ (declare (in) vec3 P)
+ (declare (in) float bias) )
+ ((return (txb (var_ref sampler) (var_ref P) (0 0 0) 1 () (var_ref bias) ))))
+
+ (signature uvec4
+ (parameters
+ (declare (in) usampler2DArray sampler)
+ (declare (in) vec3 P)
+ (declare (in) float bias) )
+ ((return (txb (var_ref sampler) (var_ref P) (0 0 0) 1 () (var_ref bias) ))))
+
+))
diff --git a/src/glsl/builtins/130_fs/textureProj b/src/glsl/builtins/130_fs/textureProj
new file mode 100644
index 00000000000..b1d8f0a2f33
--- /dev/null
+++ b/src/glsl/builtins/130_fs/textureProj
@@ -0,0 +1,107 @@
+((function textureProj
+ (signature vec4
+ (parameters
+ (declare (in) sampler1D sampler)
+ (declare (in) vec2 P)
+ (declare (in) float bias) )
+ ((return (txb (var_ref sampler) (swiz x (var_ref P)) (0 0 0) (swiz y (var_ref P)) () (var_ref bias) ))))
+
+ (signature ivec4
+ (parameters
+ (declare (in) isampler1D sampler)
+ (declare (in) vec2 P)
+ (declare (in) float bias) )
+ ((return (txb (var_ref sampler) (swiz x (var_ref P)) (0 0 0) (swiz y (var_ref P)) () (var_ref bias) ))))
+
+ (signature uvec4
+ (parameters
+ (declare (in) usampler1D sampler)
+ (declare (in) vec2 P)
+ (declare (in) float bias) )
+ ((return (txb (var_ref sampler) (swiz x (var_ref P)) (0 0 0) (swiz y (var_ref P)) () (var_ref bias) ))))
+
+ (signature vec4
+ (parameters
+ (declare (in) sampler1D sampler)
+ (declare (in) vec4 P)
+ (declare (in) float bias) )
+ ((return (txb (var_ref sampler) (swiz x (var_ref P)) (0 0 0) (swiz w (var_ref P)) () (var_ref bias) ))))
+
+ (signature ivec4
+ (parameters
+ (declare (in) isampler1D sampler)
+ (declare (in) vec4 P)
+ (declare (in) float bias) )
+ ((return (txb (var_ref sampler) (swiz x (var_ref P)) (0 0 0) (swiz w (var_ref P)) () (var_ref bias) ))))
+
+ (signature uvec4
+ (parameters
+ (declare (in) usampler1D sampler)
+ (declare (in) vec4 P)
+ (declare (in) float bias) )
+ ((return (txb (var_ref sampler) (swiz x (var_ref P)) (0 0 0) (swiz w (var_ref P)) () (var_ref bias) ))))
+
+ (signature vec4
+ (parameters
+ (declare (in) sampler2D sampler)
+ (declare (in) vec3 P)
+ (declare (in) float bias) )
+ ((return (txb (var_ref sampler) (swiz xy (var_ref P)) (0 0 0) (swiz z (var_ref P)) () (var_ref bias) ))))
+
+ (signature ivec4
+ (parameters
+ (declare (in) isampler2D sampler)
+ (declare (in) vec3 P)
+ (declare (in) float bias) )
+ ((return (txb (var_ref sampler) (swiz xy (var_ref P)) (0 0 0) (swiz z (var_ref P)) () (var_ref bias) ))))
+
+ (signature uvec4
+ (parameters
+ (declare (in) usampler2D sampler)
+ (declare (in) vec3 P)
+ (declare (in) float bias) )
+ ((return (txb (var_ref sampler) (swiz xy (var_ref P)) (0 0 0) (swiz z (var_ref P)) () (var_ref bias) ))))
+
+ (signature vec4
+ (parameters
+ (declare (in) sampler2D sampler)
+ (declare (in) vec4 P)
+ (declare (in) float bias) )
+ ((return (txb (var_ref sampler) (swiz xy (var_ref P)) (0 0 0) (swiz w (var_ref P)) () (var_ref bias) ))))
+
+ (signature ivec4
+ (parameters
+ (declare (in) isampler2D sampler)
+ (declare (in) vec4 P)
+ (declare (in) float bias) )
+ ((return (txb (var_ref sampler) (swiz xy (var_ref P)) (0 0 0) (swiz w (var_ref P)) () (var_ref bias) ))))
+
+ (signature uvec4
+ (parameters
+ (declare (in) usampler2D sampler)
+ (declare (in) vec4 P)
+ (declare (in) float bias) )
+ ((return (txb (var_ref sampler) (swiz xy (var_ref P)) (0 0 0) (swiz w (var_ref P)) () (var_ref bias) ))))
+
+ (signature vec4
+ (parameters
+ (declare (in) sampler3D sampler)
+ (declare (in) vec4 P)
+ (declare (in) float bias) )
+ ((return (txb (var_ref sampler) (swiz xyz (var_ref P)) (0 0 0) (swiz w (var_ref P)) () (var_ref bias) ))))
+
+ (signature ivec4
+ (parameters
+ (declare (in) isampler3D sampler)
+ (declare (in) vec4 P)
+ (declare (in) float bias) )
+ ((return (txb (var_ref sampler) (swiz xyz (var_ref P)) (0 0 0) (swiz w (var_ref P)) () (var_ref bias) ))))
+
+ (signature uvec4
+ (parameters
+ (declare (in) usampler3D sampler)
+ (declare (in) vec4 P)
+ (declare (in) float bias) )
+ ((return (txb (var_ref sampler) (swiz xyz (var_ref P)) (0 0 0) (swiz w (var_ref P)) () (var_ref bias) ))))
+
+))
diff --git a/src/glsl/builtins/ARB_texture_rectangle/textures b/src/glsl/builtins/ARB_texture_rectangle/textures
new file mode 100644
index 00000000000..161d8c4a541
--- /dev/null
+++ b/src/glsl/builtins/ARB_texture_rectangle/textures
@@ -0,0 +1,16 @@
+((function texture2DRect
+ (signature vec4
+ (parameters
+ (declare (in) sampler2DRect sampler)
+ (declare (in) vec2 P) )
+ ((return (tex (var_ref sampler) (var_ref P) (0 0 0) 1 () ))))
+
+)
+ (function shadow2DRect
+ (signature vec4
+ (parameters
+ (declare (in) sampler2DRectShadow sampler)
+ (declare (in) vec3 P) )
+ ((return (tex (var_ref sampler) (swiz xy (var_ref P)) (0 0 0) 1 (swiz z (var_ref P)) ))))
+
+))
diff --git a/src/glsl/builtins/EXT_texture_array/textures b/src/glsl/builtins/EXT_texture_array/textures
new file mode 100644
index 00000000000..8a91f901401
--- /dev/null
+++ b/src/glsl/builtins/EXT_texture_array/textures
@@ -0,0 +1,59 @@
+((function texture1DArray
+ (signature vec4
+ (parameters
+ (declare (in) sampler1DArray sampler)
+ (declare (in) vec2 P) )
+ ((return (tex (var_ref sampler) (var_ref P) (0 0 0) 1 () ))))
+
+)
+ (function texture1DArrayLod
+ (signature vec4
+ (parameters
+ (declare (in) sampler1DArray sampler)
+ (declare (in) vec2 P)
+ (declare (in) float lod) )
+ ((return (txl (var_ref sampler) (var_ref P) (0 0 0) 1 () (var_ref lod) ))))
+
+)
+ (function texture2DArray
+ (signature vec4
+ (parameters
+ (declare (in) sampler2DArray sampler)
+ (declare (in) vec3 P) )
+ ((return (tex (var_ref sampler) (var_ref P) (0 0 0) 1 () ))))
+
+)
+ (function texture2DArrayLod
+ (signature vec4
+ (parameters
+ (declare (in) sampler2DArray sampler)
+ (declare (in) vec3 P)
+ (declare (in) float lod) )
+ ((return (txl (var_ref sampler) (var_ref P) (0 0 0) 1 () (var_ref lod) ))))
+
+)
+ (function shadow1DArray
+ (signature vec4
+ (parameters
+ (declare (in) sampler1DArrayShadow sampler)
+ (declare (in) vec3 P) )
+ ((return (tex (var_ref sampler) (swiz xy (var_ref P)) (0 0 0) 1 (swiz z (var_ref P)) ))))
+
+)
+ (function shadow1DArrayLod
+ (signature vec4
+ (parameters
+ (declare (in) sampler1DArrayShadow sampler)
+ (declare (in) vec3 P)
+ (declare (in) float lod) )
+ ((return (txl (var_ref sampler) (swiz xy (var_ref P)) (0 0 0) 1 (swiz z (var_ref P)) (var_ref lod) ))))
+
+)
+ (function shadow2DArray
+ (signature vec4
+ (parameters
+ (declare (in) sampler2DArrayShadow sampler)
+ (declare (in) vec4 P) )
+ ((return (tex (var_ref sampler) (swiz xyz (var_ref P)) (0 0 0) 1 (swiz w (var_ref P)) ))))
+
+))
diff --git a/src/glsl/builtins/EXT_texture_array_fs/textures b/src/glsl/builtins/EXT_texture_array_fs/textures
new file mode 100644
index 00000000000..74e184387ac
--- /dev/null
+++ b/src/glsl/builtins/EXT_texture_array_fs/textures
@@ -0,0 +1,27 @@
+((function texture1DArray
+ (signature vec4
+ (parameters
+ (declare (in) sampler1DArray sampler)
+ (declare (in) vec2 P)
+ (declare (in) float bias) )
+ ((return (txb (var_ref sampler) (var_ref P) (0 0 0) 1 () (var_ref bias) ))))
+
+)
+ (function texture2DArray
+ (signature vec4
+ (parameters
+ (declare (in) sampler2DArray sampler)
+ (declare (in) vec3 P)
+ (declare (in) float bias) )
+ ((return (txb (var_ref sampler) (var_ref P) (0 0 0) 1 () (var_ref bias) ))))
+
+)
+ (function shadow1DArray
+ (signature vec4
+ (parameters
+ (declare (in) sampler1DArrayShadow sampler)
+ (declare (in) vec3 P)
+ (declare (in) float bias) )
+ ((return (txb (var_ref sampler) (swiz xy (var_ref P)) (0 0 0) 1 (swiz z (var_ref P)) (var_ref bias) ))))
+
+))
diff --git a/src/glsl/builtins/tools/generate_builtins.pl b/src/glsl/builtins/tools/generate_builtins.pl
new file mode 100755
index 00000000000..8b640ab8ff9
--- /dev/null
+++ b/src/glsl/builtins/tools/generate_builtins.pl
@@ -0,0 +1,123 @@
+#!/usr/bin/env perl
+
+sub process_version {
+ my ($version) = @_;
+ my @vars;
+ print "/* $version builtins */\n\n";
+
+ my @files = <builtins/$version/*>;
+ foreach $file (@files) {
+ push(@vars, process_file($file));
+ }
+
+ print "static const char *functions_for_$version [] = {\n";
+ foreach $var (@vars) {
+ print " $var,\n";
+ }
+ print "};\n\n"
+}
+
+sub process_file {
+ my ($file) = @_;
+
+ # Change from builtins/110/foo to builtins_110_foo
+ my $var = $file; $var =~ s!/!_!g;
+
+ print "static const char *$var = {\n";
+ open SRC, "<", "$file" or die $!;
+ while (<SRC>) {
+ s/\\/\\\\/g;
+ s/\"/\\\"/g;
+ s/\n/\\n/g;
+ print " \"$_\"\n";
+ }
+ print "};\n\n";
+ close SRC or die $!;
+ return $var;
+}
+
+print << 'EOF';
+/* DO NOT MODIFY - automatically generated by generate_builtins.pl */
+/*
+ * 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"
+#include "ir_reader.h"
+
+void
+read_builtins(_mesa_glsl_parse_state *st, exec_list *instructions,
+ const char **functions, unsigned count)
+{
+ if (st->error)
+ return;
+
+ for (unsigned i = 0; i < count; i++) {
+ _mesa_glsl_read_ir(st, instructions, functions[i]);
+
+ if (st->error) {
+ printf("error reading builtin: %.35s ...\n", functions[i]);
+ return;
+ }
+ }
+}
+
+EOF
+
+@versions = sort(<builtins/[1-9A-Z]*>);
+foreach $version (@versions) {
+ $version =~ s!builtins/!!g;
+ process_version($version);
+}
+
+print << 'EOF';
+void
+_mesa_glsl_initialize_functions(exec_list *instructions,
+ struct _mesa_glsl_parse_state *state)
+{
+EOF
+
+foreach $version_xs (@versions) {
+ $check = "";
+ if ($version_xs =~ /_vs/) {
+ $check = "state->target == vertex_shader && ";
+ } elsif ($version_xs =~ /_fs/) {
+ $check = "state->target == fragment_shader && ";
+ }
+ $version = $version_xs;
+ $version =~ s/_[vf]s//g;
+
+ if ($version =~ /^[1-9][0-9][0-9]/) {
+ $check = "${check}state->language_version >= $version";
+ } else {
+ # Not a version...an extension name
+ $check = "${check}state->${version}_enable";
+ }
+ print " if ($check)\n";
+ print " read_builtins(state, instructions,\n";
+ print " functions_for_$version_xs,\n";
+ print " sizeof(functions_for_$version_xs) / ";
+ print "sizeof(const char *));\n\n"
+}
+
+print "}\n";
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..48fb72197c3
--- /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(x) + " u, vec" + str(y) + " v)\n{"
+ print " " + type + " m;"
+
+ for i in range(x):
+ print " m[" + str(i) + "] = v * u[" + 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..23d53149161
--- /dev/null
+++ b/src/glsl/builtins/tools/texture_builtins.py
@@ -0,0 +1,298 @@
+#!/usr/bin/python
+
+from os import path
+import sys
+
+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)
+
+builtins_dir = path.join(path.dirname(path.abspath(__file__)), "..")
+
+with open(path.join(builtins_dir, "130", "texture"), 'w') as sys.stdout:
+ print "((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")
+ print "))"
+
+# txb variants are only allowed within a fragment shader (GLSL 1.30 p. 86)
+with open(path.join(builtins_dir, "130_fs", "texture"), 'w') as sys.stdout:
+ print "((function texture"
+ 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")
+ print "))"
+
+with open(path.join(builtins_dir, "130", "textureProj"), 'w') as sys.stdout:
+ print "((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)
+ print "))"
+
+with open(path.join(builtins_dir, "130_fs", "textureProj"), 'w') as sys.stdout:
+ print "((function textureProj"
+ 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)
+ print "))"
+
+with open(path.join(builtins_dir, "130", "textureLod"), 'w') as sys.stdout:
+ print "((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")
+ print "))"
+
+with open(path.join(builtins_dir, "130", "texelFetch"), 'w') as sys.stdout:
+ print "((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")
+ print "))"
+
+with open(path.join(builtins_dir, "130", "textureProjLod"), 'w') as sys.stdout:
+ print "((function textureLod"
+ 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)
+ print "))"
+
+with open(path.join(builtins_dir, "130", "textureGrad"), 'w') as sys.stdout:
+ print "((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")
+ print ")\n)"
+
+with open(path.join(builtins_dir, "130", "textureProjGrad"), 'w') as sys.stdout:
+ print "((function textureLod"
+ 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)
+ print "))"
+
+# ARB_texture_rectangle extension
+with open(path.join(builtins_dir, "ARB_texture_rectangle", "textures"), 'w') as sys.stdout:
+ print "((function texture2DRect"
+ generate_sigs("", "tex", "2DRect")
+ print ")\n (function shadow2DRect"
+ generate_sigs("", "tex", "2DRectShadow")
+ print "))"
+
+# EXT_texture_array extension
+with open(path.join(builtins_dir, "EXT_texture_array", "textures"), 'w') as sys.stdout:
+ print "((function texture1DArray"
+ generate_sigs("", "tex", "1DArray")
+ print ")\n (function texture1DArrayLod"
+ generate_sigs("", "txl", "1DArray")
+ print ")\n (function texture2DArray"
+ generate_sigs("", "tex", "2DArray")
+ print ")\n (function texture2DArrayLod"
+ generate_sigs("", "txl", "2DArray")
+ print ")\n (function shadow1DArray"
+ generate_sigs("", "tex", "1DArrayShadow")
+ print ")\n (function shadow1DArrayLod"
+ generate_sigs("", "txl", "1DArrayShadow")
+ print ")\n (function shadow2DArray"
+ generate_sigs("", "tex", "2DArrayShadow")
+ print "))"
+
+with open(path.join(builtins_dir, "EXT_texture_array_fs", "textures"), 'w') as sys.stdout:
+ print "((function texture1DArray"
+ generate_sigs("", "txb", "1DArray") # MOVE TO _fs
+ print ")\n (function texture2DArray"
+ generate_sigs("", "txb", "2DArray") # MOVE TO _fs
+ print ")\n (function shadow1DArray"
+ generate_sigs("", "txb", "1DArrayShadow")
+ print "))"
+
+# Deprecated (110/120 style) functions with silly names:
+with open(path.join(builtins_dir, "110", "textures"), 'w') as sys.stdout:
+ print "((function texture1D"
+ generate_sigs("", "tex", "1D")
+ print ")\n (function texture1DLod"
+ generate_sigs("", "txl", "1D")
+ print ")\n (function texture1DProj"
+ generate_sigs("", "tex", "1D", True)
+ generate_sigs("", "tex", "1D", True, 2)
+ print ")\n (function texture1DProjLod"
+ generate_sigs("", "txl", "1D", True)
+ generate_sigs("", "txl", "1D", True, 2)
+ print ")\n (function texture2D"
+ generate_sigs("", "tex", "2D")
+ print ")\n(function texture2DLod"
+ generate_sigs("", "txl", "2D")
+ print ")\n (function texture2DProj"
+ generate_sigs("", "tex", "2D", True)
+ generate_sigs("", "tex", "2D", True, 1)
+ print ")\n (function texture2DProjLod"
+ generate_sigs("", "txl", "2D", True)
+ generate_sigs("", "txl", "2D", True, 1)
+ print ")\n (function texture3D"
+ generate_sigs("", "tex", "3D")
+ print ")\n (function texture3DLod"
+ generate_sigs("", "txl", "3D")
+ print ")\n (function texture3DProj"
+ generate_sigs("", "tex", "3D", True)
+ print ")\n (function texture3DProjLod"
+ generate_sigs("", "txl", "3D", True)
+ print ")\n (function textureCube"
+ generate_sigs("", "tex", "Cube")
+ print ")\n (function textureCubeLod"
+ generate_sigs("", "txl", "Cube")
+ print ")\n (function shadow1D"
+ generate_sigs("", "tex", "1DShadow", False, 1)
+ print ")\n (function shadow1DLod"
+ generate_sigs("", "txl", "1DShadow", False, 1)
+ print ")\n (function shadow1DProj"
+ generate_sigs("", "tex", "1DShadow", True, 1)
+ print ")\n (function shadow1DProjLod"
+ generate_sigs("", "txl", "1DShadow", True, 1)
+ print ")\n (function shadow2D"
+ generate_sigs("", "tex", "2DShadow")
+ print ")\n (function shadow2DLod"
+ generate_sigs("", "txl", "2DShadow")
+ print ")\n (function shadow2DProj"
+ generate_sigs("", "tex", "2DShadow", True)
+ print ")\n (function shadow2DProjLod"
+ generate_sigs("", "txl", "2DShadow", True)
+ print "))"
+
+with open(path.join(builtins_dir, "110_fs", "textures"), 'w') as sys.stdout:
+ print "((function texture1D"
+ generate_sigs("", "txb", "1D")
+ print ")\n (function texture1DProj"
+ generate_sigs("", "txb", "1D", True)
+ generate_sigs("", "txb", "1D", True, 2)
+ print ")\n (function texture2D"
+ generate_sigs("", "txb", "2D")
+ print ")\n (function texture2DProj"
+ generate_sigs("", "txb", "2D", True)
+ generate_sigs("", "txb", "2D", True, 1)
+ print ")\n (function texture3D"
+ generate_sigs("", "txb", "3D")
+ print ")\n (function texture3DProj"
+ generate_sigs("", "txb", "3D", True)
+ print ")\n (function textureCube"
+ generate_sigs("", "txb", "Cube")
+ print ")\n (function shadow1D"
+ generate_sigs("", "txb", "1DShadow", False, 1)
+ print ")\n (function shadow1DProj"
+ generate_sigs("", "txb", "1DShadow", True, 1)
+ print ")\n (function shadow2D"
+ generate_sigs("", "txb", "2DShadow")
+ print ")\n (function shadow2DProj"
+ generate_sigs("", "txb", "2DShadow", True)
+ print "))"
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..c158dc8b862
--- /dev/null
+++ b/src/glsl/glcpp/.gitignore
@@ -0,0 +1,11 @@
+glcpp
+glcpp-lex.c
+glcpp-parse.c
+glcpp-parse.h
+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..a49fd615cda
--- /dev/null
+++ b/src/glsl/glcpp/Makefile.am
@@ -0,0 +1,46 @@
+# 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 \
+ hash_table.c \
+ pp.c \
+ xtalloc.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.l b/src/glsl/glcpp/glcpp-lex.l
new file mode 100644
index 00000000000..afddd7ddb32
--- /dev/null
+++ b/src/glsl/glcpp/glcpp-lex.l
@@ -0,0 +1,257 @@
+%{
+/*
+ * 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 "glcpp.h"
+#include "glcpp-parse.h"
+
+#define YY_USER_ACTION \
+ do { \
+ yylloc->source = 0; \
+ yylloc->first_column = yycolumn + 1; \
+ yylloc->first_line = yylineno; \
+ yycolumn += yyleng; \
+ } while(0);
+%}
+
+%option bison-bridge bison-locations reentrant noyywrap
+%option extra-type="glcpp_parser_t *"
+%option prefix="glcpp_"
+%option stack
+
+%x DONE COMMENT
+
+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;
+}
+
+ /* glcpp doesn't handle #extension, #version, or #pragma directives.
+ * Simply pass them through to the main compiler's lexer/parser. */
+{HASH}(extension|version|pragma)[^\n]+ {
+ yylval->str = xtalloc_strdup (yyextra, yytext);
+ yylineno++;
+ yycolumn = 0;
+ return OTHER;
+}
+
+{HASH}ifdef/.*\n {
+ yyextra->space_tokens = 0;
+ return HASH_IFDEF;
+}
+
+{HASH}ifndef/.*\n {
+ yyextra->space_tokens = 0;
+ return HASH_IFNDEF;
+}
+
+{HASH}if{HSPACE}/.*\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 less priroty 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}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 = xtalloc_strdup (yyextra, yytext);
+ return INTEGER_STRING;
+}
+
+{OCTAL_INTEGER} {
+ yylval->str = xtalloc_strdup (yyextra, yytext);
+ return INTEGER_STRING;
+}
+
+{HEXADECIMAL_INTEGER} {
+ yylval->str = xtalloc_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 = xtalloc_strdup (yyextra, yytext);
+ return IDENTIFIER;
+}
+
+{PUNCTUATION} {
+ return yytext[0];
+}
+
+{OTHER}+ {
+ yylval->str = xtalloc_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;
+}
+
+%%
+
+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.y b/src/glsl/glcpp/glcpp-parse.y
new file mode 100644
index 00000000000..6beac18c65d
--- /dev/null
+++ b/src/glsl/glcpp/glcpp-parse.y
@@ -0,0 +1,1611 @@
+%{
+/*
+ * 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 <assert.h>
+#include <inttypes.h>
+
+#include "glcpp.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_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);
+
+%}
+
+%pure-parser
+%error-verbose
+%locations
+
+%parse-param {glcpp_parser_t *parser}
+%lex-param {glcpp_parser_t *parser}
+
+%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 IDENTIFIER IF_EXPANDED INTEGER INTEGER_STRING NEWLINE OTHER PLACEHOLDER SPACE
+%token PASTE
+%type <ival> expression INTEGER operator SPACE
+%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) {
+ /* XXX: Need hash table to support a real way
+ * to remove an element rather than prefixing
+ * a new node with data of NULL like this. */
+ hash_table_insert (parser->defines, NULL, $2);
+ talloc_free (macro);
+ }
+ talloc_free ($2);
+ }
+| HASH_IF conditional_tokens NEWLINE {
+ token_list_t *expanded;
+ token_t *token;
+
+ expanded = _token_list_create (parser);
+ token = _token_create_ival (parser, IF_EXPANDED, IF_EXPANDED);
+ _token_list_append (expanded, token);
+ talloc_unlink (parser, token);
+ _glcpp_parser_expand_token_list (parser, $2);
+ _token_list_append_list (expanded, $2);
+ glcpp_parser_lex_from (parser, expanded);
+ }
+| 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 {
+ token_list_t *expanded;
+ token_t *token;
+
+ expanded = _token_list_create (parser);
+ token = _token_create_ival (parser, ELIF_EXPANDED, ELIF_EXPANDED);
+ _token_list_append (expanded, token);
+ talloc_unlink (parser, token);
+ _glcpp_parser_expand_token_list (parser, $2);
+ _token_list_append_list (expanded, $2);
+ glcpp_parser_lex_from (parser, expanded);
+ }
+| HASH_ELIF NEWLINE {
+ /* #elif without an expression results in a warning if the
+ * condition doesn't matter (we just handled #if 1 or such)
+ * but an error otherwise. */
+ if (parser->skip_stack != NULL && parser->skip_stack->type == SKIP_NO_SKIP) {
+ parser->skip_stack->type = SKIP_TO_ENDIF;
+ glcpp_warning(& @1, parser, "ignoring illegal #elif without expression");
+ } else {
+ glcpp_error(& @1, parser, "#elif needs an 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 NEWLINE
+;
+
+expression:
+ 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 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; }
+| DEFINED { $$ = DEFINED; }
+;
+
+%%
+
+string_list_t *
+_string_list_create (void *ctx)
+{
+ string_list_t *list;
+
+ list = xtalloc (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 = xtalloc (list, string_node_t);
+ node->str = xtalloc_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 = xtalloc (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 = xtalloc (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 = xtalloc (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 = xtalloc (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 = xtalloc (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 = xtalloc (list, token_node_t);
+ node->token = xtalloc_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;
+}
+
+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;
+}
+
+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, "%" PRIxMAX, 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 = xtalloc_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);
+}
+
+glcpp_parser_t *
+glcpp_parser_create (void)
+{
+ glcpp_parser_t *parser;
+
+ parser = xtalloc (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;
+
+ return parser;
+}
+
+int
+glcpp_parser_parse (glcpp_parser_t *parser)
+{
+ return yyparse (parser);
+}
+
+void
+glcpp_parser_destroy (glcpp_parser_t *parser)
+{
+ if (parser->skip_stack)
+ glcpp_error (&parser->skip_stack->loc, parser, "Unterminated #if\n");
+ 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;
+}
+
+/* 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. Specificallty, *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;
+ }
+
+ if (macro->replacements == NULL) {
+ talloc_free (arguments);
+ return _token_list_create (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) {
+ _glcpp_parser_expand_token_list (parser,
+ argument);
+ _token_list_append_list (substituted, 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. Specificallty, *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 = xtalloc_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;
+
+ if (macro->replacements == NULL)
+ return _token_list_create (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 = xtalloc (list, active_list_t);
+ node->identifier = xtalloc_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);
+}
+
+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;
+
+ _check_for_reserved_macro_name(parser, loc, identifier);
+
+ macro = xtalloc (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 = xtalloc (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 = xtalloc (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..cc87e14950b
--- /dev/null
+++ b/src/glsl/glcpp/glcpp.c
@@ -0,0 +1,88 @@
+/*
+ * 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
+preprocess(void *talloc_ctx, const char **shader, char **info_log);
+
+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);
+
+ 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..2cfa98d2b1d
--- /dev/null
+++ b/src/glsl/glcpp/glcpp.h
@@ -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.
+ */
+
+#ifndef GLCPP_H
+#define GLCPP_H
+
+#include <stdint.h>
+
+#include <talloc.h>
+
+#include "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
+
+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;
+};
+
+glcpp_parser_t *
+glcpp_parser_create (void);
+
+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);
+
+/* 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);
+
+/* xtalloc - wrappers around talloc to check for out-of-memory */
+
+#define xtalloc(ctx, type) (type *)xtalloc_named_const(ctx, sizeof(type), #type)
+
+#define xtalloc_size(ctx, size) xtalloc_named_const(ctx, size, __location__)
+
+void *
+xtalloc_named_const (const void *context, size_t size, const char *name);
+
+char *
+xtalloc_strdup (const void *t, const char *p);
+
+char *
+xtalloc_strndup (const void *t, const char *p, size_t n);
+
+char *
+xtalloc_asprintf (const void *t, const char *fmt, ...);
+
+void *
+_xtalloc_reference_loc (const void *context,
+ const void *ptr, const char *location);
+
+#define xtalloc_reference(ctx, ptr) (_TALLOC_TYPEOF(ptr))_xtalloc_reference_loc((ctx),(ptr), __location__)
+
+#endif
diff --git a/src/glsl/glcpp/hash_table.c b/src/glsl/glcpp/hash_table.c
new file mode 100644
index 00000000000..e89a2564d76
--- /dev/null
+++ b/src/glsl/glcpp/hash_table.c
@@ -0,0 +1,159 @@
+/*
+ * Copyright © 2008 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 hash_table.c
+ * \brief Implementation of a generic, opaque hash table data type.
+ *
+ * \author Ian Romanick <[email protected]>
+ */
+
+#include "main/imports.h"
+#include "main/simple_list.h"
+#include "hash_table.h"
+
+struct node {
+ struct node *next;
+ struct node *prev;
+};
+
+struct hash_table {
+ hash_func_t hash;
+ hash_compare_func_t compare;
+
+ unsigned num_buckets;
+ struct node buckets[1];
+};
+
+
+struct hash_node {
+ struct node link;
+ const void *key;
+ void *data;
+};
+
+
+struct hash_table *
+hash_table_ctor(unsigned num_buckets, hash_func_t hash,
+ hash_compare_func_t compare)
+{
+ struct hash_table *ht;
+ unsigned i;
+
+
+ if (num_buckets < 16) {
+ num_buckets = 16;
+ }
+
+ ht = _mesa_malloc(sizeof(*ht) + ((num_buckets - 1)
+ * sizeof(ht->buckets[0])));
+ if (ht != NULL) {
+ ht->hash = hash;
+ ht->compare = compare;
+ ht->num_buckets = num_buckets;
+
+ for (i = 0; i < num_buckets; i++) {
+ make_empty_list(& ht->buckets[i]);
+ }
+ }
+
+ return ht;
+}
+
+
+void
+hash_table_dtor(struct hash_table *ht)
+{
+ hash_table_clear(ht);
+ _mesa_free(ht);
+}
+
+
+void
+hash_table_clear(struct hash_table *ht)
+{
+ struct node *node;
+ struct node *temp;
+ unsigned i;
+
+
+ for (i = 0; i < ht->num_buckets; i++) {
+ foreach_s(node, temp, & ht->buckets[i]) {
+ remove_from_list(node);
+ _mesa_free(node);
+ }
+
+ assert(is_empty_list(& ht->buckets[i]));
+ }
+}
+
+
+void *
+hash_table_find(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) {
+ return hn->data;
+ }
+ }
+
+ return NULL;
+}
+
+
+void
+hash_table_insert(struct hash_table *ht, void *data, const void *key)
+{
+ const unsigned hash_value = (*ht->hash)(key);
+ const unsigned bucket = hash_value % ht->num_buckets;
+ struct hash_node *node;
+
+ node = _mesa_calloc(sizeof(*node));
+
+ node->data = data;
+ node->key = key;
+
+ insert_at_head(& ht->buckets[bucket], & node->link);
+}
+
+
+unsigned
+hash_table_string_hash(const void *key)
+{
+ const char *str = (const char *) key;
+ unsigned hash = 5381;
+
+
+ while (*str != '\0') {
+ hash = (hash * 33) + *str;
+ str++;
+ }
+
+ return hash;
+}
diff --git a/src/glsl/glcpp/hash_table.h b/src/glsl/glcpp/hash_table.h
new file mode 100644
index 00000000000..b9dd343dee9
--- /dev/null
+++ b/src/glsl/glcpp/hash_table.h
@@ -0,0 +1,125 @@
+/*
+ * Copyright © 2008 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 hash_table.h
+ * \brief Implementation of a generic, opaque hash table data type.
+ *
+ * \author Ian Romanick <[email protected]>
+ */
+
+#ifndef HASH_TABLE_H
+#define HASH_TABLE_H
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#include <string.h>
+
+struct hash_table;
+
+typedef unsigned (*hash_func_t)(const void *key);
+typedef int (*hash_compare_func_t)(const void *key1, const void *key2);
+
+/**
+ * Hash table constructor
+ *
+ * Creates a hash table with the specified number of buckets. The supplied
+ * \c hash and \c compare routines are used when adding elements to the table
+ * and when searching for elements in the table.
+ *
+ * \param num_buckets Number of buckets (bins) in the hash table.
+ * \param hash Function used to compute hash value of input keys.
+ * \param compare Function used to compare keys.
+ */
+extern struct hash_table *hash_table_ctor(unsigned num_buckets,
+ hash_func_t hash, hash_compare_func_t compare);
+
+
+/**
+ * Release all memory associated with a hash table
+ *
+ * \warning
+ * This function cannot release memory occupied either by keys or data.
+ */
+extern void hash_table_dtor(struct hash_table *ht);
+
+
+/**
+ * Flush all entries from a hash table
+ *
+ * \param ht Table to be cleared of its entries.
+ */
+extern void hash_table_clear(struct hash_table *ht);
+
+
+/**
+ * Search a hash table for a specific element
+ *
+ * \param ht Table to be searched
+ * \param key Key of the desired element
+ *
+ * \return
+ * The \c data value supplied to \c hash_table_insert when the element with
+ * the matching key was added. If no matching key exists in the table,
+ * \c NULL is returned.
+ */
+extern void *hash_table_find(struct hash_table *ht, const void *key);
+
+
+/**
+ * Add an element to a hash table
+ */
+extern void hash_table_insert(struct hash_table *ht, void *data,
+ const void *key);
+
+
+/**
+ * Compute hash value of a string
+ *
+ * Computes the hash value of a string using the DJB2 algorithm developed by
+ * Professor Daniel J. Bernstein. It was published on comp.lang.c once upon
+ * a time. I was unable to find the original posting in the archives.
+ *
+ * \param key Pointer to a NUL terminated string to be hashed.
+ *
+ * \sa hash_table_string_compare
+ */
+extern unsigned hash_table_string_hash(const void *key);
+
+
+/**
+ * Compare two strings used as keys
+ *
+ * This is just a macro wrapper around \c strcmp.
+ *
+ * \sa hash_table_string_hash
+ */
+#define hash_table_string_compare ((hash_compare_func_t) strcmp)
+
+#ifdef __cplusplus
+};
+#endif
+
+#endif /* HASH_TABLE_H */
diff --git a/src/glsl/glcpp/main/imports.h b/src/glsl/glcpp/main/imports.h
new file mode 100644
index 00000000000..d2197342c04
--- /dev/null
+++ b/src/glsl/glcpp/main/imports.h
@@ -0,0 +1,6 @@
+#include <assert.h>
+#include <stdlib.h>
+
+#define _mesa_malloc(x) malloc(x)
+#define _mesa_free(x) free(x)
+#define _mesa_calloc(x) calloc(1,x)
diff --git a/src/glsl/glcpp/main/simple_list.h b/src/glsl/glcpp/main/simple_list.h
new file mode 100644
index 00000000000..5ef39e14cc6
--- /dev/null
+++ b/src/glsl/glcpp/main/simple_list.h
@@ -0,0 +1,235 @@
+/**
+ * \file simple_list.h
+ * Simple macros for type-safe, intrusive lists.
+ *
+ * Intended to work with a list sentinal which is created as an empty
+ * list. Insert & delete are O(1).
+ *
+ * \author
+ * (C) 1997, Keith Whitwell
+ */
+
+/*
+ * Mesa 3-D graphics library
+ * Version: 3.5
+ *
+ * Copyright (C) 1999-2001 Brian Paul All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included
+ * in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
+ * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+
+#ifndef _SIMPLE_LIST_H
+#define _SIMPLE_LIST_H
+
+struct simple_node {
+ struct simple_node *next;
+ struct simple_node *prev;
+};
+
+/**
+ * Remove an element from list.
+ *
+ * \param elem element to remove.
+ */
+#define remove_from_list(elem) \
+do { \
+ (elem)->next->prev = (elem)->prev; \
+ (elem)->prev->next = (elem)->next; \
+} while (0)
+
+/**
+ * Insert an element to the list head.
+ *
+ * \param list list.
+ * \param elem element to insert.
+ */
+#define insert_at_head(list, elem) \
+do { \
+ (elem)->prev = list; \
+ (elem)->next = (list)->next; \
+ (list)->next->prev = elem; \
+ (list)->next = elem; \
+} while(0)
+
+/**
+ * Insert an element to the list tail.
+ *
+ * \param list list.
+ * \param elem element to insert.
+ */
+#define insert_at_tail(list, elem) \
+do { \
+ (elem)->next = list; \
+ (elem)->prev = (list)->prev; \
+ (list)->prev->next = elem; \
+ (list)->prev = elem; \
+} while(0)
+
+/**
+ * Move an element to the list head.
+ *
+ * \param list list.
+ * \param elem element to move.
+ */
+#define move_to_head(list, elem) \
+do { \
+ remove_from_list(elem); \
+ insert_at_head(list, elem); \
+} while (0)
+
+/**
+ * Move an element to the list tail.
+ *
+ * \param list list.
+ * \param elem element to move.
+ */
+#define move_to_tail(list, elem) \
+do { \
+ remove_from_list(elem); \
+ insert_at_tail(list, elem); \
+} while (0)
+
+/**
+ * Consatinate a cyclic list to a list
+ *
+ * Appends the sequence of nodes starting with \c tail to the list \c head.
+ * A "cyclic list" is a list that does not have a sentinal node. This means
+ * that the data pointed to by \c tail is an actual node, not a dataless
+ * sentinal. Note that if \c tail constist of a single node, this macro
+ * behaves identically to \c insert_at_tail
+ *
+ * \param head Head of the list to be appended to. This may or may not
+ * be a cyclic list.
+ * \param tail Head of the cyclic list to be appended to \c head.
+ * \param temp Temporary \c simple_list used by the macro
+ *
+ * \sa insert_at_tail
+ */
+#define concat_list_and_cycle(head, tail, temp) \
+do { \
+ (head)->prev->next = (tail); \
+ (tail)->prev->next = (head); \
+ (temp) = (head)->prev; \
+ (head)->prev = (tail)->prev; \
+ (tail)->prev = (temp); \
+} while (0)
+
+#define concat_list(head, next_list) \
+do { \
+ (next_list)->next->prev = (head)->prev; \
+ (next_list)->prev->next = (head); \
+ (head)->prev->next = (next_list)->next; \
+ (head)->prev = (next_list)->prev; \
+} while (0)
+
+/**
+ * Make a empty list empty.
+ *
+ * \param sentinal list (sentinal element).
+ */
+#define make_empty_list(sentinal) \
+do { \
+ (sentinal)->next = sentinal; \
+ (sentinal)->prev = sentinal; \
+} while (0)
+
+/**
+ * Get list first element.
+ *
+ * \param list list.
+ *
+ * \return pointer to first element.
+ */
+#define first_elem(list) ((list)->next)
+
+/**
+ * Get list last element.
+ *
+ * \param list list.
+ *
+ * \return pointer to last element.
+ */
+#define last_elem(list) ((list)->prev)
+
+/**
+ * Get next element.
+ *
+ * \param elem element.
+ *
+ * \return pointer to next element.
+ */
+#define next_elem(elem) ((elem)->next)
+
+/**
+ * Get previous element.
+ *
+ * \param elem element.
+ *
+ * \return pointer to previous element.
+ */
+#define prev_elem(elem) ((elem)->prev)
+
+/**
+ * Test whether element is at end of the list.
+ *
+ * \param list list.
+ * \param elem element.
+ *
+ * \return non-zero if element is at end of list, or zero otherwise.
+ */
+#define at_end(list, elem) ((elem) == (list))
+
+/**
+ * Test if a list is empty.
+ *
+ * \param list list.
+ *
+ * \return non-zero if list empty, or zero otherwise.
+ */
+#define is_empty_list(list) ((list)->next == (list))
+
+/**
+ * Walk through the elements of a list.
+ *
+ * \param ptr pointer to the current element.
+ * \param list list.
+ *
+ * \note It should be followed by a { } block or a single statement, as in a \c
+ * for loop.
+ */
+#define foreach(ptr, list) \
+ for( ptr=(list)->next ; ptr!=list ; ptr=(ptr)->next )
+
+/**
+ * Walk through the elements of a list.
+ *
+ * Same as #foreach but lets you unlink the current value during a list
+ * traversal. Useful for freeing a list, element by element.
+ *
+ * \param ptr pointer to the current element.
+ * \param t temporary pointer.
+ * \param list list.
+ *
+ * \note It should be followed by a { } block or a single statement, as in a \c
+ * for loop.
+ */
+#define foreach_s(ptr, t, list) \
+ for(ptr=(list)->next,t=(ptr)->next; list != ptr; ptr=t, t=(t)->next)
+
+#endif
diff --git a/src/glsl/glcpp/pp.c b/src/glsl/glcpp/pp.c
new file mode 100644
index 00000000000..a25b7b72a6b
--- /dev/null
+++ b/src/glsl/glcpp/pp.c
@@ -0,0 +1,155 @@
+/*
+ * 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 <ctype.h>
+#include "glcpp.h"
+
+void
+glcpp_error (YYLTYPE *locp, glcpp_parser_t *parser, const char *fmt, ...)
+{
+ 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_list ap;
+ 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, ...)
+{
+ parser->info_log = talloc_asprintf_append(parser->info_log,
+ "%u:%u(%u): "
+ "preprocessor warning: ",
+ locp->source,
+ locp->first_line,
+ locp->first_column);
+ va_list ap;
+ 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;
+ /* Find the preceding '\', if it exists */
+ if (newline[-1] == '\\') {
+ backslash = newline - 1;
+ } else if (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)
+{
+ int errors;
+ glcpp_parser_t *parser = glcpp_parser_create ();
+ *shader = remove_line_continuations(parser, *shader);
+
+ glcpp_lex_set_source_string (parser, *shader);
+
+ glcpp_parser_parse (parser);
+
+ *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..b28b04f6431
--- /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..b28b04f6431
--- /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..3af71113c8c
--- /dev/null
+++ b/src/glsl/glcpp/tests/064-version.c.expected
@@ -0,0 +1,3 @@
+#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/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/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..396f6e175e8
--- /dev/null
+++ b/src/glsl/glcpp/tests/glcpp-test
@@ -0,0 +1,7 @@
+#!/bin/sh
+
+for test in *.c; do
+ echo "Testing $test"
+ ../glcpp < $test > $test.out
+ diff -u $test.expected $test.out
+done
diff --git a/src/glsl/glcpp/xtalloc.c b/src/glsl/glcpp/xtalloc.c
new file mode 100644
index 00000000000..656ac2d6cb5
--- /dev/null
+++ b/src/glsl/glcpp/xtalloc.c
@@ -0,0 +1,99 @@
+/*
+ * 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 <talloc.h>
+
+void *
+xtalloc_named_const (const void *context, size_t size, const char *name)
+{
+ void *ret;
+
+ ret = talloc_named_const (context, size, name);
+ if (ret == NULL) {
+ fprintf (stderr, "Out of memory.\n");
+ exit (1);
+ }
+
+ return ret;
+}
+
+char *
+xtalloc_strdup (const void *t, const char *p)
+{
+ char *ret;
+
+ ret = talloc_strdup (t, p);
+ if (ret == NULL) {
+ fprintf (stderr, "Out of memory.\n");
+ exit (1);
+ }
+
+ return ret;
+}
+
+char *
+xtalloc_strndup (const void *t, const char *p, size_t n)
+{
+ char *ret;
+
+ ret = talloc_strndup (t, p, n);
+ if (ret == NULL) {
+ fprintf (stderr, "Out of memory.\n");
+ exit (1);
+ }
+
+ return ret;
+}
+
+char *
+xtalloc_asprintf (const void *t, const char *fmt, ...)
+{
+ va_list ap;
+ char *ret;
+
+ va_start(ap, fmt);
+
+ ret = talloc_vasprintf(t, fmt, ap);
+ if (ret == NULL) {
+ fprintf (stderr, "Out of memory.\n");
+ exit (1);
+ }
+
+ va_end(ap);
+ return ret;
+}
+
+void *
+_xtalloc_reference_loc (const void *context,
+ const void *ptr, const char *location)
+{
+ void *ret;
+
+ ret = _talloc_reference_loc (context, ptr, location);
+ if (ret == NULL) {
+ fprintf (stderr, "Out of memory.\n");
+ exit (1);
+ }
+
+ return ret;
+}
diff --git a/src/glsl/glsl_lexer.lpp b/src/glsl/glsl_lexer.lpp
new file mode 100644
index 00000000000..fa439f12787
--- /dev/null
+++ b/src/glsl/glsl_lexer.lpp
@@ -0,0 +1,336 @@
+%{
+/*
+ * 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);
+
+%}
+
+%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;
+bool return BOOL;
+float return FLOAT;
+int return INT;
+
+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 MAT2;
+mat3 return MAT3;
+mat4 return MAT4;
+mat2x2 return MAT2X2;
+mat2x3 return MAT2X3;
+mat2x4 return MAT2X4;
+mat3x2 return MAT3X2;
+mat3x3 return MAT3X3;
+mat3x4 return MAT3X4;
+mat4x2 return MAT4X2;
+mat4x3 return MAT4X3;
+mat4x4 return MAT4X4;
+
+in return IN;
+out return OUT;
+inout return INOUT;
+uniform return UNIFORM;
+varying return VARYING;
+centroid {
+ if (yyextra->language_version >= 120) {
+ return CENTROID;
+ } else {
+ yylval->identifier = strdup(yytext);
+ return IDENTIFIER;
+ }
+ }
+invariant {
+ if (yyextra->language_version >= 120) {
+ return INVARIANT;
+ } else {
+ yylval->identifier = strdup(yytext);
+ return IDENTIFIER;
+ }
+ }
+
+flat {
+ if (yyextra->language_version >= 130) {
+ return FLAT;
+ } else {
+ yylval->identifier = strdup(yytext);
+ return IDENTIFIER;
+ }
+ }
+smooth {
+ if (yyextra->language_version >= 130) {
+ return SMOOTH;
+ } else {
+ yylval->identifier = strdup(yytext);
+ return IDENTIFIER;
+ }
+ }
+noperspective {
+ if (yyextra->language_version >= 130) {
+ return NOPERSPECTIVE;
+ } else {
+ yylval->identifier = strdup(yytext);
+ return IDENTIFIER;
+ }
+ }
+
+sampler1D return SAMPLER1D;
+sampler2D return SAMPLER2D;
+sampler3D return SAMPLER3D;
+samplerCube return SAMPLERCUBE;
+sampler1DShadow return SAMPLER1DSHADOW;
+sampler2DShadow return SAMPLER2DSHADOW;
+
+struct return STRUCT;
+void return VOID;
+
+\+\+ 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 + 2, 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;
+ }
+
+true {
+ yylval->n = 1;
+ return BOOLCONSTANT;
+ }
+false {
+ yylval->n = 0;
+ return BOOLCONSTANT;
+ }
+
+
+ /* Reserved words in GLSL 1.10. */
+asm return ASM;
+class return CLASS;
+union return UNION;
+enum return ENUM;
+typedef return TYPEDEF;
+template return TEMPLATE;
+this return THIS;
+packed return PACKED;
+goto return GOTO;
+switch return SWITCH;
+default return DEFAULT;
+inline return INLINE;
+noinline return NOINLINE;
+volatile return VOLATILE;
+public return PUBLIC;
+static return STATIC;
+extern return EXTERN;
+external return EXTERNAL;
+interface return INTERFACE;
+long return LONG;
+short return SHORT;
+double return DOUBLE;
+half return HALF;
+fixed return FIXED;
+unsigned return UNSIGNED;
+input return INPUT;
+output return OUTPUT;
+hvec2 return HVEC2;
+hvec3 return HVEC3;
+hvec4 return HVEC4;
+dvec2 return DVEC2;
+dvec3 return DVEC3;
+dvec4 return DVEC4;
+fvec2 return FVEC2;
+fvec3 return FVEC3;
+fvec4 return FVEC4;
+sampler2DRect return SAMPLER2DRECT;
+sampler3DRect return SAMPLER3DRECT;
+sampler2DRectShadow return SAMPLER2DRECTSHADOW;
+sizeof return SIZEOF;
+cast return CAST;
+namespace return NAMESPACE;
+using return USING;
+
+ /* Additional reserved words in GLSL 1.20. */
+lowp return LOWP;
+mediump return MEDIUMP;
+highp return HIGHP;
+precision return PRECISION;
+
+[_a-zA-Z][_a-zA-Z0-9]* {
+ struct _mesa_glsl_parse_state *state = yyextra;
+ void *ctx = talloc_parent(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.ypp b/src/glsl/glsl_parser.ypp
new file mode 100644
index 00000000000..4132495f403
--- /dev/null
+++ b/src/glsl/glsl_parser.ypp
@@ -0,0 +1,1444 @@
+%{
+/*
+ * 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
+%locations
+%error-verbose
+
+%lex-param {void *scanner}
+%parse-param {struct _mesa_glsl_parse_state *state}
+%name-prefix "_mesa_glsl_"
+
+%union {
+ int n;
+ float real;
+ char *identifier;
+
+ union {
+ struct ast_type_qualifier q;
+ unsigned i;
+ } type_qualifier;
+
+ struct ast_node *node;
+ struct ast_type_specifier *type_specifier;
+ struct ast_fully_specified_type *fully_specified_type;
+ struct ast_function *function;
+ struct ast_parameter_declarator *parameter_declarator;
+ struct ast_function_definition *function_definition;
+ struct ast_compound_statement *compound_statement;
+ struct ast_expression *expression;
+ struct ast_declarator_list *declarator_list;
+ struct ast_struct_specifier *struct_specifier;
+ struct ast_declaration *declaration;
+
+ struct {
+ struct ast_node *cond;
+ struct ast_expression *rest;
+ } for_rest_statement;
+}
+
+%token ATTRIBUTE CONST BOOL FLOAT INT UINT
+%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 MAT2 MAT3 MAT4 CENTROID IN OUT INOUT 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 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 PRECISION
+
+%token VERSION EXTENSION LINE PRAGMA COLON EOL INTERFACE OUTPUT
+
+ /* Reserved words that are not actually used in the grammar.
+ */
+%token ASM CLASS UNION ENUM TYPEDEF TEMPLATE THIS PACKED GOTO
+%token INLINE NOINLINE VOLATILE PUBLIC STATIC EXTERN EXTERNAL
+%token LONG SHORT DOUBLE HALF FIXED UNSIGNED INPUT OUPTUT
+%token HVEC2 HVEC3 HVEC4 DVEC2 DVEC3 DVEC4 FVEC2 FVEC3 FVEC4
+%token SAMPLER2DRECT SAMPLER3DRECT SAMPLER2DRECTSHADOW
+%token SIZEOF CAST NAMESPACE USING
+
+%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_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 = talloc_parent(state);
+ $$ = new(ctx) ast_expression(ast_identifier, NULL, NULL, NULL);
+ $$->set_location(yylloc);
+ $$->primary_expression.identifier = $1;
+ }
+ | INTCONSTANT
+ {
+ void *ctx = talloc_parent(state);
+ $$ = new(ctx) ast_expression(ast_int_constant, NULL, NULL, NULL);
+ $$->set_location(yylloc);
+ $$->primary_expression.int_constant = $1;
+ }
+ | UINTCONSTANT
+ {
+ void *ctx = talloc_parent(state);
+ $$ = new(ctx) ast_expression(ast_uint_constant, NULL, NULL, NULL);
+ $$->set_location(yylloc);
+ $$->primary_expression.uint_constant = $1;
+ }
+ | FLOATCONSTANT
+ {
+ void *ctx = talloc_parent(state);
+ $$ = new(ctx) ast_expression(ast_float_constant, NULL, NULL, NULL);
+ $$->set_location(yylloc);
+ $$->primary_expression.float_constant = $1;
+ }
+ | BOOLCONSTANT
+ {
+ void *ctx = talloc_parent(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 = talloc_parent(state);
+ $$ = new(ctx) ast_expression(ast_array_index, $1, $3, NULL);
+ $$->set_location(yylloc);
+ }
+ | function_call
+ {
+ /* Function call parameters used to be stored as a circular list in
+ * subexpressions[1]. They are now stored as a regular list in
+ * expressions. This assertion validates that the old code was
+ * correctly converted. It can eventually be removed.
+ */
+ assert($1->subexpressions[1] == NULL);
+ $$ = $1;
+ }
+ | postfix_expression '.' IDENTIFIER
+ {
+ void *ctx = talloc_parent(state);
+ $$ = new(ctx) ast_expression(ast_field_selection, $1, NULL, NULL);
+ $$->set_location(yylloc);
+ $$->primary_expression.identifier = $3;
+ }
+ | postfix_expression INC_OP
+ {
+ void *ctx = talloc_parent(state);
+ $$ = new(ctx) ast_expression(ast_post_inc, $1, NULL, NULL);
+ $$->set_location(yylloc);
+ }
+ | postfix_expression DEC_OP
+ {
+ void *ctx = talloc_parent(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 = talloc_parent(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
+ | 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 = talloc_parent(state);
+ $$ = new(ctx) ast_function_expression($1);
+ $$->set_location(yylloc);
+ }
+ | IDENTIFIER
+ {
+ void *ctx = talloc_parent(state);
+ ast_expression *callee = new(ctx) ast_expression($1);
+ $$ = new(ctx) ast_function_expression(callee);
+ $$->set_location(yylloc);
+ }
+ | FIELD_SELECTION
+ {
+ void *ctx = talloc_parent(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 = talloc_parent(state);
+ $$ = new(ctx) ast_expression(ast_pre_inc, $2, NULL, NULL);
+ $$->set_location(yylloc);
+ }
+ | DEC_OP unary_expression
+ {
+ void *ctx = talloc_parent(state);
+ $$ = new(ctx) ast_expression(ast_pre_dec, $2, NULL, NULL);
+ $$->set_location(yylloc);
+ }
+ | unary_operator unary_expression
+ {
+ void *ctx = talloc_parent(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 = talloc_parent(state);
+ $$ = new(ctx) ast_expression_bin(ast_mul, $1, $3);
+ $$->set_location(yylloc);
+ }
+ | multiplicative_expression '/' unary_expression
+ {
+ void *ctx = talloc_parent(state);
+ $$ = new(ctx) ast_expression_bin(ast_div, $1, $3);
+ $$->set_location(yylloc);
+ }
+ | multiplicative_expression '%' unary_expression
+ {
+ void *ctx = talloc_parent(state);
+ $$ = new(ctx) ast_expression_bin(ast_mod, $1, $3);
+ $$->set_location(yylloc);
+ }
+ ;
+
+additive_expression:
+ multiplicative_expression
+ | additive_expression '+' multiplicative_expression
+ {
+ void *ctx = talloc_parent(state);
+ $$ = new(ctx) ast_expression_bin(ast_add, $1, $3);
+ $$->set_location(yylloc);
+ }
+ | additive_expression '-' multiplicative_expression
+ {
+ void *ctx = talloc_parent(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 = talloc_parent(state);
+ $$ = new(ctx) ast_expression_bin(ast_lshift, $1, $3);
+ $$->set_location(yylloc);
+ }
+ | shift_expression RIGHT_OP additive_expression
+ {
+ void *ctx = talloc_parent(state);
+ $$ = new(ctx) ast_expression_bin(ast_rshift, $1, $3);
+ $$->set_location(yylloc);
+ }
+ ;
+
+relational_expression:
+ shift_expression
+ | relational_expression '<' shift_expression
+ {
+ void *ctx = talloc_parent(state);
+ $$ = new(ctx) ast_expression_bin(ast_less, $1, $3);
+ $$->set_location(yylloc);
+ }
+ | relational_expression '>' shift_expression
+ {
+ void *ctx = talloc_parent(state);
+ $$ = new(ctx) ast_expression_bin(ast_greater, $1, $3);
+ $$->set_location(yylloc);
+ }
+ | relational_expression LE_OP shift_expression
+ {
+ void *ctx = talloc_parent(state);
+ $$ = new(ctx) ast_expression_bin(ast_lequal, $1, $3);
+ $$->set_location(yylloc);
+ }
+ | relational_expression GE_OP shift_expression
+ {
+ void *ctx = talloc_parent(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 = talloc_parent(state);
+ $$ = new(ctx) ast_expression_bin(ast_equal, $1, $3);
+ $$->set_location(yylloc);
+ }
+ | equality_expression NE_OP relational_expression
+ {
+ void *ctx = talloc_parent(state);
+ $$ = new(ctx) ast_expression_bin(ast_nequal, $1, $3);
+ $$->set_location(yylloc);
+ }
+ ;
+
+and_expression:
+ equality_expression
+ | and_expression '&' equality_expression
+ {
+ void *ctx = talloc_parent(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 = talloc_parent(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 = talloc_parent(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 = talloc_parent(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 = talloc_parent(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 = talloc_parent(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 = talloc_parent(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 = talloc_parent(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 = talloc_parent(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 = talloc_parent(state);
+ $$ = new(ctx) ast_function();
+ $$->set_location(yylloc);
+ $$->return_type = $1;
+ $$->identifier = $2;
+ }
+ ;
+
+parameter_declarator:
+ type_specifier IDENTIFIER
+ {
+ void *ctx = talloc_parent(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 = talloc_parent(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 = talloc_parent(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 = talloc_parent(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 { $$.i = 0; $$.q.in = 1; }
+ | OUT { $$.i = 0; $$.q.out = 1; }
+ | INOUT { $$.i = 0; $$.q.in = 1; $$.q.out = 1; }
+ ;
+
+parameter_type_specifier:
+ type_specifier
+ ;
+
+init_declarator_list:
+ single_declaration
+ | init_declarator_list ',' IDENTIFIER
+ {
+ void *ctx = talloc_parent(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 = talloc_parent(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 = talloc_parent(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 = talloc_parent(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 = talloc_parent(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 = talloc_parent(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 = talloc_parent(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 = talloc_parent(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 = talloc_parent(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 = talloc_parent(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 = talloc_parent(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 = talloc_parent(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 = talloc_parent(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 = talloc_parent(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 = talloc_parent(state);
+ $$ = new(ctx) ast_fully_specified_type();
+ $$->set_location(yylloc);
+ $$->specifier = $1;
+ }
+ | type_qualifier type_specifier
+ {
+ void *ctx = talloc_parent(state);
+ $$ = new(ctx) ast_fully_specified_type();
+ $$->set_location(yylloc);
+ $$->qualifier = $1.q;
+ $$->specifier = $2;
+ }
+ ;
+
+interpolation_qualifier:
+ SMOOTH { $$.i = 0; $$.q.smooth = 1; }
+ | FLAT { $$.i = 0; $$.q.flat = 1; }
+ | NOPERSPECTIVE { $$.i = 0; $$.q.noperspective = 1; }
+ ;
+
+parameter_type_qualifier:
+ CONST { $$.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 { $$.i = 0; $$.q.constant = 1; }
+ | ATTRIBUTE { $$.i = 0; $$.q.attribute = 1; }
+ | VARYING { $$.i = 0; $$.q.varying = 1; }
+ | CENTROID VARYING { $$.i = 0; $$.q.centroid = 1; $$.q.varying = 1; }
+ | IN { $$.i = 0; $$.q.in = 1; }
+ | OUT { $$.i = 0; $$.q.out = 1; }
+ | CENTROID IN { $$.i = 0; $$.q.centroid = 1; $$.q.in = 1; }
+ | CENTROID OUT { $$.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 = talloc_parent(state);
+ $$ = new(ctx) ast_type_specifier($1);
+ $$->set_location(yylloc);
+ }
+ | struct_specifier
+ {
+ void *ctx = talloc_parent(state);
+ $$ = new(ctx) ast_type_specifier($1);
+ $$->set_location(yylloc);
+ }
+ | IDENTIFIER
+ {
+ void *ctx = talloc_parent(state);
+ $$ = new(ctx) ast_type_specifier($1);
+ $$->set_location(yylloc);
+ }
+ ;
+
+basic_type_specifier_nonarray:
+ VOID { $$ = ast_void; }
+ | FLOAT { $$ = ast_float; }
+ | INT { $$ = ast_int; }
+ | UINT { $$ = ast_uint; }
+ | BOOL { $$ = 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; }
+ | MAT2 { $$ = ast_mat2; }
+ | MAT3 { $$ = ast_mat3; }
+ | MAT4 { $$ = ast_mat4; }
+ | 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,
+ "precission 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,
+ "precission 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,
+ "precission 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 = talloc_parent(state);
+ $$ = new(ctx) ast_struct_specifier($2, $4);
+ $$->set_location(yylloc);
+ }
+ | STRUCT '{' struct_declaration_list '}'
+ {
+ void *ctx = talloc_parent(state);
+ $$ = new(ctx) ast_struct_specifier(NULL, $3);
+ $$->set_location(yylloc);
+ }
+ ;
+
+struct_declaration_list:
+ struct_declaration
+ {
+ $$ = (struct ast_node *) $1;
+ $1->link.self_link();
+ }
+ | struct_declaration_list struct_declaration
+ {
+ $$ = (struct ast_node *) $1;
+ $$->link.insert_before(& $2->link);
+ }
+ ;
+
+struct_declaration:
+ type_specifier struct_declarator_list ';'
+ {
+ void *ctx = talloc_parent(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 = talloc_parent(state);
+ $$ = new(ctx) ast_declaration($1, false, NULL, NULL);
+ $$->set_location(yylloc);
+ }
+ | IDENTIFIER '[' constant_expression ']'
+ {
+ void *ctx = talloc_parent(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 { $$ = (struct 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 = talloc_parent(state);
+ $$ = new(ctx) ast_compound_statement(true, NULL);
+ $$->set_location(yylloc);
+ }
+ | '{' statement_list '}'
+ {
+ void *ctx = talloc_parent(state);
+ $$ = new(ctx) ast_compound_statement(true, $2);
+ $$->set_location(yylloc);
+ }
+ ;
+
+statement_no_new_scope:
+ compound_statement_no_new_scope { $$ = (struct ast_node *) $1; }
+ | simple_statement
+ ;
+
+compound_statement_no_new_scope:
+ '{' '}'
+ {
+ void *ctx = talloc_parent(state);
+ $$ = new(ctx) ast_compound_statement(false, NULL);
+ $$->set_location(yylloc);
+ }
+ | '{' statement_list '}'
+ {
+ void *ctx = talloc_parent(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 = talloc_parent(state);
+ $$ = new(ctx) ast_expression_statement(NULL);
+ $$->set_location(yylloc);
+ }
+ | expression ';'
+ {
+ void *ctx = talloc_parent(state);
+ $$ = new(ctx) ast_expression_statement($1);
+ $$->set_location(yylloc);
+ }
+ ;
+
+selection_statement_matched:
+ IF '(' expression ')' statement_matched ELSE statement_matched
+ {
+ void *ctx = talloc_parent(state);
+ $$ = new(ctx) ast_selection_statement($3, $5, $7);
+ $$->set_location(yylloc);
+ }
+ ;
+
+selection_statement_unmatched:
+ IF '(' expression ')' statement_matched
+ {
+ void *ctx = talloc_parent(state);
+ $$ = new(ctx) ast_selection_statement($3, $5, NULL);
+ $$->set_location(yylloc);
+ }
+ | IF '(' expression ')' statement_unmatched
+ {
+ void *ctx = talloc_parent(state);
+ $$ = new(ctx) ast_selection_statement($3, $5, NULL);
+ $$->set_location(yylloc);
+ }
+ | IF '(' expression ')' statement_matched ELSE statement_unmatched
+ {
+ void *ctx = talloc_parent(state);
+ $$ = new(ctx) ast_selection_statement($3, $5, $7);
+ $$->set_location(yylloc);
+ }
+ ;
+
+condition:
+ expression
+ {
+ $$ = (struct ast_node *) $1;
+ }
+ | fully_specified_type IDENTIFIER '=' initializer
+ {
+ void *ctx = talloc_parent(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 = talloc_parent(state);
+ $$ = new(ctx) ast_iteration_statement(ast_iteration_statement::ast_while,
+ NULL, $3, NULL, $5);
+ $$->set_location(yylloc);
+ }
+ | DO statement WHILE '(' expression ')' ';'
+ {
+ void *ctx = talloc_parent(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 = talloc_parent(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 = talloc_parent(state);
+ $$ = new(ctx) ast_jump_statement(ast_jump_statement::ast_continue, NULL);
+ $$->set_location(yylloc);
+ }
+ | BREAK ';'
+ {
+ void *ctx = talloc_parent(state);
+ $$ = new(ctx) ast_jump_statement(ast_jump_statement::ast_break, NULL);
+ $$->set_location(yylloc);
+ }
+ | RETURN ';'
+ {
+ void *ctx = talloc_parent(state);
+ $$ = new(ctx) ast_jump_statement(ast_jump_statement::ast_return, NULL);
+ $$->set_location(yylloc);
+ }
+ | RETURN expression ';'
+ {
+ void *ctx = talloc_parent(state);
+ $$ = new(ctx) ast_jump_statement(ast_jump_statement::ast_return, $2);
+ $$->set_location(yylloc);
+ }
+ | DISCARD ';' // Fragment shader only.
+ {
+ void *ctx = talloc_parent(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 = talloc_parent(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..1d16ef55f57
--- /dev/null
+++ b/src/glsl/glsl_parser_extras.cpp
@@ -0,0 +1,621 @@
+/*
+ * 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 "ast.h"
+#include "glsl_parser_extras.h"
+#include "glsl_parser.h"
+
+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.");
+}
+
+
+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_texture_rectangle") == 0) {
+ state->ARB_texture_rectangle_enable = (ext_mode != extension_disable);
+ state->ARB_texture_rectangle_warn = (ext_mode == extension_warn);
+ } 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)
+{
+ /* empty */
+}
+
+
+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;
+}
+
+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);
+}
diff --git a/src/glsl/glsl_parser_extras.h b/src/glsl/glsl_parser_extras.h
new file mode 100644
index 00000000000..cfe02e3b0c1
--- /dev/null
+++ b/src/glsl/glsl_parser_extras.h
@@ -0,0 +1,139 @@
+/*
+ * 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 _mesa_glsl_parse_state {
+ void *scanner;
+ exec_list translation_unit;
+ glsl_symbol_table *symbols;
+
+ unsigned language_version;
+ enum _mesa_glsl_parser_targets target;
+
+ /**
+ * 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;
+
+ /** Was there an error during compilation? */
+ bool error;
+
+ /** Index of last generated anonymous temporary. */
+ unsigned temp_index;
+
+ /** Loop or switch statement containing the current instructions. */
+ class ir_instruction *loop_or_switch_nesting;
+
+ /** 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_texture_rectangle_enable:1;
+ unsigned ARB_texture_rectangle_warn:1;
+ unsigned EXT_texture_array_enable:1;
+ unsigned EXT_texture_array_warn: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
+
+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);
+}
+
+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..ae2fd3f4f1f
--- /dev/null
+++ b/src/glsl/glsl_symbol_table.h
@@ -0,0 +1,163 @@
+/* -*- 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>
+
+#include "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;
+ }
+ /*@}*/
+
+ /**
+ * \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..bef267fa6be
--- /dev/null
+++ b/src/glsl/glsl_types.cpp
@@ -0,0 +1,773 @@
+/*
+ * 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 "glsl_symbol_table.h"
+#include "glsl_parser_extras.h"
+#include "glsl_types.h"
+#include "builtin_types.h"
+#include "hash_table.h"
+
+
+hash_table *glsl_type::array_types = NULL;
+
+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]);
+ }
+}
+
+
+static void
+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);
+}
+
+
+static void
+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);
+}
+
+
+static void
+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);
+}
+
+
+static void
+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);
+}
+
+
+static void
+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:
+ generate_110_types(state->symbols);
+ break;
+ case 120:
+ generate_120_types(state->symbols);
+ break;
+ case 130:
+ generate_130_types(state->symbols);
+ break;
+ default:
+ /* error */
+ break;
+ }
+
+ if (state->ARB_texture_rectangle_enable) {
+ 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.
+ 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;
+ }
+}
+
+
+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)
+ : new(ctx) ir_variable(fields.structure[i].type, param_name);
+
+ var->mode = 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 __retval that has
+ * the same type as the constructor. After initializing __retval,
+ * __retval is returned.
+ */
+ ir_variable *retval = new(ctx) ir_variable(this, "__retval");
+ 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;
+}
+
+
+/**
+ * Generate the function intro for a constructor
+ *
+ * \param type Data type to be constructed
+ * \param count Number of parameters to this concrete constructor. Most
+ * types have at least two constructors. One will take a
+ * single scalar parameter and the other will take "N"
+ * scalar parameters.
+ * \param parameters Storage for the list of parameters. These are
+ * typically stored in an \c ir_function_signature.
+ * \param declarations Pointers to the variable declarations for the function
+ * parameters. These are used later to avoid having to use
+ * the symbol table.
+ */
+static ir_function_signature *
+generate_constructor_intro(void *ctx,
+ const glsl_type *type, unsigned parameter_count,
+ ir_variable **declarations)
+{
+ /* Names of parameters used in vector and matrix constructors
+ */
+ static const char *const names[] = {
+ "a", "b", "c", "d", "e", "f", "g", "h",
+ "i", "j", "k", "l", "m", "n", "o", "p",
+ };
+
+ assert(parameter_count <= Elements(names));
+
+ const glsl_type *const parameter_type = type->get_base_type();
+
+ ir_function_signature *const signature = new(ctx) ir_function_signature(type);
+
+ for (unsigned i = 0; i < parameter_count; i++) {
+ ir_variable *var = new(ctx) ir_variable(parameter_type, names[i]);
+
+ var->mode = ir_var_in;
+ signature->parameters.push_tail(var);
+
+ declarations[i] = var;
+ }
+
+ ir_variable *retval = new(ctx) ir_variable(type, "__retval");
+ signature->body.push_tail(retval);
+
+ declarations[16] = retval;
+ return signature;
+}
+
+
+/**
+ * Generate the body of a vector constructor that takes a single scalar
+ */
+static void
+generate_vec_body_from_scalar(void *ctx,
+ exec_list *instructions,
+ ir_variable **declarations)
+{
+ ir_instruction *inst;
+
+ /* Generate a single assignment of the parameter to __retval.x and return
+ * __retval.xxxx for however many vector components there are.
+ */
+ ir_dereference *const lhs_ref =
+ new(ctx) ir_dereference_variable(declarations[16]);
+ ir_dereference *const rhs = new(ctx) ir_dereference_variable(declarations[0]);
+
+ ir_swizzle *lhs = new(ctx) ir_swizzle(lhs_ref, 0, 0, 0, 0, 1);
+
+ inst = new(ctx) ir_assignment(lhs, rhs, NULL);
+ instructions->push_tail(inst);
+
+ ir_dereference *const retref = new(ctx) ir_dereference_variable(declarations[16]);
+
+ ir_swizzle *retval = new(ctx) ir_swizzle(retref, 0, 0, 0, 0,
+ declarations[16]->type->vector_elements);
+
+ inst = new(ctx) ir_return(retval);
+ instructions->push_tail(inst);
+}
+
+
+/**
+ * Generate the body of a vector constructor that takes multiple scalars
+ */
+static void
+generate_vec_body_from_N_scalars(void *ctx,
+ exec_list *instructions,
+ ir_variable **declarations)
+{
+ ir_instruction *inst;
+ const glsl_type *const vec_type = declarations[16]->type;
+
+ /* Generate an assignment of each parameter to a single component of
+ * __retval.x and return __retval.
+ */
+ for (unsigned i = 0; i < vec_type->vector_elements; i++) {
+ ir_dereference *const lhs_ref =
+ new(ctx) ir_dereference_variable(declarations[16]);
+ ir_dereference *const rhs = new(ctx) ir_dereference_variable(declarations[i]);
+
+ ir_swizzle *lhs = new(ctx) ir_swizzle(lhs_ref, i, 0, 0, 0, 1);
+
+ inst = new(ctx) ir_assignment(lhs, rhs, NULL);
+ instructions->push_tail(inst);
+ }
+
+ ir_dereference *retval = new(ctx) ir_dereference_variable(declarations[16]);
+
+ inst = new(ctx) ir_return(retval);
+ instructions->push_tail(inst);
+}
+
+
+/**
+ * Generate the body of a matrix constructor that takes a single scalar
+ */
+static void
+generate_mat_body_from_scalar(void *ctx,
+ exec_list *instructions,
+ ir_variable **declarations)
+{
+ ir_instruction *inst;
+
+ /* Generate an assignment of the parameter to the X component of a
+ * temporary vector. Set the remaining fields of the vector to 0. The
+ * size of the vector is equal to the number of rows of the matrix.
+ *
+ * Set each column of the matrix to a successive "rotation" of the
+ * temporary vector. This fills the matrix with 0s, but writes the single
+ * scalar along the matrix's diagonal.
+ *
+ * For a mat4x3, this is equivalent to:
+ *
+ * vec3 tmp;
+ * mat4x3 __retval;
+ * tmp.x = a;
+ * tmp.y = 0.0;
+ * tmp.z = 0.0;
+ * __retval[0] = tmp.xyy;
+ * __retval[1] = tmp.yxy;
+ * __retval[2] = tmp.yyx;
+ * __retval[3] = tmp.yyy;
+ */
+ const glsl_type *const column_type = declarations[16]->type->column_type();
+ const glsl_type *const row_type = declarations[16]->type->row_type();
+
+ ir_variable *const column = new(ctx) ir_variable(column_type, "v");
+
+ instructions->push_tail(column);
+
+ ir_dereference *const lhs_ref = new(ctx) ir_dereference_variable(column);
+ ir_dereference *const rhs = new(ctx) ir_dereference_variable(declarations[0]);
+
+ ir_swizzle *lhs = new(ctx) ir_swizzle(lhs_ref, 0, 0, 0, 0, 1);
+
+ inst = new(ctx) ir_assignment(lhs, rhs, NULL);
+ instructions->push_tail(inst);
+
+ for (unsigned i = 1; i < column_type->vector_elements; i++) {
+ ir_dereference *const lhs_ref = new(ctx) ir_dereference_variable(column);
+ ir_constant *const zero = new(ctx) ir_constant(0.0f);
+
+ ir_swizzle *lhs = new(ctx) ir_swizzle(lhs_ref, i, 0, 0, 0, 1);
+
+ inst = new(ctx) ir_assignment(lhs, zero, NULL);
+ instructions->push_tail(inst);
+ }
+
+
+ for (unsigned i = 0; i < row_type->vector_elements; i++) {
+ static const unsigned swiz[] = { 1, 1, 1, 0, 1, 1, 1 };
+ ir_dereference *const rhs_ref = new(ctx) ir_dereference_variable(column);
+
+ /* This will be .xyyy when i=0, .yxyy when i=1, etc.
+ */
+ ir_swizzle *rhs = new(ctx) ir_swizzle(rhs_ref, swiz[3 - i], swiz[4 - i],
+ swiz[5 - i], swiz[6 - i],
+ column_type->vector_elements);
+
+ ir_constant *const idx = new(ctx) ir_constant(int(i));
+ ir_dereference *const lhs =
+ new(ctx) ir_dereference_array(declarations[16], idx);
+
+ inst = new(ctx) ir_assignment(lhs, rhs, NULL);
+ instructions->push_tail(inst);
+ }
+
+ ir_dereference *const retval = new(ctx) ir_dereference_variable(declarations[16]);
+ inst = new(ctx) ir_return(retval);
+ instructions->push_tail(inst);
+}
+
+
+/**
+ * Generate the body of a vector constructor that takes multiple scalars
+ */
+static void
+generate_mat_body_from_N_scalars(void *ctx,
+ exec_list *instructions,
+ ir_variable **declarations)
+{
+ ir_instruction *inst;
+ const glsl_type *const row_type = declarations[16]->type->row_type();
+ const glsl_type *const column_type = declarations[16]->type->column_type();
+
+ /* Generate an assignment of each parameter to a single component of
+ * of a particular column of __retval and return __retval.
+ */
+ for (unsigned i = 0; i < column_type->vector_elements; i++) {
+ for (unsigned j = 0; j < row_type->vector_elements; j++) {
+ ir_constant *row_index = new(ctx) ir_constant(int(i));
+ ir_dereference *const row_access =
+ new(ctx) ir_dereference_array(declarations[16], row_index);
+
+ ir_swizzle *component_access = new(ctx) ir_swizzle(row_access,
+ j, 0, 0, 0, 1);
+
+ const unsigned param = (i * row_type->vector_elements) + j;
+ ir_dereference *const rhs =
+ new(ctx) ir_dereference_variable(declarations[param]);
+
+ inst = new(ctx) ir_assignment(component_access, rhs, NULL);
+ instructions->push_tail(inst);
+ }
+ }
+
+ ir_dereference *retval = new(ctx) ir_dereference_variable(declarations[16]);
+
+ inst = new(ctx) ir_return(retval);
+ instructions->push_tail(inst);
+}
+
+
+/**
+ * Generate the constructors for a set of GLSL types
+ *
+ * Constructor implementations are added to \c instructions, and the symbols
+ * are added to \c symtab.
+ */
+static void
+generate_constructor(glsl_symbol_table *symtab, const struct glsl_type *types,
+ unsigned num_types, exec_list *instructions)
+{
+ void *ctx = symtab;
+ ir_variable *declarations[17];
+
+ for (unsigned i = 0; i < num_types; i++) {
+ /* Only numeric and boolean vectors and matrices get constructors here.
+ * Structures need to be handled elsewhere. It is expected that scalar
+ * constructors are never actually called, so they are not generated.
+ */
+ if (!types[i].is_numeric() && !types[i].is_boolean())
+ continue;
+
+ if (types[i].is_scalar())
+ continue;
+
+ /* Generate the function block, add it to the symbol table, and emit it.
+ */
+ ir_function *const f = new(ctx) ir_function(types[i].name);
+
+ bool added = symtab->add_function(types[i].name, f);
+ assert(added);
+
+ instructions->push_tail(f);
+
+ /* Each type has several basic constructors. The total number of forms
+ * depends on the derived type.
+ *
+ * Vectors: 1 scalar, N scalars
+ * Matrices: 1 scalar, NxM scalars
+ *
+ * Several possible types of constructors are not included in this list.
+ *
+ * Scalar constructors are not included. The expectation is that the
+ * IR generator won't actually generate these as constructor calls. The
+ * expectation is that it will just generate the necessary type
+ * conversion.
+ *
+ * Matrix contructors from matrices are also not included. The
+ * expectation is that the IR generator will generate a call to the
+ * appropriate from-scalars constructor.
+ */
+ ir_function_signature *const sig =
+ generate_constructor_intro(ctx, &types[i], 1, declarations);
+ f->add_signature(sig);
+
+ if (types[i].is_vector()) {
+ generate_vec_body_from_scalar(ctx, &sig->body, declarations);
+
+ ir_function_signature *const vec_sig =
+ generate_constructor_intro(ctx,
+ &types[i], types[i].vector_elements,
+ declarations);
+ f->add_signature(vec_sig);
+
+ generate_vec_body_from_N_scalars(ctx, &vec_sig->body, declarations);
+ } else {
+ assert(types[i].is_matrix());
+
+ generate_mat_body_from_scalar(ctx, &sig->body, declarations);
+
+ ir_function_signature *const mat_sig =
+ generate_constructor_intro(ctx,
+ &types[i],
+ (types[i].vector_elements
+ * types[i].matrix_columns),
+ declarations);
+ f->add_signature(mat_sig);
+
+ generate_mat_body_from_N_scalars(ctx, &mat_sig->body, declarations);
+ }
+ }
+}
+
+
+void
+generate_110_constructors(glsl_symbol_table *symtab, exec_list *instructions)
+{
+ generate_constructor(symtab, builtin_core_types,
+ Elements(builtin_core_types), instructions);
+}
+
+
+void
+generate_120_constructors(glsl_symbol_table *symtab, exec_list *instructions)
+{
+ generate_110_constructors(symtab, instructions);
+
+ generate_constructor(symtab, builtin_120_types,
+ Elements(builtin_120_types), instructions);
+}
+
+
+void
+generate_130_constructors(glsl_symbol_table *symtab, exec_list *instructions)
+{
+ generate_120_constructors(symtab, instructions);
+
+ generate_constructor(symtab, builtin_130_types,
+ Elements(builtin_130_types), instructions);
+}
+
+
+void
+_mesa_glsl_initialize_constructors(exec_list *instructions,
+ struct _mesa_glsl_parse_state *state)
+{
+ switch (state->language_version) {
+ case 110:
+ generate_110_constructors(state->symbols, instructions);
+ break;
+ case 120:
+ generate_120_constructors(state->symbols, instructions);
+ break;
+ case 130:
+ generate_130_constructors(state->symbols, instructions);
+ break;
+ default:
+ /* error */
+ break;
+ }
+}
+
+
+glsl_type::glsl_type(void *ctx, 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;
+
+ /* 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(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;
+}
+
+
+int
+glsl_type::array_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.
+ */
+ return ((key1->fields.array == key2->fields.array)
+ && (key1->length == key2->length)) ? 0 : 1;
+}
+
+
+unsigned
+glsl_type::array_key_hash(const void *a)
+{
+ const glsl_type *const key = (glsl_type *) a;
+
+ const struct {
+ const glsl_type *t;
+ unsigned l;
+ char nul;
+ } hash_key = {
+ key->fields.array,
+ key->length,
+ '\0'
+ };
+
+ return hash_table_string_hash(& hash_key);
+}
+
+
+const glsl_type *
+glsl_type::get_array_instance(void *ctx, const glsl_type *base,
+ unsigned array_size)
+{
+ const glsl_type key(ctx, base, array_size);
+
+ if (array_types == NULL) {
+ array_types = hash_table_ctor(64, array_key_hash, array_key_compare);
+ }
+
+ const glsl_type *t = (glsl_type *) hash_table_find(array_types, & key);
+ if (t == NULL) {
+ t = new(ctx) glsl_type(ctx, base, array_size);
+
+ hash_table_insert(array_types, (void *) t, t);
+ }
+
+ assert(t->base_type == GLSL_TYPE_ARRAY);
+ assert(t->length == array_size);
+ assert(t->fields.array == base);
+
+ 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..39e6ac970aa
--- /dev/null
+++ b/src/glsl/glsl_types.h
@@ -0,0 +1,445 @@
+/* -*- 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 <talloc.h>
+}
+
+#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 {
+ 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 'ctx' (or any of its ancestors). */
+ static void* operator new(size_t size, void *ctx)
+ {
+ void *type;
+
+ type = talloc_size(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. */
+ const 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;
+ /*@}*/
+
+
+ glsl_type(unsigned base_type, unsigned vector_elements,
+ unsigned matrix_columns, const char *name) :
+ base_type(base_type),
+ sampler_dimensionality(0), sampler_shadow(0), sampler_array(0),
+ sampler_type(0),
+ vector_elements(vector_elements), matrix_columns(matrix_columns),
+ name(name),
+ length(0)
+ {
+ /* Neither dimension is zero or both dimensions are zero.
+ */
+ assert((vector_elements == 0) == (matrix_columns == 0));
+ memset(& fields, 0, sizeof(fields));
+ }
+
+ glsl_type(enum glsl_sampler_dim dim, bool shadow, bool array,
+ unsigned type, const char *name) :
+ base_type(GLSL_TYPE_SAMPLER),
+ sampler_dimensionality(dim), sampler_shadow(shadow),
+ sampler_array(array), sampler_type(type),
+ vector_elements(0), matrix_columns(0),
+ name(name),
+ length(0)
+ {
+ memset(& fields, 0, sizeof(fields));
+ }
+
+ 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),
+ name(name),
+ length(num_fields)
+ {
+ this->fields.structure = fields;
+ }
+
+ /**
+ * 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(void *ctx,
+ const glsl_type *base,
+ unsigned elements);
+
+ /**
+ * 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:
+ /**
+ * Constructor for array types
+ */
+ glsl_type(void *ctx, const glsl_type *array, unsigned length);
+
+ /** Hash table containing the known array types. */
+ static struct hash_table *array_types;
+
+ static int array_key_compare(const void *a, const void *b);
+ static unsigned array_key_hash(const void *key);
+};
+
+struct glsl_struct_field {
+ const struct glsl_type *type;
+ const char *name;
+};
+
+struct _mesa_glsl_parse_state;
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+extern void
+_mesa_glsl_initialize_types(struct _mesa_glsl_parse_state *state);
+
+extern void
+_mesa_glsl_initialize_constructors(struct exec_list *instructions,
+ struct _mesa_glsl_parse_state *state);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* GLSL_TYPES_H */
diff --git a/src/glsl/hash_table.c b/src/glsl/hash_table.c
new file mode 100644
index 00000000000..e89a2564d76
--- /dev/null
+++ b/src/glsl/hash_table.c
@@ -0,0 +1,159 @@
+/*
+ * Copyright © 2008 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 hash_table.c
+ * \brief Implementation of a generic, opaque hash table data type.
+ *
+ * \author Ian Romanick <[email protected]>
+ */
+
+#include "main/imports.h"
+#include "main/simple_list.h"
+#include "hash_table.h"
+
+struct node {
+ struct node *next;
+ struct node *prev;
+};
+
+struct hash_table {
+ hash_func_t hash;
+ hash_compare_func_t compare;
+
+ unsigned num_buckets;
+ struct node buckets[1];
+};
+
+
+struct hash_node {
+ struct node link;
+ const void *key;
+ void *data;
+};
+
+
+struct hash_table *
+hash_table_ctor(unsigned num_buckets, hash_func_t hash,
+ hash_compare_func_t compare)
+{
+ struct hash_table *ht;
+ unsigned i;
+
+
+ if (num_buckets < 16) {
+ num_buckets = 16;
+ }
+
+ ht = _mesa_malloc(sizeof(*ht) + ((num_buckets - 1)
+ * sizeof(ht->buckets[0])));
+ if (ht != NULL) {
+ ht->hash = hash;
+ ht->compare = compare;
+ ht->num_buckets = num_buckets;
+
+ for (i = 0; i < num_buckets; i++) {
+ make_empty_list(& ht->buckets[i]);
+ }
+ }
+
+ return ht;
+}
+
+
+void
+hash_table_dtor(struct hash_table *ht)
+{
+ hash_table_clear(ht);
+ _mesa_free(ht);
+}
+
+
+void
+hash_table_clear(struct hash_table *ht)
+{
+ struct node *node;
+ struct node *temp;
+ unsigned i;
+
+
+ for (i = 0; i < ht->num_buckets; i++) {
+ foreach_s(node, temp, & ht->buckets[i]) {
+ remove_from_list(node);
+ _mesa_free(node);
+ }
+
+ assert(is_empty_list(& ht->buckets[i]));
+ }
+}
+
+
+void *
+hash_table_find(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) {
+ return hn->data;
+ }
+ }
+
+ return NULL;
+}
+
+
+void
+hash_table_insert(struct hash_table *ht, void *data, const void *key)
+{
+ const unsigned hash_value = (*ht->hash)(key);
+ const unsigned bucket = hash_value % ht->num_buckets;
+ struct hash_node *node;
+
+ node = _mesa_calloc(sizeof(*node));
+
+ node->data = data;
+ node->key = key;
+
+ insert_at_head(& ht->buckets[bucket], & node->link);
+}
+
+
+unsigned
+hash_table_string_hash(const void *key)
+{
+ const char *str = (const char *) key;
+ unsigned hash = 5381;
+
+
+ while (*str != '\0') {
+ hash = (hash * 33) + *str;
+ str++;
+ }
+
+ return hash;
+}
diff --git a/src/glsl/hash_table.h b/src/glsl/hash_table.h
new file mode 100644
index 00000000000..b9dd343dee9
--- /dev/null
+++ b/src/glsl/hash_table.h
@@ -0,0 +1,125 @@
+/*
+ * Copyright © 2008 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 hash_table.h
+ * \brief Implementation of a generic, opaque hash table data type.
+ *
+ * \author Ian Romanick <[email protected]>
+ */
+
+#ifndef HASH_TABLE_H
+#define HASH_TABLE_H
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#include <string.h>
+
+struct hash_table;
+
+typedef unsigned (*hash_func_t)(const void *key);
+typedef int (*hash_compare_func_t)(const void *key1, const void *key2);
+
+/**
+ * Hash table constructor
+ *
+ * Creates a hash table with the specified number of buckets. The supplied
+ * \c hash and \c compare routines are used when adding elements to the table
+ * and when searching for elements in the table.
+ *
+ * \param num_buckets Number of buckets (bins) in the hash table.
+ * \param hash Function used to compute hash value of input keys.
+ * \param compare Function used to compare keys.
+ */
+extern struct hash_table *hash_table_ctor(unsigned num_buckets,
+ hash_func_t hash, hash_compare_func_t compare);
+
+
+/**
+ * Release all memory associated with a hash table
+ *
+ * \warning
+ * This function cannot release memory occupied either by keys or data.
+ */
+extern void hash_table_dtor(struct hash_table *ht);
+
+
+/**
+ * Flush all entries from a hash table
+ *
+ * \param ht Table to be cleared of its entries.
+ */
+extern void hash_table_clear(struct hash_table *ht);
+
+
+/**
+ * Search a hash table for a specific element
+ *
+ * \param ht Table to be searched
+ * \param key Key of the desired element
+ *
+ * \return
+ * The \c data value supplied to \c hash_table_insert when the element with
+ * the matching key was added. If no matching key exists in the table,
+ * \c NULL is returned.
+ */
+extern void *hash_table_find(struct hash_table *ht, const void *key);
+
+
+/**
+ * Add an element to a hash table
+ */
+extern void hash_table_insert(struct hash_table *ht, void *data,
+ const void *key);
+
+
+/**
+ * Compute hash value of a string
+ *
+ * Computes the hash value of a string using the DJB2 algorithm developed by
+ * Professor Daniel J. Bernstein. It was published on comp.lang.c once upon
+ * a time. I was unable to find the original posting in the archives.
+ *
+ * \param key Pointer to a NUL terminated string to be hashed.
+ *
+ * \sa hash_table_string_compare
+ */
+extern unsigned hash_table_string_hash(const void *key);
+
+
+/**
+ * Compare two strings used as keys
+ *
+ * This is just a macro wrapper around \c strcmp.
+ *
+ * \sa hash_table_string_hash
+ */
+#define hash_table_string_compare ((hash_compare_func_t) strcmp)
+
+#ifdef __cplusplus
+};
+#endif
+
+#endif /* HASH_TABLE_H */
diff --git a/src/glsl/hir_field_selection.cpp b/src/glsl/hir_field_selection.cpp
new file mode 100644
index 00000000000..e2efff60d34
--- /dev/null
+++ b/src/glsl/hir_field_selection.cpp
@@ -0,0 +1,81 @@
+/*
+ * 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 "symbol_table.h"
+#include "glsl_parser_extras.h"
+#include "ast.h"
+#include "glsl_types.h"
+
+struct ir_rvalue *
+_mesa_ast_field_selection_to_hir(const ast_expression *expr,
+ exec_list *instructions,
+ struct _mesa_glsl_parse_state *state)
+{
+ void *ctx = talloc_parent(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 {
+ _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..2756752ba49
--- /dev/null
+++ b/src/glsl/ir.cpp
@@ -0,0 +1,818 @@
+/*
+ * 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 "ir.h"
+#include "ir_visitor.h"
+#include "glsl_types.h"
+
+ir_assignment::ir_assignment(ir_rvalue *lhs, ir_rvalue *rhs,
+ ir_rvalue *condition)
+{
+ this->lhs = lhs;
+ this->rhs = rhs;
+ this->condition = condition;
+}
+
+
+ir_expression::ir_expression(int op, const struct glsl_type *type,
+ ir_rvalue *op0, ir_rvalue *op1)
+{
+ 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_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_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",
+ "sin",
+ "cos",
+ "dFdx",
+ "dFdy",
+ "+",
+ "-",
+ "*",
+ "/",
+ "%",
+ "<",
+ ">",
+ "<=",
+ ">=",
+ "==",
+ "!=",
+ "<<",
+ ">>",
+ "&",
+ "^",
+ "|",
+ "&&",
+ "^^",
+ "||",
+ "dot",
+ "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()
+{
+ /* empty */
+}
+
+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->type = type;
+ memcpy(& this->value, data, sizeof(this->value));
+}
+
+ir_constant::ir_constant(float f)
+{
+ this->type = glsl_type::float_type;
+ this->value.f[0] = f;
+}
+
+ir_constant::ir_constant(unsigned int u)
+{
+ this->type = glsl_type::uint_type;
+ this->value.u[0] = u;
+}
+
+ir_constant::ir_constant(int i)
+{
+ this->type = glsl_type::int_type;
+ this->value.i[0] = i;
+}
+
+ir_constant::ir_constant(bool b)
+{
+ this->type = glsl_type::bool_type;
+ this->value.b[0] = b;
+}
+
+ir_constant::ir_constant(const ir_constant *c, unsigned i)
+{
+ 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->type = type;
+
+ /* FINISHME: Support array types. */
+ assert(type->is_scalar() || type->is_vector() || type->is_matrix()
+ || type->is_record());
+
+ /* 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_sentinal());
+
+ 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;
+ }
+}
+
+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_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_sentinal())
+ return NULL;
+ }
+
+ return (ir_constant *) node;
+}
+
+
+bool
+ir_constant::has_value(const ir_constant *c) const
+{
+ if (this->type != c->type)
+ return false;
+
+ /* FINISHME: This will probably also handle constant arrays as soon as those
+ * FINISHME: are supported.
+ */
+ 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_sentinal()) {
+ assert(!b_node->is_tail_sentinal());
+
+ 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->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->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->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->record = value;
+ this->field = 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->record = new(ctx) ir_dereference_variable(var);
+ this->field = 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;
+ }
+}
+
+
+ir_swizzle::ir_swizzle(ir_rvalue *val, unsigned x, unsigned y, unsigned z,
+ unsigned w, unsigned count)
+ : val(val)
+{
+ assert((count >= 1) && (count <= 4));
+
+ const unsigned dup_mask = 0
+ | ((count > 1) ? ((1U << y) & ((1U << x) )) : 0)
+ | ((count > 2) ? ((1U << z) & ((1U << x) | (1U << y) )) : 0)
+ | ((count > 3) ? ((1U << w) & ((1U << x) | (1U << y) | (1U << z))) : 0);
+
+ assert(x <= 3);
+ assert(y <= 3);
+ assert(z <= 3);
+ assert(w <= 3);
+
+ mask.x = x;
+ mask.y = y;
+ mask.z = z;
+ mask.w = w;
+ mask.num_components = count;
+ 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, ir_swizzle_mask mask)
+{
+ 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)
+ : max_array_access(0), read_only(false), centroid(false), invariant(false),
+ shader_in(false), shader_out(false),
+ mode(ir_var_auto), interpolation(ir_var_smooth), array_lvalue(false)
+{
+ this->type = type;
+ this->name = name;
+ this->location = -1;
+ this->warn_extension = NULL;
+ this->constant_value = NULL;
+
+ if (type && type->base_type == GLSL_TYPE_SAMPLER)
+ this->read_only = true;
+}
+
+
+const char *
+ir_variable::interpolation_string() const
+{
+ if (!this->shader_in && !this->shader_out)
+ return "";
+
+ 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)
+{
+ /* empty */
+}
+
+
+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)
+ : name(name)
+{
+ /* empty */
+}
+
+
+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
+visit_exec_list(exec_list *list, ir_visitor *visitor)
+{
+ foreach_iter(exec_list_iterator, iter, *list) {
+ ((ir_instruction *)iter.get())->accept(visitor);
+ }
+}
+
diff --git a/src/glsl/ir.h b/src/glsl/ir.h
new file mode 100644
index 00000000000..3d2c7ff5cf5
--- /dev/null
+++ b/src/glsl/ir.h
@@ -0,0 +1,1178 @@
+/* -*- 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
+
+struct ir_program {
+ void *bong_hits;
+};
+
+/**
+ * Base class of all IR instructions
+ */
+class ir_instruction : public exec_node {
+public:
+ const struct glsl_type *type;
+
+ class ir_constant *constant_expression_value();
+
+ /** 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(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_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()
+ {
+ /* empty */
+ }
+};
+
+
+class ir_rvalue : public ir_instruction {
+public:
+ 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()
+ {
+ /* empty */
+ }
+};
+
+
+enum ir_variable_mode {
+ ir_var_auto = 0,
+ ir_var_uniform,
+ ir_var_in,
+ ir_var_out,
+ ir_var_inout
+};
+
+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 *);
+
+ virtual ir_instruction *clone(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
+ * If none of \c shader_in or \c shader_out is set, an empty string will
+ * be returned. Otherwise the string that would be used in a shader to
+ * specify \c mode will be returned.
+ */
+ 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;
+ /** If the variable is initialized outside of the scope of the shader */
+ unsigned shader_in:1;
+ /**
+ * If the variable value is later used outside of the scope of the shader.
+ */
+ unsigned shader_out: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;
+
+ /**
+ * 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_instruction *clone(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;
+
+ /**
+ * 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;
+
+ /** 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_instruction *clone(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;
+ 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.
+ */
+ const ir_function_signature *matching_signature(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(exec_list *actual_ps);
+
+ /**
+ * Name of the function.
+ */
+ const char *name;
+
+private:
+ /**
+ * 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 function->name;
+}
+/*@}*/
+
+
+/**
+ * IR instruction representing high-level if-statements
+ */
+class ir_if : public ir_instruction {
+public:
+ ir_if(ir_rvalue *condition)
+ : condition(condition)
+ {
+ /* empty */
+ }
+
+ virtual ir_instruction *clone(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)
+ {
+ /* empty */
+ }
+
+ virtual ir_instruction *clone(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_rvalue {
+public:
+ ir_assignment(ir_rvalue *lhs, ir_rvalue *rhs, ir_rvalue *condition);
+
+ virtual ir_instruction *clone(struct hash_table *ht) const;
+
+ virtual void accept(ir_visitor *v)
+ {
+ v->visit(this);
+ }
+
+ virtual ir_visitor_status accept(ir_hierarchical_visitor *);
+
+ virtual ir_assignment * as_assignment()
+ {
+ return this;
+ }
+
+ /**
+ * Left-hand side of the assignment.
+ */
+ ir_rvalue *lhs;
+
+ /**
+ * Value being assigned
+ */
+ ir_rvalue *rhs;
+
+ /**
+ * Optional condition for the assignment.
+ */
+ ir_rvalue *condition;
+};
+
+/* 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,
+ ir_unop_log,
+ 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,
+ /*@}*/
+
+ /**
+ * \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,
+ ir_binop_mod,
+
+ /**
+ * \name Binary comparison operators
+ */
+ /*@{*/
+ ir_binop_less,
+ ir_binop_greater,
+ ir_binop_lequal,
+ ir_binop_gequal,
+ ir_binop_equal,
+ 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_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_instruction *clone(struct hash_table *ht) const;
+
+ 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(const ir_function_signature *callee, exec_list *actual_parameters)
+ : callee(callee)
+ {
+ assert(callee->return_type != NULL);
+ type = callee->return_type;
+ actual_parameters->move_nodes_to(& this->actual_parameters);
+ }
+
+ virtual ir_instruction *clone(struct hash_table *ht) const;
+
+ 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();
+ }
+
+ const ir_function_signature *get_callee()
+ {
+ return callee;
+ }
+
+ /**
+ * Generates an inline version of the function before @ir,
+ * returning the return value of the function.
+ */
+ ir_rvalue *generate_inline(ir_instruction *ir);
+
+private:
+ ir_call()
+ : callee(NULL)
+ {
+ /* empty */
+ }
+
+ const ir_function_signature *callee;
+
+ /* List of ir_rvalue of paramaters passed in this call. */
+ exec_list actual_parameters;
+};
+
+
+/**
+ * \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()
+ {
+ /* empty */
+ }
+};
+
+class ir_return : public ir_jump {
+public:
+ ir_return()
+ : value(NULL)
+ {
+ /* empty */
+ }
+
+ ir_return(ir_rvalue *value)
+ : value(value)
+ {
+ /* empty */
+ }
+
+ virtual ir_instruction *clone(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->mode = mode;
+ this->loop = loop;
+ }
+
+ virtual ir_instruction *clone(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;
+};
+/*@}*/
+
+
+/**
+ * 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)
+ {
+ /* empty */
+ }
+
+ virtual ir_instruction *clone(struct hash_table *) const;
+
+ 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, ir_swizzle_mask mask);
+
+ virtual ir_instruction *clone(struct hash_table *) const;
+
+ 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;
+};
+
+
+class ir_dereference : public ir_rvalue {
+public:
+ 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_instruction *clone(struct hash_table *) const;
+
+ /**
+ * 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_instruction *clone(struct hash_table *) const;
+
+ 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_instruction *clone(struct hash_table *) const;
+
+ /**
+ * 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);
+
+ virtual ir_instruction *clone(struct hash_table *) const;
+
+ 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_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;
+
+ 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);
+
+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);
+
+#endif /* IR_H */
diff --git a/src/glsl/ir_basic_block.cpp b/src/glsl/ir_basic_block.cpp
new file mode 100644
index 00000000000..f9953ea42da
--- /dev/null
+++ b/src/glsl/ir_basic_block.cpp
@@ -0,0 +1,144 @@
+/*
+ * 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;
+};
+
+/**
+ * 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()) {
+ ir_has_call_visitor v;
+
+ /* 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.
+ */
+ ir->accept(&v);
+ if (v.has_call) {
+ 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..84176383fca
--- /dev/null
+++ b/src/glsl/ir_clone.cpp
@@ -0,0 +1,287 @@
+/*
+ * 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"
+#include "hash_table.h"
+
+/**
+ * Duplicate an IR variable
+ *
+ * \note
+ * This will probably be made \c virtual and moved to the base class
+ * eventually.
+ */
+ir_instruction *
+ir_variable::clone(struct hash_table *ht) const
+{
+ void *ctx = talloc_parent(this);
+ ir_variable *var = new(ctx) ir_variable(type, name);
+
+ var->max_array_access = this->max_array_access;
+ var->read_only = this->read_only;
+ var->centroid = this->centroid;
+ var->invariant = this->invariant;
+ var->mode = this->mode;
+ var->interpolation = this->interpolation;
+
+ if (ht) {
+ hash_table_insert(ht, var, (void *)const_cast<ir_variable *>(this));
+ }
+
+ return var;
+}
+
+ir_instruction *
+ir_swizzle::clone(struct hash_table *ht) const
+{
+ void *ctx = talloc_parent(this);
+ return new(ctx) ir_swizzle((ir_rvalue *)this->val->clone(ht), this->mask);
+}
+
+ir_instruction *
+ir_return::clone(struct hash_table *ht) const
+{
+ void *ctx = talloc_parent(this);
+ ir_rvalue *new_value = NULL;
+
+ if (this->value)
+ new_value = (ir_rvalue *)this->value->clone(ht);
+
+ return new(ctx) ir_return(new_value);
+}
+
+ir_instruction *
+ir_loop_jump::clone(struct hash_table *ht) const
+{
+ void *ctx = talloc_parent(this);
+ (void)ht;
+
+ return new(ctx) ir_loop_jump(this->mode);
+}
+
+ir_instruction *
+ir_if::clone(struct hash_table *ht) const
+{
+ void *ctx = talloc_parent(this);
+ ir_if *new_if = new(ctx) ir_if((ir_rvalue *)this->condition->clone(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(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(ht));
+ }
+
+ return new_if;
+}
+
+ir_instruction *
+ir_loop::clone(struct hash_table *ht) const
+{
+ void *ctx = talloc_parent(this);
+ ir_loop *new_loop = new(ctx) ir_loop();
+
+ if (this->from)
+ new_loop->from = (ir_rvalue *)this->from->clone(ht);
+ if (this->to)
+ new_loop->to = (ir_rvalue *)this->to->clone(ht);
+ if (this->increment)
+ new_loop->increment = (ir_rvalue *)this->increment->clone(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(ht));
+ }
+
+ return new_loop;
+}
+
+ir_instruction *
+ir_call::clone(struct hash_table *ht) const
+{
+ void *ctx = talloc_parent(this);
+ 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(ht));
+ }
+
+ return new(ctx) ir_call(this->callee, &new_parameters);
+}
+
+ir_instruction *
+ir_expression::clone(struct hash_table *ht) const
+{
+ void *ctx = talloc_parent(this);
+ ir_rvalue *op[2] = {NULL, NULL};
+ unsigned int i;
+
+ for (i = 0; i < get_num_operands(); i++) {
+ op[i] = (ir_rvalue *)this->operands[i]->clone(ht);
+ }
+
+ return new(ctx) ir_expression(this->operation, this->type, op[0], op[1]);
+}
+
+ir_instruction *
+ir_dereference_variable::clone(struct hash_table *ht) const
+{
+ void *ctx = talloc_parent(this);
+ 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(ctx) ir_dereference_variable(new_var);
+}
+
+ir_instruction *
+ir_dereference_array::clone(struct hash_table *ht) const
+{
+ void *ctx = talloc_parent(this);
+ return new(ctx) ir_dereference_array((ir_rvalue *)this->array->clone(ht),
+ (ir_rvalue *)this->array_index->clone(ht));
+}
+
+ir_instruction *
+ir_dereference_record::clone(struct hash_table *ht) const
+{
+ void *ctx = talloc_parent(this);
+ return new(ctx) ir_dereference_record((ir_rvalue *)this->record->clone(ht),
+ this->field);
+}
+
+ir_instruction *
+ir_texture::clone(struct hash_table *ht) const
+{
+ void *ctx = talloc_parent(this);
+ ir_texture *new_tex = new(ctx) ir_texture(this->op);
+
+ new_tex->sampler = (ir_dereference *)this->sampler->clone(ht);
+ new_tex->coordinate = (ir_rvalue *)this->coordinate->clone(ht);
+ if (this->projector)
+ new_tex->projector = (ir_rvalue *)this->projector->clone(ht);
+ if (this->shadow_comparitor) {
+ new_tex->shadow_comparitor =
+ (ir_rvalue *)this->shadow_comparitor->clone(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 = (ir_rvalue *)this->lod_info.bias->clone(ht);
+ break;
+ case ir_txl:
+ case ir_txf:
+ new_tex->lod_info.lod = (ir_rvalue *)this->lod_info.lod->clone(ht);
+ break;
+ case ir_txd:
+ new_tex->lod_info.grad.dPdx =
+ (ir_rvalue *)this->lod_info.grad.dPdx->clone(ht);
+ new_tex->lod_info.grad.dPdy =
+ (ir_rvalue *)this->lod_info.grad.dPdy->clone(ht);
+ break;
+ }
+
+ return new_tex;
+}
+
+ir_instruction *
+ir_assignment::clone(struct hash_table *ht) const
+{
+ ir_rvalue *new_condition = NULL;
+
+ if (this->condition)
+ new_condition = (ir_rvalue *)this->condition->clone(ht);
+
+ void *ctx = talloc_parent(this);
+ return new(ctx) ir_assignment((ir_rvalue *)this->lhs->clone(ht),
+ (ir_rvalue *)this->rhs->clone(ht),
+ new_condition);
+}
+
+ir_instruction *
+ir_function::clone(struct hash_table *ht) const
+{
+ (void)ht;
+ /* FINISHME */
+ abort();
+}
+
+ir_instruction *
+ir_function_signature::clone(struct hash_table *ht) const
+{
+ (void)ht;
+ /* FINISHME */
+ abort();
+}
+
+ir_instruction *
+ir_constant::clone(struct hash_table *ht) const
+{
+ void *ctx = talloc_parent(this);
+ (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(ctx) ir_constant(this->type, &this->value);
+
+ case GLSL_TYPE_STRUCT: {
+ ir_constant *c = new(ctx) ir_constant;
+
+ c->type = this->type;
+ for (exec_node *node = this->components.head
+ ; !node->is_tail_sentinal()
+ ; node = node->next) {
+ ir_constant *const orig = (ir_constant *) node;
+
+ c->components.push_tail(orig->clone(NULL));
+ }
+
+ return c;
+ }
+
+ default:
+ assert(!"Should not get here."); break;
+ return NULL;
+ }
+}
diff --git a/src/glsl/ir_constant_expression.cpp b/src/glsl/ir_constant_expression.cpp
new file mode 100644
index 00000000000..3408f5256a7
--- /dev/null
+++ b/src/glsl/ir_constant_expression.cpp
@@ -0,0 +1,671 @@
+/*
+ * 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 "ir.h"
+#include "ir_visitor.h"
+#include "glsl_types.h"
+
+/**
+ * Visitor class for evaluating constant expressions
+ */
+class ir_constant_visitor : public ir_visitor {
+public:
+ ir_constant_visitor()
+ : value(NULL)
+ {
+ /* empty */
+ }
+
+ virtual ~ir_constant_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_if *);
+ virtual void visit(ir_loop *);
+ virtual void visit(ir_loop_jump *);
+ /*@}*/
+
+ /**
+ * Value of the constant expression.
+ *
+ * \note
+ * This field will be \c NULL if the expression is not constant valued.
+ */
+ /* FINIHSME: This cannot hold values for constant arrays or structures. */
+ ir_constant *value;
+};
+
+
+ir_constant *
+ir_instruction::constant_expression_value()
+{
+ ir_constant_visitor visitor;
+
+ this->accept(& visitor);
+ return visitor.value;
+}
+
+
+void
+ir_constant_visitor::visit(ir_variable *ir)
+{
+ (void) ir;
+ value = NULL;
+}
+
+
+void
+ir_constant_visitor::visit(ir_function_signature *ir)
+{
+ (void) ir;
+ value = NULL;
+}
+
+
+void
+ir_constant_visitor::visit(ir_function *ir)
+{
+ (void) ir;
+ value = NULL;
+}
+
+void
+ir_constant_visitor::visit(ir_expression *ir)
+{
+ value = NULL;
+ ir_constant *op[2];
+ unsigned int operand, c;
+ ir_constant_data data;
+
+ for (operand = 0; operand < ir->get_num_operands(); operand++) {
+ op[operand] = ir->operands[operand]->constant_expression_value();
+ if (!op[operand])
+ return;
+ }
+
+ switch (ir->operation) {
+ case ir_unop_logic_not:
+ assert(op[0]->type->base_type == GLSL_TYPE_BOOL);
+ for (c = 0; c < ir->operands[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 (c = 0; c < ir->operands[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_UINT ||
+ op[0]->type->base_type == GLSL_TYPE_INT);
+ for (c = 0; c < ir->operands[0]->type->components(); c++) {
+ if (op[0]->type->base_type == GLSL_TYPE_INT)
+ data.f[c] = op[0]->value.i[c];
+ else
+ data.f[c] = op[0]->value.u[c];
+ }
+ break;
+ case ir_unop_b2f:
+ assert(op[0]->type->base_type == GLSL_TYPE_BOOL);
+ for (c = 0; c < ir->operands[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 (c = 0; c < ir->operands[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 (c = 0; c < ir->operands[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 (c = 0; c < ir->operands[0]->type->components(); c++) {
+ data.b[c] = bool(op[0]->value.u[c]);
+ }
+ break;
+
+ case ir_unop_neg:
+ for (c = 0; c < ir->operands[0]->type->components(); c++) {
+ switch (ir->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:
+ assert(op[0]->type->base_type == GLSL_TYPE_FLOAT);
+ for (c = 0; c < ir->operands[0]->type->components(); c++) {
+ switch (ir->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_rcp:
+ assert(op[0]->type->base_type == GLSL_TYPE_FLOAT);
+ for (c = 0; c < ir->operands[0]->type->components(); c++) {
+ switch (ir->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 (c = 0; c < ir->operands[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 (c = 0; c < ir->operands[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 (c = 0; c < ir->operands[0]->type->components(); c++) {
+ data.f[c] = expf(op[0]->value.f[c]);
+ }
+ break;
+
+ case ir_unop_log:
+ assert(op[0]->type->base_type == GLSL_TYPE_FLOAT);
+ for (c = 0; c < ir->operands[0]->type->components(); c++) {
+ data.f[c] = logf(op[0]->value.f[c]);
+ }
+ break;
+
+ case ir_unop_dFdx:
+ case ir_unop_dFdy:
+ assert(op[0]->type->base_type == GLSL_TYPE_FLOAT);
+ for (c = 0; c < ir->operands[0]->type->components(); c++) {
+ data.f[c] = 0.0;
+ }
+ break;
+
+ case ir_binop_add:
+ if (ir->operands[0]->type == ir->operands[1]->type) {
+ for (c = 0; c < ir->operands[0]->type->components(); c++) {
+ switch (ir->operands[0]->type->base_type) {
+ case GLSL_TYPE_UINT:
+ data.u[c] = op[0]->value.u[c] + op[1]->value.u[c];
+ break;
+ case GLSL_TYPE_INT:
+ data.i[c] = op[0]->value.i[c] + op[1]->value.i[c];
+ break;
+ case GLSL_TYPE_FLOAT:
+ data.f[c] = op[0]->value.f[c] + op[1]->value.f[c];
+ break;
+ default:
+ assert(0);
+ }
+ }
+ } else
+ /* FINISHME: Support operations with non-equal types. */
+ return;
+
+ break;
+ case ir_binop_sub:
+ if (ir->operands[0]->type == ir->operands[1]->type) {
+ for (c = 0; c < ir->operands[0]->type->components(); c++) {
+ switch (ir->operands[0]->type->base_type) {
+ case GLSL_TYPE_UINT:
+ data.u[c] = op[0]->value.u[c] - op[1]->value.u[c];
+ break;
+ case GLSL_TYPE_INT:
+ data.i[c] = op[0]->value.i[c] - op[1]->value.i[c];
+ break;
+ case GLSL_TYPE_FLOAT:
+ data.f[c] = op[0]->value.f[c] - op[1]->value.f[c];
+ break;
+ default:
+ assert(0);
+ }
+ }
+ } else
+ /* FINISHME: Support operations with non-equal types. */
+ return;
+
+ break;
+ case ir_binop_mul:
+ if (ir->operands[0]->type == ir->operands[1]->type &&
+ !ir->operands[0]->type->is_matrix()) {
+ for (c = 0; c < ir->operands[0]->type->components(); c++) {
+ switch (ir->operands[0]->type->base_type) {
+ case GLSL_TYPE_UINT:
+ data.u[c] = op[0]->value.u[c] * op[1]->value.u[c];
+ break;
+ case GLSL_TYPE_INT:
+ data.i[c] = op[0]->value.i[c] * op[1]->value.i[c];
+ break;
+ case GLSL_TYPE_FLOAT:
+ data.f[c] = op[0]->value.f[c] * op[1]->value.f[c];
+ break;
+ default:
+ assert(0);
+ }
+ }
+ } else
+ /* FINISHME: Support operations with non-equal types. */
+ return;
+
+ break;
+ case ir_binop_div:
+ if (ir->operands[0]->type == ir->operands[1]->type) {
+ for (c = 0; c < ir->operands[0]->type->components(); c++) {
+ switch (ir->operands[0]->type->base_type) {
+ case GLSL_TYPE_UINT:
+ data.u[c] = op[0]->value.u[c] / op[1]->value.u[c];
+ break;
+ case GLSL_TYPE_INT:
+ data.i[c] = op[0]->value.i[c] / op[1]->value.i[c];
+ break;
+ case GLSL_TYPE_FLOAT:
+ data.f[c] = op[0]->value.f[c] / op[1]->value.f[c];
+ break;
+ default:
+ assert(0);
+ }
+ }
+ } else
+ /* FINISHME: Support operations with non-equal types. */
+ return;
+
+ break;
+ case ir_binop_logic_and:
+ assert(op[0]->type->base_type == GLSL_TYPE_BOOL);
+ for (c = 0; c < ir->operands[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 (c = 0; c < ir->operands[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 (c = 0; c < ir->operands[0]->type->components(); c++)
+ data.b[c] = op[0]->value.b[c] || op[1]->value.b[c];
+ break;
+
+ case ir_binop_less:
+ switch (ir->operands[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 (ir->operands[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 (ir->operands[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 (ir->operands[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] = true;
+ for (c = 0; c < ir->operands[0]->type->components(); c++) {
+ switch (ir->operands[0]->type->base_type) {
+ case GLSL_TYPE_UINT:
+ data.b[0] = data.b[0] && op[0]->value.u[c] == op[1]->value.u[c];
+ break;
+ case GLSL_TYPE_INT:
+ data.b[0] = data.b[0] && op[0]->value.i[c] == op[1]->value.i[c];
+ break;
+ case GLSL_TYPE_FLOAT:
+ data.b[0] = data.b[0] && op[0]->value.f[c] == op[1]->value.f[c];
+ break;
+ case GLSL_TYPE_BOOL:
+ data.b[0] = data.b[0] && op[0]->value.b[c] == op[1]->value.b[c];
+ break;
+ default:
+ assert(0);
+ }
+ }
+ break;
+ case ir_binop_nequal:
+ data.b[0] = false;
+ for (c = 0; c < ir->operands[0]->type->components(); c++) {
+ switch (ir->operands[0]->type->base_type) {
+ case GLSL_TYPE_UINT:
+ data.b[0] = data.b[0] || op[0]->value.u[c] != op[1]->value.u[c];
+ break;
+ case GLSL_TYPE_INT:
+ data.b[0] = data.b[0] || op[0]->value.i[c] != op[1]->value.i[c];
+ break;
+ case GLSL_TYPE_FLOAT:
+ data.b[0] = data.b[0] || op[0]->value.f[c] != op[1]->value.f[c];
+ break;
+ case GLSL_TYPE_BOOL:
+ data.b[0] = data.b[0] || op[0]->value.b[c] != op[1]->value.b[c];
+ break;
+ default:
+ assert(0);
+ }
+ }
+ break;
+
+ default:
+ /* FINISHME: Should handle all expression types. */
+ return;
+ }
+
+ void *ctx = talloc_parent(ir);
+ this->value = new(ctx) ir_constant(ir->type, &data);
+}
+
+
+void
+ir_constant_visitor::visit(ir_texture *ir)
+{
+ // FINISHME: Do stuff with texture lookups
+ (void) ir;
+ value = NULL;
+}
+
+
+void
+ir_constant_visitor::visit(ir_swizzle *ir)
+{
+ ir_constant *v = ir->val->constant_expression_value();
+
+ this->value = NULL;
+
+ if (v != NULL) {
+ ir_constant_data data;
+
+ const unsigned swiz_idx[4] = {
+ ir->mask.x, ir->mask.y, ir->mask.z, ir->mask.w
+ };
+
+ for (unsigned i = 0; i < ir->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(ir);
+ this->value = new(ctx) ir_constant(ir->type, &data);
+ }
+}
+
+
+void
+ir_constant_visitor::visit(ir_dereference_variable *ir)
+{
+ value = NULL;
+
+ ir_variable *var = ir->variable_referenced();
+ if (var && var->constant_value)
+ value = (ir_constant *)var->constant_value->clone(NULL);
+}
+
+
+void
+ir_constant_visitor::visit(ir_dereference_array *ir)
+{
+ void *ctx = talloc_parent(ir);
+ ir_constant *array = ir->array->constant_expression_value();
+ ir_constant *idx = ir->array_index->constant_expression_value();
+
+ this->value = NULL;
+
+ if ((array != NULL) && (idx != NULL)) {
+ 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;
+ }
+
+ this->value = new(ctx) ir_constant(column_type, &data);
+ } else if (array->type->is_vector()) {
+ const unsigned component = idx->value.u[0];
+
+ this->value = new(ctx) ir_constant(array, component);
+ } else {
+ /* FINISHME: Handle access of constant arrays. */
+ }
+ }
+}
+
+
+void
+ir_constant_visitor::visit(ir_dereference_record *ir)
+{
+ ir_constant *v = ir->record->constant_expression_value();
+
+ this->value = (v != NULL) ? v->get_record_field(ir->field) : NULL;
+}
+
+
+void
+ir_constant_visitor::visit(ir_assignment *ir)
+{
+ (void) ir;
+ value = NULL;
+}
+
+
+void
+ir_constant_visitor::visit(ir_constant *ir)
+{
+ value = ir;
+}
+
+
+void
+ir_constant_visitor::visit(ir_call *ir)
+{
+ (void) ir;
+ value = NULL;
+}
+
+
+void
+ir_constant_visitor::visit(ir_return *ir)
+{
+ (void) ir;
+ value = NULL;
+}
+
+
+void
+ir_constant_visitor::visit(ir_if *ir)
+{
+ (void) ir;
+ value = NULL;
+}
+
+
+void
+ir_constant_visitor::visit(ir_loop *ir)
+{
+ (void) ir;
+ value = NULL;
+}
+
+
+void
+ir_constant_visitor::visit(ir_loop_jump *ir)
+{
+ (void) ir;
+ value = NULL;
+}
diff --git a/src/glsl/ir_constant_folding.cpp b/src/glsl/ir_constant_folding.cpp
new file mode 100644
index 00000000000..342d027bbe8
--- /dev/null
+++ b/src/glsl/ir_constant_folding.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_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()
+ {
+ /* empty */
+ }
+
+ 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_if *);
+ virtual void visit(ir_loop *);
+ virtual void visit(ir_loop_jump *);
+ /*@}*/
+};
+
+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)
+{
+ ir_constant *op[2];
+ unsigned int operand;
+
+ for (operand = 0; operand < ir->get_num_operands(); operand++) {
+ op[operand] = ir->operands[operand]->constant_expression_value();
+ if (op[operand]) {
+ ir->operands[operand] = op[operand];
+ } else {
+ ir->operands[operand]->accept(this);
+ }
+ }
+}
+
+
+void
+ir_constant_folding_visitor::visit(ir_texture *ir)
+{
+ // FINISHME: Do stuff with texture lookups
+ (void) ir;
+}
+
+
+void
+ir_constant_folding_visitor::visit(ir_swizzle *ir)
+{
+ ir->val->accept(this);
+}
+
+
+void
+ir_constant_folding_visitor::visit(ir_dereference_variable *ir)
+{
+ (void) ir;
+}
+
+
+void
+ir_constant_folding_visitor::visit(ir_dereference_array *ir)
+{
+ ir_constant *const_val =
+ ir->array_index->constant_expression_value();
+
+ if (const_val)
+ ir->array_index = const_val;
+ else
+ ir->array_index->accept(this);
+
+ 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)
+{
+ ir_constant *const_val = ir->rhs->constant_expression_value();
+ if (const_val)
+ ir->rhs = const_val;
+ else
+ ir->rhs->accept(this);
+}
+
+
+void
+ir_constant_folding_visitor::visit(ir_constant *ir)
+{
+ (void) ir;
+}
+
+
+void
+ir_constant_folding_visitor::visit(ir_call *ir)
+{
+ (void) ir;
+}
+
+
+void
+ir_constant_folding_visitor::visit(ir_return *ir)
+{
+ (void) ir;
+}
+
+
+void
+ir_constant_folding_visitor::visit(ir_if *ir)
+{
+ ir_constant *const_val = ir->condition->constant_expression_value();
+ if (const_val)
+ ir->condition = const_val;
+ else
+ ir->condition->accept(this);
+
+ 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);
+
+ /* FINISHME: Return real progress. */
+ return false;
+}
diff --git a/src/glsl/ir_constant_variable.cpp b/src/glsl/ir_constant_variable.cpp
new file mode 100644
index 00000000000..ef5e1e418e5
--- /dev/null
+++ b/src/glsl/ir_constant_variable.cpp
@@ -0,0 +1,156 @@
+/*
+ * 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;
+};
+
+class ir_constant_variable_visitor : public ir_hierarchical_visitor {
+public:
+ virtual ir_visitor_status visit_enter(ir_assignment *);
+
+ 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_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->lhs->whole_variable_referenced();
+ 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;
+}
+
+/**
+ * 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->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..46ef6679d9f
--- /dev/null
+++ b/src/glsl/ir_copy_propagation.cpp
@@ -0,0 +1,256 @@
+/*
+ * 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 within basic blocks.
+ *
+ * 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 ir_copy_propagation_visitor : public ir_hierarchical_visitor {
+public:
+ ir_copy_propagation_visitor(exec_list *acp)
+ {
+ progress = false;
+ in_lhs = false;
+ this->acp = acp;
+ }
+
+ 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 *);
+
+ /** List of acp_entry */
+ exec_list *acp;
+ bool progress;
+
+ /** Currently in the LHS of an assignment? */
+ bool in_lhs;
+};
+
+
+ir_visitor_status
+ir_copy_propagation_visitor::visit_enter(ir_loop *ir)
+{
+ (void)ir;
+ return visit_continue_with_parent;
+}
+
+ir_visitor_status
+ir_copy_propagation_visitor::visit_enter(ir_function_signature *ir)
+{
+ (void)ir;
+ return visit_continue_with_parent;
+}
+
+ir_visitor_status
+ir_copy_propagation_visitor::visit_enter(ir_assignment *ir)
+{
+ (void) ir;
+ this->in_lhs = true;
+ return visit_continue;
+}
+
+ir_visitor_status
+ir_copy_propagation_visitor::visit_enter(ir_function *ir)
+{
+ (void) ir;
+ return visit_continue_with_parent;
+}
+
+/**
+ * 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)
+{
+ /* Ignores the LHS. Don't want to rewrite the LHS to point at some
+ * other storage!
+ */
+ if (this->in_lhs) {
+ this->in_lhs = false;
+ return visit_continue;
+ }
+
+ ir_variable *var = ir->variable_referenced();
+
+ 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)
+{
+ (void)ir;
+
+ /* Note, if we were to do copy propagation to parameters of calls, we'd
+ * have to be careful about out params.
+ */
+ return visit_continue_with_parent;
+}
+
+
+ir_visitor_status
+ir_copy_propagation_visitor::visit_enter(ir_if *ir)
+{
+ ir->condition->accept(this);
+
+ /* Do not traverse into the body of the if-statement since that is a
+ * different basic block.
+ */
+ return visit_continue_with_parent;
+}
+
+static bool
+propagate_copies(ir_instruction *ir, exec_list *acp)
+{
+ ir_copy_propagation_visitor v(acp);
+
+ ir->accept(&v);
+
+ return v.progress;
+}
+
+static void
+kill_invalidated_copies(ir_assignment *ir, exec_list *acp)
+{
+ ir_variable *var = ir->lhs->variable_referenced();
+ assert(var != NULL);
+
+ foreach_iter(exec_list_iterator, iter, *acp) {
+ acp_entry *entry = (acp_entry *)iter.get();
+
+ if (entry->lhs == var || entry->rhs == var) {
+ entry->remove();
+ }
+ }
+}
+
+/**
+ * Adds an entry to the available copy list if it's a plain assignment
+ * of a variable to a variable.
+ */
+static void
+add_copy(ir_assignment *ir, exec_list *acp)
+{
+ void *ctx = talloc_parent(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->lhs->whole_variable_referenced();
+ ir_variable *rhs_var = ir->rhs->whole_variable_referenced();
+
+ if ((lhs_var != NULL) && (rhs_var != NULL)) {
+ entry = new(ctx) acp_entry(lhs_var, rhs_var);
+ acp->push_tail(entry);
+ }
+}
+
+static void
+copy_propagation_basic_block(ir_instruction *first,
+ ir_instruction *last,
+ void *data)
+{
+ ir_instruction *ir;
+ /* List of avaialble_copy */
+ exec_list acp;
+ bool *out_progress = (bool *)data;
+ bool progress = false;
+
+ for (ir = first;; ir = (ir_instruction *)ir->next) {
+ ir_assignment *ir_assign = ir->as_assignment();
+
+ progress = propagate_copies(ir, &acp) || progress;
+
+ if (ir_assign) {
+ kill_invalidated_copies(ir_assign, &acp);
+
+ add_copy(ir_assign, &acp);
+ }
+ if (ir == last)
+ break;
+ }
+ *out_progress = progress;
+}
+
+/**
+ * Does a copy propagation pass on the code present in the instruction stream.
+ */
+bool
+do_copy_propagation(exec_list *instructions)
+{
+ bool progress = false;
+
+ call_for_basic_blocks(instructions, copy_propagation_basic_block, &progress);
+
+ return progress;
+}
diff --git a/src/glsl/ir_dead_code.cpp b/src/glsl/ir_dead_code.cpp
new file mode 100644
index 00000000000..88213046825
--- /dev/null
+++ b/src/glsl/ir_dead_code.cpp
@@ -0,0 +1,219 @@
+/*
+ * 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_expression_flattening.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 assignmened. */
+ unsigned assigned_count;
+
+ bool declaration; /* If the variable had a decl in the instruction stream */
+};
+
+class ir_dead_code_visitor : public ir_hierarchical_visitor {
+public:
+ virtual ir_visitor_status visit(ir_variable *);
+ virtual ir_visitor_status visit(ir_dereference_variable *);
+
+ virtual ir_visitor_status visit_enter(ir_function *);
+ virtual ir_visitor_status visit_leave(ir_assignment *);
+
+ variable_entry *get_variable_entry(ir_variable *var);
+
+ bool (*predicate)(ir_instruction *ir);
+ ir_instruction *base_ir;
+
+ /* List of variable_entry */
+ exec_list variable_list;
+};
+
+
+variable_entry *
+ir_dead_code_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;
+ }
+
+ void *ctx = talloc_parent(var);
+
+ variable_entry *entry = new(ctx) variable_entry(var);
+ this->variable_list.push_tail(entry);
+ return entry;
+}
+
+
+ir_visitor_status
+ir_dead_code_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_dead_code_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_dead_code_visitor::visit_enter(ir_function *ir)
+{
+ (void) ir;
+ return visit_continue_with_parent;
+}
+
+
+ir_visitor_status
+ir_dead_code_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;
+}
+
+
+/**
+ * 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_dead_code_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 ((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->shader_out) {
+ entry->assign->remove();
+ progress = true;
+ }
+ } else {
+ /* If there are no assignments or references to the variable left,
+ * then we can remove its declaration.
+ */
+ entry->var->remove();
+ progress = true;
+ }
+ }
+ 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..e01877077c9
--- /dev/null
+++ b/src/glsl/ir_dead_code_local.cpp
@@ -0,0 +1,223 @@
+/*
+ * 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(ir_assignment *ir, exec_list *assignments)
+{
+ void *ctx = talloc_parent(ir);
+ 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->lhs->whole_variable_referenced() != 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. */
+ 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;
+
+ /* 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(ir_assign, &assignments) || progress;
+ } else {
+ kill_for_derefs_visitor kill(&assignments);
+ ir->accept(&kill);
+ }
+
+ if (ir == last)
+ break;
+ }
+ *out_progress = progress;
+}
+
+/**
+ * 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_expression_flattening.cpp b/src/glsl/ir_expression_flattening.cpp
new file mode 100644
index 00000000000..5ba24e390b4
--- /dev/null
+++ b/src/glsl/ir_expression_flattening.cpp
@@ -0,0 +1,172 @@
+/*
+ * 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_expression *);
+ virtual ir_visitor_status visit_leave(ir_swizzle *);
+
+ 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);
+ }
+}
+
+
+static ir_rvalue *
+operand_to_temp(ir_instruction *base_ir, ir_rvalue *ir)
+{
+ void *ctx = talloc_parent(base_ir);
+ ir_variable *var;
+ ir_assignment *assign;
+
+ var = new(ctx) ir_variable(ir->type, "flattening_tmp");
+ 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.
+ */
+ if (this->predicate(ir->operands[operand])) {
+ ir->operands[operand] = operand_to_temp(base_ir,
+ ir->operands[operand]);
+ }
+ }
+
+ 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(this->base_ir, ir->val);
+ }
+
+ return visit_continue;
+}
+
+ir_visitor_status
+ir_expression_flattening_visitor::visit_enter(ir_call *ir)
+{
+ /* FINISHME: Why not process the call parameters? (Same behavior as original
+ * FINISHME: code.)
+ */
+ (void) ir;
+ return visit_continue_with_parent;
+}
+
+
+ir_visitor_status
+ir_expression_flattening_visitor::visit_enter(ir_return *ir)
+{
+ /* FINISHME: Why not process the return value? (Same behavior as original
+ * FINISHME: code.)
+ */
+ (void) ir;
+ return visit_continue_with_parent;
+}
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..5db93f67fb8
--- /dev/null
+++ b/src/glsl/ir_function.cpp
@@ -0,0 +1,225 @@
+/*
+ * 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(exec_list *list_a, exec_list *list_b)
+{
+ exec_list_iterator iter_a = list_a->iterator();
+ exec_list_iterator iter_b = list_b->iterator();
+ int total_score = 0;
+
+ for (/* empty */ ; iter_a.has_next(); iter_a.next(), iter_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 (!iter_b.has_next())
+ return -1;
+
+
+ const ir_variable *const param = (ir_variable *) iter_a.get();
+ const ir_instruction *const actual = (ir_instruction *) iter_b.get();
+
+ /* 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:
+ /* 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 (iter_b.has_next())
+ return -1;
+
+ return total_score;
+}
+
+
+const ir_function_signature *
+ir_function::matching_signature(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(exec_list *list_a, exec_list *list_b)
+{
+ exec_list_iterator iter_a = list_a->iterator();
+ exec_list_iterator iter_b = list_b->iterator();
+
+ while (iter_a.has_next() && iter_b.has_next()) {
+ ir_variable *a = (ir_variable *)iter_a.get();
+ ir_variable *b = (ir_variable *)iter_b.get();
+
+ /* If the types of the parameters do not match, the parameters lists
+ * are different.
+ */
+ if (a->type != b->type)
+ return false;
+
+ iter_a.next();
+ iter_b.next();
+ }
+
+ /* Unless both lists are exhausted, they differ in length and, by
+ * definition, do not match.
+ */
+ if (iter_a.has_next() != iter_b.has_next())
+ return false;
+
+ return true;
+}
+
+ir_function_signature *
+ir_function::exact_matching_signature(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..e55780c940e
--- /dev/null
+++ b/src/glsl/ir_function_inlining.cpp
@@ -0,0 +1,272 @@
+/*
+ * 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 <inttypes.h>
+#include "ir.h"
+#include "ir_visitor.h"
+#include "ir_function_inlining.h"
+#include "ir_expression_flattening.h"
+#include "glsl_types.h"
+#include "hash_table.h"
+
+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;
+};
+
+
+unsigned int hash_func(const void *key)
+{
+ return (unsigned int)(uintptr_t)key;
+}
+
+int hash_compare_func(const void *key1, const void *key2)
+{
+ return key1 == key2 ? 0 : 1;
+}
+
+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->insert_before(new(ctx) ir_assignment(lhs, ret->value, NULL));
+ ret->remove();
+ } 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_sentinal());
+ }
+ }
+}
+
+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_func, hash_compare_func);
+
+ 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, "__retval");
+ 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++) {
+ const ir_variable *const sig_param = (ir_variable *) sig_param_iter.get();
+ ir_rvalue *param = (ir_rvalue *) param_iter.get();
+
+ /* Generate a new variable for the parameter. */
+ parameters[i] = (ir_variable *)sig_param->clone(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 (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();
+ }
+
+ /* Generate the inlined body of the function. */
+ foreach_iter(exec_list_iterator, iter, callee->body) {
+ ir_instruction *ir = (ir_instruction *)iter.get();
+ ir_instruction *new_ir = ir->clone(ht);
+
+ next_ir->insert_before(new_ir);
+ visit_tree(new_ir, replace_return_with_assignment, retval);
+ }
+
+ /* Copy back the value of any 'out' parameters from the function body
+ * variables to our own.
+ */
+ i = 0;
+ param_iter = this->actual_parameters.iterator();
+ for (i = 0; i < num_parameters; i++) {
+ ir_instruction *const param = (ir_instruction *) param_iter.get();
+
+ /* Move our param variable into the actual param if it's an 'out' type. */
+ if (parameters[i]->mode == ir_var_out ||
+ parameters[i]->mode == ir_var_inout) {
+ ir_assignment *assign;
+
+ assign = new(ctx) ir_assignment(param->as_rvalue(),
+ new(ctx) ir_dereference_variable(parameters[i]),
+ NULL);
+ next_ir->insert_before(assign);
+ }
+
+ 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)) {
+ (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;
+}
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..0d520b127f2
--- /dev/null
+++ b/src/glsl/ir_hierarchical_visitor.cpp
@@ -0,0 +1,284 @@
+/*
+ * 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_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)
+{
+ foreach_list(n, instructions) {
+ ir_instruction *ir = (ir_instruction *) n;
+
+ if (ir->accept(this) != visit_continue)
+ break;
+ }
+}
+
+
+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..8b9e49dab13
--- /dev/null
+++ b/src/glsl/ir_hierarchical_visitor.h
@@ -0,0 +1,162 @@
+/* -*- 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_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);
+
+ /**
+ * 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);
+
+#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..f936b3500eb
--- /dev/null
+++ b/src/glsl/ir_hv_accept.cpp
@@ -0,0 +1,348 @@
+/*
+ * 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 list. However, if nodes are added to the list after the node being
+ * processed, some of the added noded may not be processed.
+ */
+static ir_visitor_status
+visit_list_elements(ir_hierarchical_visitor *v, exec_list *l)
+{
+ exec_node *next;
+
+ for (exec_node *n = l->head; n->next != NULL; n = next) {
+ next = n->next;
+
+ ir_instruction *const ir = (ir_instruction *) n;
+ ir_visitor_status s = ir->accept(v);
+
+ if (s != visit_continue)
+ return s;
+ }
+
+ 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->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 visit_continue_with_parent;
+}
+
+
+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_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_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_optimization.h b/src/glsl/ir_optimization.h
new file mode 100644
index 00000000000..432a33458c2
--- /dev/null
+++ b/src/glsl/ir_optimization.h
@@ -0,0 +1,41 @@
+/*
+ * 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.h
+ *
+ * Prototypes for optimization passes to be called by the compiler and drivers.
+ */
+
+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_dead_code(exec_list *instructions);
+bool do_dead_code_local(exec_list *instructions);
+bool do_dead_code_unlinked(exec_list *instructions);
+bool do_function_inlining(exec_list *instructions);
+bool do_if_simplification(exec_list *instructions);
+bool do_swizzle_swizzle(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..be5a843f67d
--- /dev/null
+++ b/src/glsl/ir_print_visitor.cpp
@@ -0,0 +1,373 @@
+/*
+ * 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)
+{
+ 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, 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 *)iter.get())->print();
+ printf("\n");
+ }
+ printf("\n)");
+}
+
+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, 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 " };
+ 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, ir);
+}
+
+
+void ir_print_visitor::visit(ir_function_signature *ir)
+{
+ printf("(signature ");
+ print_type(ir->return_type);
+ printf("\n (parameters\n");
+ foreach_iter(exec_list_iterator, iter, ir->parameters) {
+ ir_variable *const inst = (ir_variable *) iter.get();
+
+ inst->accept(this);
+ printf("\n");
+ }
+ printf(" )\n(");
+
+ foreach_iter(exec_list_iterator, iter, ir->body) {
+ ir_instruction *const inst = (ir_instruction *) iter.get();
+
+ inst->accept(this);
+ printf("\n");
+ }
+ printf("))\n");
+}
+
+
+void ir_print_visitor::visit(ir_function *ir)
+{
+ printf("(function %s\n", ir->name);
+ foreach_iter(exec_list_iterator, iter, *ir) {
+ ir_function_signature *const sig = (ir_function_signature *) iter.get();
+
+ sig->accept(this);
+ printf("\n");
+ }
+
+ printf(")\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, 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))");
+
+ printf(" ");
+
+ 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(" (");
+
+ 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_if *ir)
+{
+ printf("(if ");
+ ir->condition->accept(this);
+
+ printf("(\n");
+ foreach_iter(exec_list_iterator, iter, ir->then_instructions) {
+ ir_instruction *const inst = (ir_instruction *) iter.get();
+
+ inst->accept(this);
+ printf("\n");
+ }
+ printf(")\n");
+
+ printf("(\n");
+ foreach_iter(exec_list_iterator, iter, ir->else_instructions) {
+ ir_instruction *const inst = (ir_instruction *) iter.get();
+
+ inst->accept(this);
+ printf("\n");
+ }
+ 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");
+ foreach_iter(exec_list_iterator, iter, ir->body_instructions) {
+ ir_instruction *const inst = (ir_instruction *) iter.get();
+
+ inst->accept(this);
+ printf("\n");
+ }
+ 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..e97b823522a
--- /dev/null
+++ b/src/glsl/ir_print_visitor.h
@@ -0,0 +1,81 @@
+/* -*- 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()
+ : deref_depth(0)
+ {
+ /* empty */
+ }
+
+ virtual ~ir_print_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_if *);
+ virtual void visit(ir_loop *);
+ virtual void visit(ir_loop_jump *);
+ /*@}*/
+
+private:
+ int deref_depth;
+};
+
+#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..7383c42cbc7
--- /dev/null
+++ b/src/glsl/ir_reader.cpp
@@ -0,0 +1,1053 @@
+/*
+ * 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)
+{
+ void *ctx = talloc_parent(state);
+ s_expression *expr = s_expression::read_expression(ctx, src);
+ if (expr == NULL) {
+ ir_read_error(state, NULL, "couldn't parse S-Expression.");
+ return;
+ }
+
+ scan_for_prototypes(state, instructions, expr);
+ if (state->error)
+ return;
+
+ read_instructions(state, instructions, expr, NULL);
+}
+
+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(st, 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 = talloc_parent(st);
+ 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());
+ bool added = st->symbols->add_function(name->value(), 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 f;
+}
+
+static void
+read_function_sig(_mesa_glsl_parse_state *st, ir_function *f, s_list *list,
+ bool skip_body)
+{
+ void *ctx = talloc_parent(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) {
+ 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 {
+ sig = new(ctx) ir_function_signature(return_type);
+ f->add_signature(sig);
+ }
+
+ sig->replace_parameters(&hir_parameters);
+
+ if (!skip_body) {
+ 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) {
+ ir_read_error(st, sub, "Invalid instruction.\n");
+ return;
+ }
+ instructions->push_tail(ir);
+ }
+}
+
+
+static ir_instruction *
+read_instruction(_mesa_glsl_parse_state *st, s_expression *expr,
+ ir_loop *loop_ctx)
+{
+ void *ctx = talloc_parent(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())
+ 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(), "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 = talloc_parent(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());
+
+ 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->value(), var);
+
+ return var;
+}
+
+
+static ir_if *
+read_if(_mesa_glsl_parse_state *st, s_list *list, ir_loop *loop_ctx)
+{
+ void *ctx = talloc_parent(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 = talloc_parent(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 = talloc_parent(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(), "assign") == 0) {
+ rvalue = read_assignment(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 = talloc_parent(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 = talloc_parent(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;
+ }
+
+ const 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 = talloc_parent(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 = talloc_parent(st);
+ if (list->length() != 3) {
+ ir_read_error(st, list, "expected (constant <type> (<num> ... <num>))");
+ 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> (<num> ... <num>))");
+ return NULL;
+ }
+
+ 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 = talloc_parent(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 = talloc_parent(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 = talloc_parent(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 = talloc_parent(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..b6afdc81ab1
--- /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);
+
+#endif /* IR_READER_H */
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_to_mesa.cpp b/src/glsl/ir_to_mesa.cpp
new file mode 100644
index 00000000000..26449c5a5c4
--- /dev/null
+++ b/src/glsl/ir_to_mesa.cpp
@@ -0,0 +1,1211 @@
+/*
+ * 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 "ir.h"
+#include "ir_visitor.h"
+#include "ir_print_visitor.h"
+#include "ir_expression_flattening.h"
+#include "glsl_types.h"
+
+extern "C" {
+#include "shader/prog_instruction.h"
+#include "shader/prog_print.h"
+}
+
+/**
+ * This struct is a corresponding struct to Mesa prog_src_register, with
+ * wider fields.
+ */
+typedef struct ir_to_mesa_src_reg {
+ int file; /**< PROGRAM_* from Mesa */
+ int index; /**< temporary index, VERT_ATTRIB_*, FRAG_ATTRIB_*, etc. */
+ int swizzle; /**< SWIZZLE_XYZWONEZERO swizzles from Mesa. */
+ int negate; /**< NEGATE_XYZW mask from mesa */
+ bool reladdr; /**< Register index should be offset by address reg. */
+} 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] */
+} 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;
+};
+
+class temp_entry : public exec_node {
+public:
+ temp_entry(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 ir_to_mesa_visitor : public ir_visitor {
+public:
+ ir_to_mesa_visitor();
+
+ int next_temp;
+ int next_constant;
+ int next_uniform;
+
+ temp_entry *find_variable_storage(ir_variable *var);
+
+ ir_to_mesa_src_reg get_temp(const glsl_type *type);
+
+ 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_texture *);
+ virtual void visit(ir_if *);
+ /*@}*/
+
+ struct ir_to_mesa_src_reg result;
+
+ /** List of temp_entry */
+ exec_list variable_storage;
+
+ /** List of ir_to_mesa_instruction */
+ exec_list instructions;
+
+ 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);
+
+ /* talloc context (the ) */
+ void *ctx;
+};
+
+ir_to_mesa_src_reg ir_to_mesa_undef = {
+ PROGRAM_UNDEFINED, 0, SWIZZLE_NOOP, NEGATE_NONE, false,
+};
+
+ir_to_mesa_dst_reg ir_to_mesa_undef_dst = {
+ PROGRAM_UNDEFINED, 0, SWIZZLE_NOOP
+};
+
+ir_to_mesa_dst_reg ir_to_mesa_address_reg = {
+ PROGRAM_ADDRESS, 0, WRITEMASK_X
+};
+
+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];
+}
+
+/* This list should match up with builtin_variables.h */
+static const struct {
+ const char *name;
+ int file;
+ int index;
+} builtin_var_to_mesa_reg[] = {
+ /* core_vs */
+ {"gl_Position", PROGRAM_OUTPUT, VERT_RESULT_HPOS},
+ {"gl_PointSize", PROGRAM_OUTPUT, VERT_RESULT_PSIZ},
+
+ /* core_fs */
+ {"gl_FragCoord", PROGRAM_INPUT, FRAG_ATTRIB_WPOS},
+ {"gl_FrontFacing", PROGRAM_INPUT, FRAG_ATTRIB_FACE},
+ {"gl_FragColor", PROGRAM_OUTPUT, FRAG_ATTRIB_COL0},
+ {"gl_FragDepth", PROGRAM_UNDEFINED, FRAG_ATTRIB_WPOS}, /* FINISHME: WPOS.z */
+
+ /* 110_deprecated_fs */
+ {"gl_Color", PROGRAM_INPUT, FRAG_ATTRIB_COL0},
+ {"gl_SecondaryColor", PROGRAM_INPUT, FRAG_ATTRIB_COL1},
+ {"gl_FogFragCoord", PROGRAM_INPUT, FRAG_ATTRIB_FOGC},
+ {"gl_TexCoord", PROGRAM_INPUT, FRAG_ATTRIB_TEX0}, /* array */
+
+ /* 110_deprecated_vs */
+ {"gl_Vertex", PROGRAM_INPUT, VERT_ATTRIB_POS},
+ {"gl_Normal", PROGRAM_INPUT, VERT_ATTRIB_NORMAL},
+ {"gl_Color", PROGRAM_INPUT, VERT_ATTRIB_COLOR0},
+ {"gl_SecondaryColor", PROGRAM_INPUT, VERT_ATTRIB_COLOR1},
+ {"gl_MultiTexCoord0", PROGRAM_INPUT, VERT_ATTRIB_TEX0},
+ {"gl_MultiTexCoord1", PROGRAM_INPUT, VERT_ATTRIB_TEX1},
+ {"gl_MultiTexCoord2", PROGRAM_INPUT, VERT_ATTRIB_TEX2},
+ {"gl_MultiTexCoord3", PROGRAM_INPUT, VERT_ATTRIB_TEX3},
+ {"gl_MultiTexCoord4", PROGRAM_INPUT, VERT_ATTRIB_TEX4},
+ {"gl_MultiTexCoord5", PROGRAM_INPUT, VERT_ATTRIB_TEX5},
+ {"gl_MultiTexCoord6", PROGRAM_INPUT, VERT_ATTRIB_TEX6},
+ {"gl_MultiTexCoord7", PROGRAM_INPUT, VERT_ATTRIB_TEX7},
+ {"gl_TexCoord", PROGRAM_OUTPUT, VERT_RESULT_TEX0}, /* array */
+ {"gl_FogCoord", PROGRAM_INPUT, VERT_RESULT_FOGC},
+ /*{"gl_ClipVertex", PROGRAM_OUTPUT, VERT_ATTRIB_FOGC},*/ /* FINISHME */
+ {"gl_FrontColor", PROGRAM_OUTPUT, VERT_RESULT_COL0},
+ {"gl_BackColor", PROGRAM_OUTPUT, VERT_RESULT_BFC0},
+ {"gl_FrontSecondaryColor", PROGRAM_OUTPUT, VERT_RESULT_COL1},
+ {"gl_BackSecondaryColor", PROGRAM_OUTPUT, VERT_RESULT_BFC1},
+ {"gl_FogFragCoord", PROGRAM_OUTPUT, VERT_RESULT_FOGC},
+
+ /* 130_vs */
+ /*{"gl_VertexID", PROGRAM_INPUT, VERT_ATTRIB_FOGC},*/ /* FINISHME */
+
+ {"gl_FragData", PROGRAM_OUTPUT, FRAG_RESULT_DATA0}, /* array */
+};
+
+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(ctx) ir_to_mesa_instruction();
+
+ 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;
+
+ 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)
+{
+ return ir_to_mesa_emit_op3(ir, op, dst,
+ src0, ir_to_mesa_undef, ir_to_mesa_undef);
+}
+
+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;
+
+ return dst_reg;
+}
+
+/**
+ * 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_op1(ir_instruction *ir,
+ enum prog_opcode op,
+ ir_to_mesa_dst_reg dst,
+ ir_to_mesa_src_reg src0)
+{
+ 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++) {
+ int this_mask = (1 << i);
+ ir_to_mesa_instruction *inst;
+ ir_to_mesa_src_reg src = src0;
+
+ if (done_mask & this_mask)
+ continue;
+
+ int src_swiz = GET_SWZ(src.swizzle, i);
+ for (j = i + 1; j < 4; j++) {
+ if (!(done_mask & (1 << j)) && GET_SWZ(src.swizzle, j) == src_swiz) {
+ this_mask |= (1 << j);
+ }
+ }
+ src.swizzle = MAKE_SWIZZLE4(src_swiz, src_swiz,
+ src_swiz, src_swiz);
+
+ inst = ir_to_mesa_emit_op1(ir, op,
+ dst,
+ src);
+ inst->dst_reg.writemask = this_mask;
+ done_mask |= this_mask;
+ }
+}
+
+struct ir_to_mesa_src_reg
+ir_to_mesa_visitor::src_reg_for_float(float val)
+{
+ ir_to_mesa_src_reg src_reg;
+
+ /* FINISHME: This will end up being _mesa_add_unnamed_constant,
+ * which handles sharing values and sharing channels of vec4
+ * constants for small values.
+ */
+ /* FINISHME: Do something with the constant values for now.
+ */
+ (void)val;
+ src_reg.file = PROGRAM_CONSTANT;
+ src_reg.index = this->next_constant++;
+ src_reg.swizzle = SWIZZLE_NOOP;
+
+ return src_reg;
+}
+
+/**
+ * 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;
+
+ assert(!type->is_array());
+
+ src_reg.file = PROGRAM_TEMPORARY;
+ src_reg.index = type->matrix_columns;
+ src_reg.reladdr = false;
+
+ 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]);
+
+ 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 4; /* FINISHME: Not all matrices are 4x4. */
+ } 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;
+ default:
+ assert(0);
+ }
+}
+
+temp_entry *
+ir_to_mesa_visitor::find_variable_storage(ir_variable *var)
+{
+
+ temp_entry *entry;
+
+ foreach_iter(exec_list_iterator, iter, this->variable_storage) {
+ entry = (temp_entry *)iter.get();
+
+ if (entry->var == var)
+ return entry;
+ }
+
+ return NULL;
+}
+
+void
+ir_to_mesa_visitor::visit(ir_variable *ir)
+{
+ (void)ir;
+}
+
+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_op1(NULL, OPCODE_BGNLOOP,
+ ir_to_mesa_undef_dst, ir_to_mesa_undef);
+
+ visit_exec_list(&ir->body_instructions, this);
+
+ ir_to_mesa_emit_op1(NULL, OPCODE_ENDLOOP,
+ ir_to_mesa_undef_dst, ir_to_mesa_undef);
+}
+
+void
+ir_to_mesa_visitor::visit(ir_loop_jump *ir)
+{
+ switch (ir->mode) {
+ case ir_loop_jump::jump_break:
+ ir_to_mesa_emit_op1(NULL, OPCODE_BRK,
+ ir_to_mesa_undef_dst, ir_to_mesa_undef);
+ break;
+ case ir_loop_jump::jump_continue:
+ ir_to_mesa_emit_op1(NULL, OPCODE_CONT,
+ ir_to_mesa_undef_dst, ir_to_mesa_undef);
+ 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);
+ }
+ }
+}
+
+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);
+
+ 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;
+
+ /* Only expression implemented for matrices yet */
+ assert(!ir->operands[operand]->type->is_matrix() ||
+ ir->operation == ir_binop_mul);
+ }
+
+ 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_exp:
+ ir_to_mesa_emit_scalar_op1(ir, OPCODE_EXP, 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_log:
+ ir_to_mesa_emit_scalar_op1(ir, OPCODE_LOG, result_dst, op[0]);
+ 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_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:
+ if (ir->operands[0]->type->is_matrix() &&
+ !ir->operands[1]->type->is_matrix()) {
+ if (ir->operands[0]->type->is_scalar()) {
+ ir_to_mesa_dst_reg dst_column = result_dst;
+ ir_to_mesa_src_reg src_column = op[0];
+ for (int i = 0; i < ir->operands[0]->type->matrix_columns; i++) {
+ ir_to_mesa_emit_op2(ir, OPCODE_MUL,
+ dst_column, src_column, op[1]);
+ dst_column.index++;
+ src_column.index++;
+ }
+ } else {
+ ir_to_mesa_dst_reg dst_chan = result_dst;
+ ir_to_mesa_src_reg src_column = op[0];
+ ir_to_mesa_src_reg src_chan = op[1];
+ for (int i = 0; i < ir->operands[0]->type->matrix_columns; i++) {
+ dst_chan.writemask = (1 << i);
+ src_chan.swizzle = MAKE_SWIZZLE4(i, i, i, i);
+ ir_to_mesa_emit_op2(ir, OPCODE_MUL,
+ dst_chan, src_column, src_chan);
+ src_column.index++;
+ }
+ }
+ } else {
+ assert(!ir->operands[0]->type->is_matrix());
+ assert(!ir->operands[1]->type->is_matrix());
+ ir_to_mesa_emit_op2(ir, OPCODE_MUL, result_dst, op[0], op[1]);
+ }
+ break;
+ case ir_binop_div:
+ ir_to_mesa_emit_scalar_op1(ir, OPCODE_RCP, result_dst, op[1]);
+ ir_to_mesa_emit_op2(ir, OPCODE_MUL, result_dst, op[0], result_src);
+ 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_unop_sqrt:
+ ir_to_mesa_emit_scalar_op1(ir, OPCODE_RSQ, result_dst, op[0]);
+ ir_to_mesa_emit_op1(ir, OPCODE_RCP, result_dst, 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:
+ /* 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:
+ 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_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;
+ default:
+ ir_print_visitor v;
+ printf("Failed to get tree for expression:\n");
+ ir->accept(&v);
+ exit(1);
+ 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] = ir->mask.x;
+ break;
+ case 1:
+ swizzle[i] = ir->mask.y;
+ break;
+ case 2:
+ swizzle[i] = ir->mask.z;
+ break;
+ case 3:
+ swizzle[i] = ir->mask.w;
+ break;
+ }
+ } else {
+ /* If the type is smaller than a vec4, replicate the last
+ * channel out.
+ */
+ swizzle[i] = ir->type->vector_elements - 1;
+ }
+ }
+
+ src_reg.swizzle = MAKE_SWIZZLE4(swizzle[0],
+ swizzle[1],
+ swizzle[2],
+ swizzle[3]);
+
+ this->result = src_reg;
+}
+
+void
+ir_to_mesa_visitor::visit(ir_dereference_variable *ir)
+{
+ ir_to_mesa_src_reg src_reg;
+ temp_entry *entry = find_variable_storage(ir->var);
+ unsigned int i;
+ bool var_in;
+
+ if (!entry) {
+ switch (ir->var->mode) {
+ case ir_var_uniform:
+ entry = new(ctx) temp_entry(ir->var, PROGRAM_UNIFORM,
+ this->next_uniform);
+ this->variable_storage.push_tail(entry);
+
+ this->next_uniform += type_size(ir->var->type);
+ break;
+ case ir_var_in:
+ case ir_var_out:
+ case ir_var_inout:
+ var_in = (ir->var->mode == ir_var_in ||
+ ir->var->mode == ir_var_inout);
+
+ for (i = 0; i < ARRAY_SIZE(builtin_var_to_mesa_reg); i++) {
+ bool in = builtin_var_to_mesa_reg[i].file == PROGRAM_INPUT;
+
+ if (strcmp(ir->var->name, builtin_var_to_mesa_reg[i].name) == 0 &&
+ !(var_in ^ in))
+ break;
+ }
+ if (i == ARRAY_SIZE(builtin_var_to_mesa_reg)) {
+ printf("Failed to find builtin for %s variable %s\n",
+ var_in ? "in" : "out",
+ ir->var->name);
+ abort();
+ }
+ entry = new(ctx) temp_entry(ir->var,
+ builtin_var_to_mesa_reg[i].file,
+ builtin_var_to_mesa_reg[i].index);
+ break;
+ case ir_var_auto:
+ entry = new(ctx) temp_entry(ir->var, PROGRAM_TEMPORARY,
+ this->next_temp);
+ this->variable_storage.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);
+ }
+ }
+
+ src_reg.file = entry->file;
+ src_reg.index = entry->index;
+ /* If the type is smaller than a vec4, replicate the last channel out. */
+ src_reg.swizzle = swizzle_for_size(ir->var->type->vector_elements);
+ src_reg.reladdr = false;
+ src_reg.negate = 0;
+
+ this->result = src_reg;
+}
+
+void
+ir_to_mesa_visitor::visit(ir_dereference_array *ir)
+{
+ ir_constant *index;
+ ir_to_mesa_src_reg src_reg;
+
+ index = ir->array_index->constant_expression_value();
+
+ /* By the time we make it to this stage, matrices should be broken down
+ * to vectors.
+ */
+ assert(!ir->type->is_matrix());
+
+ ir->array->accept(this);
+ src_reg = this->result;
+
+ if (src_reg.file == PROGRAM_INPUT ||
+ src_reg.file == PROGRAM_OUTPUT) {
+ assert(index); /* FINISHME: Handle variable indexing of builtins. */
+
+ src_reg.index += index->value.i[0];
+ } else {
+ if (index) {
+ src_reg.index += index->value.i[0];
+ } 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);
+
+ /* FINISHME: This doesn't work when we're trying to do the LHS
+ * of an assignment.
+ */
+ src_reg.reladdr = true;
+ ir_to_mesa_emit_op1(ir, OPCODE_ARL, ir_to_mesa_address_reg,
+ this->result);
+
+ this->result = get_temp(ir->type);
+ ir_to_mesa_emit_op1(ir, OPCODE_MOV,
+ ir_to_mesa_dst_reg_from_src(this->result),
+ src_reg);
+ }
+ }
+
+ /* If the type is smaller than a vec4, replicate the last channel out. */
+ src_reg.swizzle = swizzle_for_size(ir->type->vector_elements);
+
+ 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->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.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.
+ *
+ * Thanks to ir_swizzle_swizzle, and ir_vec_index_to_swizzle, we
+ * should only see potentially one variable array index of a vector,
+ * and one swizzle, before getting to actual vec4 storage. So handle
+ * those, then go use ir_dereference to handle the rest.
+ */
+static struct ir_to_mesa_dst_reg
+get_assignment_lhs(ir_instruction *ir, ir_to_mesa_visitor *v)
+{
+ struct ir_to_mesa_dst_reg dst_reg;
+ ir_dereference *deref;
+ ir_swizzle *swiz;
+
+ /* Use the rvalue deref handler for the most part. We'll ignore
+ * swizzles in it and write swizzles using writemask, though.
+ */
+ ir->accept(v);
+ dst_reg = ir_to_mesa_dst_reg_from_src(v->result);
+
+ if ((deref = ir->as_dereference())) {
+ ir_dereference_array *deref_array = ir->as_dereference_array();
+ assert(!deref_array || deref_array->array->type->is_array());
+
+ ir->accept(v);
+ } else if ((swiz = ir->as_swizzle())) {
+ dst_reg.writemask = 0;
+ if (swiz->mask.num_components >= 1)
+ dst_reg.writemask |= (1 << swiz->mask.x);
+ if (swiz->mask.num_components >= 2)
+ dst_reg.writemask |= (1 << swiz->mask.y);
+ if (swiz->mask.num_components >= 3)
+ dst_reg.writemask |= (1 << swiz->mask.z);
+ if (swiz->mask.num_components >= 4)
+ dst_reg.writemask |= (1 << swiz->mask.w);
+ }
+
+ return dst_reg;
+}
+
+void
+ir_to_mesa_visitor::visit(ir_assignment *ir)
+{
+ struct ir_to_mesa_dst_reg l;
+ struct ir_to_mesa_src_reg r;
+
+ assert(!ir->lhs->type->is_matrix());
+ assert(!ir->lhs->type->is_array());
+ assert(ir->lhs->type->base_type != GLSL_TYPE_STRUCT);
+
+ l = get_assignment_lhs(ir->lhs, this);
+
+ ir->rhs->accept(this);
+ r = this->result;
+ assert(l.file != PROGRAM_UNDEFINED);
+ assert(r.file != PROGRAM_UNDEFINED);
+
+ if (ir->condition) {
+ ir_constant *condition_constant;
+
+ condition_constant = ir->condition->constant_expression_value();
+
+ assert(condition_constant && condition_constant->value.b[0]);
+ }
+
+ ir_to_mesa_emit_op1(ir, OPCODE_MOV, l, r);
+}
+
+
+void
+ir_to_mesa_visitor::visit(ir_constant *ir)
+{
+ ir_to_mesa_src_reg src_reg;
+
+ assert(ir->type->base_type == GLSL_TYPE_FLOAT ||
+ ir->type->base_type == GLSL_TYPE_UINT ||
+ ir->type->base_type == GLSL_TYPE_INT ||
+ ir->type->base_type == GLSL_TYPE_BOOL);
+
+ /* FINISHME: This will end up being _mesa_add_unnamed_constant,
+ * which handles sharing values and sharing channels of vec4
+ * constants for small values.
+ */
+ /* FINISHME: Do something with the constant values for now.
+ */
+ src_reg.file = PROGRAM_CONSTANT;
+ src_reg.index = this->next_constant;
+ src_reg.swizzle = SWIZZLE_NOOP;
+ src_reg.reladdr = false;
+ src_reg.negate = 0;
+
+ this->next_constant += type_size(ir->type);
+
+ this->result = src_reg;
+}
+
+
+void
+ir_to_mesa_visitor::visit(ir_call *ir)
+{
+ printf("Can't support call to %s\n", ir->callee_name());
+ exit(1);
+}
+
+
+void
+ir_to_mesa_visitor::visit(ir_texture *ir)
+{
+ assert(0);
+
+ ir->coordinate->accept(this);
+}
+
+void
+ir_to_mesa_visitor::visit(ir_return *ir)
+{
+ assert(0);
+
+ ir->get_value()->accept(this);
+}
+
+
+void
+ir_to_mesa_visitor::visit(ir_if *ir)
+{
+ ir_to_mesa_instruction *if_inst, *else_inst = NULL;
+
+ ir->condition->accept(this);
+ assert(this->result.file != PROGRAM_UNDEFINED);
+
+ 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_op1(ir->condition, OPCODE_ELSE,
+ ir_to_mesa_undef_dst,
+ ir_to_mesa_undef);
+ visit_exec_list(&ir->then_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_constant = 0;
+ next_uniform = 0;
+}
+
+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;
+
+ return mesa_reg;
+}
+
+static void
+set_branchtargets(struct prog_instruction *mesa_instructions,
+ int num_instructions)
+{
+ int if_count = 0, loop_count;
+ 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;
+ 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;
+
+ for (i = 0; i < num_instructions; i++) {
+ struct prog_instruction *mesa_inst = mesa_instructions + i;
+ ir_instruction *ir = mesa_instruction_annotation[i];
+
+ if (last_ir != ir && ir) {
+ ir_print_visitor print;
+ ir->accept(&print);
+ printf("\n");
+ last_ir = ir;
+ }
+
+ _mesa_print_instruction(mesa_inst);
+ }
+}
+
+void
+do_ir_to_mesa(exec_list *instructions)
+{
+ ir_to_mesa_visitor v;
+ struct prog_instruction *mesa_instructions, *mesa_inst;
+ ir_instruction **mesa_instruction_annotation;
+ int i;
+
+ v.ctx = talloc_new(NULL);
+ visit_exec_list(instructions, &v);
+
+ 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 =
+ (ir_instruction **)calloc(num_instructions,
+ sizeof(*mesa_instruction_annotation));
+
+ 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->DstReg.File = inst->dst_reg.file;
+ mesa_inst->DstReg.Index = inst->dst_reg.index;
+ mesa_inst->DstReg.CondMask = COND_TR;
+ mesa_inst->DstReg.WriteMask = inst->dst_reg.writemask;
+ 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_instruction_annotation[i] = inst->ir;
+
+ mesa_inst++;
+ i++;
+ }
+
+ set_branchtargets(mesa_instructions, num_instructions);
+ print_program(mesa_instructions, mesa_instruction_annotation, num_instructions);
+
+ free(mesa_instruction_annotation);
+ talloc_free(v.ctx);
+}
diff --git a/src/glsl/ir_validate.cpp b/src/glsl/ir_validate.cpp
new file mode 100644
index 00000000000..507e88993f2
--- /dev/null
+++ b/src/glsl/ir_validate.cpp
@@ -0,0 +1,104 @@
+/*
+ * 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 <inttypes.h>
+#include "ir.h"
+#include "ir_hierarchical_visitor.h"
+#include "hash_table.h"
+
+static unsigned int hash_func(const void *key)
+{
+ return (unsigned int)(uintptr_t)key;
+}
+
+static int hash_compare_func(const void *key1, const void *key2)
+{
+ return key1 == key2 ? 0 : 1;
+}
+
+
+class ir_validate : public ir_hierarchical_visitor {
+public:
+ ir_validate()
+ {
+ this->ht = hash_table_ctor(0, hash_func, hash_compare_func);
+
+ this->callback = ir_validate::validate_ir;
+ this->data = ht;
+ }
+
+ ~ir_validate()
+ {
+ hash_table_dtor(this->ht);
+ }
+
+ virtual ir_visitor_status visit(ir_variable *v);
+
+ static void validate_ir(ir_instruction *ir, void *data);
+
+ struct hash_table *ht;
+};
+
+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.
+ */
+ (void) ir;
+ 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
+validate_ir_tree(exec_list *instructions)
+{
+ ir_validate v;
+
+ v.run(instructions);
+}
diff --git a/src/glsl/ir_variable.cpp b/src/glsl/ir_variable.cpp
new file mode 100644
index 00000000000..15a4a92f628
--- /dev/null
+++ b/src/glsl/ir_variable.cpp
@@ -0,0 +1,345 @@
+/*
+ * 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 "glsl_parser_extras.h"
+#include "glsl_symbol_table.h"
+#include "builtin_variables.h"
+
+#ifndef Elements
+#define Elements(x) (sizeof(x)/sizeof(*(x)))
+#endif
+
+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);
+
+ var->mode = mode;
+ switch (var->mode) {
+ case ir_var_in:
+ var->shader_in = true;
+ var->read_only = true;
+ break;
+ case ir_var_inout:
+ var->shader_in = true;
+ var->shader_out = true;
+ break;
+ case ir_var_out:
+ var->shader_out = true;
+ break;
+ case ir_var_uniform:
+ var->shader_in = true;
+ var->read_only = true;
+ 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 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
+generate_110_uniforms(exec_list *instructions,
+ glsl_symbol_table *symtab)
+{
+ for (unsigned i = 0
+ ; i < Elements(builtin_110_deprecated_uniforms)
+ ; i++) {
+ add_builtin_variable(& builtin_110_deprecated_uniforms[i],
+ instructions, symtab);
+ }
+
+ /* FINISHME: The size of this array is implementation dependent based on the
+ * FINISHME: value of GL_MAX_TEXTURE_COORDS. Every platform that supports
+ * FINISHME: GLSL sets GL_MAX_TEXTURE_COORDS to at least 4, so hard-code 4
+ * FINISHME: for now.
+ */
+ const glsl_type *const mat4_array_type =
+ glsl_type::get_array_instance(symtab, glsl_type::mat4_type, 4);
+
+ add_variable("gl_TextureMatrix", ir_var_uniform, -1, mat4_array_type,
+ instructions, symtab);
+
+ /* FINISHME: Add support for gl_DepthRangeParameters */
+ /* FINISHME: Add support for gl_ClipPlane[] */
+ /* FINISHME: Add support for gl_PointParameters */
+
+ /* FINISHME: Add support for gl_MaterialParameters
+ * FINISHME: (glFrontMaterial, glBackMaterial)
+ */
+
+ /* FINISHME: The size of this array is implementation dependent based on the
+ * FINISHME: value of GL_MAX_TEXTURE_LIGHTS. GL_MAX_TEXTURE_LIGHTS must be
+ * FINISHME: at least 8, so hard-code 8 for now.
+ */
+ const glsl_type *const light_source_array_type =
+ glsl_type::get_array_instance(symtab,
+ symtab->get_type("gl_LightSourceParameters"), 8);
+
+ add_variable("gl_LightSource", ir_var_uniform, -1, light_source_array_type,
+ instructions, symtab);
+
+ /* FINISHME: Add support for gl_LightModel */
+ /* FINISHME: Add support for gl_FrontLightProduct[], gl_BackLightProduct[] */
+ /* FINISHME: Add support for gl_TextureEnvColor[] */
+ /* FINISHME: Add support for gl_ObjectPlane*[], gl_EyePlane*[] */
+ /* FINISHME: Add support for gl_Fog */
+}
+
+static void
+generate_110_vs_variables(exec_list *instructions,
+ glsl_symbol_table *symtab)
+{
+ for (unsigned i = 0; i < Elements(builtin_core_vs_variables); i++) {
+ add_builtin_variable(& builtin_core_vs_variables[i],
+ instructions, symtab);
+ }
+
+ for (unsigned i = 0
+ ; i < Elements(builtin_110_deprecated_vs_variables)
+ ; i++) {
+ add_builtin_variable(& builtin_110_deprecated_vs_variables[i],
+ instructions, symtab);
+ }
+ generate_110_uniforms(instructions, symtab);
+
+ /* FINISHME: The size of this array is implementation dependent based on the
+ * FINISHME: value of GL_MAX_TEXTURE_COORDS. Every platform that supports
+ * FINISHME: GLSL sets GL_MAX_TEXTURE_COORDS to at least 4, so hard-code 4
+ * FINISHME: for now.
+ */
+ const glsl_type *const vec4_array_type =
+ glsl_type::get_array_instance(symtab, glsl_type::vec4_type, 4);
+
+ add_variable("gl_TexCoord", ir_var_out, VERT_RESULT_TEX0, vec4_array_type,
+ instructions, symtab);
+}
+
+
+static void
+generate_120_vs_variables(exec_list *instructions,
+ glsl_symbol_table *symtab)
+{
+ /* GLSL version 1.20 did not add any built-in variables in the vertex
+ * shader.
+ */
+ generate_110_vs_variables(instructions, symtab);
+}
+
+
+static void
+generate_130_vs_variables(exec_list *instructions,
+ glsl_symbol_table *symtab)
+{
+ void *ctx = symtab;
+ generate_120_vs_variables(instructions, symtab);
+
+ for (unsigned i = 0; i < Elements(builtin_130_vs_variables); i++) {
+ add_builtin_variable(& builtin_130_vs_variables[i],
+ instructions, symtab);
+ }
+
+ /* FINISHME: The size of this array is implementation dependent based on
+ * FINISHME: the value of GL_MAX_CLIP_DISTANCES.
+ */
+ const glsl_type *const clip_distance_array_type =
+ glsl_type::get_array_instance(ctx, glsl_type::float_type, 8);
+
+ /* FINISHME: gl_ClipDistance needs a real location assigned. */
+ add_variable("gl_ClipDistance", ir_var_out, -1, clip_distance_array_type,
+ instructions, symtab);
+
+}
+
+
+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->symbols);
+ break;
+ case 120:
+ generate_120_vs_variables(instructions, state->symbols);
+ break;
+ case 130:
+ generate_130_vs_variables(instructions, state->symbols);
+ break;
+ }
+}
+
+static void
+generate_110_fs_variables(exec_list *instructions,
+ glsl_symbol_table *symtab)
+{
+ for (unsigned i = 0; i < Elements(builtin_core_fs_variables); i++) {
+ add_builtin_variable(& builtin_core_fs_variables[i],
+ instructions, symtab);
+ }
+
+ for (unsigned i = 0
+ ; i < Elements(builtin_110_deprecated_fs_variables)
+ ; i++) {
+ add_builtin_variable(& builtin_110_deprecated_fs_variables[i],
+ instructions, symtab);
+ }
+ generate_110_uniforms(instructions, symtab);
+
+ /* FINISHME: The size of this array is implementation dependent based on the
+ * FINISHME: value of GL_MAX_TEXTURE_COORDS. Every platform that supports
+ * FINISHME: GLSL sets GL_MAX_TEXTURE_COORDS to at least 4, so hard-code 4
+ * FINISHME: for now.
+ */
+ const glsl_type *const vec4_array_type =
+ glsl_type::get_array_instance(symtab, glsl_type::vec4_type, 4);
+
+ add_variable("gl_TexCoord", ir_var_in, FRAG_ATTRIB_TEX0, vec4_array_type,
+ instructions, symtab);
+}
+
+
+static void
+generate_ARB_draw_buffers_fs_variables(exec_list *instructions,
+ glsl_symbol_table *symtab, bool warn)
+{
+ /* FINISHME: The size of this array is implementation dependent based on the
+ * FINISHME: value of GL_MAX_DRAW_BUFFERS. GL_MAX_DRAW_BUFFERS must be
+ * FINISHME: at least 1, so hard-code 1 for now.
+ */
+ const glsl_type *const vec4_array_type =
+ glsl_type::get_array_instance(symtab, glsl_type::vec4_type, 1);
+
+ ir_variable *const fd =
+ add_variable("gl_FragData", ir_var_out, FRAG_RESULT_DATA0,
+ vec4_array_type, instructions, symtab);
+
+ if (warn)
+ fd->warn_extension = "GL_ARB_draw_buffers";
+}
+
+
+static void
+generate_120_fs_variables(exec_list *instructions,
+ glsl_symbol_table *symtab)
+{
+ generate_110_fs_variables(instructions, symtab);
+ generate_ARB_draw_buffers_fs_variables(instructions, symtab, false);
+}
+
+static void
+generate_130_fs_variables(exec_list *instructions,
+ glsl_symbol_table *symtab)
+{
+ void *ctx = symtab;
+ generate_120_fs_variables(instructions, symtab);
+
+ /* FINISHME: The size of this array is implementation dependent based on
+ * FINISHME: the value of GL_MAX_CLIP_DISTANCES.
+ */
+ const glsl_type *const clip_distance_array_type =
+ glsl_type::get_array_instance(ctx, glsl_type::float_type, 8);
+
+ /* FINISHME: gl_ClipDistance needs a real location assigned. */
+ add_variable("gl_ClipDistance", ir_var_in, -1, clip_distance_array_type,
+ instructions, symtab);
+}
+
+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->symbols);
+ break;
+ case 120:
+ generate_120_fs_variables(instructions, state->symbols);
+ break;
+ case 130:
+ generate_130_fs_variables(instructions, state->symbols);
+ break;
+ }
+
+
+ /* Since GL_ARB_draw_buffers is included in GLSL 1.20 and later, we
+ * can basically ignore any extension settings for it.
+ */
+ if (state->language_version < 120) {
+ if (state->ARB_draw_buffers_enable) {
+ generate_ARB_draw_buffers_fs_variables(instructions, state->symbols,
+ state->ARB_draw_buffers_warn);
+ }
+ }
+}
+
+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_vec_index_to_swizzle.cpp b/src/glsl/ir_vec_index_to_swizzle.cpp
new file mode 100644
index 00000000000..abeb43cd68e
--- /dev/null
+++ b/src/glsl/ir_vec_index_to_swizzle.cpp
@@ -0,0 +1,158 @@
+/*
+ * 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->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->insert_before(new_param);
+ param->remove();
+ }
+ }
+
+ 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 false;
+}
diff --git a/src/glsl/ir_visitor.h b/src/glsl/ir_visitor.h
new file mode 100644
index 00000000000..a6f9d2b7ee3
--- /dev/null
+++ b/src/glsl/ir_visitor.h
@@ -0,0 +1,66 @@
+/* -*- 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_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/linker.cpp b/src/glsl/linker.cpp
new file mode 100644
index 00000000000..ba382fe8816
--- /dev/null
+++ b/src/glsl/linker.cpp
@@ -0,0 +1,871 @@
+/*
+ * 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>
+
+extern "C" {
+#include <talloc.h>
+}
+
+#include "main/mtypes.h"
+#include "glsl_symbol_table.h"
+#include "glsl_parser_extras.h"
+#include "ir.h"
+#include "ir_optimization.h"
+#include "program.h"
+#include "hash_table.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? */
+};
+
+
+void
+linker_error_printf(glsl_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(glsl_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 glsl_program *prog,
+ struct glsl_shader *shader)
+{
+ if (shader == NULL)
+ return true;
+
+ if (!shader->symbols->get_function("main")) {
+ linker_error_printf(prog, "vertex shader lacks `main'\n");
+ return false;
+ }
+
+ 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 glsl_program *prog,
+ struct glsl_shader *shader)
+{
+ if (shader == NULL)
+ return true;
+
+ if (!shader->symbols->get_function("main")) {
+ linker_error_printf(prog, "fragment shader lacks `main'\n");
+ return false;
+ }
+
+ 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 does not write to "
+ "`gl_FragColor' or `gl_FragData'\n");
+ return false;
+ }
+
+ 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;
+}
+
+
+/**
+ * Perform validation of uniforms used across multiple shader stages
+ */
+bool
+cross_validate_uniforms(struct glsl_program *prog)
+{
+ /* Examine all of the uniforms in all of the shaders and cross validate
+ * them.
+ */
+ glsl_symbol_table uniforms;
+ for (unsigned i = 0; i < prog->_NumLinkedShaders; i++) {
+ 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;
+
+ /* If a uniform with this name has already been seen, verify that the
+ * new instance has the same type. In addition, if the uniforms have
+ * initializers, the values of the initializers must be the same.
+ */
+ ir_variable *const existing = uniforms.get_variable(var->name);
+ if (existing != NULL) {
+ if (var->type != existing->type) {
+ linker_error_printf(prog, "uniform `%s' declared as type "
+ "`%s' and type `%s'\n",
+ var->name, var->type->name,
+ existing->type->name);
+ return false;
+ }
+
+ 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 uniform "
+ "`%s' have differing values\n",
+ 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.
+ */
+ existing->constant_value =
+ (ir_constant *)var->constant_value->clone(NULL);
+ }
+ } else
+ uniforms.add_variable(var->name, var);
+ }
+ }
+
+ return true;
+}
+
+
+/**
+ * Validate that outputs from one stage match inputs of another
+ */
+bool
+cross_validate_outputs_to_inputs(struct glsl_program *prog,
+ glsl_shader *producer, glsl_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;
+}
+
+
+struct uniform_node {
+ exec_node link;
+ struct gl_uniform *u;
+ unsigned slots;
+};
+
+void
+assign_uniform_locations(struct glsl_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;
+ assert(vec4_slots != 0);
+
+ 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(glsl_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);
+
+ glsl_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);
+
+ 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(glsl_shader *producer, glsl_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.
+ */
+ var->shader_out = (var->location != -1);
+ }
+
+ foreach_list(node, &consumer->ir) {
+ ir_variable *const var = ((ir_instruction *) node)->as_variable();
+
+ if ((var == NULL) || (var->mode != ir_var_in))
+ continue;
+
+ /* An 'in' variable is only really a shader input if its value is written
+ * by the previous stage.
+ */
+ var->shader_in = (var->location != -1);
+ }
+}
+
+
+void
+link_shaders(struct glsl_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 glsl_shader **vert_shader_list;
+ unsigned num_vert_shaders = 0;
+ struct glsl_shader **frag_shader_list;
+ unsigned num_frag_shaders = 0;
+
+ vert_shader_list = (struct glsl_shader **)
+ calloc(2 * prog->NumShaders, sizeof(struct glsl_shader *));
+ frag_shader_list = &vert_shader_list[prog->NumShaders];
+
+ for (unsigned i = 0; i < prog->NumShaders; i++) {
+ 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;
+ }
+ }
+
+ /* FINISHME: Implement intra-stage linking. */
+ assert(num_vert_shaders <= 1);
+ assert(num_frag_shaders <= 1);
+
+ /* Verify that each of the per-target executables is valid.
+ */
+ if (!validate_vertex_shader_executable(prog, vert_shader_list[0])
+ || !validate_fragment_shader_executable(prog, frag_shader_list[0]))
+ goto done;
+
+
+ prog->_LinkedShaders = (struct glsl_shader **)
+ calloc(2, sizeof(struct glsl_shader *));
+ prog->_NumLinkedShaders = 0;
+
+ if (num_vert_shaders > 0) {
+ prog->_LinkedShaders[prog->_NumLinkedShaders] = vert_shader_list[0];
+ prog->_NumLinkedShaders++;
+ }
+
+ if (num_frag_shaders > 0) {
+ prog->_LinkedShaders[prog->_NumLinkedShaders] = frag_shader_list[0];
+ 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;
+ }
+
+ /* FINISHME: Perform whole-program optimization here. */
+
+ 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->_LinkedShaders[i - 1],
+ prog->_LinkedShaders[i]);
+
+ /* FINISHME: Assign fragment shader output locations. */
+
+done:
+ free(vert_shader_list);
+}
diff --git a/src/glsl/list.h b/src/glsl/list.h
new file mode 100644
index 00000000000..7732d66d7a6
--- /dev/null
+++ b/src/glsl/list.h
@@ -0,0 +1,403 @@
+/*
+ * 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 sentinal head and tail node. These nodes
+ * contain no data. The head sentinal can be identified by its \c prev
+ * pointer being \c NULL. The tail sentinal can be identified by its
+ * \c next pointer being \c NULL.
+ *
+ * A list is empty if either the head sentinal's \c next pointer points to the
+ * tail sentinal or the tail sentinal's \c prev poiner points to the head
+ * sentinal.
+ *
+ * Instead of tracking two separate \c node structures and a \c list structure
+ * that points to them, the sentinal nodes are in a single structure. Noting
+ * that each sentinal 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 sentinal node.
+ * - A \c tail pointer that represents the \c prev pointer of the head
+ * sentinal node and the \c next pointer of the tail sentinal node. This
+ * pointer is \b always \c NULL.
+ * - A \c tail_prev pointer that represents the \c prev pointer of the
+ * tail sentinal 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;
+ }
+
+ /**
+ * Is this the sentinal at the tail of the list?
+ */
+ bool is_tail_sentinal() const
+ {
+ return this->next == NULL;
+ }
+
+ /**
+ * Is this the sentinal at the head of the list?
+ */
+ bool is_head_sentinal() 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
+ 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 sentinal 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();
+ }
+ }
+
+ exec_list_iterator iterator()
+ {
+ return exec_list_iterator(head);
+ }
+
+ exec_list_iterator iterator() const
+ {
+ return exec_list_iterator((exec_node *) head);
+ }
+#endif
+};
+
+#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..dcd9bd69c0c
--- /dev/null
+++ b/src/glsl/main.cpp
@@ -0,0 +1,256 @@
+/*
+ * 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"
+
+/* Returned string will have 'ctx' as its talloc owner. */
+static char *
+load_text_file(void *ctx, const char *file_name, size_t *size)
+{
+ char *text = NULL;
+ struct stat st;
+ ssize_t total_read = 0;
+ int fd = open(file_name, O_RDONLY);
+
+ *size = 0;
+ 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';
+ *size = total_read;
+ }
+ }
+
+ 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_lir = 0;
+int do_link = 0;
+
+const struct option compiler_opts[] = {
+ { "dump-ast", 0, &dump_ast, 1 },
+ { "dump-lir", 0, &dump_lir, 1 },
+ { "link", 0, &do_link, 1 },
+ { NULL, 0, NULL, 0 }
+};
+
+void
+compile_shader(struct glsl_shader *shader)
+{
+ struct _mesa_glsl_parse_state *state;
+
+ state = talloc_zero(talloc_parent(shader), struct _mesa_glsl_parse_state);
+
+ switch (shader->Type) {
+ case GL_VERTEX_SHADER: state->target = vertex_shader; break;
+ case GL_FRAGMENT_SHADER: state->target = fragment_shader; break;
+ case GL_GEOMETRY_SHADER: state->target = geometry_shader; break;
+ }
+
+ state->scanner = NULL;
+ state->translation_unit.make_empty();
+ state->symbols = new(shader) glsl_symbol_table;
+ state->info_log = talloc_strdup(shader, "");
+ state->error = false;
+ state->temp_index = 0;
+ state->loop_or_switch_nesting = NULL;
+ state->ARB_texture_rectangle_enable = true;
+
+ /* Create a new context for the preprocessor output. Ultimately, this
+ * should probably be the parser context, but there isn't one yet.
+ */
+ const char *source = shader->Source;
+ state->error = preprocess(shader, &source, &state->info_log);
+
+ 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.make_empty();
+ if (!state->error && !state->translation_unit.is_empty())
+ _mesa_ast_to_hir(&shader->ir, state);
+
+ validate_ir_tree(&shader->ir);
+
+ /* 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_constant_variable_unlinked(&shader->ir) || progress;
+ progress = do_constant_folding(&shader->ir) || progress;
+ progress = do_vec_index_to_swizzle(&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;
+
+ if (shader->InfoLog)
+ talloc_free(shader->InfoLog);
+
+ shader->InfoLog = state->info_log;
+
+ 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 glsl_program *whole_program;
+
+ whole_program = talloc_zero (NULL, struct glsl_program);
+ assert(whole_program != NULL);
+
+ for (/* empty */; argc > optind; optind++) {
+ whole_program->Shaders = (struct glsl_shader **)
+ talloc_realloc(whole_program, whole_program->Shaders,
+ struct glsl_shader *, whole_program->NumShaders + 1);
+ assert(whole_program->Shaders != NULL);
+
+ struct glsl_shader *shader = talloc_zero(whole_program, glsl_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], &shader->SourceLen);
+ 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;
+ }
+
+ talloc_free(whole_program);
+
+ return status;
+}
diff --git a/src/glsl/main/imports.h b/src/glsl/main/imports.h
new file mode 100644
index 00000000000..d2197342c04
--- /dev/null
+++ b/src/glsl/main/imports.h
@@ -0,0 +1,6 @@
+#include <assert.h>
+#include <stdlib.h>
+
+#define _mesa_malloc(x) malloc(x)
+#define _mesa_free(x) free(x)
+#define _mesa_calloc(x) calloc(1,x)
diff --git a/src/glsl/main/mtypes.h b/src/glsl/main/mtypes.h
new file mode 100644
index 00000000000..06e2dd4b540
--- /dev/null
+++ b/src/glsl/main/mtypes.h
@@ -0,0 +1,270 @@
+/*
+ * Mesa 3-D graphics library
+ * Version: 7.7
+ *
+ * Copyright (C) 1999-2008 Brian Paul All Rights Reserved.
+ * Copyright (C) 2009 VMware, Inc. All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included
+ * in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
+ * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+/**
+ * \file mtypes.h
+ * Main Mesa data structures.
+ *
+ * Please try to mark derived values with a leading underscore ('_').
+ */
+
+#ifndef MTYPES_H
+#define MTYPES_H
+
+#define MAX_DRAW_BUFFERS 8
+#define MAX_VARYING 16
+
+#include <GL/gl.h>
+
+/**
+ * Indexes for vertex program attributes.
+ * GL_NV_vertex_program aliases generic attributes over the conventional
+ * attributes. In GL_ARB_vertex_program shader the aliasing is optional.
+ * In GL_ARB_vertex_shader / OpenGL 2.0 the aliasing is disallowed (the
+ * generic attributes are distinct/separate).
+ */
+typedef enum
+{
+ VERT_ATTRIB_POS = 0,
+ VERT_ATTRIB_WEIGHT = 1,
+ VERT_ATTRIB_NORMAL = 2,
+ VERT_ATTRIB_COLOR0 = 3,
+ VERT_ATTRIB_COLOR1 = 4,
+ VERT_ATTRIB_FOG = 5,
+ VERT_ATTRIB_COLOR_INDEX = 6,
+ VERT_ATTRIB_POINT_SIZE = 6, /*alias*/
+ VERT_ATTRIB_EDGEFLAG = 7,
+ VERT_ATTRIB_TEX0 = 8,
+ VERT_ATTRIB_TEX1 = 9,
+ VERT_ATTRIB_TEX2 = 10,
+ VERT_ATTRIB_TEX3 = 11,
+ VERT_ATTRIB_TEX4 = 12,
+ VERT_ATTRIB_TEX5 = 13,
+ VERT_ATTRIB_TEX6 = 14,
+ VERT_ATTRIB_TEX7 = 15,
+ VERT_ATTRIB_GENERIC0 = 16,
+ VERT_ATTRIB_GENERIC1 = 17,
+ VERT_ATTRIB_GENERIC2 = 18,
+ VERT_ATTRIB_GENERIC3 = 19,
+ VERT_ATTRIB_GENERIC4 = 20,
+ VERT_ATTRIB_GENERIC5 = 21,
+ VERT_ATTRIB_GENERIC6 = 22,
+ VERT_ATTRIB_GENERIC7 = 23,
+ VERT_ATTRIB_GENERIC8 = 24,
+ VERT_ATTRIB_GENERIC9 = 25,
+ VERT_ATTRIB_GENERIC10 = 26,
+ VERT_ATTRIB_GENERIC11 = 27,
+ VERT_ATTRIB_GENERIC12 = 28,
+ VERT_ATTRIB_GENERIC13 = 29,
+ VERT_ATTRIB_GENERIC14 = 30,
+ VERT_ATTRIB_GENERIC15 = 31,
+ VERT_ATTRIB_MAX = 32
+} gl_vert_attrib;
+
+/**
+ * Bitflags for vertex attributes.
+ * These are used in bitfields in many places.
+ */
+/*@{*/
+#define VERT_BIT_POS (1 << VERT_ATTRIB_POS)
+#define VERT_BIT_WEIGHT (1 << VERT_ATTRIB_WEIGHT)
+#define VERT_BIT_NORMAL (1 << VERT_ATTRIB_NORMAL)
+#define VERT_BIT_COLOR0 (1 << VERT_ATTRIB_COLOR0)
+#define VERT_BIT_COLOR1 (1 << VERT_ATTRIB_COLOR1)
+#define VERT_BIT_FOG (1 << VERT_ATTRIB_FOG)
+#define VERT_BIT_COLOR_INDEX (1 << VERT_ATTRIB_COLOR_INDEX)
+#define VERT_BIT_EDGEFLAG (1 << VERT_ATTRIB_EDGEFLAG)
+#define VERT_BIT_TEX0 (1 << VERT_ATTRIB_TEX0)
+#define VERT_BIT_TEX1 (1 << VERT_ATTRIB_TEX1)
+#define VERT_BIT_TEX2 (1 << VERT_ATTRIB_TEX2)
+#define VERT_BIT_TEX3 (1 << VERT_ATTRIB_TEX3)
+#define VERT_BIT_TEX4 (1 << VERT_ATTRIB_TEX4)
+#define VERT_BIT_TEX5 (1 << VERT_ATTRIB_TEX5)
+#define VERT_BIT_TEX6 (1 << VERT_ATTRIB_TEX6)
+#define VERT_BIT_TEX7 (1 << VERT_ATTRIB_TEX7)
+#define VERT_BIT_GENERIC0 (1 << VERT_ATTRIB_GENERIC0)
+#define VERT_BIT_GENERIC1 (1 << VERT_ATTRIB_GENERIC1)
+#define VERT_BIT_GENERIC2 (1 << VERT_ATTRIB_GENERIC2)
+#define VERT_BIT_GENERIC3 (1 << VERT_ATTRIB_GENERIC3)
+#define VERT_BIT_GENERIC4 (1 << VERT_ATTRIB_GENERIC4)
+#define VERT_BIT_GENERIC5 (1 << VERT_ATTRIB_GENERIC5)
+#define VERT_BIT_GENERIC6 (1 << VERT_ATTRIB_GENERIC6)
+#define VERT_BIT_GENERIC7 (1 << VERT_ATTRIB_GENERIC7)
+#define VERT_BIT_GENERIC8 (1 << VERT_ATTRIB_GENERIC8)
+#define VERT_BIT_GENERIC9 (1 << VERT_ATTRIB_GENERIC9)
+#define VERT_BIT_GENERIC10 (1 << VERT_ATTRIB_GENERIC10)
+#define VERT_BIT_GENERIC11 (1 << VERT_ATTRIB_GENERIC11)
+#define VERT_BIT_GENERIC12 (1 << VERT_ATTRIB_GENERIC12)
+#define VERT_BIT_GENERIC13 (1 << VERT_ATTRIB_GENERIC13)
+#define VERT_BIT_GENERIC14 (1 << VERT_ATTRIB_GENERIC14)
+#define VERT_BIT_GENERIC15 (1 << VERT_ATTRIB_GENERIC15)
+
+#define VERT_BIT_TEX(u) (1 << (VERT_ATTRIB_TEX0 + (u)))
+#define VERT_BIT_GENERIC(g) (1 << (VERT_ATTRIB_GENERIC0 + (g)))
+/*@}*/
+
+
+/**
+ * Indexes for vertex program result attributes
+ */
+typedef enum
+{
+ VERT_RESULT_HPOS = 0,
+ VERT_RESULT_COL0 = 1,
+ VERT_RESULT_COL1 = 2,
+ VERT_RESULT_FOGC = 3,
+ VERT_RESULT_TEX0 = 4,
+ VERT_RESULT_TEX1 = 5,
+ VERT_RESULT_TEX2 = 6,
+ VERT_RESULT_TEX3 = 7,
+ VERT_RESULT_TEX4 = 8,
+ VERT_RESULT_TEX5 = 9,
+ VERT_RESULT_TEX6 = 10,
+ VERT_RESULT_TEX7 = 11,
+ VERT_RESULT_PSIZ = 12,
+ VERT_RESULT_BFC0 = 13,
+ VERT_RESULT_BFC1 = 14,
+ VERT_RESULT_EDGE = 15,
+ VERT_RESULT_VAR0 = 16, /**< shader varying */
+ VERT_RESULT_MAX = (VERT_RESULT_VAR0 + MAX_VARYING)
+} gl_vert_result;
+
+
+/**
+ * Indexes for fragment program input attributes.
+ */
+typedef enum
+{
+ FRAG_ATTRIB_WPOS = 0,
+ FRAG_ATTRIB_COL0 = 1,
+ FRAG_ATTRIB_COL1 = 2,
+ FRAG_ATTRIB_FOGC = 3,
+ FRAG_ATTRIB_TEX0 = 4,
+ FRAG_ATTRIB_TEX1 = 5,
+ FRAG_ATTRIB_TEX2 = 6,
+ FRAG_ATTRIB_TEX3 = 7,
+ FRAG_ATTRIB_TEX4 = 8,
+ FRAG_ATTRIB_TEX5 = 9,
+ FRAG_ATTRIB_TEX6 = 10,
+ FRAG_ATTRIB_TEX7 = 11,
+ FRAG_ATTRIB_FACE = 12, /**< front/back face */
+ FRAG_ATTRIB_PNTC = 13, /**< sprite/point coord */
+ FRAG_ATTRIB_VAR0 = 14, /**< shader varying */
+ FRAG_ATTRIB_MAX = (FRAG_ATTRIB_VAR0 + MAX_VARYING)
+} gl_frag_attrib;
+
+/**
+ * Bitflags for fragment program input attributes.
+ */
+/*@{*/
+#define FRAG_BIT_WPOS (1 << FRAG_ATTRIB_WPOS)
+#define FRAG_BIT_COL0 (1 << FRAG_ATTRIB_COL0)
+#define FRAG_BIT_COL1 (1 << FRAG_ATTRIB_COL1)
+#define FRAG_BIT_FOGC (1 << FRAG_ATTRIB_FOGC)
+#define FRAG_BIT_FACE (1 << FRAG_ATTRIB_FACE)
+#define FRAG_BIT_PNTC (1 << FRAG_ATTRIB_PNTC)
+#define FRAG_BIT_TEX0 (1 << FRAG_ATTRIB_TEX0)
+#define FRAG_BIT_TEX1 (1 << FRAG_ATTRIB_TEX1)
+#define FRAG_BIT_TEX2 (1 << FRAG_ATTRIB_TEX2)
+#define FRAG_BIT_TEX3 (1 << FRAG_ATTRIB_TEX3)
+#define FRAG_BIT_TEX4 (1 << FRAG_ATTRIB_TEX4)
+#define FRAG_BIT_TEX5 (1 << FRAG_ATTRIB_TEX5)
+#define FRAG_BIT_TEX6 (1 << FRAG_ATTRIB_TEX6)
+#define FRAG_BIT_TEX7 (1 << FRAG_ATTRIB_TEX7)
+#define FRAG_BIT_VAR0 (1 << FRAG_ATTRIB_VAR0)
+
+#define FRAG_BIT_TEX(U) (FRAG_BIT_TEX0 << (U))
+#define FRAG_BIT_VAR(V) (FRAG_BIT_VAR0 << (V))
+
+#define FRAG_BITS_TEX_ANY (FRAG_BIT_TEX0| \
+ FRAG_BIT_TEX1| \
+ FRAG_BIT_TEX2| \
+ FRAG_BIT_TEX3| \
+ FRAG_BIT_TEX4| \
+ FRAG_BIT_TEX5| \
+ FRAG_BIT_TEX6| \
+ FRAG_BIT_TEX7)
+/*@}*/
+
+
+/**
+ * Fragment program results
+ */
+typedef enum
+{
+ FRAG_RESULT_DEPTH = 0,
+ FRAG_RESULT_COLOR = 1,
+ FRAG_RESULT_DATA0 = 2,
+ FRAG_RESULT_MAX = (FRAG_RESULT_DATA0 + MAX_DRAW_BUFFERS)
+} gl_frag_result;
+
+/**
+ * Names of the various vertex/fragment program register files, etc.
+ *
+ * NOTE: first four tokens must fit into 2 bits (see t_vb_arbprogram.c)
+ * All values should fit in a 4-bit field.
+ *
+ * NOTE: PROGRAM_ENV_PARAM, PROGRAM_STATE_VAR, PROGRAM_NAMED_PARAM,
+ * PROGRAM_CONSTANT, and PROGRAM_UNIFORM can all be considered to
+ * be "uniform" variables since they can only be set outside glBegin/End.
+ * They're also all stored in the same Parameters array.
+ */
+typedef enum
+{
+ PROGRAM_TEMPORARY, /**< machine->Temporary[] */
+ PROGRAM_INPUT, /**< machine->Inputs[] */
+ PROGRAM_OUTPUT, /**< machine->Outputs[] */
+ PROGRAM_VARYING, /**< machine->Inputs[]/Outputs[] */
+ PROGRAM_LOCAL_PARAM, /**< gl_program->LocalParams[] */
+ PROGRAM_ENV_PARAM, /**< gl_program->Parameters[] */
+ PROGRAM_STATE_VAR, /**< gl_program->Parameters[] */
+ PROGRAM_NAMED_PARAM, /**< gl_program->Parameters[] */
+ PROGRAM_CONSTANT, /**< gl_program->Parameters[] */
+ PROGRAM_UNIFORM, /**< gl_program->Parameters[] */
+ PROGRAM_WRITE_ONLY, /**< A dummy, write-only register */
+ PROGRAM_ADDRESS, /**< machine->AddressReg */
+ PROGRAM_SAMPLER, /**< for shader samplers, compile-time only */
+ PROGRAM_UNDEFINED, /**< Invalid/TBD value */
+ PROGRAM_FILE_MAX
+} gl_register_file;
+
+/**
+ * An index for each type of texture object. These correspond to the GL
+ * texture target enums, such as GL_TEXTURE_2D, GL_TEXTURE_CUBE_MAP, etc.
+ * Note: the order is from highest priority to lowest priority.
+ */
+typedef enum
+{
+ TEXTURE_2D_ARRAY_INDEX,
+ TEXTURE_1D_ARRAY_INDEX,
+ TEXTURE_CUBE_INDEX,
+ TEXTURE_3D_INDEX,
+ TEXTURE_RECT_INDEX,
+ TEXTURE_2D_INDEX,
+ TEXTURE_1D_INDEX,
+ NUM_TEXTURE_TARGETS
+} gl_texture_index;
+
+#endif /* MTYPES_H */
diff --git a/src/glsl/main/simple_list.h b/src/glsl/main/simple_list.h
new file mode 100644
index 00000000000..5ef39e14cc6
--- /dev/null
+++ b/src/glsl/main/simple_list.h
@@ -0,0 +1,235 @@
+/**
+ * \file simple_list.h
+ * Simple macros for type-safe, intrusive lists.
+ *
+ * Intended to work with a list sentinal which is created as an empty
+ * list. Insert & delete are O(1).
+ *
+ * \author
+ * (C) 1997, Keith Whitwell
+ */
+
+/*
+ * Mesa 3-D graphics library
+ * Version: 3.5
+ *
+ * Copyright (C) 1999-2001 Brian Paul All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included
+ * in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
+ * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+
+#ifndef _SIMPLE_LIST_H
+#define _SIMPLE_LIST_H
+
+struct simple_node {
+ struct simple_node *next;
+ struct simple_node *prev;
+};
+
+/**
+ * Remove an element from list.
+ *
+ * \param elem element to remove.
+ */
+#define remove_from_list(elem) \
+do { \
+ (elem)->next->prev = (elem)->prev; \
+ (elem)->prev->next = (elem)->next; \
+} while (0)
+
+/**
+ * Insert an element to the list head.
+ *
+ * \param list list.
+ * \param elem element to insert.
+ */
+#define insert_at_head(list, elem) \
+do { \
+ (elem)->prev = list; \
+ (elem)->next = (list)->next; \
+ (list)->next->prev = elem; \
+ (list)->next = elem; \
+} while(0)
+
+/**
+ * Insert an element to the list tail.
+ *
+ * \param list list.
+ * \param elem element to insert.
+ */
+#define insert_at_tail(list, elem) \
+do { \
+ (elem)->next = list; \
+ (elem)->prev = (list)->prev; \
+ (list)->prev->next = elem; \
+ (list)->prev = elem; \
+} while(0)
+
+/**
+ * Move an element to the list head.
+ *
+ * \param list list.
+ * \param elem element to move.
+ */
+#define move_to_head(list, elem) \
+do { \
+ remove_from_list(elem); \
+ insert_at_head(list, elem); \
+} while (0)
+
+/**
+ * Move an element to the list tail.
+ *
+ * \param list list.
+ * \param elem element to move.
+ */
+#define move_to_tail(list, elem) \
+do { \
+ remove_from_list(elem); \
+ insert_at_tail(list, elem); \
+} while (0)
+
+/**
+ * Consatinate a cyclic list to a list
+ *
+ * Appends the sequence of nodes starting with \c tail to the list \c head.
+ * A "cyclic list" is a list that does not have a sentinal node. This means
+ * that the data pointed to by \c tail is an actual node, not a dataless
+ * sentinal. Note that if \c tail constist of a single node, this macro
+ * behaves identically to \c insert_at_tail
+ *
+ * \param head Head of the list to be appended to. This may or may not
+ * be a cyclic list.
+ * \param tail Head of the cyclic list to be appended to \c head.
+ * \param temp Temporary \c simple_list used by the macro
+ *
+ * \sa insert_at_tail
+ */
+#define concat_list_and_cycle(head, tail, temp) \
+do { \
+ (head)->prev->next = (tail); \
+ (tail)->prev->next = (head); \
+ (temp) = (head)->prev; \
+ (head)->prev = (tail)->prev; \
+ (tail)->prev = (temp); \
+} while (0)
+
+#define concat_list(head, next_list) \
+do { \
+ (next_list)->next->prev = (head)->prev; \
+ (next_list)->prev->next = (head); \
+ (head)->prev->next = (next_list)->next; \
+ (head)->prev = (next_list)->prev; \
+} while (0)
+
+/**
+ * Make a empty list empty.
+ *
+ * \param sentinal list (sentinal element).
+ */
+#define make_empty_list(sentinal) \
+do { \
+ (sentinal)->next = sentinal; \
+ (sentinal)->prev = sentinal; \
+} while (0)
+
+/**
+ * Get list first element.
+ *
+ * \param list list.
+ *
+ * \return pointer to first element.
+ */
+#define first_elem(list) ((list)->next)
+
+/**
+ * Get list last element.
+ *
+ * \param list list.
+ *
+ * \return pointer to last element.
+ */
+#define last_elem(list) ((list)->prev)
+
+/**
+ * Get next element.
+ *
+ * \param elem element.
+ *
+ * \return pointer to next element.
+ */
+#define next_elem(elem) ((elem)->next)
+
+/**
+ * Get previous element.
+ *
+ * \param elem element.
+ *
+ * \return pointer to previous element.
+ */
+#define prev_elem(elem) ((elem)->prev)
+
+/**
+ * Test whether element is at end of the list.
+ *
+ * \param list list.
+ * \param elem element.
+ *
+ * \return non-zero if element is at end of list, or zero otherwise.
+ */
+#define at_end(list, elem) ((elem) == (list))
+
+/**
+ * Test if a list is empty.
+ *
+ * \param list list.
+ *
+ * \return non-zero if list empty, or zero otherwise.
+ */
+#define is_empty_list(list) ((list)->next == (list))
+
+/**
+ * Walk through the elements of a list.
+ *
+ * \param ptr pointer to the current element.
+ * \param list list.
+ *
+ * \note It should be followed by a { } block or a single statement, as in a \c
+ * for loop.
+ */
+#define foreach(ptr, list) \
+ for( ptr=(list)->next ; ptr!=list ; ptr=(ptr)->next )
+
+/**
+ * Walk through the elements of a list.
+ *
+ * Same as #foreach but lets you unlink the current value during a list
+ * traversal. Useful for freeing a list, element by element.
+ *
+ * \param ptr pointer to the current element.
+ * \param t temporary pointer.
+ * \param list list.
+ *
+ * \note It should be followed by a { } block or a single statement, as in a \c
+ * for loop.
+ */
+#define foreach_s(ptr, t, list) \
+ for(ptr=(list)->next,t=(ptr)->next; list != ptr; ptr=t, t=(t)->next)
+
+#endif
diff --git a/src/glsl/mesa/shader/prog_instruction.c b/src/glsl/mesa/shader/prog_instruction.c
new file mode 100644
index 00000000000..fbcf868f509
--- /dev/null
+++ b/src/glsl/mesa/shader/prog_instruction.c
@@ -0,0 +1,363 @@
+/*
+ * Mesa 3-D graphics library
+ * Version: 7.3
+ *
+ * Copyright (C) 1999-2008 Brian Paul All Rights Reserved.
+ * Copyright (C) 1999-2009 VMware, Inc. All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included
+ * in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
+ * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+
+#define _GNU_SOURCE
+#include <stdio.h>
+#include <string.h>
+#include <assert.h>
+
+#if 0
+#include "main/glheader.h"
+#else
+#define _mesa_strdup strdup
+#define _mesa_snprintf snprintf
+#define ASSERT assert
+#endif
+#include "main/imports.h"
+#include "main/mtypes.h"
+#include "prog_instruction.h"
+
+
+/**
+ * Initialize program instruction fields to defaults.
+ * \param inst first instruction to initialize
+ * \param count number of instructions to initialize
+ */
+void
+_mesa_init_instructions(struct prog_instruction *inst, GLuint count)
+{
+ GLuint i;
+
+ memset(inst, 0, count * sizeof(struct prog_instruction));
+
+ for (i = 0; i < count; i++) {
+ inst[i].SrcReg[0].File = PROGRAM_UNDEFINED;
+ inst[i].SrcReg[0].Swizzle = SWIZZLE_NOOP;
+ inst[i].SrcReg[1].File = PROGRAM_UNDEFINED;
+ inst[i].SrcReg[1].Swizzle = SWIZZLE_NOOP;
+ inst[i].SrcReg[2].File = PROGRAM_UNDEFINED;
+ inst[i].SrcReg[2].Swizzle = SWIZZLE_NOOP;
+
+ inst[i].DstReg.File = PROGRAM_UNDEFINED;
+ inst[i].DstReg.WriteMask = WRITEMASK_XYZW;
+ inst[i].DstReg.CondMask = COND_TR;
+ inst[i].DstReg.CondSwizzle = SWIZZLE_NOOP;
+
+ inst[i].SaturateMode = SATURATE_OFF;
+ inst[i].Precision = FLOAT32;
+ }
+}
+
+
+/**
+ * Allocate an array of program instructions.
+ * \param numInst number of instructions
+ * \return pointer to instruction memory
+ */
+struct prog_instruction *
+_mesa_alloc_instructions(GLuint numInst)
+{
+ return (struct prog_instruction *)
+ calloc(1, numInst * sizeof(struct prog_instruction));
+}
+
+
+/**
+ * Reallocate memory storing an array of program instructions.
+ * This is used when we need to append additional instructions onto an
+ * program.
+ * \param oldInst pointer to first of old/src instructions
+ * \param numOldInst number of instructions at <oldInst>
+ * \param numNewInst desired size of new instruction array.
+ * \return pointer to start of new instruction array.
+ */
+struct prog_instruction *
+_mesa_realloc_instructions(struct prog_instruction *oldInst,
+ GLuint numOldInst, GLuint numNewInst)
+{
+ struct prog_instruction *newInst;
+
+ (void)numOldInst;
+ newInst = (struct prog_instruction *)
+ realloc(oldInst,
+ numNewInst * sizeof(struct prog_instruction));
+
+ return newInst;
+}
+
+
+/**
+ * Copy an array of program instructions.
+ * \param dest pointer to destination.
+ * \param src pointer to source.
+ * \param n number of instructions to copy.
+ * \return pointer to destination.
+ */
+struct prog_instruction *
+_mesa_copy_instructions(struct prog_instruction *dest,
+ const struct prog_instruction *src, GLuint n)
+{
+ GLuint i;
+ memcpy(dest, src, n * sizeof(struct prog_instruction));
+ for (i = 0; i < n; i++) {
+ if (src[i].Comment)
+ dest[i].Comment = _mesa_strdup(src[i].Comment);
+ }
+ return dest;
+}
+
+
+/**
+ * Free an array of instructions
+ */
+void
+_mesa_free_instructions(struct prog_instruction *inst, GLuint count)
+{
+ GLuint i;
+ for (i = 0; i < count; i++) {
+ if (inst[i].Data)
+ free(inst[i].Data);
+ if (inst[i].Comment)
+ free((char *) inst[i].Comment);
+ }
+ free(inst);
+}
+
+
+/**
+ * Basic info about each instruction
+ */
+struct instruction_info
+{
+ gl_inst_opcode Opcode;
+ const char *Name;
+ GLuint NumSrcRegs;
+ GLuint NumDstRegs;
+};
+
+/**
+ * Instruction info
+ * \note Opcode should equal array index!
+ */
+static const struct instruction_info InstInfo[MAX_OPCODE] = {
+ { OPCODE_NOP, "NOP", 0, 0 },
+ { OPCODE_ABS, "ABS", 1, 1 },
+ { OPCODE_ADD, "ADD", 2, 1 },
+ { OPCODE_AND, "AND", 2, 1 },
+ { OPCODE_ARA, "ARA", 1, 1 },
+ { OPCODE_ARL, "ARL", 1, 1 },
+ { OPCODE_ARL_NV, "ARL_NV", 1, 1 },
+ { OPCODE_ARR, "ARL", 1, 1 },
+ { OPCODE_BGNLOOP,"BGNLOOP", 0, 0 },
+ { OPCODE_BGNSUB, "BGNSUB", 0, 0 },
+ { OPCODE_BRA, "BRA", 0, 0 },
+ { OPCODE_BRK, "BRK", 0, 0 },
+ { OPCODE_CAL, "CAL", 0, 0 },
+ { OPCODE_CMP, "CMP", 3, 1 },
+ { OPCODE_CONT, "CONT", 0, 0 },
+ { OPCODE_COS, "COS", 1, 1 },
+ { OPCODE_DDX, "DDX", 1, 1 },
+ { OPCODE_DDY, "DDY", 1, 1 },
+ { OPCODE_DP2, "DP2", 2, 1 },
+ { OPCODE_DP2A, "DP2A", 3, 1 },
+ { OPCODE_DP3, "DP3", 2, 1 },
+ { OPCODE_DP4, "DP4", 2, 1 },
+ { OPCODE_DPH, "DPH", 2, 1 },
+ { OPCODE_DST, "DST", 2, 1 },
+ { OPCODE_ELSE, "ELSE", 0, 0 },
+ { OPCODE_END, "END", 0, 0 },
+ { OPCODE_ENDIF, "ENDIF", 0, 0 },
+ { OPCODE_ENDLOOP,"ENDLOOP", 0, 0 },
+ { OPCODE_ENDSUB, "ENDSUB", 0, 0 },
+ { OPCODE_EX2, "EX2", 1, 1 },
+ { OPCODE_EXP, "EXP", 1, 1 },
+ { OPCODE_FLR, "FLR", 1, 1 },
+ { OPCODE_FRC, "FRC", 1, 1 },
+ { OPCODE_IF, "IF", 1, 0 },
+ { OPCODE_KIL, "KIL", 1, 0 },
+ { OPCODE_KIL_NV, "KIL_NV", 0, 0 },
+ { OPCODE_LG2, "LG2", 1, 1 },
+ { OPCODE_LIT, "LIT", 1, 1 },
+ { OPCODE_LOG, "LOG", 1, 1 },
+ { OPCODE_LRP, "LRP", 3, 1 },
+ { OPCODE_MAD, "MAD", 3, 1 },
+ { OPCODE_MAX, "MAX", 2, 1 },
+ { OPCODE_MIN, "MIN", 2, 1 },
+ { OPCODE_MOV, "MOV", 1, 1 },
+ { OPCODE_MUL, "MUL", 2, 1 },
+ { OPCODE_NOISE1, "NOISE1", 1, 1 },
+ { OPCODE_NOISE2, "NOISE2", 1, 1 },
+ { OPCODE_NOISE3, "NOISE3", 1, 1 },
+ { OPCODE_NOISE4, "NOISE4", 1, 1 },
+ { OPCODE_NOT, "NOT", 1, 1 },
+ { OPCODE_NRM3, "NRM3", 1, 1 },
+ { OPCODE_NRM4, "NRM4", 1, 1 },
+ { OPCODE_OR, "OR", 2, 1 },
+ { OPCODE_PK2H, "PK2H", 1, 1 },
+ { OPCODE_PK2US, "PK2US", 1, 1 },
+ { OPCODE_PK4B, "PK4B", 1, 1 },
+ { OPCODE_PK4UB, "PK4UB", 1, 1 },
+ { OPCODE_POW, "POW", 2, 1 },
+ { OPCODE_POPA, "POPA", 0, 0 },
+ { OPCODE_PRINT, "PRINT", 1, 0 },
+ { OPCODE_PUSHA, "PUSHA", 0, 0 },
+ { OPCODE_RCC, "RCC", 1, 1 },
+ { OPCODE_RCP, "RCP", 1, 1 },
+ { OPCODE_RET, "RET", 0, 0 },
+ { OPCODE_RFL, "RFL", 1, 1 },
+ { OPCODE_RSQ, "RSQ", 1, 1 },
+ { OPCODE_SCS, "SCS", 1, 1 },
+ { OPCODE_SEQ, "SEQ", 2, 1 },
+ { OPCODE_SFL, "SFL", 0, 1 },
+ { OPCODE_SGE, "SGE", 2, 1 },
+ { OPCODE_SGT, "SGT", 2, 1 },
+ { OPCODE_SIN, "SIN", 1, 1 },
+ { OPCODE_SLE, "SLE", 2, 1 },
+ { OPCODE_SLT, "SLT", 2, 1 },
+ { OPCODE_SNE, "SNE", 2, 1 },
+ { OPCODE_SSG, "SSG", 1, 1 },
+ { OPCODE_STR, "STR", 0, 1 },
+ { OPCODE_SUB, "SUB", 2, 1 },
+ { OPCODE_SWZ, "SWZ", 1, 1 },
+ { OPCODE_TEX, "TEX", 1, 1 },
+ { OPCODE_TXB, "TXB", 1, 1 },
+ { OPCODE_TXD, "TXD", 3, 1 },
+ { OPCODE_TXL, "TXL", 1, 1 },
+ { OPCODE_TXP, "TXP", 1, 1 },
+ { OPCODE_TXP_NV, "TXP_NV", 1, 1 },
+ { OPCODE_TRUNC, "TRUNC", 1, 1 },
+ { OPCODE_UP2H, "UP2H", 1, 1 },
+ { OPCODE_UP2US, "UP2US", 1, 1 },
+ { OPCODE_UP4B, "UP4B", 1, 1 },
+ { OPCODE_UP4UB, "UP4UB", 1, 1 },
+ { OPCODE_X2D, "X2D", 3, 1 },
+ { OPCODE_XOR, "XOR", 2, 1 },
+ { OPCODE_XPD, "XPD", 2, 1 }
+};
+
+
+/**
+ * Return the number of src registers for the given instruction/opcode.
+ */
+GLuint
+_mesa_num_inst_src_regs(gl_inst_opcode opcode)
+{
+ ASSERT(opcode < MAX_OPCODE);
+ ASSERT(opcode == InstInfo[opcode].Opcode);
+ ASSERT(OPCODE_XPD == InstInfo[OPCODE_XPD].Opcode);
+ return InstInfo[opcode].NumSrcRegs;
+}
+
+
+/**
+ * Return the number of dst registers for the given instruction/opcode.
+ */
+GLuint
+_mesa_num_inst_dst_regs(gl_inst_opcode opcode)
+{
+ ASSERT(opcode < MAX_OPCODE);
+ ASSERT(opcode == InstInfo[opcode].Opcode);
+ ASSERT(OPCODE_XPD == InstInfo[OPCODE_XPD].Opcode);
+ return InstInfo[opcode].NumDstRegs;
+}
+
+
+GLboolean
+_mesa_is_tex_instruction(gl_inst_opcode opcode)
+{
+ return (opcode == OPCODE_TEX ||
+ opcode == OPCODE_TXB ||
+ opcode == OPCODE_TXD ||
+ opcode == OPCODE_TXL ||
+ opcode == OPCODE_TXP);
+}
+
+
+/**
+ * Check if there's a potential src/dst register data dependency when
+ * using SOA execution.
+ * Example:
+ * MOV T, T.yxwz;
+ * This would expand into:
+ * MOV t0, t1;
+ * MOV t1, t0;
+ * MOV t2, t3;
+ * MOV t3, t2;
+ * The second instruction will have the wrong value for t0 if executed as-is.
+ */
+GLboolean
+_mesa_check_soa_dependencies(const struct prog_instruction *inst)
+{
+ GLuint i, chan;
+
+ if (inst->DstReg.WriteMask == WRITEMASK_X ||
+ inst->DstReg.WriteMask == WRITEMASK_Y ||
+ inst->DstReg.WriteMask == WRITEMASK_Z ||
+ inst->DstReg.WriteMask == WRITEMASK_W ||
+ inst->DstReg.WriteMask == 0x0) {
+ /* no chance of data dependency */
+ return GL_FALSE;
+ }
+
+ /* loop over src regs */
+ for (i = 0; i < 3; i++) {
+ if (inst->SrcReg[i].File == inst->DstReg.File &&
+ inst->SrcReg[i].Index == inst->DstReg.Index) {
+ /* loop over dest channels */
+ GLuint channelsWritten = 0x0;
+ for (chan = 0; chan < 4; chan++) {
+ if (inst->DstReg.WriteMask & (1 << chan)) {
+ /* check if we're reading a channel that's been written */
+ GLuint swizzle = GET_SWZ(inst->SrcReg[i].Swizzle, chan);
+ if (swizzle <= SWIZZLE_W &&
+ (channelsWritten & (1 << swizzle))) {
+ return GL_TRUE;
+ }
+
+ channelsWritten |= (1 << chan);
+ }
+ }
+ }
+ }
+ return GL_FALSE;
+}
+
+
+/**
+ * Return string name for given program opcode.
+ */
+const char *
+_mesa_opcode_string(gl_inst_opcode opcode)
+{
+ if (opcode < MAX_OPCODE)
+ return InstInfo[opcode].Name;
+ else {
+ static char s[20];
+ _mesa_snprintf(s, sizeof(s), "OP%u", opcode);
+ return s;
+ }
+}
+
diff --git a/src/glsl/mesa/shader/prog_instruction.h b/src/glsl/mesa/shader/prog_instruction.h
new file mode 100644
index 00000000000..2c95d274cab
--- /dev/null
+++ b/src/glsl/mesa/shader/prog_instruction.h
@@ -0,0 +1,437 @@
+/*
+ * Mesa 3-D graphics library
+ * Version: 7.3
+ *
+ * Copyright (C) 1999-2008 Brian Paul All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included
+ * in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
+ * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+
+/**
+ * \file prog_instruction.h
+ *
+ * Vertex/fragment program instruction datatypes and constants.
+ *
+ * \author Brian Paul
+ * \author Keith Whitwell
+ * \author Ian Romanick <[email protected]>
+ */
+
+
+#ifndef PROG_INSTRUCTION_H
+#define PROG_INSTRUCTION_H
+
+
+#include "main/mtypes.h"
+
+
+/**
+ * Swizzle indexes.
+ * Do not change!
+ */
+/*@{*/
+#define SWIZZLE_X 0
+#define SWIZZLE_Y 1
+#define SWIZZLE_Z 2
+#define SWIZZLE_W 3
+#define SWIZZLE_ZERO 4 /**< For SWZ instruction only */
+#define SWIZZLE_ONE 5 /**< For SWZ instruction only */
+#define SWIZZLE_NIL 7 /**< used during shader code gen (undefined value) */
+/*@}*/
+
+#define MAKE_SWIZZLE4(a,b,c,d) (((a)<<0) | ((b)<<3) | ((c)<<6) | ((d)<<9))
+#define SWIZZLE_NOOP MAKE_SWIZZLE4(0,1,2,3)
+#define GET_SWZ(swz, idx) (((swz) >> ((idx)*3)) & 0x7)
+#define GET_BIT(msk, idx) (((msk) >> (idx)) & 0x1)
+
+#define SWIZZLE_XYZW MAKE_SWIZZLE4(SWIZZLE_X, SWIZZLE_Y, SWIZZLE_Z, SWIZZLE_W)
+#define SWIZZLE_XXXX MAKE_SWIZZLE4(SWIZZLE_X, SWIZZLE_X, SWIZZLE_X, SWIZZLE_X)
+#define SWIZZLE_YYYY MAKE_SWIZZLE4(SWIZZLE_Y, SWIZZLE_Y, SWIZZLE_Y, SWIZZLE_Y)
+#define SWIZZLE_ZZZZ MAKE_SWIZZLE4(SWIZZLE_Z, SWIZZLE_Z, SWIZZLE_Z, SWIZZLE_Z)
+#define SWIZZLE_WWWW MAKE_SWIZZLE4(SWIZZLE_W, SWIZZLE_W, SWIZZLE_W, SWIZZLE_W)
+
+
+/**
+ * Writemask values, 1 bit per component.
+ */
+/*@{*/
+#define WRITEMASK_X 0x1
+#define WRITEMASK_Y 0x2
+#define WRITEMASK_XY 0x3
+#define WRITEMASK_Z 0x4
+#define WRITEMASK_XZ 0x5
+#define WRITEMASK_YZ 0x6
+#define WRITEMASK_XYZ 0x7
+#define WRITEMASK_W 0x8
+#define WRITEMASK_XW 0x9
+#define WRITEMASK_YW 0xa
+#define WRITEMASK_XYW 0xb
+#define WRITEMASK_ZW 0xc
+#define WRITEMASK_XZW 0xd
+#define WRITEMASK_YZW 0xe
+#define WRITEMASK_XYZW 0xf
+/*@}*/
+
+
+/**
+ * Condition codes
+ */
+/*@{*/
+#define COND_GT 1 /**< greater than zero */
+#define COND_EQ 2 /**< equal to zero */
+#define COND_LT 3 /**< less than zero */
+#define COND_UN 4 /**< unordered (NaN) */
+#define COND_GE 5 /**< greater than or equal to zero */
+#define COND_LE 6 /**< less than or equal to zero */
+#define COND_NE 7 /**< not equal to zero */
+#define COND_TR 8 /**< always true */
+#define COND_FL 9 /**< always false */
+/*@}*/
+
+
+/**
+ * Instruction precision for GL_NV_fragment_program
+ */
+/*@{*/
+#define FLOAT32 0x1
+#define FLOAT16 0x2
+#define FIXED12 0x4
+/*@}*/
+
+
+/**
+ * Saturation modes when storing values.
+ */
+/*@{*/
+#define SATURATE_OFF 0
+#define SATURATE_ZERO_ONE 1
+/*@}*/
+
+
+/**
+ * Per-component negation masks
+ */
+/*@{*/
+#define NEGATE_X 0x1
+#define NEGATE_Y 0x2
+#define NEGATE_Z 0x4
+#define NEGATE_W 0x8
+#define NEGATE_XYZ 0x7
+#define NEGATE_XYZW 0xf
+#define NEGATE_NONE 0x0
+/*@}*/
+
+
+/**
+ * Program instruction opcodes, for both vertex and fragment programs.
+ * \note changes to this opcode list must be reflected in t_vb_arbprogram.c
+ */
+typedef enum prog_opcode {
+ /* ARB_vp ARB_fp NV_vp NV_fp GLSL */
+ /*------------------------------------------*/
+ OPCODE_NOP = 0, /* X */
+ OPCODE_ABS, /* X X 1.1 X */
+ OPCODE_ADD, /* X X X X X */
+ OPCODE_AND, /* */
+ OPCODE_ARA, /* 2 */
+ OPCODE_ARL, /* X X */
+ OPCODE_ARL_NV, /* 2 */
+ OPCODE_ARR, /* 2 */
+ OPCODE_BGNLOOP, /* opt */
+ OPCODE_BGNSUB, /* opt */
+ OPCODE_BRA, /* 2 X */
+ OPCODE_BRK, /* 2 opt */
+ OPCODE_CAL, /* 2 2 */
+ OPCODE_CMP, /* X */
+ OPCODE_CONT, /* opt */
+ OPCODE_COS, /* X 2 X X */
+ OPCODE_DDX, /* X X */
+ OPCODE_DDY, /* X X */
+ OPCODE_DP2, /* 2 */
+ OPCODE_DP2A, /* 2 */
+ OPCODE_DP3, /* X X X X X */
+ OPCODE_DP4, /* X X X X X */
+ OPCODE_DPH, /* X X 1.1 */
+ OPCODE_DST, /* X X X X */
+ OPCODE_ELSE, /* X */
+ OPCODE_END, /* X X X X opt */
+ OPCODE_ENDIF, /* opt */
+ OPCODE_ENDLOOP, /* opt */
+ OPCODE_ENDSUB, /* opt */
+ OPCODE_EX2, /* X X 2 X X */
+ OPCODE_EXP, /* X X X */
+ OPCODE_FLR, /* X X 2 X X */
+ OPCODE_FRC, /* X X 2 X X */
+ OPCODE_IF, /* opt */
+ OPCODE_KIL, /* X */
+ OPCODE_KIL_NV, /* X X */
+ OPCODE_LG2, /* X X 2 X X */
+ OPCODE_LIT, /* X X X X */
+ OPCODE_LOG, /* X X X */
+ OPCODE_LRP, /* X X */
+ OPCODE_MAD, /* X X X X X */
+ OPCODE_MAX, /* X X X X X */
+ OPCODE_MIN, /* X X X X X */
+ OPCODE_MOV, /* X X X X X */
+ OPCODE_MUL, /* X X X X X */
+ OPCODE_NOISE1, /* X */
+ OPCODE_NOISE2, /* X */
+ OPCODE_NOISE3, /* X */
+ OPCODE_NOISE4, /* X */
+ OPCODE_NOT, /* */
+ OPCODE_NRM3, /* */
+ OPCODE_NRM4, /* */
+ OPCODE_OR, /* */
+ OPCODE_PK2H, /* X */
+ OPCODE_PK2US, /* X */
+ OPCODE_PK4B, /* X */
+ OPCODE_PK4UB, /* X */
+ OPCODE_POW, /* X X X X */
+ OPCODE_POPA, /* 3 */
+ OPCODE_PRINT, /* X X */
+ OPCODE_PUSHA, /* 3 */
+ OPCODE_RCC, /* 1.1 */
+ OPCODE_RCP, /* X X X X X */
+ OPCODE_RET, /* 2 2 */
+ OPCODE_RFL, /* X X */
+ OPCODE_RSQ, /* X X X X X */
+ OPCODE_SCS, /* X */
+ OPCODE_SEQ, /* 2 X X */
+ OPCODE_SFL, /* 2 X */
+ OPCODE_SGE, /* X X X X X */
+ OPCODE_SGT, /* 2 X X */
+ OPCODE_SIN, /* X 2 X X */
+ OPCODE_SLE, /* 2 X X */
+ OPCODE_SLT, /* X X X X X */
+ OPCODE_SNE, /* 2 X X */
+ OPCODE_SSG, /* 2 */
+ OPCODE_STR, /* 2 X */
+ OPCODE_SUB, /* X X 1.1 X X */
+ OPCODE_SWZ, /* X X */
+ OPCODE_TEX, /* X 3 X X */
+ OPCODE_TXB, /* X 3 X */
+ OPCODE_TXD, /* X X */
+ OPCODE_TXL, /* 3 2 X */
+ OPCODE_TXP, /* X X */
+ OPCODE_TXP_NV, /* 3 X */
+ OPCODE_TRUNC, /* X */
+ OPCODE_UP2H, /* X */
+ OPCODE_UP2US, /* X */
+ OPCODE_UP4B, /* X */
+ OPCODE_UP4UB, /* X */
+ OPCODE_X2D, /* X */
+ OPCODE_XOR, /* */
+ OPCODE_XPD, /* X X X */
+ MAX_OPCODE
+} gl_inst_opcode;
+
+
+/**
+ * Number of bits for the src/dst register Index field.
+ * This limits the size of temp/uniform register files.
+ */
+#define INST_INDEX_BITS 10
+
+
+/**
+ * Instruction source register.
+ */
+struct prog_src_register
+{
+ GLuint File:4; /**< One of the PROGRAM_* register file values. */
+ GLint Index:(INST_INDEX_BITS+1); /**< Extra bit here for sign bit.
+ * May be negative for relative addressing.
+ */
+ GLuint Swizzle:12;
+ GLuint RelAddr:1;
+
+ /** Take the component-wise absolute value */
+ GLuint Abs:1;
+
+ /**
+ * Post-Abs negation.
+ * This will either be NEGATE_NONE or NEGATE_XYZW, except for the SWZ
+ * instruction which allows per-component negation.
+ */
+ GLuint Negate:4;
+};
+
+
+/**
+ * Instruction destination register.
+ */
+struct prog_dst_register
+{
+ GLuint File:4; /**< One of the PROGRAM_* register file values */
+ GLuint Index:INST_INDEX_BITS; /**< Unsigned, never negative */
+ GLuint WriteMask:4;
+ GLuint RelAddr:1;
+
+ /**
+ * \name Conditional destination update control.
+ *
+ * \since
+ * NV_fragment_program, NV_fragment_program_option, NV_vertex_program2,
+ * NV_vertex_program2_option.
+ */
+ /*@{*/
+ /**
+ * Takes one of the 9 possible condition values (EQ, FL, GT, GE, LE, LT,
+ * NE, TR, or UN). Dest reg is only written to if the matching
+ * (swizzled) condition code value passes. When a conditional update mask
+ * is not specified, this will be \c COND_TR.
+ */
+ GLuint CondMask:4;
+
+ /**
+ * Condition code swizzle value.
+ */
+ GLuint CondSwizzle:12;
+
+ /**
+ * Selects the condition code register to use for conditional destination
+ * update masking. In NV_fragmnet_program or NV_vertex_program2 mode, only
+ * condition code register 0 is available. In NV_vertex_program3 mode,
+ * condition code registers 0 and 1 are available.
+ */
+ GLuint CondSrc:1;
+ /*@}*/
+};
+
+
+/**
+ * Vertex/fragment program instruction.
+ */
+struct prog_instruction
+{
+ gl_inst_opcode Opcode;
+ struct prog_src_register SrcReg[3];
+ struct prog_dst_register DstReg;
+
+ /**
+ * Indicates that the instruction should update the condition code
+ * register.
+ *
+ * \since
+ * NV_fragment_program, NV_fragment_program_option, NV_vertex_program2,
+ * NV_vertex_program2_option.
+ */
+ GLuint CondUpdate:1;
+
+ /**
+ * If prog_instruction::CondUpdate is \c GL_TRUE, this value selects the
+ * condition code register that is to be updated.
+ *
+ * In GL_NV_fragment_program or GL_NV_vertex_program2 mode, only condition
+ * code register 0 is available. In GL_NV_vertex_program3 mode, condition
+ * code registers 0 and 1 are available.
+ *
+ * \since
+ * NV_fragment_program, NV_fragment_program_option, NV_vertex_program2,
+ * NV_vertex_program2_option.
+ */
+ GLuint CondDst:1;
+
+ /**
+ * Saturate each value of the vectored result to the range [0,1] or the
+ * range [-1,1]. \c SSAT mode (i.e., saturation to the range [-1,1]) is
+ * only available in NV_fragment_program2 mode.
+ * Value is one of the SATURATE_* tokens.
+ *
+ * \since
+ * NV_fragment_program, NV_fragment_program_option, NV_vertex_program3.
+ */
+ GLuint SaturateMode:2;
+
+ /**
+ * Per-instruction selectable precision: FLOAT32, FLOAT16, FIXED12.
+ *
+ * \since
+ * NV_fragment_program, NV_fragment_program_option.
+ */
+ GLuint Precision:3;
+
+ /**
+ * \name Extra fields for TEX, TXB, TXD, TXL, TXP instructions.
+ */
+ /*@{*/
+ /** Source texture unit. */
+ GLuint TexSrcUnit:5;
+
+ /** Source texture target, one of TEXTURE_{1D,2D,3D,CUBE,RECT}_INDEX */
+ GLuint TexSrcTarget:3;
+
+ /** True if tex instruction should do shadow comparison */
+ GLuint TexShadow:1;
+ /*@}*/
+
+ /**
+ * 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 IF, points to ELSE or ENDIF.
+ * For ELSE, points to ENDIF.
+ */
+ GLint BranchTarget;
+
+ /** for debugging purposes */
+ const char *Comment;
+
+ /** Arbitrary data. Used for OPCODE_PRINT and some drivers */
+ void *Data;
+
+ /** for driver use (try to remove someday) */
+ GLint Aux;
+};
+
+
+extern void
+_mesa_init_instructions(struct prog_instruction *inst, GLuint count);
+
+extern struct prog_instruction *
+_mesa_alloc_instructions(GLuint numInst);
+
+extern struct prog_instruction *
+_mesa_realloc_instructions(struct prog_instruction *oldInst,
+ GLuint numOldInst, GLuint numNewInst);
+
+extern struct prog_instruction *
+_mesa_copy_instructions(struct prog_instruction *dest,
+ const struct prog_instruction *src, GLuint n);
+
+extern void
+_mesa_free_instructions(struct prog_instruction *inst, GLuint count);
+
+extern GLuint
+_mesa_num_inst_src_regs(gl_inst_opcode opcode);
+
+extern GLuint
+_mesa_num_inst_dst_regs(gl_inst_opcode opcode);
+
+extern GLboolean
+_mesa_is_tex_instruction(gl_inst_opcode opcode);
+
+extern GLboolean
+_mesa_check_soa_dependencies(const struct prog_instruction *inst);
+
+extern const char *
+_mesa_opcode_string(gl_inst_opcode opcode);
+
+
+#endif /* PROG_INSTRUCTION_H */
diff --git a/src/glsl/mesa/shader/prog_print.c b/src/glsl/mesa/shader/prog_print.c
new file mode 100644
index 00000000000..3f1cb48e4bf
--- /dev/null
+++ b/src/glsl/mesa/shader/prog_print.c
@@ -0,0 +1,1089 @@
+/*
+ * Mesa 3-D graphics library
+ * Version: 7.3
+ *
+ * Copyright (C) 1999-2008 Brian Paul All Rights Reserved.
+ * Copyright (C) 2009 VMware, Inc. All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included
+ * in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
+ * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+/**
+ * \file prog_print.c
+ * Print vertex/fragment programs - for debugging.
+ * \author Brian Paul
+ */
+
+#if 0
+#include "main/glheader.h"
+#include "main/context.h"
+#include "main/imports.h"
+#else
+
+#define _GNU_SOURCE
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <assert.h>
+struct gl_program {
+ int Target;
+};
+
+void _mesa_problem(void *ctx, char *msg)
+{
+ (void)ctx;
+ fprintf(stderr, "%s", msg);
+ exit(1);
+}
+
+#endif
+
+#include "prog_instruction.h"
+#include "prog_print.h"
+
+
+
+/**
+ * Return string name for given program/register file.
+ */
+static const char *
+file_string(gl_register_file f, gl_prog_print_mode mode)
+{
+ (void)mode;
+ switch (f) {
+ case PROGRAM_TEMPORARY:
+ return "TEMP";
+ case PROGRAM_LOCAL_PARAM:
+ return "LOCAL";
+ case PROGRAM_ENV_PARAM:
+ return "ENV";
+ case PROGRAM_STATE_VAR:
+ return "STATE";
+ case PROGRAM_INPUT:
+ return "INPUT";
+ case PROGRAM_OUTPUT:
+ return "OUTPUT";
+ case PROGRAM_NAMED_PARAM:
+ return "NAMED";
+ case PROGRAM_CONSTANT:
+ return "CONST";
+ case PROGRAM_UNIFORM:
+ return "UNIFORM";
+ case PROGRAM_VARYING:
+ return "VARYING";
+ case PROGRAM_WRITE_ONLY:
+ return "WRITE_ONLY";
+ case PROGRAM_ADDRESS:
+ return "ADDR";
+ case PROGRAM_SAMPLER:
+ return "SAMPLER";
+ case PROGRAM_UNDEFINED:
+ return "UNDEFINED";
+ default:
+ {
+ static char s[20];
+ snprintf(s, sizeof(s), "FILE%u", f);
+ return s;
+ }
+ }
+}
+
+
+/**
+ * Return ARB_v/f_prog-style input attrib string.
+ */
+static const char *
+arb_input_attrib_string(GLint index, GLenum progType)
+{
+ /*
+ * These strings should match the VERT_ATTRIB_x and FRAG_ATTRIB_x tokens.
+ */
+ const char *vertAttribs[] = {
+ "vertex.position",
+ "vertex.weight",
+ "vertex.normal",
+ "vertex.color.primary",
+ "vertex.color.secondary",
+ "vertex.fogcoord",
+ "vertex.(six)",
+ "vertex.(seven)",
+ "vertex.texcoord[0]",
+ "vertex.texcoord[1]",
+ "vertex.texcoord[2]",
+ "vertex.texcoord[3]",
+ "vertex.texcoord[4]",
+ "vertex.texcoord[5]",
+ "vertex.texcoord[6]",
+ "vertex.texcoord[7]",
+ "vertex.attrib[0]",
+ "vertex.attrib[1]",
+ "vertex.attrib[2]",
+ "vertex.attrib[3]",
+ "vertex.attrib[4]",
+ "vertex.attrib[5]",
+ "vertex.attrib[6]",
+ "vertex.attrib[7]",
+ "vertex.attrib[8]",
+ "vertex.attrib[9]",
+ "vertex.attrib[10]",
+ "vertex.attrib[11]",
+ "vertex.attrib[12]",
+ "vertex.attrib[13]",
+ "vertex.attrib[14]",
+ "vertex.attrib[15]"
+ };
+ const char *fragAttribs[] = {
+ "fragment.position",
+ "fragment.color.primary",
+ "fragment.color.secondary",
+ "fragment.fogcoord",
+ "fragment.texcoord[0]",
+ "fragment.texcoord[1]",
+ "fragment.texcoord[2]",
+ "fragment.texcoord[3]",
+ "fragment.texcoord[4]",
+ "fragment.texcoord[5]",
+ "fragment.texcoord[6]",
+ "fragment.texcoord[7]",
+ "fragment.varying[0]",
+ "fragment.varying[1]",
+ "fragment.varying[2]",
+ "fragment.varying[3]",
+ "fragment.varying[4]",
+ "fragment.varying[5]",
+ "fragment.varying[6]",
+ "fragment.varying[7]"
+ };
+
+ /* sanity checks */
+ assert(strcmp(vertAttribs[VERT_ATTRIB_TEX0], "vertex.texcoord[0]") == 0);
+ assert(strcmp(vertAttribs[VERT_ATTRIB_GENERIC15], "vertex.attrib[15]") == 0);
+
+ if (progType == GL_VERTEX_PROGRAM_ARB) {
+ assert((unsigned int)index < sizeof(vertAttribs) / sizeof(vertAttribs[0]));
+ return vertAttribs[index];
+ }
+ else {
+ assert((unsigned int)index < sizeof(fragAttribs) / sizeof(fragAttribs[0]));
+ return fragAttribs[index];
+ }
+}
+
+
+/**
+ * Print a vertex program's InputsRead field in human-readable format.
+ * For debugging.
+ */
+void
+_mesa_print_vp_inputs(GLbitfield inputs)
+{
+ printf("VP Inputs 0x%x: \n", inputs);
+ while (inputs) {
+ GLint attr = ffs(inputs) - 1;
+ const char *name = arb_input_attrib_string(attr,
+ GL_VERTEX_PROGRAM_ARB);
+ printf(" %d: %s\n", attr, name);
+ inputs &= ~(1 << attr);
+ }
+}
+
+
+/**
+ * Print a fragment program's InputsRead field in human-readable format.
+ * For debugging.
+ */
+void
+_mesa_print_fp_inputs(GLbitfield inputs)
+{
+ printf("FP Inputs 0x%x: \n", inputs);
+ while (inputs) {
+ GLint attr = ffs(inputs) - 1;
+ const char *name = arb_input_attrib_string(attr,
+ GL_FRAGMENT_PROGRAM_ARB);
+ printf(" %d: %s\n", attr, name);
+ inputs &= ~(1 << attr);
+ }
+}
+
+
+#if 0
+/**
+ * Return ARB_v/f_prog-style output attrib string.
+ */
+static const char *
+arb_output_attrib_string(GLint index, GLenum progType)
+{
+ /*
+ * These strings should match the VERT_RESULT_x and FRAG_RESULT_x tokens.
+ */
+ const char *vertResults[] = {
+ "result.position",
+ "result.color.primary",
+ "result.color.secondary",
+ "result.fogcoord",
+ "result.texcoord[0]",
+ "result.texcoord[1]",
+ "result.texcoord[2]",
+ "result.texcoord[3]",
+ "result.texcoord[4]",
+ "result.texcoord[5]",
+ "result.texcoord[6]",
+ "result.texcoord[7]",
+ "result.varying[0]",
+ "result.varying[1]",
+ "result.varying[2]",
+ "result.varying[3]",
+ "result.varying[4]",
+ "result.varying[5]",
+ "result.varying[6]",
+ "result.varying[7]"
+ };
+ const char *fragResults[] = {
+ "result.color",
+ "result.color(half)",
+ "result.depth",
+ "result.color[0]",
+ "result.color[1]",
+ "result.color[2]",
+ "result.color[3]"
+ };
+
+ if (progType == GL_VERTEX_PROGRAM_ARB) {
+ assert(index < sizeof(vertResults) / sizeof(vertResults[0]));
+ return vertResults[index];
+ }
+ else {
+ assert(index < sizeof(fragResults) / sizeof(fragResults[0]));
+ return fragResults[index];
+ }
+}
+#endif
+
+/**
+ * Return string representation of the given register.
+ * Note that some types of registers (like PROGRAM_UNIFORM) aren't defined
+ * by the ARB/NV program languages so we've taken some liberties here.
+ * \param f the register file (PROGRAM_INPUT, PROGRAM_TEMPORARY, etc)
+ * \param index number of the register in the register file
+ * \param mode the output format/mode/style
+ * \param prog pointer to containing program
+ */
+static const char *
+reg_string(gl_register_file f, GLint index, gl_prog_print_mode mode,
+ GLboolean relAddr, const struct gl_program *prog)
+{
+ static char str[100];
+ const char *addr = relAddr ? "ADDR+" : "";
+
+ str[0] = 0;
+
+ switch (mode) {
+ case PROG_PRINT_DEBUG:
+ sprintf(str, "%s[%s%d]", file_string(f, mode), addr, index);
+ break;
+ case PROG_PRINT_ARB:
+#if 0
+ switch (f) {
+ case PROGRAM_INPUT:
+ sprintf(str, "%s", arb_input_attrib_string(index, prog->Target));
+ break;
+ case PROGRAM_OUTPUT:
+ sprintf(str, "%s", arb_output_attrib_string(index, prog->Target));
+ break;
+ case PROGRAM_TEMPORARY:
+ sprintf(str, "temp%d", index);
+ break;
+ case PROGRAM_ENV_PARAM:
+ sprintf(str, "program.env[%s%d]", addr, index);
+ break;
+ case PROGRAM_LOCAL_PARAM:
+ sprintf(str, "program.local[%s%d]", addr, index);
+ break;
+ case PROGRAM_VARYING: /* extension */
+ sprintf(str, "varying[%s%d]", addr, index);
+ break;
+ case PROGRAM_CONSTANT: /* extension */
+ sprintf(str, "constant[%s%d]", addr, index);
+ break;
+ case PROGRAM_UNIFORM: /* extension */
+ sprintf(str, "uniform[%s%d]", addr, index);
+ break;
+ case PROGRAM_STATE_VAR:
+ {
+ struct gl_program_parameter *param
+ = prog->Parameters->Parameters + index;
+ char *state = _mesa_program_state_string(param->StateIndexes);
+ sprintf(str, "%s", state);
+ free(state);
+ }
+ break;
+ case PROGRAM_ADDRESS:
+ sprintf(str, "A%d", index);
+ break;
+ default:
+ _mesa_problem(NULL, "bad file in reg_string()");
+ }
+ break;
+#else
+ assert(0);
+ break;
+#endif
+
+ case PROG_PRINT_NV:
+ switch (f) {
+ case PROGRAM_INPUT:
+ if (prog->Target == GL_VERTEX_PROGRAM_ARB)
+ sprintf(str, "v[%d]", index);
+ else
+ sprintf(str, "f[%d]", index);
+ break;
+ case PROGRAM_OUTPUT:
+ sprintf(str, "o[%d]", index);
+ break;
+ case PROGRAM_TEMPORARY:
+ sprintf(str, "R%d", index);
+ break;
+ case PROGRAM_ENV_PARAM:
+ sprintf(str, "c[%d]", index);
+ break;
+ case PROGRAM_VARYING: /* extension */
+ sprintf(str, "varying[%s%d]", addr, index);
+ break;
+ case PROGRAM_UNIFORM: /* extension */
+ sprintf(str, "uniform[%s%d]", addr, index);
+ break;
+ case PROGRAM_CONSTANT: /* extension */
+ sprintf(str, "constant[%s%d]", addr, index);
+ break;
+ case PROGRAM_STATE_VAR: /* extension */
+ sprintf(str, "state[%s%d]", addr, index);
+ break;
+ default:
+ _mesa_problem(NULL, "bad file in reg_string()");
+ }
+ break;
+
+ default:
+ _mesa_problem(NULL, "bad mode in reg_string()");
+ }
+
+ return str;
+}
+
+
+/**
+ * Return a string representation of the given swizzle word.
+ * If extended is true, use extended (comma-separated) format.
+ * \param swizzle the swizzle field
+ * \param negateBase 4-bit negation vector
+ * \param extended if true, also allow 0, 1 values
+ */
+const char *
+_mesa_swizzle_string(GLuint swizzle, GLuint negateMask, GLboolean extended)
+{
+ static const char swz[] = "xyzw01!?"; /* See SWIZZLE_x definitions */
+ static char s[20];
+ GLuint i = 0;
+
+ if (!extended && swizzle == SWIZZLE_NOOP && negateMask == 0)
+ return ""; /* no swizzle/negation */
+
+ if (!extended)
+ s[i++] = '.';
+
+ if (negateMask & NEGATE_X)
+ s[i++] = '-';
+ s[i++] = swz[GET_SWZ(swizzle, 0)];
+
+ if (extended) {
+ s[i++] = ',';
+ }
+
+ if (negateMask & NEGATE_Y)
+ s[i++] = '-';
+ s[i++] = swz[GET_SWZ(swizzle, 1)];
+
+ if (extended) {
+ s[i++] = ',';
+ }
+
+ if (negateMask & NEGATE_Z)
+ s[i++] = '-';
+ s[i++] = swz[GET_SWZ(swizzle, 2)];
+
+ if (extended) {
+ s[i++] = ',';
+ }
+
+ if (negateMask & NEGATE_W)
+ s[i++] = '-';
+ s[i++] = swz[GET_SWZ(swizzle, 3)];
+
+ s[i] = 0;
+ return s;
+}
+
+
+void
+_mesa_print_swizzle(GLuint swizzle)
+{
+ if (swizzle == SWIZZLE_XYZW) {
+ printf(".xyzw\n");
+ }
+ else {
+ const char *s = _mesa_swizzle_string(swizzle, 0, 0);
+ printf("%s\n", s);
+ }
+}
+
+
+const char *
+_mesa_writemask_string(GLuint writeMask)
+{
+ static char s[10];
+ GLuint i = 0;
+
+ if (writeMask == WRITEMASK_XYZW)
+ return "";
+
+ s[i++] = '.';
+ if (writeMask & WRITEMASK_X)
+ s[i++] = 'x';
+ if (writeMask & WRITEMASK_Y)
+ s[i++] = 'y';
+ if (writeMask & WRITEMASK_Z)
+ s[i++] = 'z';
+ if (writeMask & WRITEMASK_W)
+ s[i++] = 'w';
+
+ s[i] = 0;
+ return s;
+}
+
+
+const char *
+_mesa_condcode_string(GLuint condcode)
+{
+ switch (condcode) {
+ case COND_GT: return "GT";
+ case COND_EQ: return "EQ";
+ case COND_LT: return "LT";
+ case COND_UN: return "UN";
+ case COND_GE: return "GE";
+ case COND_LE: return "LE";
+ case COND_NE: return "NE";
+ case COND_TR: return "TR";
+ case COND_FL: return "FL";
+ default: return "cond???";
+ }
+}
+
+
+static void
+fprint_dst_reg(FILE * f,
+ const struct prog_dst_register *dstReg,
+ gl_prog_print_mode mode,
+ const struct gl_program *prog)
+{
+ fprintf(f, "%s%s",
+ reg_string((gl_register_file) dstReg->File,
+ dstReg->Index, mode, dstReg->RelAddr, prog),
+ _mesa_writemask_string(dstReg->WriteMask));
+
+ if (dstReg->CondMask != COND_TR) {
+ fprintf(f, " (%s.%s)",
+ _mesa_condcode_string(dstReg->CondMask),
+ _mesa_swizzle_string(dstReg->CondSwizzle,
+ GL_FALSE, GL_FALSE));
+ }
+
+#if 0
+ fprintf(f, "%s[%d]%s",
+ file_string((gl_register_file) dstReg->File, mode),
+ dstReg->Index,
+ _mesa_writemask_string(dstReg->WriteMask));
+#endif
+}
+
+
+static void
+fprint_src_reg(FILE *f,
+ const struct prog_src_register *srcReg,
+ gl_prog_print_mode mode,
+ const struct gl_program *prog)
+{
+ const char *abs = srcReg->Abs ? "|" : "";
+
+ fprintf(f, "%s%s%s%s",
+ abs,
+ reg_string((gl_register_file) srcReg->File,
+ srcReg->Index, mode, srcReg->RelAddr, prog),
+ _mesa_swizzle_string(srcReg->Swizzle,
+ srcReg->Negate, GL_FALSE),
+ abs);
+#if 0
+ fprintf(f, "%s[%d]%s",
+ file_string((gl_register_file) srcReg->File, mode),
+ srcReg->Index,
+ _mesa_swizzle_string(srcReg->Swizzle,
+ srcReg->Negate, GL_FALSE));
+#endif
+}
+
+
+static void
+fprint_comment(FILE *f, const struct prog_instruction *inst)
+{
+ if (inst->Comment)
+ fprintf(f, "; # %s\n", inst->Comment);
+ else
+ fprintf(f, ";\n");
+}
+
+
+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)
+{
+ GLuint j;
+
+ fprintf(f, "%s", opcode_string);
+ if (inst->CondUpdate)
+ fprintf(f, ".C");
+
+ /* frag prog only */
+ if (inst->SaturateMode == SATURATE_ZERO_ONE)
+ fprintf(f, "_SAT");
+
+ fprintf(f, " ");
+ if (inst->DstReg.File != PROGRAM_UNDEFINED) {
+ fprint_dst_reg(f, &inst->DstReg, mode, prog);
+ }
+ else {
+ fprintf(f, " ???");
+ }
+
+ if (numRegs > 0)
+ fprintf(f, ", ");
+
+ for (j = 0; j < numRegs; j++) {
+ fprint_src_reg(f, inst->SrcReg + j, mode, prog);
+ if (j + 1 < numRegs)
+ fprintf(f, ", ");
+ }
+
+ fprint_comment(f, inst);
+}
+
+
+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);
+}
+
+
+/**
+ * Print a single vertex/fragment program instruction.
+ */
+GLint
+_mesa_fprint_instruction_opt(FILE *f,
+ const struct prog_instruction *inst,
+ GLint indent,
+ gl_prog_print_mode mode,
+ const struct gl_program *prog)
+{
+ GLint i;
+
+ if (inst->Opcode == OPCODE_ELSE ||
+ inst->Opcode == OPCODE_ENDIF ||
+ inst->Opcode == OPCODE_ENDLOOP ||
+ inst->Opcode == OPCODE_ENDSUB) {
+ indent -= 3;
+ }
+ for (i = 0; i < indent; i++) {
+ fprintf(f, " ");
+ }
+
+ switch (inst->Opcode) {
+ case OPCODE_PRINT:
+ fprintf(f, "PRINT '%s'", (char *) inst->Data);
+ if (inst->SrcReg[0].File != PROGRAM_UNDEFINED) {
+ fprintf(f, ", ");
+ fprintf(f, "%s[%d]%s",
+ file_string((gl_register_file) inst->SrcReg[0].File,
+ mode),
+ inst->SrcReg[0].Index,
+ _mesa_swizzle_string(inst->SrcReg[0].Swizzle,
+ inst->SrcReg[0].Negate, GL_FALSE));
+ }
+ if (inst->Comment)
+ fprintf(f, " # %s", inst->Comment);
+ fprint_comment(f, inst);
+ break;
+ case OPCODE_SWZ:
+ fprintf(f, "SWZ");
+ if (inst->SaturateMode == SATURATE_ZERO_ONE)
+ fprintf(f, "_SAT");
+ fprintf(f, " ");
+ fprint_dst_reg(f, &inst->DstReg, mode, prog);
+ fprintf(f, ", %s[%d], %s",
+ file_string((gl_register_file) inst->SrcReg[0].File,
+ mode),
+ inst->SrcReg[0].Index,
+ _mesa_swizzle_string(inst->SrcReg[0].Swizzle,
+ inst->SrcReg[0].Negate, GL_TRUE));
+ fprint_comment(f, inst);
+ break;
+ case OPCODE_TEX:
+ case OPCODE_TXP:
+ case OPCODE_TXL:
+ case OPCODE_TXB:
+ fprintf(f, "%s", _mesa_opcode_string(inst->Opcode));
+ if (inst->SaturateMode == SATURATE_ZERO_ONE)
+ fprintf(f, "_SAT");
+ fprintf(f, " ");
+ fprint_dst_reg(f, &inst->DstReg, mode, prog);
+ fprintf(f, ", ");
+ fprint_src_reg(f, &inst->SrcReg[0], mode, prog);
+ fprintf(f, ", texture[%d], ", inst->TexSrcUnit);
+ switch (inst->TexSrcTarget) {
+ case TEXTURE_1D_INDEX: fprintf(f, "1D"); break;
+ case TEXTURE_2D_INDEX: fprintf(f, "2D"); break;
+ case TEXTURE_3D_INDEX: fprintf(f, "3D"); break;
+ case TEXTURE_CUBE_INDEX: fprintf(f, "CUBE"); break;
+ case TEXTURE_RECT_INDEX: fprintf(f, "RECT"); break;
+ case TEXTURE_1D_ARRAY_INDEX: fprintf(f, "1D_ARRAY"); break;
+ case TEXTURE_2D_ARRAY_INDEX: fprintf(f, "2D_ARRAY"); break;
+ default:
+ ;
+ }
+ if (inst->TexShadow)
+ fprintf(f, " SHADOW");
+ fprint_comment(f, inst);
+ break;
+
+ case OPCODE_KIL:
+ fprintf(f, "%s", _mesa_opcode_string(inst->Opcode));
+ fprintf(f, " ");
+ fprint_src_reg(f, &inst->SrcReg[0], mode, prog);
+ fprint_comment(f, inst);
+ break;
+ case OPCODE_KIL_NV:
+ fprintf(f, "%s", _mesa_opcode_string(inst->Opcode));
+ fprintf(f, " ");
+ fprintf(f, "%s.%s",
+ _mesa_condcode_string(inst->DstReg.CondMask),
+ _mesa_swizzle_string(inst->DstReg.CondSwizzle,
+ GL_FALSE, GL_FALSE));
+ fprint_comment(f, inst);
+ break;
+
+ case OPCODE_ARL:
+ fprintf(f, "ARL ");
+ fprint_dst_reg(f, &inst->DstReg, mode, prog);
+ fprintf(f, ", ");
+ fprint_src_reg(f, &inst->SrcReg[0], mode, prog);
+ fprint_comment(f, inst);
+ break;
+ case OPCODE_BRA:
+ fprintf(f, "BRA %d (%s%s)",
+ inst->BranchTarget,
+ _mesa_condcode_string(inst->DstReg.CondMask),
+ _mesa_swizzle_string(inst->DstReg.CondSwizzle, 0, GL_FALSE));
+ fprint_comment(f, inst);
+ break;
+ case OPCODE_IF:
+ if (inst->SrcReg[0].File != PROGRAM_UNDEFINED) {
+ /* Use ordinary register */
+ fprintf(f, "IF ");
+ fprint_src_reg(f, &inst->SrcReg[0], mode, prog);
+ fprintf(f, "; ");
+ }
+ else {
+ /* Use cond codes */
+ fprintf(f, "IF (%s%s);",
+ _mesa_condcode_string(inst->DstReg.CondMask),
+ _mesa_swizzle_string(inst->DstReg.CondSwizzle,
+ 0, GL_FALSE));
+ }
+ fprintf(f, " # (if false, goto %d)", inst->BranchTarget);
+ fprint_comment(f, inst);
+ return indent + 3;
+ case OPCODE_ELSE:
+ fprintf(f, "ELSE; # (goto %d)\n", inst->BranchTarget);
+ return indent + 3;
+ case OPCODE_ENDIF:
+ fprintf(f, "ENDIF;\n");
+ break;
+ case OPCODE_BGNLOOP:
+ fprintf(f, "BGNLOOP; # (end at %d)\n", inst->BranchTarget);
+ return indent + 3;
+ case OPCODE_ENDLOOP:
+ fprintf(f, "ENDLOOP; # (goto %d)\n", inst->BranchTarget);
+ break;
+ case OPCODE_BRK:
+ case OPCODE_CONT:
+ fprintf(f, "%s (%s%s); # (goto %d)",
+ _mesa_opcode_string(inst->Opcode),
+ _mesa_condcode_string(inst->DstReg.CondMask),
+ _mesa_swizzle_string(inst->DstReg.CondSwizzle, 0, GL_FALSE),
+ inst->BranchTarget);
+ fprint_comment(f, inst);
+ break;
+
+ case OPCODE_BGNSUB:
+ if (mode == PROG_PRINT_NV) {
+ fprintf(f, "%s:\n", inst->Comment); /* comment is label */
+ return indent;
+ }
+ else {
+ fprintf(f, "BGNSUB");
+ fprint_comment(f, inst);
+ return indent + 3;
+ }
+ case OPCODE_ENDSUB:
+ if (mode == PROG_PRINT_DEBUG) {
+ fprintf(f, "ENDSUB");
+ fprint_comment(f, inst);
+ }
+ break;
+ case OPCODE_CAL:
+ if (mode == PROG_PRINT_NV) {
+ fprintf(f, "CAL %s; # (goto %d)\n", inst->Comment, inst->BranchTarget);
+ }
+ else {
+ fprintf(f, "CAL %u", inst->BranchTarget);
+ fprint_comment(f, inst);
+ }
+ break;
+ case OPCODE_RET:
+ fprintf(f, "RET (%s%s)",
+ _mesa_condcode_string(inst->DstReg.CondMask),
+ _mesa_swizzle_string(inst->DstReg.CondSwizzle, 0, GL_FALSE));
+ fprint_comment(f, inst);
+ break;
+
+ case OPCODE_END:
+ fprintf(f, "END\n");
+ break;
+ case OPCODE_NOP:
+ if (mode == PROG_PRINT_DEBUG) {
+ fprintf(f, "NOP");
+ fprint_comment(f, inst);
+ }
+ else if (inst->Comment) {
+ /* ARB/NV extensions don't have NOP instruction */
+ fprintf(f, "# %s\n", inst->Comment);
+ }
+ break;
+ /* XXX may need other special-case instructions */
+ 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);
+ }
+ else {
+ fprint_alu_instruction(f, inst,
+ _mesa_opcode_string(inst->Opcode),
+ 3/*_mesa_num_inst_src_regs(inst->Opcode)*/,
+ mode, prog);
+ }
+ break;
+ }
+ return indent;
+}
+
+
+GLint
+_mesa_print_instruction_opt(const struct prog_instruction *inst,
+ GLint indent,
+ gl_prog_print_mode mode,
+ const struct gl_program *prog)
+{
+ return _mesa_fprint_instruction_opt(stderr, inst, indent, mode, prog);
+}
+
+
+void
+_mesa_print_instruction(const struct prog_instruction *inst)
+{
+ /* note: 4th param should be ignored for PROG_PRINT_DEBUG */
+ _mesa_fprint_instruction_opt(stdout, inst, 0, PROG_PRINT_DEBUG, NULL);
+}
+
+#if 0
+/**
+ * Print program, with options.
+ */
+void
+_mesa_fprint_program_opt(FILE *f,
+ const struct gl_program *prog,
+ gl_prog_print_mode mode,
+ GLboolean lineNumbers)
+{
+ GLuint i, indent = 0;
+
+ switch (prog->Target) {
+ case GL_VERTEX_PROGRAM_ARB:
+ if (mode == PROG_PRINT_ARB)
+ fprintf(f, "!!ARBvp1.0\n");
+ else if (mode == PROG_PRINT_NV)
+ fprintf(f, "!!VP1.0\n");
+ else
+ fprintf(f, "# Vertex Program/Shader %u\n", prog->Id);
+ break;
+ case GL_FRAGMENT_PROGRAM_ARB:
+ case GL_FRAGMENT_PROGRAM_NV:
+ if (mode == PROG_PRINT_ARB)
+ fprintf(f, "!!ARBfp1.0\n");
+ else if (mode == PROG_PRINT_NV)
+ fprintf(f, "!!FP1.0\n");
+ else
+ fprintf(f, "# Fragment Program/Shader %u\n", prog->Id);
+ break;
+ }
+
+ for (i = 0; i < prog->NumInstructions; i++) {
+ if (lineNumbers)
+ fprintf(f, "%3d: ", i);
+ indent = _mesa_fprint_instruction_opt(f, prog->Instructions + i,
+ indent, mode, prog);
+ }
+}
+
+
+/**
+ * Print program to stderr, default options.
+ */
+void
+_mesa_print_program(const struct gl_program *prog)
+{
+ _mesa_fprint_program_opt(stderr, prog, PROG_PRINT_DEBUG, GL_TRUE);
+}
+
+/**
+ * Return binary representation of 64-bit value (as a string).
+ * Insert a comma to separate each group of 8 bits.
+ * Note we return a pointer to local static storage so this is not
+ * re-entrant, etc.
+ * XXX move to imports.[ch] if useful elsewhere.
+ */
+static const char *
+binary(GLbitfield64 val)
+{
+ static char buf[80];
+ GLint i, len = 0;
+ for (i = 63; i >= 0; --i) {
+ if (val & (1ULL << i))
+ buf[len++] = '1';
+ else if (len > 0 || i == 0)
+ buf[len++] = '0';
+ if (len > 0 && ((i-1) % 8) == 7)
+ buf[len++] = ',';
+ }
+ buf[len] = '\0';
+ return buf;
+}
+
+
+/**
+ * Print all of a program's parameters/fields to given file.
+ */
+static void
+_mesa_fprint_program_parameters(FILE *f,
+ GLcontext *ctx,
+ const struct gl_program *prog)
+{
+ GLuint i;
+
+ fprintf(f, "InputsRead: 0x%x (0b%s)\n",
+ prog->InputsRead, binary(prog->InputsRead));
+ fprintf(f, "OutputsWritten: 0x%llx (0b%s)\n",
+ prog->OutputsWritten, binary(prog->OutputsWritten));
+ fprintf(f, "NumInstructions=%d\n", prog->NumInstructions);
+ fprintf(f, "NumTemporaries=%d\n", prog->NumTemporaries);
+ fprintf(f, "NumParameters=%d\n", prog->NumParameters);
+ fprintf(f, "NumAttributes=%d\n", prog->NumAttributes);
+ fprintf(f, "NumAddressRegs=%d\n", prog->NumAddressRegs);
+ fprintf(f, "SamplersUsed: 0x%x (0b%s)\n",
+ prog->SamplersUsed, binary(prog->SamplersUsed));
+ fprintf(f, "Samplers=[ ");
+ for (i = 0; i < MAX_SAMPLERS; i++) {
+ fprintf(f, "%d ", prog->SamplerUnits[i]);
+ }
+ fprintf(f, "]\n");
+
+ _mesa_load_state_parameters(ctx, prog->Parameters);
+
+#if 0
+ fprintf(f, "Local Params:\n");
+ for (i = 0; i < MAX_PROGRAM_LOCAL_PARAMS; i++){
+ const GLfloat *p = prog->LocalParams[i];
+ fprintf(f, "%2d: %f, %f, %f, %f\n", i, p[0], p[1], p[2], p[3]);
+ }
+#endif
+ _mesa_print_parameter_list(prog->Parameters);
+}
+
+
+/**
+ * Print all of a program's parameters/fields to stderr.
+ */
+void
+_mesa_print_program_parameters(GLcontext *ctx, const struct gl_program *prog)
+{
+ _mesa_fprint_program_parameters(stderr, ctx, prog);
+}
+
+
+/**
+ * Print a program parameter list to given file.
+ */
+static void
+_mesa_fprint_parameter_list(FILE *f,
+ const struct gl_program_parameter_list *list)
+{
+ const gl_prog_print_mode mode = PROG_PRINT_DEBUG;
+ GLuint i;
+
+ if (!list)
+ return;
+
+ if (0)
+ fprintf(f, "param list %p\n", (void *) list);
+ fprintf(f, "dirty state flags: 0x%x\n", list->StateFlags);
+ for (i = 0; i < list->NumParameters; i++){
+ struct gl_program_parameter *param = list->Parameters + i;
+ const GLfloat *v = list->ParameterValues[i];
+ fprintf(f, "param[%d] sz=%d %s %s = {%.3g, %.3g, %.3g, %.3g}",
+ i, param->Size,
+ file_string(list->Parameters[i].Type, mode),
+ param->Name, v[0], v[1], v[2], v[3]);
+ if (param->Flags & PROG_PARAM_BIT_CENTROID)
+ fprintf(f, " Centroid");
+ if (param->Flags & PROG_PARAM_BIT_INVARIANT)
+ fprintf(f, " Invariant");
+ if (param->Flags & PROG_PARAM_BIT_FLAT)
+ fprintf(f, " Flat");
+ if (param->Flags & PROG_PARAM_BIT_LINEAR)
+ fprintf(f, " Linear");
+ fprintf(f, "\n");
+ }
+}
+
+
+/**
+ * Print a program parameter list to stderr.
+ */
+void
+_mesa_print_parameter_list(const struct gl_program_parameter_list *list)
+{
+ _mesa_fprint_parameter_list(stderr, list);
+}
+
+
+/**
+ * Write shader and associated info to a file.
+ */
+void
+_mesa_write_shader_to_file(const struct gl_shader *shader)
+{
+ const char *type;
+ char filename[100];
+ FILE *f;
+
+ if (shader->Type == GL_FRAGMENT_SHADER)
+ type = "frag";
+ else
+ type = "vert";
+
+ snprintf(filename, sizeof(filename), "shader_%u.%s", shader->Name, type);
+ f = fopen(filename, "w");
+ if (!f) {
+ fprintf(stderr, "Unable to open %s for writing\n", filename);
+ return;
+ }
+
+ fprintf(f, "/* Shader %u source, checksum %u */\n", shader->Name, shader->SourceChecksum);
+ fputs(shader->Source, f);
+ fprintf(f, "\n");
+
+ fprintf(f, "/* Compile status: %s */\n",
+ shader->CompileStatus ? "ok" : "fail");
+ if (!shader->CompileStatus) {
+ fprintf(f, "/* Log Info: */\n");
+ fputs(shader->InfoLog, f);
+ }
+ else {
+ fprintf(f, "/* GPU code */\n");
+ fprintf(f, "/*\n");
+ _mesa_fprint_program_opt(f, shader->Program, PROG_PRINT_DEBUG, GL_TRUE);
+ fprintf(f, "*/\n");
+ fprintf(f, "/* Parameters / constants */\n");
+ fprintf(f, "/*\n");
+ _mesa_fprint_parameter_list(f, shader->Program->Parameters);
+ fprintf(f, "*/\n");
+ }
+
+ fclose(f);
+}
+
+
+/**
+ * Append the shader's uniform info/values to the shader log file.
+ * The log file will typically have been created by the
+ * _mesa_write_shader_to_file function.
+ */
+void
+_mesa_append_uniforms_to_file(const struct gl_shader *shader,
+ const struct gl_program *prog)
+{
+ const char *type;
+ char filename[100];
+ FILE *f;
+
+ if (shader->Type == GL_FRAGMENT_SHADER)
+ type = "frag";
+ else
+ type = "vert";
+
+ snprintf(filename, sizeof(filename), "shader_%u.%s", shader->Name, type);
+ f = fopen(filename, "a"); /* append */
+ if (!f) {
+ fprintf(stderr, "Unable to open %s for appending\n", filename);
+ return;
+ }
+
+ fprintf(f, "/* First-draw parameters / constants */\n");
+ fprintf(f, "/*\n");
+ _mesa_fprint_parameter_list(f, prog->Parameters);
+ fprintf(f, "*/\n");
+
+ fclose(f);
+}
+#endif
diff --git a/src/glsl/mesa/shader/prog_print.h b/src/glsl/mesa/shader/prog_print.h
new file mode 100644
index 00000000000..f0df77b5129
--- /dev/null
+++ b/src/glsl/mesa/shader/prog_print.h
@@ -0,0 +1,98 @@
+/*
+ * Mesa 3-D graphics library
+ * Version: 6.5.3
+ *
+ * Copyright (C) 1999-2007 Brian Paul All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included
+ * in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
+ * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+
+#ifndef PROG_PRINT_H
+#define PROG_PRINT_H
+
+
+/**
+ * The output style to use when printing programs.
+ */
+typedef enum {
+ PROG_PRINT_ARB,
+ PROG_PRINT_NV,
+ PROG_PRINT_DEBUG
+} gl_prog_print_mode;
+
+
+extern void
+_mesa_print_vp_inputs(GLbitfield inputs);
+
+extern void
+_mesa_print_fp_inputs(GLbitfield inputs);
+
+extern const char *
+_mesa_condcode_string(GLuint condcode);
+
+extern const char *
+_mesa_swizzle_string(GLuint swizzle, GLuint negateBase, GLboolean extended);
+
+const char *
+_mesa_writemask_string(GLuint writeMask);
+
+extern void
+_mesa_print_swizzle(GLuint swizzle);
+
+extern void
+_mesa_print_alu_instruction(const struct prog_instruction *inst,
+ const char *opcode_string, GLuint numRegs);
+
+extern void
+_mesa_print_instruction(const struct prog_instruction *inst);
+
+extern GLint
+_mesa_fprint_instruction_opt(FILE *f,
+ const struct prog_instruction *inst,
+ GLint indent,
+ gl_prog_print_mode mode,
+ const struct gl_program *prog);
+
+extern GLint
+_mesa_print_instruction_opt(const struct prog_instruction *inst, GLint indent,
+ gl_prog_print_mode mode,
+ const struct gl_program *prog);
+
+extern void
+_mesa_print_program(const struct gl_program *prog);
+
+extern void
+_mesa_fprint_program_opt(FILE *f,
+ const struct gl_program *prog, gl_prog_print_mode mode,
+ GLboolean lineNumbers);
+
+#if 0
+extern void
+_mesa_print_parameter_list(const struct gl_program_parameter_list *list);
+
+extern void
+_mesa_write_shader_to_file(const struct gl_shader *shader);
+
+extern void
+_mesa_append_uniforms_to_file(const struct gl_shader *shader,
+ const struct gl_program *prog);
+#endif
+
+
+#endif /* PROG_PRINT_H */
diff --git a/src/glsl/program.h b/src/glsl/program.h
new file mode 100644
index 00000000000..d21b04344cd
--- /dev/null
+++ b/src/glsl/program.h
@@ -0,0 +1,155 @@
+/*
+ * 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"
+
+/**
+ * Based on gl_shader in Mesa's mtypes.h.
+ */
+struct glsl_shader {
+ GLenum Type;
+ GLuint Name;
+ GLint RefCount;
+ GLboolean DeletePending;
+ GLboolean CompileStatus;
+ const GLchar *Source; /**< Source code string */
+ size_t SourceLen;
+ GLchar *InfoLog;
+
+ struct exec_list ir;
+ struct glsl_symbol_table *symbols;
+};
+
+
+typedef int gl_state_index;
+#define STATE_LENGTH 5
+
+/**
+ * Program parameter.
+ * Used by shaders/programs for uniforms, constants, varying vars, etc.
+ */
+struct gl_program_parameter
+{
+ const char *Name; /**< Null-terminated string */
+ gl_register_file Type; /**< PROGRAM_NAMED_PARAM, CONSTANT or STATE_VAR */
+ GLenum DataType; /**< GL_FLOAT, GL_FLOAT_VEC2, etc */
+ /**
+ * Number of components (1..4), or more.
+ * If the number of components is greater than 4,
+ * this parameter is part of a larger uniform like a GLSL matrix or array.
+ * The next program parameter's Size will be Size-4 of this parameter.
+ */
+ GLuint Size;
+ GLboolean Used; /**< Helper flag for GLSL uniform tracking */
+ GLboolean Initialized; /**< Has the ParameterValue[] been set? */
+ GLbitfield Flags; /**< Bitmask of PROG_PARAM_*_BIT */
+ /**
+ * A sequence of STATE_* tokens and integers to identify GL state.
+ */
+ gl_state_index StateIndexes[STATE_LENGTH];
+};
+
+
+/**
+ * List of gl_program_parameter instances.
+ */
+struct gl_program_parameter_list
+{
+ GLuint Size; /**< allocated size of Parameters, ParameterValues */
+ GLuint NumParameters; /**< number of parameters in arrays */
+ struct gl_program_parameter *Parameters; /**< Array [Size] */
+ GLfloat (*ParameterValues)[4]; /**< Array [Size] of GLfloat[4] */
+ GLbitfield StateFlags; /**< _NEW_* flags indicating which state changes
+ might invalidate ParameterValues[] */
+};
+
+
+/**
+ * Shader program uniform variable.
+ * The glGetUniformLocation() and glUniform() commands will use this
+ * information.
+ * Note that a uniform such as "binormal" might be used in both the
+ * vertex shader and the fragment shader. When glUniform() is called to
+ * set the uniform's value, it must be updated in both the vertex and
+ * fragment shaders. The uniform may be in different locations in the
+ * two shaders so we keep track of that here.
+ */
+struct gl_uniform
+{
+ const char *Name; /**< Null-terminated string */
+ GLint VertPos;
+ GLint FragPos;
+ GLboolean Initialized; /**< For debug. Has this uniform been set? */
+#if 0
+ GLenum DataType; /**< GL_FLOAT, GL_FLOAT_VEC2, etc */
+ GLuint Size; /**< Number of components (1..4) */
+#endif
+};
+
+
+/**
+ * List of gl_uniforms
+ */
+struct gl_uniform_list
+{
+ GLuint Size; /**< allocated size of Uniforms array */
+ GLuint NumUniforms; /**< number of uniforms in the array */
+ struct gl_uniform *Uniforms; /**< Array [Size] */
+};
+
+
+/**
+ * Based on gl_shader_program in Mesa's mtypes.h.
+ */
+struct glsl_program {
+ GLenum Type; /**< Always GL_SHADER_PROGRAM (internal token) */
+ GLuint Name; /**< aka handle or ID */
+ GLint RefCount; /**< Reference count */
+ GLboolean DeletePending;
+
+ GLuint NumShaders; /**< number of attached shaders */
+ struct glsl_shader **Shaders; /**< List of attached the shaders */
+
+ /**
+ * Per-stage shaders resulting from the first stage of linking.
+ */
+ /*@{*/
+ unsigned _NumLinkedShaders;
+ struct glsl_shader **_LinkedShaders;
+ /*@}*/
+
+ /** User-defined attribute bindings (glBindAttribLocation) */
+ struct gl_program_parameter_list *Attributes;
+
+ /* post-link info: */
+ struct gl_uniform_list *Uniforms;
+ struct gl_program_parameter_list *Varying;
+ GLboolean LinkStatus; /**< GL_LINK_STATUS */
+ GLboolean Validated;
+ GLboolean _Used; /**< Ever used for drawing? */
+ GLchar *InfoLog;
+};
+
+extern void
+link_shaders(struct glsl_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/symbol_table.c b/src/glsl/symbol_table.c
new file mode 100644
index 00000000000..0f0df7a261b
--- /dev/null
+++ b/src/glsl/symbol_table.c
@@ -0,0 +1,413 @@
+/*
+ * Copyright © 2008 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/imports.h"
+#include "symbol_table.h"
+#include "hash_table.h"
+
+struct symbol {
+ /**
+ * Link to the next symbol in the table with the same name
+ *
+ * The linked list of symbols with the same name is ordered by scope
+ * from inner-most to outer-most.
+ */
+ struct symbol *next_with_same_name;
+
+
+ /**
+ * Link to the next symbol in the table with the same scope
+ *
+ * The linked list of symbols with the same scope is unordered. Symbols
+ * in this list my have unique names.
+ */
+ struct symbol *next_with_same_scope;
+
+
+ /**
+ * Header information for the list of symbols with the same name.
+ */
+ struct symbol_header *hdr;
+
+
+ /**
+ * Name space of the symbol
+ *
+ * Name space are arbitrary user assigned integers. No two symbols can
+ * exist in the same name space at the same scope level.
+ */
+ int name_space;
+
+
+ /**
+ * Arbitrary user supplied data.
+ */
+ void *data;
+
+ /** Scope depth where this symbol was defined. */
+ unsigned depth;
+};
+
+
+/**
+ */
+struct symbol_header {
+ /** Linkage in list of all headers in a given symbol table. */
+ struct symbol_header *next;
+
+ /** Symbol name. */
+ const char *name;
+
+ /** Linked list of symbols with the same name. */
+ struct symbol *symbols;
+};
+
+
+/**
+ * Element of the scope stack.
+ */
+struct scope_level {
+ /** Link to next (inner) scope level. */
+ struct scope_level *next;
+
+ /** Linked list of symbols with the same scope. */
+ struct symbol *symbols;
+};
+
+
+/**
+ *
+ */
+struct _mesa_symbol_table {
+ /** Hash table containing all symbols in the symbol table. */
+ struct hash_table *ht;
+
+ /** Top of scope stack. */
+ struct scope_level *current_scope;
+
+ /** List of all symbol headers in the table. */
+ struct symbol_header *hdr;
+
+ /** Current scope depth. */
+ unsigned depth;
+};
+
+
+struct _mesa_symbol_table_iterator {
+ /**
+ * Name space of symbols returned by this iterator.
+ */
+ int name_space;
+
+
+ /**
+ * Currently iterated symbol
+ *
+ * The next call to \c _mesa_symbol_table_iterator_get will return this
+ * value. It will also update this value to the value that should be
+ * returned by the next call.
+ */
+ struct symbol *curr;
+};
+
+
+static void
+check_symbol_table(struct _mesa_symbol_table *table)
+{
+#if 1
+ struct scope_level *scope;
+
+ for (scope = table->current_scope; scope != NULL; scope = scope->next) {
+ struct symbol *sym;
+
+ for (sym = scope->symbols
+ ; sym != NULL
+ ; sym = sym->next_with_same_name) {
+ const struct symbol_header *const hdr = sym->hdr;
+ struct symbol *sym2;
+
+ for (sym2 = hdr->symbols
+ ; sym2 != NULL
+ ; sym2 = sym2->next_with_same_name) {
+ assert(sym2->hdr == hdr);
+ }
+ }
+ }
+#endif
+}
+
+void
+_mesa_symbol_table_pop_scope(struct _mesa_symbol_table *table)
+{
+ struct scope_level *const scope = table->current_scope;
+ struct symbol *sym = scope->symbols;
+
+ table->current_scope = scope->next;
+ table->depth--;
+
+ free(scope);
+
+ while (sym != NULL) {
+ struct symbol *const next = sym->next_with_same_scope;
+ struct symbol_header *const hdr = sym->hdr;
+
+ assert(hdr->symbols == sym);
+
+ hdr->symbols = sym->next_with_same_name;
+
+ free(sym);
+
+ sym = next;
+ }
+
+ check_symbol_table(table);
+}
+
+
+void
+_mesa_symbol_table_push_scope(struct _mesa_symbol_table *table)
+{
+ struct scope_level *const scope = calloc(1, sizeof(*scope));
+
+ scope->next = table->current_scope;
+ table->current_scope = scope;
+ table->depth++;
+}
+
+
+static struct symbol_header *
+find_symbol(struct _mesa_symbol_table *table, const char *name)
+{
+ return (struct symbol_header *) hash_table_find(table->ht, name);
+}
+
+
+struct _mesa_symbol_table_iterator *
+_mesa_symbol_table_iterator_ctor(struct _mesa_symbol_table *table,
+ int name_space, const char *name)
+{
+ struct _mesa_symbol_table_iterator *iter = calloc(1, sizeof(*iter));
+ struct symbol_header *const hdr = find_symbol(table, name);
+
+ iter->name_space = name_space;
+
+ if (hdr != NULL) {
+ struct symbol *sym;
+
+ 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)) {
+ iter->curr = sym;
+ break;
+ }
+ }
+ }
+
+ return iter;
+}
+
+
+void
+_mesa_symbol_table_iterator_dtor(struct _mesa_symbol_table_iterator *iter)
+{
+ free(iter);
+}
+
+
+void *
+_mesa_symbol_table_iterator_get(struct _mesa_symbol_table_iterator *iter)
+{
+ return (iter->curr == NULL) ? NULL : iter->curr->data;
+}
+
+
+int
+_mesa_symbol_table_iterator_next(struct _mesa_symbol_table_iterator *iter)
+{
+ struct symbol_header *hdr;
+
+ if (iter->curr == NULL) {
+ return 0;
+ }
+
+ hdr = iter->curr->hdr;
+ iter->curr = iter->curr->next_with_same_name;
+
+ while (iter->curr != NULL) {
+ assert(iter->curr->hdr == hdr);
+
+ if ((iter->name_space == -1)
+ || (iter->curr->name_space == iter->name_space)) {
+ return 1;
+ }
+
+ iter->curr = iter->curr->next_with_same_name;
+ }
+
+ return 0;
+}
+
+
+/**
+ * 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)
+{
+ struct symbol_header *const hdr = find_symbol(table, name);
+
+ if (hdr != NULL) {
+ struct symbol *sym;
+
+
+ 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)) {
+ return sym->data;
+ }
+ }
+ }
+
+ return NULL;
+}
+
+
+int
+_mesa_symbol_table_add_symbol(struct _mesa_symbol_table *table,
+ int name_space, const char *name,
+ void *declaration)
+{
+ struct symbol_header *hdr;
+ struct symbol *sym;
+
+ check_symbol_table(table);
+
+ hdr = find_symbol(table, name);
+
+ check_symbol_table(table);
+
+ if (hdr == NULL) {
+ hdr = calloc(1, sizeof(*hdr));
+ hdr->name = name;
+
+ hash_table_insert(table->ht, 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);
+
+ hdr->symbols = sym;
+ table->current_scope->symbols = sym;
+
+ check_symbol_table(table);
+ return 0;
+}
+
+
+struct _mesa_symbol_table *
+_mesa_symbol_table_ctor(void)
+{
+ struct _mesa_symbol_table *table = calloc(1, sizeof(*table));
+
+ if (table != NULL) {
+ table->ht = hash_table_ctor(32, hash_table_string_hash,
+ hash_table_string_compare);
+
+ _mesa_symbol_table_push_scope(table);
+ }
+
+ return table;
+}
+
+
+void
+_mesa_symbol_table_dtor(struct _mesa_symbol_table *table)
+{
+ struct symbol_header *hdr;
+ struct symbol_header *next;
+
+ while (table->current_scope != NULL) {
+ _mesa_symbol_table_pop_scope(table);
+ }
+
+ for (hdr = table->hdr; hdr != NULL; hdr = next) {
+ next = hdr->next;
+ _mesa_free(hdr);
+ }
+
+ hash_table_dtor(table->ht);
+ free(table);
+}
diff --git a/src/glsl/symbol_table.h b/src/glsl/symbol_table.h
new file mode 100644
index 00000000000..3a9994c1ac9
--- /dev/null
+++ b/src/glsl/symbol_table.h
@@ -0,0 +1,66 @@
+/*
+ * Copyright © 2008 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 MESA_SYMBOL_TABLE_H
+#define MESA_SYMBOL_TABLE_H
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+struct _mesa_symbol_table;
+struct _mesa_symbol_table_iterator;
+
+extern void _mesa_symbol_table_push_scope(struct _mesa_symbol_table *table);
+
+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);
+
+extern struct _mesa_symbol_table *_mesa_symbol_table_ctor(void);
+
+extern void _mesa_symbol_table_dtor(struct _mesa_symbol_table *);
+
+extern struct _mesa_symbol_table_iterator *_mesa_symbol_table_iterator_ctor(
+ struct _mesa_symbol_table *table, int name_space, const char *name);
+
+extern void _mesa_symbol_table_iterator_dtor(
+ struct _mesa_symbol_table_iterator *);
+
+extern void *_mesa_symbol_table_iterator_get(
+ struct _mesa_symbol_table_iterator *iter);
+
+extern int _mesa_symbol_table_iterator_next(
+ struct _mesa_symbol_table_iterator *iter);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* MESA_SYMBOL_TABLE_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;