$(DIRECTORY)/src/glsl/Makefile.template \
$(DIRECTORY)/src/glsl/SConscript \
$(DIRECTORY)/src/glsl/*/Makefile \
- $(DIRECTORY)/src/glsl/*/*.[ch] \
+ $(DIRECTORY)/src/glsl/*.[ch] \
+ $(DIRECTORY)/src/glsl/*.[cly]pp \
+ $(DIRECTORY)/src/glsl/README \
+ $(DIRECTORY)/src/glsl/glcpp/README \
$(DIRECTORY)/src/Makefile \
$(DIRECTORY)/src/mesa/Makefile* \
$(DIRECTORY)/src/mesa/sources.mak \
$(DIRECTORY)/src/mesa/depend \
$(MAIN_ES_FILES) \
$(DIRECTORY)/src/mesa/main/*.[chS] \
+ $(DIRECTORY)/src/mesa/main/*.cpp \
$(DIRECTORY)/src/mesa/main/descrip.mms \
$(DIRECTORY)/src/mesa/math/*.[ch] \
$(DIRECTORY)/src/mesa/math/descrip.mms \
$(DIRECTORY)/src/mesa/program/*.[chly] \
$(DIRECTORY)/src/mesa/program/Makefile \
$(DIRECTORY)/src/mesa/program/descrip.mms \
- $(DIRECTORY)/src/mesa/slang/*.[ch] \
- $(DIRECTORY)/src/mesa/slang/descrip.mms \
- $(DIRECTORY)/src/mesa/slang/library/*.gc \
- $(DIRECTORY)/src/mesa/slang/library/Makefile \
$(DIRECTORY)/src/mesa/swrast/*.[ch] \
$(DIRECTORY)/src/mesa/swrast/descrip.mms \
$(DIRECTORY)/src/mesa/swrast_setup/*.[ch] \
$(DIRECTORY)/src/mesa/drivers/x11/Makefile \
$(DIRECTORY)/src/mesa/drivers/x11/descrip.mms \
$(DIRECTORY)/src/mesa/drivers/x11/*.[ch] \
- $(DIRECTORY)/src/mesa/drivers/glslcompiler/Makefile \
- $(DIRECTORY)/src/mesa/drivers/glslcompiler/glslcompiler.c \
$(DIRECTORY)/src/mesa/ppc/*.[ch] \
$(DIRECTORY)/src/mesa/sparc/*.[chS] \
$(DIRECTORY)/src/mesa/x86/Makefile \
+++ /dev/null
-#src/glsl/cl/Makefile
-
-TOP = ../../..
-
-include $(TOP)/configs/current
-
-LIBNAME = glslcl
-
-C_SOURCES = \
- sl_cl_parse.c
-
-include ../Makefile.template
-
+++ /dev/null
-/**************************************************************************
- *
- * Copyright 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, 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 TUNGSTEN GRAPHICS AND/OR ITS 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.
- *
- **************************************************************************/
-
-#include <assert.h>
-#include <stdlib.h>
-#include <string.h>
-#include "../pp/sl_pp_public.h"
-#include "../pp/sl_pp_token.h"
-#include "sl_cl_parse.h"
-
-
-/* revision number - increment after each change affecting emitted output */
-#define REVISION 5
-
-/* external declaration (or precision or invariant stmt) */
-#define EXTERNAL_NULL 0
-#define EXTERNAL_FUNCTION_DEFINITION 1
-#define EXTERNAL_DECLARATION 2
-#define DEFAULT_PRECISION 3
-#define INVARIANT_STMT 4
-
-/* precision */
-#define PRECISION_DEFAULT 0
-#define PRECISION_LOW 1
-#define PRECISION_MEDIUM 2
-#define PRECISION_HIGH 3
-
-/* declaration */
-#define DECLARATION_FUNCTION_PROTOTYPE 1
-#define DECLARATION_INIT_DECLARATOR_LIST 2
-
-/* function type */
-#define FUNCTION_ORDINARY 0
-#define FUNCTION_CONSTRUCTOR 1
-#define FUNCTION_OPERATOR 2
-
-/* function call type */
-#define FUNCTION_CALL_NONARRAY 0
-#define FUNCTION_CALL_ARRAY 1
-
-/* operator type */
-#define OPERATOR_ADDASSIGN 1
-#define OPERATOR_SUBASSIGN 2
-#define OPERATOR_MULASSIGN 3
-#define OPERATOR_DIVASSIGN 4
-/*#define OPERATOR_MODASSIGN 5*/
-/*#define OPERATOR_LSHASSIGN 6*/
-/*#define OPERATOR_RSHASSIGN 7*/
-/*#define OPERATOR_ORASSIGN 8*/
-/*#define OPERATOR_XORASSIGN 9*/
-/*#define OPERATOR_ANDASSIGN 10*/
-#define OPERATOR_LOGICALXOR 11
-/*#define OPERATOR_BITOR 12*/
-/*#define OPERATOR_BITXOR 13*/
-/*#define OPERATOR_BITAND 14*/
-#define OPERATOR_LESS 15
-#define OPERATOR_GREATER 16
-#define OPERATOR_LESSEQUAL 17
-#define OPERATOR_GREATEREQUAL 18
-/*#define OPERATOR_LSHIFT 19*/
-/*#define OPERATOR_RSHIFT 20*/
-#define OPERATOR_MULTIPLY 21
-#define OPERATOR_DIVIDE 22
-/*#define OPERATOR_MODULUS 23*/
-#define OPERATOR_INCREMENT 24
-#define OPERATOR_DECREMENT 25
-#define OPERATOR_PLUS 26
-#define OPERATOR_MINUS 27
-/*#define OPERATOR_COMPLEMENT 28*/
-#define OPERATOR_NOT 29
-
-/* init declarator list */
-#define DECLARATOR_NONE 0
-#define DECLARATOR_NEXT 1
-
-/* variable declaration */
-#define VARIABLE_NONE 0
-#define VARIABLE_IDENTIFIER 1
-#define VARIABLE_INITIALIZER 2
-#define VARIABLE_ARRAY_EXPLICIT 3
-#define VARIABLE_ARRAY_UNKNOWN 4
-
-/* type qualifier */
-#define TYPE_QUALIFIER_NONE 0
-#define TYPE_QUALIFIER_CONST 1
-#define TYPE_QUALIFIER_ATTRIBUTE 2
-#define TYPE_QUALIFIER_VARYING 3
-#define TYPE_QUALIFIER_UNIFORM 4
-#define TYPE_QUALIFIER_FIXEDOUTPUT 5
-#define TYPE_QUALIFIER_FIXEDINPUT 6
-
-/* invariant qualifier */
-#define TYPE_VARIANT 90
-#define TYPE_INVARIANT 91
-
-/* centroid qualifier */
-#define TYPE_CENTER 95
-#define TYPE_CENTROID 96
-
-/* layout qualifiers */
-#define LAYOUT_QUALIFIER_NONE 0
-#define LAYOUT_QUALIFIER_UPPER_LEFT 1
-#define LAYOUT_QUALIFIER_PIXEL_CENTER_INTEGER 2
-
-/* type specifier */
-#define TYPE_SPECIFIER_VOID 0
-#define TYPE_SPECIFIER_BOOL 1
-#define TYPE_SPECIFIER_BVEC2 2
-#define TYPE_SPECIFIER_BVEC3 3
-#define TYPE_SPECIFIER_BVEC4 4
-#define TYPE_SPECIFIER_INT 5
-#define TYPE_SPECIFIER_IVEC2 6
-#define TYPE_SPECIFIER_IVEC3 7
-#define TYPE_SPECIFIER_IVEC4 8
-#define TYPE_SPECIFIER_FLOAT 9
-#define TYPE_SPECIFIER_VEC2 10
-#define TYPE_SPECIFIER_VEC3 11
-#define TYPE_SPECIFIER_VEC4 12
-#define TYPE_SPECIFIER_MAT2 13
-#define TYPE_SPECIFIER_MAT3 14
-#define TYPE_SPECIFIER_MAT4 15
-#define TYPE_SPECIFIER_SAMPLER1D 16
-#define TYPE_SPECIFIER_SAMPLER2D 17
-#define TYPE_SPECIFIER_SAMPLER3D 18
-#define TYPE_SPECIFIER_SAMPLERCUBE 19
-#define TYPE_SPECIFIER_SAMPLER1DSHADOW 20
-#define TYPE_SPECIFIER_SAMPLER2DSHADOW 21
-#define TYPE_SPECIFIER_SAMPLER2DRECT 22
-#define TYPE_SPECIFIER_SAMPLER2DRECTSHADOW 23
-#define TYPE_SPECIFIER_STRUCT 24
-#define TYPE_SPECIFIER_TYPENAME 25
-
-/* OpenGL 2.1 */
-#define TYPE_SPECIFIER_MAT23 26
-#define TYPE_SPECIFIER_MAT32 27
-#define TYPE_SPECIFIER_MAT24 28
-#define TYPE_SPECIFIER_MAT42 29
-#define TYPE_SPECIFIER_MAT34 30
-#define TYPE_SPECIFIER_MAT43 31
-
-/* GL_EXT_texture_array */
-#define TYPE_SPECIFIER_SAMPLER_1D_ARRAY 32
-#define TYPE_SPECIFIER_SAMPLER_2D_ARRAY 33
-#define TYPE_SPECIFIER_SAMPLER_1D_ARRAY_SHADOW 34
-#define TYPE_SPECIFIER_SAMPLER_2D_ARRAY_SHADOW 35
-
-/* type specifier array */
-#define TYPE_SPECIFIER_NONARRAY 0
-#define TYPE_SPECIFIER_ARRAY 1
-
-/* structure field */
-#define FIELD_NONE 0
-#define FIELD_NEXT 1
-#define FIELD_ARRAY 2
-
-/* operation */
-#define OP_END 0
-#define OP_BLOCK_BEGIN_NO_NEW_SCOPE 1
-#define OP_BLOCK_BEGIN_NEW_SCOPE 2
-#define OP_DECLARE 3
-#define OP_ASM 4
-#define OP_BREAK 5
-#define OP_CONTINUE 6
-#define OP_DISCARD 7
-#define OP_RETURN 8
-#define OP_EXPRESSION 9
-#define OP_IF 10
-#define OP_WHILE 11
-#define OP_DO 12
-#define OP_FOR 13
-#define OP_PUSH_VOID 14
-#define OP_PUSH_BOOL 15
-#define OP_PUSH_INT 16
-#define OP_PUSH_FLOAT 17
-#define OP_PUSH_IDENTIFIER 18
-#define OP_SEQUENCE 19
-#define OP_ASSIGN 20
-#define OP_ADDASSIGN 21
-#define OP_SUBASSIGN 22
-#define OP_MULASSIGN 23
-#define OP_DIVASSIGN 24
-/*#define OP_MODASSIGN 25*/
-/*#define OP_LSHASSIGN 26*/
-/*#define OP_RSHASSIGN 27*/
-/*#define OP_ORASSIGN 28*/
-/*#define OP_XORASSIGN 29*/
-/*#define OP_ANDASSIGN 30*/
-#define OP_SELECT 31
-#define OP_LOGICALOR 32
-#define OP_LOGICALXOR 33
-#define OP_LOGICALAND 34
-/*#define OP_BITOR 35*/
-/*#define OP_BITXOR 36*/
-/*#define OP_BITAND 37*/
-#define OP_EQUAL 38
-#define OP_NOTEQUAL 39
-#define OP_LESS 40
-#define OP_GREATER 41
-#define OP_LESSEQUAL 42
-#define OP_GREATEREQUAL 43
-/*#define OP_LSHIFT 44*/
-/*#define OP_RSHIFT 45*/
-#define OP_ADD 46
-#define OP_SUBTRACT 47
-#define OP_MULTIPLY 48
-#define OP_DIVIDE 49
-/*#define OP_MODULUS 50*/
-#define OP_PREINCREMENT 51
-#define OP_PREDECREMENT 52
-#define OP_PLUS 53
-#define OP_MINUS 54
-/*#define OP_COMPLEMENT 55*/
-#define OP_NOT 56
-#define OP_SUBSCRIPT 57
-#define OP_CALL 58
-#define OP_FIELD 59
-#define OP_POSTINCREMENT 60
-#define OP_POSTDECREMENT 61
-#define OP_PRECISION 62
-#define OP_METHOD 63
-
-/* parameter qualifier */
-#define PARAM_QUALIFIER_IN 0
-#define PARAM_QUALIFIER_OUT 1
-#define PARAM_QUALIFIER_INOUT 2
-#define PARAM_QUALIFIER_NONE 3
-
-/* function parameter */
-#define PARAMETER_NONE 0
-#define PARAMETER_NEXT 1
-
-/* function parameter array presence */
-#define PARAMETER_ARRAY_NOT_PRESENT 0
-#define PARAMETER_ARRAY_PRESENT 1
-
-
-struct parse_dict {
- int _void;
- int _float;
- int _int;
- int _bool;
- int vec2;
- int vec3;
- int vec4;
- int bvec2;
- int bvec3;
- int bvec4;
- int ivec2;
- int ivec3;
- int ivec4;
- int mat2;
- int mat3;
- int mat4;
- int mat2x3;
- int mat3x2;
- int mat2x4;
- int mat4x2;
- int mat3x4;
- int mat4x3;
- int sampler1D;
- int sampler2D;
- int sampler3D;
- int samplerCube;
- int sampler1DShadow;
- int sampler2DShadow;
- int sampler2DRect;
- int sampler2DRectShadow;
- int sampler1DArray;
- int sampler2DArray;
- int sampler1DArrayShadow;
- int sampler2DArrayShadow;
-
- int invariant;
-
- int centroid;
-
- int precision;
- int lowp;
- int mediump;
- int highp;
-
- int _const;
- int attribute;
- int varying;
- int uniform;
- int __fixed_output;
- int __fixed_input;
-
- int in;
- int out;
- int inout;
-
- int layout;
- int origin_upper_left;
- int pixel_center_integer;
-
- int _struct;
-
- int __constructor;
- int __operator;
- int ___asm;
-
- int _if;
- int _else;
- int _for;
- int _while;
- int _do;
-
- int _continue;
- int _break;
- int _return;
- int discard;
-
- int _false;
- int _true;
-
- int all;
- int _GL_ARB_fragment_coord_conventions;
- int _GL_ARB_texture_rectangle;
-};
-
-
-struct parse_context {
- struct sl_pp_context *context;
-
- struct parse_dict dict;
-
- struct sl_pp_token_info *tokens;
- unsigned int tokens_read;
- unsigned int tokens_cap;
-
- unsigned char *out_buf;
- unsigned int out_cap;
-
- unsigned int shader_type;
- unsigned int parsing_builtin;
-
- unsigned int fragment_coord_conventions:1;
- unsigned int texture_rectangle:1;
-
- char error[256];
- int process_error;
-};
-
-
-struct parse_state {
- unsigned int in;
- unsigned int out;
-};
-
-
-static unsigned int
-_emit(struct parse_context *ctx,
- unsigned int *out,
- unsigned char b)
-{
- if (*out == ctx->out_cap) {
- ctx->out_cap += 4096;
- ctx->out_buf = (unsigned char *)realloc(ctx->out_buf, ctx->out_cap * sizeof(unsigned char));
- }
- ctx->out_buf[*out] = b;
- return (*out)++;
-}
-
-
-static void
-_update(struct parse_context *ctx,
- unsigned int out,
- unsigned char b)
-{
- ctx->out_buf[out] = b;
-}
-
-
-static void
-_error(struct parse_context *ctx,
- const char *msg)
-{
- if (ctx->error[0] == '\0') {
- strncpy(ctx->error, msg, sizeof(ctx->error) - 1);
- ctx->error[sizeof(ctx->error) - 1] = '\0';
- }
-}
-
-
-static const struct sl_pp_token_info *
-_fetch_token(struct parse_context *ctx,
- unsigned int pos)
-{
- if (ctx->process_error) {
- return NULL;
- }
-
- while (pos >= ctx->tokens_read) {
- if (ctx->tokens_read == ctx->tokens_cap) {
- ctx->tokens_cap += 1024;
- ctx->tokens = realloc(ctx->tokens,
- ctx->tokens_cap * sizeof(struct sl_pp_token_info));
- if (!ctx->tokens) {
- _error(ctx, "out of memory");
- ctx->process_error = 1;
- return NULL;
- }
- }
- if (sl_pp_process_get(ctx->context, &ctx->tokens[ctx->tokens_read])) {
- _error(ctx, sl_pp_context_error_message(ctx->context));
- ctx->process_error = 1;
- return NULL;
- }
- switch (ctx->tokens[ctx->tokens_read].token) {
- case SL_PP_COMMA:
- case SL_PP_SEMICOLON:
- case SL_PP_LBRACE:
- case SL_PP_RBRACE:
- case SL_PP_LPAREN:
- case SL_PP_RPAREN:
- case SL_PP_LBRACKET:
- case SL_PP_RBRACKET:
- case SL_PP_DOT:
- case SL_PP_INCREMENT:
- case SL_PP_ADDASSIGN:
- case SL_PP_PLUS:
- case SL_PP_DECREMENT:
- case SL_PP_SUBASSIGN:
- case SL_PP_MINUS:
- case SL_PP_BITNOT:
- case SL_PP_NOTEQUAL:
- case SL_PP_NOT:
- case SL_PP_MULASSIGN:
- case SL_PP_STAR:
- case SL_PP_DIVASSIGN:
- case SL_PP_SLASH:
- case SL_PP_MODASSIGN:
- case SL_PP_MODULO:
- case SL_PP_LSHIFTASSIGN:
- case SL_PP_LSHIFT:
- case SL_PP_LESSEQUAL:
- case SL_PP_LESS:
- case SL_PP_RSHIFTASSIGN:
- case SL_PP_RSHIFT:
- case SL_PP_GREATEREQUAL:
- case SL_PP_GREATER:
- case SL_PP_EQUAL:
- case SL_PP_ASSIGN:
- case SL_PP_AND:
- case SL_PP_BITANDASSIGN:
- case SL_PP_BITAND:
- case SL_PP_XOR:
- case SL_PP_BITXORASSIGN:
- case SL_PP_BITXOR:
- case SL_PP_OR:
- case SL_PP_BITORASSIGN:
- case SL_PP_BITOR:
- case SL_PP_QUESTION:
- case SL_PP_COLON:
- case SL_PP_IDENTIFIER:
- case SL_PP_UINT:
- case SL_PP_FLOAT:
- case SL_PP_EXTENSION_REQUIRE:
- case SL_PP_EXTENSION_ENABLE:
- case SL_PP_EXTENSION_WARN:
- case SL_PP_EXTENSION_DISABLE:
- case SL_PP_EOF:
- ctx->tokens_read++;
- break;
- default:
- ; /* no-op */
- }
- }
- return &ctx->tokens[pos];
-}
-
-
-/**
- * Try to parse/match a particular token.
- * \return 0 for success, -1 for error.
- */
-static int
-_parse_token(struct parse_context *ctx,
- enum sl_pp_token token,
- struct parse_state *ps)
-{
- const struct sl_pp_token_info *input = _fetch_token(ctx, ps->in);
-
- if (input && input->token == token) {
- ps->in++;
- return 0;
- }
- return -1;
-}
-
-
-/**
- * Try to parse an identifer.
- * \return 0 for success, -1 for error
- */
-static int
-_parse_id(struct parse_context *ctx,
- int id,
- struct parse_state *ps)
-{
- const struct sl_pp_token_info *input = _fetch_token(ctx, ps->in);
-
- if (input && input->token == SL_PP_IDENTIFIER && input->data.identifier == id) {
- ps->in++;
- return 0;
- }
- return -1;
-}
-
-
-static int
-_parse_identifier(struct parse_context *ctx,
- struct parse_state *ps)
-{
- const struct sl_pp_token_info *input = _fetch_token(ctx, ps->in);
-
- if (input && input->token == SL_PP_IDENTIFIER) {
- const char *cstr = sl_pp_context_cstr(ctx->context, input->data.identifier);
-
- do {
- _emit(ctx, &ps->out, *cstr);
- } while (*cstr++);
- ps->in++;
- return 0;
- }
- return -1;
-}
-
-
-static int
-_parse_float(struct parse_context *ctx,
- struct parse_state *ps)
-{
- const struct sl_pp_token_info *input = _fetch_token(ctx, ps->in);
-
- if (input && input->token == SL_PP_FLOAT) {
- const char *cstr = sl_pp_context_cstr(ctx->context, input->data._float);
-
- _emit(ctx, &ps->out, 1);
- do {
- _emit(ctx, &ps->out, *cstr);
- } while (*cstr++);
- ps->in++;
- return 0;
- }
- return -1;
-}
-
-
-static int
-_parse_uint(struct parse_context *ctx,
- struct parse_state *ps)
-{
- const struct sl_pp_token_info *input = _fetch_token(ctx, ps->in);
-
- if (input && input->token == SL_PP_UINT) {
- const char *cstr = sl_pp_context_cstr(ctx->context, input->data._uint);
-
- _emit(ctx, &ps->out, 1);
- do {
- _emit(ctx, &ps->out, *cstr);
- } while (*cstr++);
- ps->in++;
- return 0;
- }
- return -1;
-}
-
-
-/**************************************/
-
-
-static int
-_parse_unary_expression(struct parse_context *ctx,
- struct parse_state *ps);
-
-static int
-_parse_conditional_expression(struct parse_context *ctx,
- struct parse_state *ps);
-
-
-static int
-_parse_constant_expression(struct parse_context *ctx,
- struct parse_state *ps);
-
-
-static int
-_parse_primary_expression(struct parse_context *ctx,
- struct parse_state *ps);
-
-
-static int
-_parse_statement(struct parse_context *ctx,
- struct parse_state *ps);
-
-
-static int
-_parse_type_specifier(struct parse_context *ctx,
- struct parse_state *ps);
-
-
-static int
-_parse_declaration(struct parse_context *ctx,
- struct parse_state *ps);
-
-
-static int
-_parse_statement_list(struct parse_context *ctx,
- struct parse_state *ps);
-
-
-static int
-_parse_assignment_expression(struct parse_context *ctx,
- struct parse_state *ps);
-
-
-static int
-_parse_precision(struct parse_context *ctx,
- struct parse_state *ps);
-
-
-static int
-_parse_overriden_operator(struct parse_context *ctx,
- struct parse_state *ps)
-{
- unsigned int op;
-
- if (_parse_token(ctx, SL_PP_INCREMENT, ps) == 0) {
- op = OPERATOR_INCREMENT;
- } else if (_parse_token(ctx, SL_PP_ADDASSIGN, ps) == 0) {
- op = OPERATOR_ADDASSIGN;
- } else if (_parse_token(ctx, SL_PP_PLUS, ps) == 0) {
- op = OPERATOR_PLUS;
- } else if (_parse_token(ctx, SL_PP_DECREMENT, ps) == 0) {
- op = OPERATOR_DECREMENT;
- } else if (_parse_token(ctx, SL_PP_SUBASSIGN, ps) == 0) {
- op = OPERATOR_SUBASSIGN;
- } else if (_parse_token(ctx, SL_PP_MINUS, ps) == 0) {
- op = OPERATOR_MINUS;
- } else if (_parse_token(ctx, SL_PP_NOT, ps) == 0) {
- op = OPERATOR_NOT;
- } else if (_parse_token(ctx, SL_PP_MULASSIGN, ps) == 0) {
- op = OPERATOR_MULASSIGN;
- } else if (_parse_token(ctx, SL_PP_STAR, ps) == 0) {
- op = OPERATOR_MULTIPLY;
- } else if (_parse_token(ctx, SL_PP_DIVASSIGN, ps) == 0) {
- op = OPERATOR_DIVASSIGN;
- } else if (_parse_token(ctx, SL_PP_SLASH, ps) == 0) {
- op = OPERATOR_DIVIDE;
- } else if (_parse_token(ctx, SL_PP_LESSEQUAL, ps) == 0) {
- op = OPERATOR_LESSEQUAL;
- } else if (_parse_token(ctx, SL_PP_LESS, ps) == 0) {
- op = OPERATOR_LESS;
- } else if (_parse_token(ctx, SL_PP_GREATEREQUAL, ps) == 0) {
- op = OPERATOR_GREATEREQUAL;
- } else if (_parse_token(ctx, SL_PP_GREATER, ps) == 0) {
- op = OPERATOR_GREATER;
- } else if (_parse_token(ctx, SL_PP_XOR, ps) == 0) {
- op = OPERATOR_LOGICALXOR;
- } else {
- return -1;
- }
-
- _emit(ctx, &ps->out, op);
- return 0;
-}
-
-
-static int
-_parse_function_decl_identifier(struct parse_context *ctx,
- struct parse_state *ps)
-{
- struct parse_state p = *ps;
- unsigned int e = _emit(ctx, &p.out, 0);
-
- if (ctx->parsing_builtin && _parse_id(ctx, ctx->dict.__constructor, &p) == 0) {
- _update(ctx, e, FUNCTION_CONSTRUCTOR);
- *ps = p;
- return 0;
- }
-
- if (ctx->parsing_builtin && _parse_id(ctx, ctx->dict.__operator, &p) == 0) {
- _update(ctx, e, FUNCTION_OPERATOR);
- if (_parse_overriden_operator(ctx, &p) == 0) {
- *ps = p;
- return 0;
- }
- return -1;
- }
-
- if (_parse_identifier(ctx, &p) == 0) {
- _update(ctx, e, FUNCTION_ORDINARY);
- *ps = p;
- return 0;
- }
-
- return -1;
-}
-
-
-static int
-_parse_invariant_qualifier(struct parse_context *ctx,
- struct parse_state *ps)
-{
- if (_parse_id(ctx, ctx->dict.invariant, ps)) {
- return -1;
- }
- _emit(ctx, &ps->out, TYPE_INVARIANT);
- return 0;
-}
-
-
-static int
-_parse_centroid_qualifier(struct parse_context *ctx,
- struct parse_state *ps)
-{
- if (_parse_id(ctx, ctx->dict.centroid, ps)) {
- return -1;
- }
- _emit(ctx, &ps->out, TYPE_CENTROID);
- return 0;
-}
-
-
-static int
-_parse_layout_qualifier(struct parse_context *ctx,
- struct parse_state *ps)
-{
- if (_parse_id(ctx, ctx->dict.layout, ps) == 0) {
- if (!ctx->fragment_coord_conventions) {
- _error(ctx, "GL_ARB_fragment_coord_conventions extension must be enabled "
- "in order to use a layout qualifier");
- return -1;
- }
-
- /* Layout qualifiers are only defined for fragment shaders,
- * so do an early check.
- */
- if (ctx->shader_type != 1) {
- _error(ctx, "layout qualifiers are only valid for fragment shaders");
- return -1;
- }
-
- /* start of a parenthesised list of layout qualifiers */
-
- if (_parse_token(ctx, SL_PP_LPAREN, ps)) {
- _error(ctx, "expected `('");
- return -1;
- }
-
- /* parse comma-separated ID list */
- while (1) {
- if (_parse_id(ctx, ctx->dict.origin_upper_left, ps) == 0) {
- _emit(ctx, &ps->out, LAYOUT_QUALIFIER_UPPER_LEFT);
- }
- else if (_parse_id(ctx, ctx->dict.pixel_center_integer, ps) == 0) {
- _emit(ctx, &ps->out, LAYOUT_QUALIFIER_PIXEL_CENTER_INTEGER);
- }
- else {
- _error(ctx, "expected a layout qualifier name");
- return -1;
- }
-
- if (_parse_token(ctx, SL_PP_RPAREN, ps) == 0) {
- /* all done */
- break;
- }
- else if (_parse_token(ctx, SL_PP_COMMA, ps) == 0) {
- /* another layout qualifier is coming */
- }
- else {
- _error(ctx, "expected `,' or `)'");
- return -1;
- }
- }
- }
-
- return 0;
-}
-
-
-static int
-_parse_storage_qualifier(struct parse_context *ctx,
- struct parse_state *ps)
-{
- struct parse_state p = *ps;
- const struct sl_pp_token_info *input = _fetch_token(ctx, p.in);
- unsigned int e = _emit(ctx, &p.out, 0);
- int id;
-
- if (!input || input->token != SL_PP_IDENTIFIER) {
- return -1;
- }
- id = input->data.identifier;
-
- if (id == ctx->dict._const) {
- _update(ctx, e, TYPE_QUALIFIER_CONST);
- } else if (ctx->shader_type == 2 && id == ctx->dict.attribute) {
- _update(ctx, e, TYPE_QUALIFIER_ATTRIBUTE);
- } else if (id == ctx->dict.varying) {
- _update(ctx, e, TYPE_QUALIFIER_VARYING);
- } else if (id == ctx->dict.uniform) {
- _update(ctx, e, TYPE_QUALIFIER_UNIFORM);
- } else if (ctx->parsing_builtin && id == ctx->dict.__fixed_output) {
- _update(ctx, e, TYPE_QUALIFIER_FIXEDOUTPUT);
- } else if (ctx->parsing_builtin && id == ctx->dict.__fixed_input) {
- _update(ctx, e, TYPE_QUALIFIER_FIXEDINPUT);
- } else {
- return -1;
- }
- _parse_token(ctx, SL_PP_IDENTIFIER, &p);
- *ps = p;
- return 0;
-}
-
-static int
-_parse_struct_declarator(struct parse_context *ctx,
- struct parse_state *ps)
-{
- struct parse_state p = *ps;
- unsigned int e;
-
- if (_parse_identifier(ctx, &p)) {
- return -1;
- }
- e = _emit(ctx, &p.out, FIELD_NONE);
- *ps = p;
-
- if (_parse_token(ctx, SL_PP_LBRACKET, &p)) {
- return 0;
- }
- if (_parse_constant_expression(ctx, &p)) {
- _error(ctx, "expected constant integral expression");
- return -1;
- }
- if (_parse_token(ctx, SL_PP_RBRACKET, &p)) {
- _error(ctx, "expected `]'");
- return -1;
- }
- _update(ctx, e, FIELD_ARRAY);
- *ps = p;
- return 0;
-}
-
-
-static int
-_parse_struct_declarator_list(struct parse_context *ctx,
- struct parse_state *ps)
-{
- struct parse_state p = *ps;
-
- if (_parse_struct_declarator(ctx, &p)) {
- return -1;
- }
-
- for (;;) {
- *ps = p;
- _emit(ctx, &p.out, FIELD_NEXT);
- if (_parse_token(ctx, SL_PP_COMMA, &p)) {
- return 0;
- }
- if (_parse_struct_declarator(ctx, &p)) {
- return 0;
- }
- }
-}
-
-
-static int
-_parse_struct_declaration(struct parse_context *ctx,
- struct parse_state *ps)
-{
- struct parse_state p = *ps;
-
- if (_parse_type_specifier(ctx, &p)) {
- return -1;
- }
- if (_parse_struct_declarator_list(ctx, &p)) {
- return -1;
- }
- if (_parse_token(ctx, SL_PP_SEMICOLON, &p)) {
- return -1;
- }
- _emit(ctx, &p.out, FIELD_NONE);
- *ps = p;
- return 0;
-}
-
-
-static int
-_parse_struct_declaration_list(struct parse_context *ctx,
- struct parse_state *ps)
-{
- struct parse_state p = *ps;
-
- if (_parse_struct_declaration(ctx, &p)) {
- return -1;
- }
-
- for (;;) {
- *ps = p;
- _emit(ctx, &p.out, FIELD_NEXT);
- if (_parse_struct_declaration(ctx, &p)) {
- return 0;
- }
- }
-}
-
-
-static int
-_parse_struct_specifier(struct parse_context *ctx,
- struct parse_state *ps)
-{
- struct parse_state p = *ps;
-
- if (_parse_id(ctx, ctx->dict._struct, &p)) {
- return -1;
- }
- if (_parse_identifier(ctx, &p)) {
- _emit(ctx, &p.out, '\0');
- }
- if (_parse_token(ctx, SL_PP_LBRACE, &p)) {
- _error(ctx, "expected `{'");
- return -1;
- }
- if (_parse_struct_declaration_list(ctx, &p)) {
- return -1;
- }
- if (_parse_token(ctx, SL_PP_RBRACE, &p)) {
- return -1;
- }
- _emit(ctx, &p.out, FIELD_NONE);
- *ps = p;
- return 0;
-}
-
-
-static int
-_parse_type_specifier_nonarray(struct parse_context *ctx,
- struct parse_state *ps)
-{
- struct parse_state p = *ps;
- unsigned int e = _emit(ctx, &p.out, 0);
- const struct sl_pp_token_info *input;
- int id;
-
- if (_parse_struct_specifier(ctx, &p) == 0) {
- _update(ctx, e, TYPE_SPECIFIER_STRUCT);
- *ps = p;
- return 0;
- }
-
- input = _fetch_token(ctx, p.in);
- if (!input || input->token != SL_PP_IDENTIFIER) {
- return -1;
- }
- id = input->data.identifier;
-
- if (id == ctx->dict._void) {
- _update(ctx, e, TYPE_SPECIFIER_VOID);
- } else if (id == ctx->dict._float) {
- _update(ctx, e, TYPE_SPECIFIER_FLOAT);
- } else if (id == ctx->dict._int) {
- _update(ctx, e, TYPE_SPECIFIER_INT);
- } else if (id == ctx->dict._bool) {
- _update(ctx, e, TYPE_SPECIFIER_BOOL);
- } else if (id == ctx->dict.vec2) {
- _update(ctx, e, TYPE_SPECIFIER_VEC2);
- } else if (id == ctx->dict.vec3) {
- _update(ctx, e, TYPE_SPECIFIER_VEC3);
- } else if (id == ctx->dict.vec4) {
- _update(ctx, e, TYPE_SPECIFIER_VEC4);
- } else if (id == ctx->dict.bvec2) {
- _update(ctx, e, TYPE_SPECIFIER_BVEC2);
- } else if (id == ctx->dict.bvec3) {
- _update(ctx, e, TYPE_SPECIFIER_BVEC3);
- } else if (id == ctx->dict.bvec4) {
- _update(ctx, e, TYPE_SPECIFIER_BVEC4);
- } else if (id == ctx->dict.ivec2) {
- _update(ctx, e, TYPE_SPECIFIER_IVEC2);
- } else if (id == ctx->dict.ivec3) {
- _update(ctx, e, TYPE_SPECIFIER_IVEC3);
- } else if (id == ctx->dict.ivec4) {
- _update(ctx, e, TYPE_SPECIFIER_IVEC4);
- } else if (id == ctx->dict.mat2) {
- _update(ctx, e, TYPE_SPECIFIER_MAT2);
- } else if (id == ctx->dict.mat3) {
- _update(ctx, e, TYPE_SPECIFIER_MAT3);
- } else if (id == ctx->dict.mat4) {
- _update(ctx, e, TYPE_SPECIFIER_MAT4);
- } else if (id == ctx->dict.mat2x3) {
- _update(ctx, e, TYPE_SPECIFIER_MAT23);
- } else if (id == ctx->dict.mat3x2) {
- _update(ctx, e, TYPE_SPECIFIER_MAT32);
- } else if (id == ctx->dict.mat2x4) {
- _update(ctx, e, TYPE_SPECIFIER_MAT24);
- } else if (id == ctx->dict.mat4x2) {
- _update(ctx, e, TYPE_SPECIFIER_MAT42);
- } else if (id == ctx->dict.mat3x4) {
- _update(ctx, e, TYPE_SPECIFIER_MAT34);
- } else if (id == ctx->dict.mat4x3) {
- _update(ctx, e, TYPE_SPECIFIER_MAT43);
- } else if (id == ctx->dict.sampler1D) {
- _update(ctx, e, TYPE_SPECIFIER_SAMPLER1D);
- } else if (id == ctx->dict.sampler2D) {
- _update(ctx, e, TYPE_SPECIFIER_SAMPLER2D);
- } else if (id == ctx->dict.sampler3D) {
- _update(ctx, e, TYPE_SPECIFIER_SAMPLER3D);
- } else if (id == ctx->dict.samplerCube) {
- _update(ctx, e, TYPE_SPECIFIER_SAMPLERCUBE);
- } else if (id == ctx->dict.sampler1DShadow) {
- _update(ctx, e, TYPE_SPECIFIER_SAMPLER1DSHADOW);
- } else if (id == ctx->dict.sampler2DShadow) {
- _update(ctx, e, TYPE_SPECIFIER_SAMPLER2DSHADOW);
- } else if (id == ctx->dict.sampler2DRect) {
- if (!ctx->texture_rectangle) {
- _error(ctx, "GL_ARB_texture_rectangle extension must be enabled "
- "in order to use a rect sampler");
- return -1;
- }
- _update(ctx, e, TYPE_SPECIFIER_SAMPLER2DRECT);
- } else if (id == ctx->dict.sampler2DRectShadow) {
- if (!ctx->texture_rectangle) {
- _error(ctx, "GL_ARB_texture_rectangle extension must be enabled "
- "in order to use a rect sampler");
- return -1;
- }
- _update(ctx, e, TYPE_SPECIFIER_SAMPLER2DRECTSHADOW);
- } else if (id == ctx->dict.sampler1DArray) {
- _update(ctx, e, TYPE_SPECIFIER_SAMPLER_1D_ARRAY);
- } else if (id == ctx->dict.sampler2DArray) {
- /* XXX check for GL_EXT_texture_array */
- _update(ctx, e, TYPE_SPECIFIER_SAMPLER_2D_ARRAY);
- } else if (id == ctx->dict.sampler1DArrayShadow) {
- _update(ctx, e, TYPE_SPECIFIER_SAMPLER_1D_ARRAY_SHADOW);
- } else if (id == ctx->dict.sampler2DArrayShadow) {
- _update(ctx, e, TYPE_SPECIFIER_SAMPLER_2D_ARRAY_SHADOW);
- } else if (_parse_identifier(ctx, &p) == 0) {
- _update(ctx, e, TYPE_SPECIFIER_TYPENAME);
- *ps = p;
- return 0;
- } else {
- return -1;
- }
-
- _parse_token(ctx, SL_PP_IDENTIFIER, &p);
- *ps = p;
- return 0;
-}
-
-
-static int
-_parse_type_specifier_array(struct parse_context *ctx,
- struct parse_state *ps)
-{
- struct parse_state p = *ps;
-
- if (_parse_token(ctx, SL_PP_LBRACKET, &p)) {
- return -1;
- }
- if (_parse_constant_expression(ctx, &p)) {
- _error(ctx, "expected constant integral expression");
- return -1;
- }
- if (_parse_token(ctx, SL_PP_RBRACKET, &p)) {
- _error(ctx, "expected `]'");
- return -1;
- }
- *ps = p;
- return 0;
-}
-
-
-static int
-_parse_type_specifier(struct parse_context *ctx,
- struct parse_state *ps)
-{
- struct parse_state p = *ps;
- unsigned int e;
-
- if (_parse_type_specifier_nonarray(ctx, &p)) {
- return -1;
- }
-
- e = _emit(ctx, &p.out, TYPE_SPECIFIER_ARRAY);
- if (_parse_type_specifier_array(ctx, &p)) {
- _update(ctx, e, TYPE_SPECIFIER_NONARRAY);
- }
- *ps = p;
- return 0;
-}
-
-static int
-_parse_parameter_qualifier(struct parse_context *ctx,
- struct parse_state *ps)
-{
- unsigned int e = _emit(ctx, &ps->out, PARAM_QUALIFIER_NONE);
-
- if (_parse_id(ctx, ctx->dict.in, ps) == 0) {
- _update(ctx, e, PARAM_QUALIFIER_IN);
- } else if (_parse_id(ctx, ctx->dict.out, ps) == 0) {
- _update(ctx, e, PARAM_QUALIFIER_OUT);
- } else if (_parse_id(ctx, ctx->dict.inout, ps) == 0) {
- _update(ctx, e, PARAM_QUALIFIER_INOUT);
- }
- return 0;
-}
-
-static int
-_parse_fully_specified_type(struct parse_context *ctx,
- struct parse_state *ps)
-{
- struct parse_state p = *ps;
-
- if (_parse_layout_qualifier(ctx, &p)) {
- return -1;
- }
- _emit(ctx, &p.out, LAYOUT_QUALIFIER_NONE);
-
- if (_parse_invariant_qualifier(ctx, &p)) {
- _emit(ctx, &p.out, TYPE_VARIANT);
- }
-
- if (_parse_centroid_qualifier(ctx, &p)) {
- _emit(ctx, &p.out, TYPE_CENTER);
- }
- if (_parse_storage_qualifier(ctx, &p)) {
- _emit(ctx, &p.out, TYPE_QUALIFIER_NONE);
- }
- _parse_parameter_qualifier(ctx, &p);
- if (_parse_precision(ctx, &p)) {
- _emit(ctx, &p.out, PRECISION_DEFAULT);
- }
- if (_parse_type_specifier(ctx, &p)) {
- return -1;
- }
- *ps = p;
- return 0;
-}
-
-
-static int
-_parse_function_header(struct parse_context *ctx,
- struct parse_state *ps)
-{
- struct parse_state p = *ps;
-
- if (_parse_fully_specified_type(ctx, &p)) {
- return -1;
- }
- if (_parse_function_decl_identifier(ctx, &p)) {
- return -1;
- }
- if (_parse_token(ctx, SL_PP_LPAREN, &p)) {
- return -1;
- }
- *ps = p;
- return 0;
-}
-
-
-static int
-_parse_function_identifier(struct parse_context *ctx,
- struct parse_state *ps)
-{
- struct parse_state p;
- unsigned int e;
-
- if (_parse_identifier(ctx, ps)) {
- return -1;
- }
- e = _emit(ctx, &ps->out, FUNCTION_CALL_NONARRAY);
-
- p = *ps;
- if (_parse_token(ctx, SL_PP_LBRACKET, &p)) {
- return 0;
- }
- if (_parse_constant_expression(ctx, &p)) {
- _error(ctx, "expected constant integral expression");
- return -1;
- }
- if (_parse_token(ctx, SL_PP_RBRACKET, &p)) {
- _error(ctx, "expected `]'");
- return -1;
- }
- _update(ctx, e, FUNCTION_CALL_ARRAY);
- *ps = p;
- return 0;
-}
-
-
-static int
-_parse_function_call_header(struct parse_context *ctx,
- struct parse_state *ps)
-{
- struct parse_state p = *ps;
-
- if (_parse_function_identifier(ctx, &p)) {
- return -1;
- }
- if (_parse_token(ctx, SL_PP_LPAREN, &p)) {
- return -1;
- }
- *ps = p;
- return 0;
-}
-
-
-static int
-_parse_assign_expression(struct parse_context *ctx,
- struct parse_state *ps)
-{
- struct parse_state p = *ps;
- unsigned int op;
-
- if (_parse_unary_expression(ctx, &p)) {
- return -1;
- }
-
- if (_parse_token(ctx, SL_PP_ASSIGN, &p) == 0) {
- op = OP_ASSIGN;
- } else if (_parse_token(ctx, SL_PP_MULASSIGN, &p) == 0) {
- op = OP_MULASSIGN;
- } else if (_parse_token(ctx, SL_PP_DIVASSIGN, &p) == 0) {
- op = OP_DIVASSIGN;
- } else if (_parse_token(ctx, SL_PP_ADDASSIGN, &p) == 0) {
- op = OP_ADDASSIGN;
- } else if (_parse_token(ctx, SL_PP_SUBASSIGN, &p) == 0) {
- op = OP_SUBASSIGN;
- } else {
- return -1;
- }
-
- if (_parse_assignment_expression(ctx, &p)) {
- return -1;
- }
- _emit(ctx, &p.out, op);
-
- *ps = p;
- return 0;
-}
-
-
-static int
-_parse_assignment_expression(struct parse_context *ctx,
- struct parse_state *ps)
-{
- if (_parse_assign_expression(ctx, ps) == 0) {
- return 0;
- }
-
- if (_parse_conditional_expression(ctx, ps) == 0) {
- return 0;
- }
-
- return -1;
-}
-
-
-static int
-_parse_function_call_header_with_parameters(struct parse_context *ctx,
- struct parse_state *ps)
-{
- struct parse_state p = *ps;
-
- if (_parse_function_call_header(ctx, &p)) {
- return -1;
- }
- if (_parse_assignment_expression(ctx, &p)) {
- return -1;
- }
- _emit(ctx, &p.out, OP_END);
- for (;;) {
- *ps = p;
- if (_parse_token(ctx, SL_PP_COMMA, &p)) {
- return 0;
- }
- if (_parse_assignment_expression(ctx, &p)) {
- return 0;
- }
- _emit(ctx, &p.out, OP_END);
- }
-}
-
-
-static int
-_parse_function_call_header_no_parameters(struct parse_context *ctx,
- struct parse_state *ps)
-{
- if (_parse_function_call_header(ctx, ps)) {
- return -1;
- }
- _parse_id(ctx, ctx->dict._void, ps);
- return 0;
-}
-
-
-static int
-_parse_function_call_generic(struct parse_context *ctx,
- struct parse_state *ps)
-{
- struct parse_state p = *ps;
-
- if (_parse_function_call_header_with_parameters(ctx, &p) == 0) {
- if (_parse_token(ctx, SL_PP_RPAREN, &p) == 0) {
- *ps = p;
- return 0;
- }
- _error(ctx, "expected `)'");
- return -1;
- }
-
- p = *ps;
- if (_parse_function_call_header_no_parameters(ctx, &p) == 0) {
- if (_parse_token(ctx, SL_PP_RPAREN, &p) == 0) {
- *ps = p;
- return 0;
- }
- _error(ctx, "expected `)'");
- return -1;
- }
-
- return -1;
-}
-
-
-static int
-_parse_method_call(struct parse_context *ctx,
- struct parse_state *ps)
-{
- struct parse_state p = *ps;
-
- _emit(ctx, &p.out, OP_METHOD);
- if (_parse_identifier(ctx, &p)) {
- return -1;
- }
- if (_parse_token(ctx, SL_PP_DOT, &p)) {
- return -1;
- }
- if (_parse_function_call_generic(ctx, &p)) {
- return -1;
- }
- _emit(ctx, &p.out, OP_END);
- *ps = p;
- return 0;
-}
-
-
-static int
-_parse_regular_function_call(struct parse_context *ctx,
- struct parse_state *ps)
-{
- struct parse_state p = *ps;
-
- _emit(ctx, &p.out, OP_CALL);
- if (_parse_function_call_generic(ctx, &p)) {
- return -1;
- }
- _emit(ctx, &p.out, OP_END);
- *ps = p;
- return 0;
-}
-
-
-static int
-_parse_function_call(struct parse_context *ctx,
- struct parse_state *ps)
-{
- if (_parse_regular_function_call(ctx, ps) == 0) {
- return 0;
- }
-
- if (_parse_method_call(ctx, ps) == 0) {
- return 0;
- }
-
- return -1;
-}
-
-
-static int
-_parse_expression(struct parse_context *ctx,
- struct parse_state *ps)
-{
- struct parse_state p = *ps;
-
- if (_parse_assignment_expression(ctx, &p)) {
- return -1;
- }
-
- for (;;) {
- *ps = p;
- if (_parse_token(ctx, SL_PP_COMMA, &p)) {
- return 0;
- }
- if (_parse_assignment_expression(ctx, &p)) {
- return 0;
- }
- _emit(ctx, &p.out, OP_SEQUENCE);
- }
-}
-
-
-static int
-_parse_postfix_expression(struct parse_context *ctx,
- struct parse_state *ps)
-{
- struct parse_state p;
-
- if (_parse_function_call(ctx, ps)) {
- if (_parse_primary_expression(ctx, ps)) {
- return -1;
- }
- }
-
- for (p = *ps;;) {
- *ps = p;
- if (_parse_token(ctx, SL_PP_INCREMENT, &p) == 0) {
- _emit(ctx, &p.out, OP_POSTINCREMENT);
- } else if (_parse_token(ctx, SL_PP_DECREMENT, &p) == 0) {
- _emit(ctx, &p.out, OP_POSTDECREMENT);
- } else if (_parse_token(ctx, SL_PP_LBRACKET, &p) == 0) {
- if (_parse_expression(ctx, &p)) {
- _error(ctx, "expected an integral expression");
- return -1;
- }
- if (_parse_token(ctx, SL_PP_RBRACKET, &p)) {
- _error(ctx, "expected `]'");
- return -1;
- }
- _emit(ctx, &p.out, OP_SUBSCRIPT);
- } else if (_parse_token(ctx, SL_PP_DOT, &p) == 0) {
- _emit(ctx, &p.out, OP_FIELD);
- if (_parse_identifier(ctx, &p)) {
- return 0;
- }
- } else {
- return 0;
- }
- }
-}
-
-
-static int
-_parse_unary_expression(struct parse_context *ctx,
- struct parse_state *ps)
-{
- struct parse_state p;
- unsigned int op;
-
- if (_parse_postfix_expression(ctx, ps) == 0) {
- return 0;
- }
-
- p = *ps;
- if (_parse_token(ctx, SL_PP_INCREMENT, &p) == 0) {
- op = OP_PREINCREMENT;
- } else if (_parse_token(ctx, SL_PP_DECREMENT, &p) == 0) {
- op = OP_PREDECREMENT;
- } else if (_parse_token(ctx, SL_PP_PLUS, &p) == 0) {
- op = OP_PLUS;
- } else if (_parse_token(ctx, SL_PP_MINUS, &p) == 0) {
- op = OP_MINUS;
- } else if (_parse_token(ctx, SL_PP_NOT, &p) == 0) {
- op = OP_NOT;
- } else {
- return -1;
- }
-
- if (_parse_unary_expression(ctx, &p)) {
- return -1;
- }
- _emit(ctx, &p.out, op);
- *ps = p;
- return 0;
-}
-
-
-static int
-_parse_multiplicative_expression(struct parse_context *ctx,
- struct parse_state *ps)
-{
- struct parse_state p = *ps;
-
- if (_parse_unary_expression(ctx, &p)) {
- return -1;
- }
- for (;;) {
- unsigned int op;
-
- *ps = p;
- if (_parse_token(ctx, SL_PP_STAR, &p) == 0) {
- op = OP_MULTIPLY;
- } else if (_parse_token(ctx, SL_PP_SLASH, &p) == 0) {
- op = OP_DIVIDE;
- } else {
- return 0;
- }
- if (_parse_unary_expression(ctx, &p)) {
- return 0;
- }
- _emit(ctx, &p.out, op);
- }
-}
-
-
-static int
-_parse_additive_expression(struct parse_context *ctx,
- struct parse_state *ps)
-{
- struct parse_state p = *ps;
-
- if (_parse_multiplicative_expression(ctx, &p)) {
- return -1;
- }
- for (;;) {
- unsigned int op;
-
- *ps = p;
- if (_parse_token(ctx, SL_PP_PLUS, &p) == 0) {
- op = OP_ADD;
- } else if (_parse_token(ctx, SL_PP_MINUS, &p) == 0) {
- op = OP_SUBTRACT;
- } else {
- return 0;
- }
- if (_parse_multiplicative_expression(ctx, &p)) {
- return 0;
- }
- _emit(ctx, &p.out, op);
- }
-}
-
-
-static int
-_parse_relational_expression(struct parse_context *ctx,
- struct parse_state *ps)
-{
- struct parse_state p = *ps;
-
- if (_parse_additive_expression(ctx, &p)) {
- return -1;
- }
- for (;;) {
- unsigned int op;
-
- *ps = p;
- if (_parse_token(ctx, SL_PP_LESS, &p) == 0) {
- op = OP_LESS;
- } else if (_parse_token(ctx, SL_PP_GREATER, &p) == 0) {
- op = OP_GREATER;
- } else if (_parse_token(ctx, SL_PP_LESSEQUAL, &p) == 0) {
- op = OP_LESSEQUAL;
- } else if (_parse_token(ctx, SL_PP_GREATEREQUAL, &p) == 0) {
- op = OP_GREATEREQUAL;
- } else {
- return 0;
- }
- if (_parse_additive_expression(ctx, &p)) {
- return 0;
- }
- _emit(ctx, &p.out, op);
- }
-}
-
-
-static int
-_parse_equality_expression(struct parse_context *ctx,
- struct parse_state *ps)
-{
- struct parse_state p = *ps;
-
- if (_parse_relational_expression(ctx, &p)) {
- return -1;
- }
- for (;;) {
- unsigned int op;
-
- *ps = p;
- if (_parse_token(ctx, SL_PP_EQUAL, &p) == 0) {
- op = OP_EQUAL;
- } else if (_parse_token(ctx, SL_PP_NOTEQUAL, &p) == 0) {
- op = OP_NOTEQUAL;
- } else {
- return 0;
- }
- if (_parse_relational_expression(ctx, &p)) {
- return -1;
- }
- _emit(ctx, &p.out, op);
- }
-}
-
-
-static int
-_parse_logical_and_expression(struct parse_context *ctx,
- struct parse_state *ps)
-{
- struct parse_state p = *ps;
-
- if (_parse_equality_expression(ctx, &p)) {
- return -1;
- }
- for (;;) {
- *ps = p;
- if (_parse_token(ctx, SL_PP_AND, &p)) {
- return 0;
- }
- if (_parse_equality_expression(ctx, &p)) {
- return 0;
- }
- _emit(ctx, &p.out, OP_LOGICALAND);
- }
-}
-
-
-static int
-_parse_logical_xor_expression(struct parse_context *ctx,
- struct parse_state *ps)
-{
- struct parse_state p = *ps;
-
- if (_parse_logical_and_expression(ctx, &p)) {
- return -1;
- }
- for (;;) {
- *ps = p;
- if (_parse_token(ctx, SL_PP_XOR, &p)) {
- return 0;
- }
- if (_parse_logical_and_expression(ctx, &p)) {
- return 0;
- }
- _emit(ctx, &p.out, OP_LOGICALXOR);
- }
-}
-
-
-static int
-_parse_logical_or_expression(struct parse_context *ctx,
- struct parse_state *ps)
-{
- struct parse_state p = *ps;
-
- if (_parse_logical_xor_expression(ctx, &p)) {
- return -1;
- }
- for (;;) {
- *ps = p;
- if (_parse_token(ctx, SL_PP_OR, &p)) {
- return 0;
- }
- if (_parse_logical_xor_expression(ctx, &p)) {
- return 0;
- }
- _emit(ctx, &p.out, OP_LOGICALOR);
- }
-}
-
-
-static int
-_parse_conditional_expression(struct parse_context *ctx,
- struct parse_state *ps)
-{
- struct parse_state p = *ps;
-
- if (_parse_logical_or_expression(ctx, &p)) {
- return -1;
- }
- for (;;) {
- *ps = p;
- if (_parse_token(ctx, SL_PP_QUESTION, &p)) {
- return 0;
- }
- if (_parse_expression(ctx, &p)) {
- return 0;
- }
- if (_parse_token(ctx, SL_PP_COLON, &p)) {
- return 0;
- }
- if (_parse_conditional_expression(ctx, &p)) {
- return 0;
- }
- _emit(ctx, &p.out, OP_SELECT);
- }
-}
-
-
-static int
-_parse_constant_expression(struct parse_context *ctx,
- struct parse_state *ps)
-{
- if (_parse_conditional_expression(ctx, ps)) {
- return -1;
- }
- _emit(ctx, &ps->out, OP_END);
- return 0;
-}
-
-
-static int
-_parse_parameter_declarator_array(struct parse_context *ctx,
- struct parse_state *ps)
-{
- struct parse_state p = *ps;
-
- if (_parse_token(ctx, SL_PP_LBRACKET, &p)) {
- return -1;
- }
- if (_parse_constant_expression(ctx, &p)) {
- _error(ctx, "expected constant integral expression");
- return -1;
- }
- if (_parse_token(ctx, SL_PP_RBRACKET, &p)) {
- _error(ctx, "expected `]'");
- return -1;
- }
- *ps = p;
- return 0;
-}
-
-
-static int
-_parse_parameter_declarator(struct parse_context *ctx,
- struct parse_state *ps)
-{
- struct parse_state p = *ps;
- unsigned int e;
-
- if (_parse_type_specifier(ctx, &p)) {
- return -1;
- }
- if (_parse_identifier(ctx, &p)) {
- return -1;
- }
- e = _emit(ctx, &p.out, PARAMETER_ARRAY_PRESENT);
- if (_parse_parameter_declarator_array(ctx, &p)) {
- _update(ctx, e, PARAMETER_ARRAY_NOT_PRESENT);
- }
- *ps = p;
- return 0;
-}
-
-
-static int
-_parse_parameter_type_specifier_array(struct parse_context *ctx,
- struct parse_state *ps)
-{
- struct parse_state p = *ps;
-
- if (_parse_token(ctx, SL_PP_LBRACKET, &p)) {
- return -1;
- }
- if (_parse_constant_expression(ctx, &p)) {
- _error(ctx, "expected constant integral expression");
- return -1;
- }
- if (_parse_token(ctx, SL_PP_RBRACKET, &p)) {
- _error(ctx, "expected `]'");
- return -1;
- }
- *ps = p;
- return 0;
-}
-
-
-static int
-_parse_parameter_type_specifier(struct parse_context *ctx,
- struct parse_state *ps)
-{
- struct parse_state p = *ps;
- unsigned int e;
-
- if (_parse_type_specifier(ctx, &p)) {
- return -1;
- }
- _emit(ctx, &p.out, '\0');
-
- e = _emit(ctx, &p.out, PARAMETER_ARRAY_PRESENT);
- if (_parse_parameter_type_specifier_array(ctx, &p)) {
- _update(ctx, e, PARAMETER_ARRAY_NOT_PRESENT);
- }
- *ps = p;
- return 0;
-}
-
-
-static int
-_parse_parameter_declaration(struct parse_context *ctx,
- struct parse_state *ps)
-{
- struct parse_state p = *ps;
- unsigned int e = _emit(ctx, &p.out, PARAMETER_NEXT);
-
- (void) e;
-
- if (_parse_storage_qualifier(ctx, &p)) {
- _emit(ctx, &p.out, TYPE_QUALIFIER_NONE);
- }
- _parse_parameter_qualifier(ctx, &p);
- if (_parse_precision(ctx, &p)) {
- _emit(ctx, &p.out, PRECISION_DEFAULT);
- }
- if (_parse_parameter_declarator(ctx, &p) == 0) {
- *ps = p;
- return 0;
- }
- if (_parse_parameter_type_specifier(ctx, &p) == 0) {
- *ps = p;
- return 0;
- }
-
- return -1;
-}
-
-
-static int
-_parse_function_header_with_parameters(struct parse_context *ctx,
- struct parse_state *ps)
-{
- struct parse_state p = *ps;
-
- if (_parse_function_header(ctx, &p)) {
- return -1;
- }
- if (_parse_parameter_declaration(ctx, &p)) {
- return -1;
- }
-
- for (;;) {
- *ps = p;
- if (_parse_token(ctx, SL_PP_COMMA, &p)) {
- return 0;
- }
- if (_parse_parameter_declaration(ctx, &p)) {
- return 0;
- }
- }
-}
-
-
-static int
-_parse_function_declarator(struct parse_context *ctx,
- struct parse_state *ps)
-{
- if (_parse_function_header_with_parameters(ctx, ps) == 0) {
- return 0;
- }
-
- if (_parse_function_header(ctx, ps) == 0) {
- return 0;
- }
-
- return -1;
-}
-
-
-static int
-_parse_function_prototype(struct parse_context *ctx,
- struct parse_state *ps)
-{
- struct parse_state p = *ps;
-
- if (_parse_function_header(ctx, &p) == 0) {
- if (_parse_id(ctx, ctx->dict._void, &p) == 0) {
- if (_parse_token(ctx, SL_PP_RPAREN, &p) == 0) {
- _emit(ctx, &p.out, PARAMETER_NONE);
- *ps = p;
- return 0;
- }
- _error(ctx, "expected `)'");
- return -1;
- }
- }
-
- p = *ps;
- if (_parse_function_declarator(ctx, &p) == 0) {
- if (_parse_token(ctx, SL_PP_RPAREN, &p) == 0) {
- _emit(ctx, &p.out, PARAMETER_NONE);
- *ps = p;
- return 0;
- }
- _error(ctx, "expected `)'");
- return -1;
- }
-
- return -1;
-}
-
-
-static int
-_parse_precision(struct parse_context *ctx,
- struct parse_state *ps)
-{
- const struct sl_pp_token_info *input = _fetch_token(ctx, ps->in);
- int id;
- unsigned int precision;
-
- if (!input || input->token != SL_PP_IDENTIFIER) {
- return -1;
- }
- id = input->data.identifier;
-
- if (id == ctx->dict.lowp) {
- precision = PRECISION_LOW;
- } else if (id == ctx->dict.mediump) {
- precision = PRECISION_MEDIUM;
- } else if (id == ctx->dict.highp) {
- precision = PRECISION_HIGH;
- } else {
- return -1;
- }
-
- _parse_token(ctx, SL_PP_IDENTIFIER, ps);
- _emit(ctx, &ps->out, precision);
- return 0;
-}
-
-
-static int
-_parse_prectype(struct parse_context *ctx,
- struct parse_state *ps)
-{
- const struct sl_pp_token_info *input = _fetch_token(ctx, ps->in);
- int id;
- unsigned int type;
-
- if (!input || input->token != SL_PP_IDENTIFIER) {
- return -1;
- }
- id = input->data.identifier;
-
- if (id == ctx->dict._int) {
- type = TYPE_SPECIFIER_INT;
- } else if (id == ctx->dict._float) {
- type = TYPE_SPECIFIER_FLOAT;
- } else if (id == ctx->dict.sampler1D) {
- type = TYPE_SPECIFIER_SAMPLER1D;
- } else if (id == ctx->dict.sampler2D) {
- type = TYPE_SPECIFIER_SAMPLER2D;
- } else if (id == ctx->dict.sampler3D) {
- type = TYPE_SPECIFIER_SAMPLER3D;
- } else if (id == ctx->dict.samplerCube) {
- type = TYPE_SPECIFIER_SAMPLERCUBE;
- } else if (id == ctx->dict.sampler1DShadow) {
- type = TYPE_SPECIFIER_SAMPLER1DSHADOW;
- } else if (id == ctx->dict.sampler2DShadow) {
- type = TYPE_SPECIFIER_SAMPLER2DSHADOW;
- } else if (id == ctx->dict.sampler2DRect) {
- if (!ctx->texture_rectangle) {
- _error(ctx, "GL_ARB_texture_rectangle extension must be enabled "
- "in order to use a rect sampler");
- return -1;
- }
- type = TYPE_SPECIFIER_SAMPLER2DRECT;
- } else if (id == ctx->dict.sampler2DRectShadow) {
- if (!ctx->texture_rectangle) {
- _error(ctx, "GL_ARB_texture_rectangle extension must be enabled "
- "in order to use a rect sampler");
- return -1;
- }
- type = TYPE_SPECIFIER_SAMPLER2DRECTSHADOW;
- } else if (id == ctx->dict.sampler1DArray) {
- type = TYPE_SPECIFIER_SAMPLER_1D_ARRAY;
- } else if (id == ctx->dict.sampler2DArray) {
- type = TYPE_SPECIFIER_SAMPLER_2D_ARRAY;
- } else if (id == ctx->dict.sampler1DArrayShadow) {
- type = TYPE_SPECIFIER_SAMPLER_1D_ARRAY_SHADOW;
- } else if (id == ctx->dict.sampler2DArrayShadow) {
- type = TYPE_SPECIFIER_SAMPLER_2D_ARRAY_SHADOW;
- } else {
- return -1;
- }
-
- _parse_token(ctx, SL_PP_IDENTIFIER, ps);
- _emit(ctx, &ps->out, type);
- return 0;
-}
-
-
-static int
-_parse_precision_stmt(struct parse_context *ctx,
- struct parse_state *ps)
-{
- struct parse_state p = *ps;
-
- if (_parse_id(ctx, ctx->dict.precision, &p)) {
- return -1;
- }
- if (_parse_precision(ctx, &p)) {
- return -1;
- }
- if (_parse_prectype(ctx, &p)) {
- return -1;
- }
- if (_parse_token(ctx, SL_PP_SEMICOLON, &p)) {
- return -1;
- }
- *ps = p;
- return 0;
-}
-
-
-static int
-_parse_floatconstant(struct parse_context *ctx,
- struct parse_state *ps)
-{
- struct parse_state p = *ps;
-
- _emit(ctx, &p.out, OP_PUSH_FLOAT);
- if (_parse_float(ctx, &p)) {
- return -1;
- }
- *ps = p;
- return 0;
-}
-
-
-static int
-_parse_intconstant(struct parse_context *ctx,
- struct parse_state *ps)
-{
- struct parse_state p = *ps;
-
- _emit(ctx, &p.out, OP_PUSH_INT);
- if (_parse_uint(ctx, &p)) {
- return -1;
- }
- *ps = p;
- return 0;
-}
-
-
-static int
-_parse_boolconstant(struct parse_context *ctx,
- struct parse_state *ps)
-{
- if (_parse_id(ctx, ctx->dict._false, ps) == 0) {
- _emit(ctx, &ps->out, OP_PUSH_BOOL);
- _emit(ctx, &ps->out, 2); /* radix */
- _emit(ctx, &ps->out, '0');
- _emit(ctx, &ps->out, '\0');
- return 0;
- }
-
- if (_parse_id(ctx, ctx->dict._true, ps) == 0) {
- _emit(ctx, &ps->out, OP_PUSH_BOOL);
- _emit(ctx, &ps->out, 2); /* radix */
- _emit(ctx, &ps->out, '1');
- _emit(ctx, &ps->out, '\0');
- return 0;
- }
-
- return -1;
-}
-
-
-static int
-_parse_variable_identifier(struct parse_context *ctx,
- struct parse_state *ps)
-{
- struct parse_state p = *ps;
-
- _emit(ctx, &p.out, OP_PUSH_IDENTIFIER);
- if (_parse_identifier(ctx, &p)) {
- return -1;
- }
- *ps = p;
- return 0;
-}
-
-
-static int
-_parse_primary_expression(struct parse_context *ctx,
- struct parse_state *ps)
-{
- struct parse_state p;
-
- if (_parse_floatconstant(ctx, ps) == 0) {
- return 0;
- }
- if (_parse_boolconstant(ctx, ps) == 0) {
- return 0;
- }
- if (_parse_intconstant(ctx, ps) == 0) {
- return 0;
- }
- if (_parse_variable_identifier(ctx, ps) == 0) {
- return 0;
- }
-
- p = *ps;
- if (_parse_token(ctx, SL_PP_LPAREN, &p)) {
- return -1;
- }
- if (_parse_expression(ctx, &p)) {
- return -1;
- }
- if (_parse_token(ctx, SL_PP_RPAREN, &p)) {
- return -1;
- }
-
- *ps = p;
- return 0;
-}
-
-
-static int
-_parse_asm_argument(struct parse_context *ctx,
- struct parse_state *ps)
-{
- if (_parse_variable_identifier(ctx, ps) == 0) {
- struct parse_state p = *ps;
-
- if (_parse_token(ctx, SL_PP_DOT, &p)) {
- return 0;
- }
- _emit(ctx, &p.out, OP_FIELD);
- if (_parse_identifier(ctx, &p)) {
- return 0;
- }
- *ps = p;
- return 0;
- }
-
- if (_parse_floatconstant(ctx, ps) == 0) {
- return 0;
- }
-
- return -1;
-}
-
-
-static int
-_parse_asm_arguments(struct parse_context *ctx,
- struct parse_state *ps)
-{
- struct parse_state p = *ps;
-
- if (_parse_asm_argument(ctx, &p)) {
- return -1;
- }
- _emit(ctx, &p.out, OP_END);
-
- for (;;) {
- *ps = p;
- if (_parse_token(ctx, SL_PP_COMMA, &p)) {
- return 0;
- }
- if (_parse_asm_argument(ctx, &p)) {
- return 0;
- }
- _emit(ctx, &p.out, OP_END);
- }
-}
-
-
-static int
-_parse_asm_statement(struct parse_context *ctx,
- struct parse_state *ps)
-{
- struct parse_state p = *ps;
-
- if (_parse_id(ctx, ctx->dict.___asm, &p)) {
- return -1;
- }
- if (_parse_identifier(ctx, &p)) {
- return -1;
- }
- /* optional arguments */
- _parse_asm_arguments(ctx, &p);
- if (_parse_token(ctx, SL_PP_SEMICOLON, &p)) {
- return -1;
- }
- _emit(ctx, &p.out, OP_END);
- *ps = p;
- return 0;
-}
-
-
-static int
-_parse_selection_statement(struct parse_context *ctx,
- struct parse_state *ps)
-{
- struct parse_state p = *ps;
-
- _emit(ctx, &p.out, OP_IF);
- if (_parse_id(ctx, ctx->dict._if, &p)) {
- return -1;
- }
- if (_parse_token(ctx, SL_PP_LPAREN, &p)) {
- _error(ctx, "expected `('");
- return -1;
- }
- if (_parse_expression(ctx, &p)) {
- _error(ctx, "expected an expression");
- return -1;
- }
- if (_parse_token(ctx, SL_PP_RPAREN, &p)) {
- _error(ctx, "expected `)'");
- return -1;
- }
- _emit(ctx, &p.out, OP_END);
- if (_parse_statement(ctx, &p)) {
- return -1;
- }
-
- *ps = p;
- if (_parse_id(ctx, ctx->dict._else, &p) == 0) {
- if (_parse_statement(ctx, &p) == 0) {
- *ps = p;
- return 0;
- }
- }
-
- _emit(ctx, &ps->out, OP_EXPRESSION);
- _emit(ctx, &ps->out, OP_PUSH_VOID);
- _emit(ctx, &ps->out, OP_END);
- return 0;
-}
-
-
-static int
-_parse_expression_statement(struct parse_context *ctx,
- struct parse_state *ps)
-{
- struct parse_state p = *ps;
-
- if (_parse_expression(ctx, &p)) {
- _emit(ctx, &p.out, OP_PUSH_VOID);
- }
- if (_parse_token(ctx, SL_PP_SEMICOLON, &p)) {
- return -1;
- }
- _emit(ctx, &p.out, OP_END);
- *ps = p;
- return 0;
-}
-
-
-static int
-_parse_for_init_statement(struct parse_context *ctx,
- struct parse_state *ps)
-{
- struct parse_state p = *ps;
- unsigned int e = _emit(ctx, &p.out, OP_EXPRESSION);
-
- if (_parse_expression_statement(ctx, &p) == 0) {
- *ps = p;
- return 0;
- }
-
- if (_parse_declaration(ctx, &p) == 0) {
- _update(ctx, e, OP_DECLARE);
- *ps = p;
- return 0;
- }
-
- return -1;
-}
-
-
-static int
-_parse_initializer(struct parse_context *ctx,
- struct parse_state *ps)
-{
- if (_parse_assignment_expression(ctx, ps) == 0) {
- _emit(ctx, &ps->out, OP_END);
- return 0;
- }
- return -1;
-}
-
-
-static int
-_parse_condition_initializer(struct parse_context *ctx,
- struct parse_state *ps)
-{
- struct parse_state p = *ps;
-
- _emit(ctx, &p.out, OP_DECLARE);
- _emit(ctx, &p.out, DECLARATION_INIT_DECLARATOR_LIST);
- if (_parse_fully_specified_type(ctx, &p)) {
- return -1;
- }
- _emit(ctx, &p.out, VARIABLE_IDENTIFIER);
- if (_parse_identifier(ctx, &p)) {
- return -1;
- }
- if (_parse_token(ctx, SL_PP_ASSIGN, &p)) {
- _error(ctx, "expected `='");
- return -1;
- }
- _emit(ctx, &p.out, VARIABLE_INITIALIZER);
- if (_parse_initializer(ctx, &p)) {
- _error(ctx, "expected an initialiser");
- return -1;
- }
- _emit(ctx, &p.out, DECLARATOR_NONE);
- *ps = p;
- return 0;
-}
-
-
-static int
-_parse_condition(struct parse_context *ctx,
- struct parse_state *ps)
-{
- struct parse_state p;
-
- if (_parse_condition_initializer(ctx, ps) == 0) {
- return 0;
- }
-
- p = *ps;
- _emit(ctx, &p.out, OP_EXPRESSION);
- if (_parse_expression(ctx, &p) == 0) {
- _emit(ctx, &p.out, OP_END);
- *ps = p;
- return 0;
- }
-
- return -1;
-}
-
-
-static int
-_parse_for_rest_statement(struct parse_context *ctx,
- struct parse_state *ps)
-{
- struct parse_state p = *ps;
-
- if (_parse_condition(ctx, &p)) {
- _emit(ctx, &p.out, OP_EXPRESSION);
- _emit(ctx, &p.out, OP_PUSH_BOOL);
- _emit(ctx, &p.out, 2);
- _emit(ctx, &p.out, '1');
- _emit(ctx, &p.out, '\0');
- _emit(ctx, &p.out, OP_END);
- }
- if (_parse_token(ctx, SL_PP_SEMICOLON, &p)) {
- return -1;
- }
- if (_parse_expression(ctx, &p)) {
- _emit(ctx, &p.out, OP_PUSH_VOID);
- }
- _emit(ctx, &p.out, OP_END);
- *ps = p;
- return 0;
-}
-
-
-static int
-_parse_iteration_statement(struct parse_context *ctx,
- struct parse_state *ps)
-{
- struct parse_state p = *ps;
-
- if (_parse_id(ctx, ctx->dict._while, &p) == 0) {
- _emit(ctx, &p.out, OP_WHILE);
- if (_parse_token(ctx, SL_PP_LPAREN, &p)) {
- _error(ctx, "expected `('");
- return -1;
- }
- if (_parse_condition(ctx, &p)) {
- _error(ctx, "expected an expression");
- return -1;
- }
- if (_parse_token(ctx, SL_PP_RPAREN, &p)) {
- _error(ctx, "expected `)'");
- return -1;
- }
- if (_parse_statement(ctx, &p)) {
- return -1;
- }
- *ps = p;
- return 0;
- }
-
- if (_parse_id(ctx, ctx->dict._do, &p) == 0) {
- _emit(ctx, &p.out, OP_DO);
- if (_parse_statement(ctx, &p)) {
- return -1;
- }
- if (_parse_id(ctx, ctx->dict._while, &p)) {
- return -1;
- }
- if (_parse_token(ctx, SL_PP_LPAREN, &p)) {
- _error(ctx, "expected `('");
- return -1;
- }
- if (_parse_expression(ctx, &p)) {
- _error(ctx, "expected an expression");
- return -1;
- }
- if (_parse_token(ctx, SL_PP_RPAREN, &p)) {
- _error(ctx, "expected `)'");
- return -1;
- }
- _emit(ctx, &p.out, OP_END);
- if (_parse_token(ctx, SL_PP_SEMICOLON, &p)) {
- _error(ctx, "expected `;'");
- return -1;
- }
- *ps = p;
- return 0;
- }
-
- if (_parse_id(ctx, ctx->dict._for, &p) == 0) {
- _emit(ctx, &p.out, OP_FOR);
- if (_parse_token(ctx, SL_PP_LPAREN, &p)) {
- _error(ctx, "expected `('");
- return -1;
- }
- if (_parse_for_init_statement(ctx, &p)) {
- return -1;
- }
- if (_parse_for_rest_statement(ctx, &p)) {
- return -1;
- }
- if (_parse_token(ctx, SL_PP_RPAREN, &p)) {
- _error(ctx, "expected `)'");
- return -1;
- }
- if (_parse_statement(ctx, &p)) {
- return -1;
- }
- *ps = p;
- return 0;
- }
-
- return -1;
-}
-
-
-static int
-_parse_jump_statement(struct parse_context *ctx,
- struct parse_state *ps)
-{
- struct parse_state p = *ps;
- unsigned int e = _emit(ctx, &p.out, 0);
-
- if (_parse_id(ctx, ctx->dict._continue, &p) == 0) {
- _update(ctx, e, OP_CONTINUE);
- } else if (_parse_id(ctx, ctx->dict._break, &p) == 0) {
- _update(ctx, e, OP_BREAK);
- } else if (_parse_id(ctx, ctx->dict._return, &p) == 0) {
- _update(ctx, e, OP_RETURN);
- if (_parse_expression(ctx, &p)) {
- _emit(ctx, &p.out, OP_PUSH_VOID);
- }
- _emit(ctx, &p.out, OP_END);
- } else if (ctx->shader_type == 1 && _parse_id(ctx, ctx->dict.discard, &p) == 0) {
- _update(ctx, e, OP_DISCARD);
- } else {
- return -1;
- }
- if (_parse_token(ctx, SL_PP_SEMICOLON, &p)) {
- return -1;
- }
- *ps = p;
- return 0;
-}
-
-
-static int
-_parse_simple_statement(struct parse_context *ctx,
- struct parse_state *ps)
-{
- struct parse_state p;
- unsigned int e;
-
- if (_parse_selection_statement(ctx, ps) == 0) {
- return 0;
- }
-
- if (_parse_iteration_statement(ctx, ps) == 0) {
- return 0;
- }
-
- if (_parse_jump_statement(ctx, ps) == 0) {
- return 0;
- }
-
- p = *ps;
- e = _emit(ctx, &p.out, OP_EXPRESSION);
- if (_parse_expression_statement(ctx, &p) == 0) {
- *ps = p;
- return 0;
- }
-
- if (_parse_precision_stmt(ctx, &p) == 0) {
- _update(ctx, e, OP_PRECISION);
- *ps = p;
- return 0;
- }
-
- if (ctx->parsing_builtin && _parse_asm_statement(ctx, &p) == 0) {
- _update(ctx, e, OP_ASM);
- *ps = p;
- return 0;
- }
-
- if (_parse_declaration(ctx, &p) == 0) {
- _update(ctx, e, OP_DECLARE);
- *ps = p;
- return 0;
- }
-
- return -1;
-}
-
-
-static int
-_parse_compound_statement(struct parse_context *ctx,
- struct parse_state *ps)
-{
- struct parse_state p = *ps;
-
- if (_parse_token(ctx, SL_PP_LBRACE, &p)) {
- return -1;
- }
- _emit(ctx, &p.out, OP_BLOCK_BEGIN_NEW_SCOPE);
- _parse_statement_list(ctx, &p);
- if (_parse_token(ctx, SL_PP_RBRACE, &p)) {
- return -1;
- }
- _emit(ctx, &p.out, OP_END);
- *ps = p;
- return 0;
-}
-
-
-static int
-_parse_statement(struct parse_context *ctx,
- struct parse_state *ps)
-{
- if (_parse_compound_statement(ctx, ps) == 0) {
- return 0;
- }
-
- if (_parse_simple_statement(ctx, ps) == 0) {
- return 0;
- }
-
- return -1;
-}
-
-
-static int
-_parse_statement_list(struct parse_context *ctx,
- struct parse_state *ps)
-{
- struct parse_state p = *ps;
-
- if (_parse_statement(ctx, &p)) {
- return -1;
- }
-
- for (;;) {
- *ps = p;
- if (_parse_statement(ctx, &p)) {
- return 0;
- }
- }
-}
-
-
-static int
-_parse_compound_statement_no_new_scope(struct parse_context *ctx,
- struct parse_state *ps)
-{
- struct parse_state p = *ps;
-
- if (_parse_token(ctx, SL_PP_LBRACE, &p)) {
- return -1;
- }
- _emit(ctx, &p.out, OP_BLOCK_BEGIN_NO_NEW_SCOPE);
- _parse_statement_list(ctx, &p);
- if (_parse_token(ctx, SL_PP_RBRACE, &p)) {
- return -1;
- }
- _emit(ctx, &p.out, OP_END);
- *ps = p;
- return 0;
-}
-
-
-static int
-_parse_function_definition(struct parse_context *ctx,
- struct parse_state *ps)
-{
- struct parse_state p = *ps;
-
- if (_parse_function_prototype(ctx, &p)) {
- return -1;
- }
- if (_parse_compound_statement_no_new_scope(ctx, &p)) {
- return -1;
- }
- *ps = p;
- return 0;
-}
-
-
-static int
-_parse_invariant_stmt(struct parse_context *ctx,
- struct parse_state *ps)
-{
- struct parse_state p = *ps;
-
- if (_parse_id(ctx, ctx->dict.invariant, &p)) {
- return -1;
- }
- if (_parse_identifier(ctx, &p)) {
- return -1;
- }
- if (_parse_token(ctx, SL_PP_SEMICOLON, &p)) {
- return -1;
- }
- *ps = p;
- return 0;
-}
-
-
-static int
-_parse_single_declaration(struct parse_context *ctx,
- struct parse_state *ps)
-{
- struct parse_state p = *ps;
- unsigned int e;
-
- if (_parse_fully_specified_type(ctx, &p)) {
- return -1;
- }
-
- e = _emit(ctx, &p.out, VARIABLE_IDENTIFIER);
- if (_parse_identifier(ctx, &p)) {
- _update(ctx, e, VARIABLE_NONE);
- *ps = p;
- return 0;
- }
-
- e = _emit(ctx, &p.out, VARIABLE_NONE);
- *ps = p;
-
- if (_parse_token(ctx, SL_PP_ASSIGN, &p) == 0) {
- _update(ctx, e, VARIABLE_INITIALIZER);
- if (_parse_initializer(ctx, &p) == 0) {
- *ps = p;
- return 0;
- }
- _error(ctx, "expected an initialiser");
- return -1;
- }
- p = *ps;
-
- if (_parse_token(ctx, SL_PP_LBRACKET, &p) == 0) {
- if (_parse_constant_expression(ctx, &p)) {
- _update(ctx, e, VARIABLE_ARRAY_UNKNOWN);
- } else {
- _update(ctx, e, VARIABLE_ARRAY_EXPLICIT);
- }
- if (_parse_token(ctx, SL_PP_RBRACKET, &p) == 0) {
- *ps = p;
- return 0;
- }
- _error(ctx, "expected `]'");
- return -1;
- }
- return 0;
-}
-
-
-static int
-_parse_init_declarator_list(struct parse_context *ctx,
- struct parse_state *ps)
-{
- struct parse_state p = *ps;
-
- if (_parse_single_declaration(ctx, &p)) {
- return -1;
- }
-
- for (;;) {
- unsigned int e;
-
- *ps = p;
- if (_parse_token(ctx, SL_PP_COMMA, &p)) {
- break;
- }
- _emit(ctx, &p.out, DECLARATOR_NEXT);
- _emit(ctx, &p.out, VARIABLE_IDENTIFIER);
- if (_parse_identifier(ctx, &p)) {
- break;
- }
-
- e = _emit(ctx, &p.out, VARIABLE_NONE);
- *ps = p;
-
- if (_parse_token(ctx, SL_PP_ASSIGN, &p) == 0) {
- if (_parse_initializer(ctx, &p) == 0) {
- _update(ctx, e, VARIABLE_INITIALIZER);
- *ps = p;
- continue;
- }
- _error(ctx, "expected an initialiser");
- break;
- }
- p = *ps;
-
- if (_parse_token(ctx, SL_PP_LBRACKET, &p) == 0) {
- unsigned int arr;
-
- if (_parse_constant_expression(ctx, &p)) {
- arr = VARIABLE_ARRAY_UNKNOWN;
- } else {
- arr = VARIABLE_ARRAY_EXPLICIT;
- }
- if (_parse_token(ctx, SL_PP_RBRACKET, &p) == 0) {
- _update(ctx, e, arr);
- *ps = p;
- continue;
- }
- _error(ctx, "expected `]'");
- break;
- }
- p = *ps;
- }
-
- _emit(ctx, &ps->out, DECLARATOR_NONE);
- return 0;
-}
-
-
-static int
-_parse_declaration(struct parse_context *ctx,
- struct parse_state *ps)
-{
- struct parse_state p = *ps;
- unsigned int e = _emit(ctx, &p.out, DECLARATION_FUNCTION_PROTOTYPE);
-
- if (_parse_function_prototype(ctx, &p)) {
- if (_parse_init_declarator_list(ctx, &p)) {
- return -1;
- }
- _update(ctx, e, DECLARATION_INIT_DECLARATOR_LIST);
- }
- if (_parse_token(ctx, SL_PP_SEMICOLON, &p)) {
- _error(ctx, "expected `;'");
- return -1;
- }
- *ps = p;
- return 0;
-}
-
-
-static int
-_parse_external_declaration(struct parse_context *ctx,
- struct parse_state *ps)
-{
- struct parse_state p = *ps;
- unsigned int e = _emit(ctx, &p.out, 0);
-
- if (_parse_precision_stmt(ctx, &p) == 0) {
- _update(ctx, e, DEFAULT_PRECISION);
- *ps = p;
- return 0;
- }
-
- if (_parse_function_definition(ctx, &p) == 0) {
- _update(ctx, e, EXTERNAL_FUNCTION_DEFINITION);
- *ps = p;
- return 0;
- }
-
- if (_parse_invariant_stmt(ctx, &p) == 0) {
- _update(ctx, e, INVARIANT_STMT);
- *ps = p;
- return 0;
- }
-
- if (_parse_declaration(ctx, &p) == 0) {
- _update(ctx, e, EXTERNAL_DECLARATION);
- *ps = p;
- return 0;
- }
-
- _error(ctx, "expected an identifier");
- return -1;
-}
-
-
-static int
-_parse_extensions(struct parse_context *ctx,
- struct parse_state *ps)
-{
- for (;;) {
- const struct sl_pp_token_info *input = _fetch_token(ctx, ps->in);
- unsigned int enable;
-
- if (!input) {
- return -1;
- }
-
- switch (input->token) {
- case SL_PP_EXTENSION_REQUIRE:
- case SL_PP_EXTENSION_ENABLE:
- case SL_PP_EXTENSION_WARN:
- enable = 1;
- break;
- case SL_PP_EXTENSION_DISABLE:
- enable = 0;
- break;
- default:
- return 0;
- }
-
- ps->in++;
- if (input->data.extension == ctx->dict.all) {
- ctx->fragment_coord_conventions = enable;
- }
- else if (input->data.extension == ctx->dict._GL_ARB_fragment_coord_conventions) {
- ctx->fragment_coord_conventions = enable;
- }
- else if (input->data.extension == ctx->dict._GL_ARB_texture_rectangle) {
- ctx->texture_rectangle = enable;
- }
- }
-}
-
-
-static int
-_parse_translation_unit(struct parse_context *ctx,
- struct parse_state *ps)
-{
- _emit(ctx, &ps->out, REVISION);
- if (_parse_extensions(ctx, ps)) {
- return -1;
- }
- if (_parse_external_declaration(ctx, ps)) {
- return -1;
- }
- for (;;) {
- if (_parse_extensions(ctx, ps)) {
- return -1;
- }
- if (_parse_external_declaration(ctx, ps)) {
- break;
- }
- }
- _emit(ctx, &ps->out, EXTERNAL_NULL);
- if (_parse_token(ctx, SL_PP_EOF, ps)) {
- return -1;
- }
- return 0;
-}
-
-
-#define ADD_NAME_STR(CTX, NAME, STR)\
- do {\
- (CTX).dict.NAME = sl_pp_context_add_unique_str((CTX).context, (STR));\
- if ((CTX).dict.NAME == -1) {\
- return -1;\
- }\
- } while (0)
-
-#define ADD_NAME(CTX, NAME) ADD_NAME_STR(CTX, NAME, #NAME)
-
-
-int
-sl_cl_compile(struct sl_pp_context *context,
- unsigned int shader_type,
- unsigned int parsing_builtin,
- unsigned char **output,
- unsigned int *cboutput,
- char *error,
- unsigned int cberror)
-{
- struct parse_context ctx;
- struct parse_state ps;
-
- ctx.context = context;
-
- ADD_NAME_STR(ctx, _void, "void");
- ADD_NAME_STR(ctx, _float, "float");
- ADD_NAME_STR(ctx, _int, "int");
- ADD_NAME_STR(ctx, _bool, "bool");
- ADD_NAME(ctx, vec2);
- ADD_NAME(ctx, vec3);
- ADD_NAME(ctx, vec4);
- ADD_NAME(ctx, bvec2);
- ADD_NAME(ctx, bvec3);
- ADD_NAME(ctx, bvec4);
- ADD_NAME(ctx, ivec2);
- ADD_NAME(ctx, ivec3);
- ADD_NAME(ctx, ivec4);
- ADD_NAME(ctx, mat2);
- ADD_NAME(ctx, mat3);
- ADD_NAME(ctx, mat4);
- ADD_NAME(ctx, mat2x3);
- ADD_NAME(ctx, mat3x2);
- ADD_NAME(ctx, mat2x4);
- ADD_NAME(ctx, mat4x2);
- ADD_NAME(ctx, mat3x4);
- ADD_NAME(ctx, mat4x3);
- ADD_NAME(ctx, sampler1D);
- ADD_NAME(ctx, sampler2D);
- ADD_NAME(ctx, sampler3D);
- ADD_NAME(ctx, samplerCube);
- ADD_NAME(ctx, sampler1DShadow);
- ADD_NAME(ctx, sampler2DShadow);
- ADD_NAME(ctx, sampler2DRect);
- ADD_NAME(ctx, sampler2DRectShadow);
- ADD_NAME(ctx, sampler1DArray);
- ADD_NAME(ctx, sampler2DArray);
- ADD_NAME(ctx, sampler1DArrayShadow);
- ADD_NAME(ctx, sampler2DArrayShadow);
-
- ADD_NAME(ctx, invariant);
-
- ADD_NAME(ctx, centroid);
-
- ADD_NAME(ctx, precision);
- ADD_NAME(ctx, lowp);
- ADD_NAME(ctx, mediump);
- ADD_NAME(ctx, highp);
-
- ADD_NAME_STR(ctx, _const, "const");
- ADD_NAME(ctx, attribute);
- ADD_NAME(ctx, varying);
- ADD_NAME(ctx, uniform);
- ADD_NAME(ctx, __fixed_output);
- ADD_NAME(ctx, __fixed_input);
-
- ADD_NAME(ctx, in);
- ADD_NAME(ctx, out);
- ADD_NAME(ctx, inout);
-
- ADD_NAME(ctx, layout);
- ADD_NAME(ctx, origin_upper_left);
- ADD_NAME(ctx, pixel_center_integer);
-
- ADD_NAME_STR(ctx, _struct, "struct");
-
- ADD_NAME(ctx, __constructor);
- ADD_NAME(ctx, __operator);
- ADD_NAME_STR(ctx, ___asm, "__asm");
-
- ADD_NAME_STR(ctx, _if, "if");
- ADD_NAME_STR(ctx, _else, "else");
- ADD_NAME_STR(ctx, _for, "for");
- ADD_NAME_STR(ctx, _while, "while");
- ADD_NAME_STR(ctx, _do, "do");
-
- ADD_NAME_STR(ctx, _continue, "continue");
- ADD_NAME_STR(ctx, _break, "break");
- ADD_NAME_STR(ctx, _return, "return");
- ADD_NAME(ctx, discard);
-
- ADD_NAME_STR(ctx, _false, "false");
- ADD_NAME_STR(ctx, _true, "true");
-
- ADD_NAME(ctx, all);
- ADD_NAME_STR(ctx, _GL_ARB_fragment_coord_conventions, "GL_ARB_fragment_coord_conventions");
- ADD_NAME_STR(ctx, _GL_ARB_texture_rectangle, "GL_ARB_texture_rectangle");
-
- ctx.out_buf = NULL;
- ctx.out_cap = 0;
-
- ctx.shader_type = shader_type;
- ctx.parsing_builtin = 1;
-
- ctx.fragment_coord_conventions = 0;
- ctx.texture_rectangle = 1;
-
- ctx.error[0] = '\0';
- ctx.process_error = 0;
-
- ctx.tokens_cap = 1024;
- ctx.tokens_read = 0;
- ctx.tokens = malloc(ctx.tokens_cap * sizeof(struct sl_pp_token_info));
- if (!ctx.tokens) {
- strncpy(error, "out of memory", cberror - 1);
- error[cberror - 1] = '\0';
- return -1;
- }
-
- ps.in = 0;
- ps.out = 0;
-
- if (_parse_translation_unit(&ctx, &ps)) {
- strncpy(error, ctx.error, cberror);
- free(ctx.tokens);
- return -1;
- }
-
- *output = ctx.out_buf;
- *cboutput = ps.out;
- free(ctx.tokens);
- return 0;
-}
+++ /dev/null
-/**************************************************************************
- *
- * Copyright 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, 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 TUNGSTEN GRAPHICS AND/OR ITS 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.
- *
- **************************************************************************/
-
-#ifndef SL_CL_PARSE_H
-#define SL_CL_PARSE_H
-
-struct sl_pp_context;
-
-int
-sl_cl_compile(struct sl_pp_context *context,
- unsigned int shader_type,
- unsigned int parsing_builtin,
- unsigned char **output,
- unsigned int *cboutput,
- char *error,
- unsigned int cberror);
-
-#endif /* SL_CL_PARSE_H */
+++ /dev/null
-#src/glsl/pp/Makefile
-
-TOP = ../../..
-
-include $(TOP)/configs/current
-
-LIBNAME = glslpp
-
-C_SOURCES = \
- sl_pp_context.c \
- sl_pp_define.c \
- sl_pp_dict.c \
- sl_pp_error.c \
- sl_pp_expression.c \
- sl_pp_extension.c \
- sl_pp_if.c \
- sl_pp_line.c \
- sl_pp_macro.c \
- sl_pp_pragma.c \
- sl_pp_process.c \
- sl_pp_purify.c \
- sl_pp_token.c \
- sl_pp_token_util.c \
- sl_pp_version.c
-
-include ../Makefile.template
-
+++ /dev/null
-/**************************************************************************
- *
- * Copyright 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, 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 TUNGSTEN GRAPHICS AND/OR ITS 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.
- *
- **************************************************************************/
-
-#include <stdlib.h>
-#include <string.h>
-#include "sl_pp_macro.h"
-#include "sl_pp_public.h"
-#include "sl_pp_context.h"
-
-
-struct sl_pp_context *
-sl_pp_context_create(const char *input,
- const struct sl_pp_purify_options *options)
-{
- struct sl_pp_context *context;
-
- context = calloc(1, sizeof(struct sl_pp_context));
- if (!context) {
- return NULL;
- }
-
- if (sl_pp_dict_init(context)) {
- sl_pp_context_destroy(context);
- return NULL;
- }
-
- context->getc_buf_capacity = 64;
- context->getc_buf = malloc(context->getc_buf_capacity * sizeof(char));
- if (!context->getc_buf) {
- sl_pp_context_destroy(context);
- return NULL;
- }
-
- if (sl_pp_token_buffer_init(&context->tokens, context)) {
- sl_pp_context_destroy(context);
- return NULL;
- }
-
- context->macro_tail = &context->macro;
- context->if_ptr = SL_PP_MAX_IF_NESTING;
- context->if_value = 1;
- memset(context->error_msg, 0, sizeof(context->error_msg));
- context->error_line = 1;
- context->line = 1;
- context->file = 0;
-
- sl_pp_purify_state_init(&context->pure, input, options);
-
- memset(&context->process_state, 0, sizeof(context->process_state));
-
- return context;
-}
-
-void
-sl_pp_context_destroy(struct sl_pp_context *context)
-{
- if (context) {
- free(context->cstr_pool);
- sl_pp_macro_free(context->macro);
- free(context->getc_buf);
- sl_pp_token_buffer_destroy(&context->tokens);
- free(context->process_state.out);
- free(context);
- }
-}
-
-const char *
-sl_pp_context_error_message(const struct sl_pp_context *context)
-{
- return context->error_msg;
-}
-
-void
-sl_pp_context_error_position(const struct sl_pp_context *context,
- unsigned int *file,
- unsigned int *line)
-{
- if (file) {
- *file = 0;
- }
- if (line) {
- *line = context->error_line;
- }
-}
-
-int
-sl_pp_context_add_predefined(struct sl_pp_context *context,
- const char *name,
- const char *value)
-{
- struct sl_pp_predefined pre;
-
- if (context->num_predefined == SL_PP_MAX_PREDEFINED) {
- return -1;
- }
-
- pre.name = sl_pp_context_add_unique_str(context, name);
- if (pre.name == -1) {
- return -1;
- }
-
- pre.value = sl_pp_context_add_unique_str(context, value);
- if (pre.value == -1) {
- return -1;
- }
-
- context->predefined[context->num_predefined++] = pre;
- return 0;
-}
-
-int
-sl_pp_context_add_unique_str(struct sl_pp_context *context,
- const char *str)
-{
- unsigned int size;
- unsigned int offset = 0;
-
- size = strlen(str) + 1;
-
- /* Find out if this is a unique string. */
- while (offset < context->cstr_pool_len) {
- const char *str2;
- unsigned int size2;
-
- str2 = &context->cstr_pool[offset];
- size2 = strlen(str2) + 1;
- if (size == size2 && !memcmp(str, str2, size - 1)) {
- return offset;
- }
-
- offset += size2;
- }
-
- if (context->cstr_pool_len + size > context->cstr_pool_max) {
- context->cstr_pool_max = (context->cstr_pool_len + size + 0xffff) & ~0xffff;
- context->cstr_pool = realloc(context->cstr_pool, context->cstr_pool_max);
- }
-
- if (!context->cstr_pool) {
- strcpy(context->error_msg, "out of memory");
- return -1;
- }
-
- offset = context->cstr_pool_len;
- memcpy(&context->cstr_pool[offset], str, size);
- context->cstr_pool_len += size;
-
- return offset;
-}
-
-const char *
-sl_pp_context_cstr(const struct sl_pp_context *context,
- int offset)
-{
- if (offset == -1) {
- return NULL;
- }
- return &context->cstr_pool[offset];
-}
+++ /dev/null
-/**************************************************************************
- *
- * Copyright 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, 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 TUNGSTEN GRAPHICS AND/OR ITS 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.
- *
- **************************************************************************/
-
-#ifndef SL_PP_CONTEXT_H
-#define SL_PP_CONTEXT_H
-
-#include "sl_pp_dict.h"
-#include "sl_pp_process.h"
-#include "sl_pp_purify.h"
-#include "sl_pp_token_util.h"
-
-
-#define SL_PP_MAX_IF_NESTING 64
-
-#define SL_PP_MAX_ERROR_MSG 1024
-
-#define SL_PP_MAX_EXTENSIONS 16
-
-#define SL_PP_MAX_PREDEFINED 16
-
-struct sl_pp_extension {
- int name; /*< GL_VENDOR_extension_name */
-};
-
-struct sl_pp_predefined {
- int name;
- int value;
-};
-
-union sl_pp_if_state {
- struct {
- unsigned int condition:1;
- unsigned int went_thru_else:1;
- unsigned int had_true_cond:1;
- } u;
- unsigned int value;
-};
-
-struct sl_pp_context {
- char *cstr_pool;
- unsigned int cstr_pool_max;
- unsigned int cstr_pool_len;
- struct sl_pp_dict dict;
-
- struct sl_pp_macro *macro;
- struct sl_pp_macro **macro_tail;
-
- struct sl_pp_extension extensions[SL_PP_MAX_EXTENSIONS];
- unsigned int num_extensions;
-
- struct sl_pp_predefined predefined[SL_PP_MAX_PREDEFINED];
- unsigned int num_predefined;
-
- union sl_pp_if_state if_stack[SL_PP_MAX_IF_NESTING];
- unsigned int if_ptr;
- unsigned int if_value;
-
- char error_msg[SL_PP_MAX_ERROR_MSG];
- unsigned int error_line;
-
- unsigned int line;
- unsigned int file;
-
- struct sl_pp_purify_state pure;
-
- char *getc_buf;
- unsigned int getc_buf_size;
- unsigned int getc_buf_capacity;
-
- struct sl_pp_token_buffer tokens;
-
- struct sl_pp_process_state process_state;
-};
-
-#endif /* SL_PP_CONTEXT_H */
+++ /dev/null
-/**************************************************************************
- *
- * Copyright 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, 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 TUNGSTEN GRAPHICS AND/OR ITS 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.
- *
- **************************************************************************/
-
-#include <stdlib.h>
-#include <string.h>
-#include "sl_pp_context.h"
-#include "sl_pp_macro.h"
-#include "sl_pp_process.h"
-#include "sl_pp_public.h"
-#include "sl_pp_token.h"
-
-
-static void
-skip_whitespace(const struct sl_pp_token_info *input,
- unsigned int *first,
- unsigned int last)
-{
- while (*first < last && input[*first].token == SL_PP_WHITESPACE) {
- (*first)++;
- }
-}
-
-
-static int
-_parse_formal_args(struct sl_pp_context *context,
- const struct sl_pp_token_info *input,
- unsigned int *first,
- unsigned int last,
- struct sl_pp_macro *macro)
-{
- struct sl_pp_macro_formal_arg **arg;
-
- macro->num_args = 0;
-
- skip_whitespace(input, first, last);
- if (*first < last) {
- if (input[*first].token == SL_PP_RPAREN) {
- (*first)++;
- return 0;
- }
- } else {
- strcpy(context->error_msg, "expected either macro formal argument or `)'");
- return -1;
- }
-
- arg = ¯o->arg;
-
- for (;;) {
- if (*first < last && input[*first].token != SL_PP_IDENTIFIER) {
- strcpy(context->error_msg, "expected macro formal argument");
- return -1;
- }
-
- *arg = malloc(sizeof(struct sl_pp_macro_formal_arg));
- if (!*arg) {
- strcpy(context->error_msg, "out of memory");
- return -1;
- }
-
- (**arg).name = input[*first].data.identifier;
- (*first)++;
-
- (**arg).next = NULL;
- arg = &(**arg).next;
-
- macro->num_args++;
-
- skip_whitespace(input, first, last);
- if (*first < last) {
- if (input[*first].token == SL_PP_COMMA) {
- (*first)++;
- skip_whitespace(input, first, last);
- } else if (input[*first].token == SL_PP_RPAREN) {
- (*first)++;
- return 0;
- } else {
- strcpy(context->error_msg, "expected either `,' or `)'");
- return -1;
- }
- } else {
- strcpy(context->error_msg, "expected either `,' or `)'");
- return -1;
- }
- }
-
- /* Should not gete here. */
-}
-
-
-int
-sl_pp_process_define(struct sl_pp_context *context,
- const struct sl_pp_token_info *input,
- unsigned int first,
- unsigned int last)
-{
- int macro_name = -1;
- struct sl_pp_macro *macro;
- unsigned int i;
- unsigned int body_len;
- unsigned int j;
-
- if (first < last && input[first].token == SL_PP_IDENTIFIER) {
- macro_name = input[first].data.identifier;
- first++;
- }
- if (macro_name == -1) {
- strcpy(context->error_msg, "expected macro name");
- return -1;
- }
-
- /* Check for reserved macro names */
- {
- const char *name = sl_pp_context_cstr(context, macro_name);
-
- if (strstr(name, "__")) {
- strcpy(context->error_msg, "macro names containing `__' are reserved");
- return 1;
- }
- if (name[0] == 'G' && name[1] == 'L' && name[2] == '_') {
- strcpy(context->error_msg, "macro names prefixed with `GL_' are reserved");
- return 1;
- }
- }
-
- for (macro = context->macro; macro; macro = macro->next) {
- if (macro->name == macro_name) {
- break;
- }
- }
-
- if (!macro) {
- macro = sl_pp_macro_new();
- if (!macro) {
- strcpy(context->error_msg, "out of memory");
- return -1;
- }
-
- *context->macro_tail = macro;
- context->macro_tail = ¯o->next;
- } else {
- sl_pp_macro_reset(macro);
- }
-
- macro->name = macro_name;
-
- /*
- * If there is no whitespace between macro name and left paren, a macro
- * formal argument list follows. This is the only place where the presence
- * of a whitespace matters and it's the only reason why we are dealing
- * with whitespace at this level.
- */
- if (first < last && input[first].token == SL_PP_LPAREN) {
- first++;
- if (_parse_formal_args(context, input, &first, last, macro)) {
- return -1;
- }
- }
-
- /* Calculate body size, trim out whitespace, make room for EOF. */
- body_len = 1;
- for (i = first; i < last; i++) {
- if (input[i].token != SL_PP_WHITESPACE) {
- body_len++;
- }
- }
-
- macro->body = malloc(sizeof(struct sl_pp_token_info) * body_len);
- if (!macro->body) {
- strcpy(context->error_msg, "out of memory");
- return -1;
- }
-
- for (j = 0, i = first; i < last; i++) {
- if (input[i].token != SL_PP_WHITESPACE) {
- macro->body[j++] = input[i];
- }
- }
- macro->body[j++].token = SL_PP_EOF;
-
- return 0;
-}
-
-
-int
-sl_pp_process_undef(struct sl_pp_context *context,
- const struct sl_pp_token_info *input,
- unsigned int first,
- unsigned int last)
-{
- int macro_name = -1;
- struct sl_pp_macro **pmacro;
- struct sl_pp_macro *macro;
-
- if (first < last && input[first].token == SL_PP_IDENTIFIER) {
- macro_name = input[first].data.identifier;
- }
- if (macro_name == -1) {
- return 0;
- }
-
- for (pmacro = &context->macro; *pmacro; pmacro = &(**pmacro).next) {
- if ((**pmacro).name == macro_name) {
- break;
- }
- }
- if (!*pmacro) {
- return 0;
- }
-
- macro = *pmacro;
- *pmacro = macro->next;
- macro->next = NULL;
- sl_pp_macro_free(macro);
-
- return 0;
-}
+++ /dev/null
-/**************************************************************************
- *
- * Copyright 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, 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 TUNGSTEN GRAPHICS AND/OR ITS 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.
- *
- **************************************************************************/
-
-#include "sl_pp_public.h"
-#include "sl_pp_context.h"
-#include "sl_pp_dict.h"
-
-
-#define ADD_NAME_STR(CTX, NAME, STR)\
- do {\
- (CTX)->dict.NAME = sl_pp_context_add_unique_str((CTX), (STR));\
- if ((CTX)->dict.NAME == -1) {\
- return -1;\
- }\
- } while (0)
-
-#define ADD_NAME(CTX, NAME) ADD_NAME_STR(CTX, NAME, #NAME)
-
-
-int
-sl_pp_dict_init(struct sl_pp_context *context)
-{
- ADD_NAME(context, all);
-
- ADD_NAME(context, require);
- ADD_NAME(context, enable);
- ADD_NAME(context, warn);
- ADD_NAME(context, disable);
-
- ADD_NAME(context, defined);
-
- ADD_NAME_STR(context, ___LINE__, "__LINE__");
- ADD_NAME_STR(context, ___FILE__, "__FILE__");
- ADD_NAME_STR(context, ___VERSION__, "__VERSION__");
-
- ADD_NAME(context, optimize);
- ADD_NAME(context, debug);
-
- ADD_NAME(context, off);
- ADD_NAME(context, on);
-
- ADD_NAME(context, define);
- ADD_NAME(context, elif);
- ADD_NAME_STR(context, _else, "else");
- ADD_NAME(context, endif);
- ADD_NAME(context, error);
- ADD_NAME(context, extension);
- ADD_NAME_STR(context, _if, "if");
- ADD_NAME(context, ifdef);
- ADD_NAME(context, ifndef);
- ADD_NAME(context, line);
- ADD_NAME(context, pragma);
- ADD_NAME(context, undef);
-
- ADD_NAME(context, version);
-
- ADD_NAME_STR(context, _0, "0");
- ADD_NAME_STR(context, _1, "1");
-
- return 0;
-}
+++ /dev/null
-/**************************************************************************
- *
- * Copyright 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, 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 TUNGSTEN GRAPHICS AND/OR ITS 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.
- *
- **************************************************************************/
-
-#ifndef SL_PP_DICT_H
-#define SL_PP_DICT_H
-
-
-struct sl_pp_context;
-
-struct sl_pp_dict {
- int all;
-
- int require;
- int enable;
- int warn;
- int disable;
-
- int defined;
-
- int ___LINE__;
- int ___FILE__;
- int ___VERSION__;
-
- int optimize;
- int debug;
-
- int off;
- int on;
-
- int define;
- int elif;
- int _else;
- int endif;
- int error;
- int extension;
- int _if;
- int ifdef;
- int ifndef;
- int line;
- int pragma;
- int undef;
-
- int version;
-
- int _0;
- int _1;
-};
-
-
-int
-sl_pp_dict_init(struct sl_pp_context *context);
-
-#endif /* SL_PP_DICT_H */
+++ /dev/null
-/**************************************************************************
- *
- * Copyright 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, 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 TUNGSTEN GRAPHICS AND/OR ITS 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.
- *
- **************************************************************************/
-
-#include <stdlib.h>
-#include <string.h>
-#include "sl_pp_context.h"
-#include "sl_pp_process.h"
-#include "sl_pp_public.h"
-#include "sl_pp_token.h"
-
-
-void
-sl_pp_process_error(struct sl_pp_context *context,
- const struct sl_pp_token_info *input,
- unsigned int first,
- unsigned int last)
-{
- unsigned int out_len = 0;
- unsigned int i;
-
- for (i = first; i < last; i++) {
- const char *s = NULL;
- char buf[2];
-
- switch (input[i].token) {
- case SL_PP_WHITESPACE:
- s = " ";
- break;
-
- case SL_PP_NEWLINE:
- s = "\n";
- break;
-
- case SL_PP_HASH:
- s = "#";
- break;
-
- case SL_PP_COMMA:
- s = ",";
- break;
-
- case SL_PP_SEMICOLON:
- s = ";";
- break;
-
- case SL_PP_LBRACE:
- s = "{";
- break;
-
- case SL_PP_RBRACE:
- s = "}";
- break;
-
- case SL_PP_LPAREN:
- s = "(";
- break;
-
- case SL_PP_RPAREN:
- s = ")";
- break;
-
- case SL_PP_LBRACKET:
- s = "[";
- break;
-
- case SL_PP_RBRACKET:
- s = "]";
- break;
-
- case SL_PP_DOT:
- s = ".";
- break;
-
- case SL_PP_INCREMENT:
- s = "++";
- break;
-
- case SL_PP_ADDASSIGN:
- s = "+=";
- break;
-
- case SL_PP_PLUS:
- s = "+";
- break;
-
- case SL_PP_DECREMENT:
- s = "--";
- break;
-
- case SL_PP_SUBASSIGN:
- s = "-=";
- break;
-
- case SL_PP_MINUS:
- s = "-";
- break;
-
- case SL_PP_BITNOT:
- s = "~";
- break;
-
- case SL_PP_NOTEQUAL:
- s = "!=";
- break;
-
- case SL_PP_NOT:
- s = "!";
- break;
-
- case SL_PP_MULASSIGN:
- s = "*=";
- break;
-
- case SL_PP_STAR:
- s = "*";
- break;
-
- case SL_PP_DIVASSIGN:
- s = "/=";
- break;
-
- case SL_PP_SLASH:
- s = "/";
- break;
-
- case SL_PP_MODASSIGN:
- s = "%=";
- break;
-
- case SL_PP_MODULO:
- s = "%";
- break;
-
- case SL_PP_LSHIFTASSIGN:
- s = "<<=";
- break;
-
- case SL_PP_LSHIFT:
- s = "<<";
- break;
-
- case SL_PP_LESSEQUAL:
- s = "<=";
- break;
-
- case SL_PP_LESS:
- s = "<";
- break;
-
- case SL_PP_RSHIFTASSIGN:
- s = ">>=";
- break;
-
- case SL_PP_RSHIFT:
- s = ">>";
- break;
-
- case SL_PP_GREATEREQUAL:
- s = ">=";
- break;
-
- case SL_PP_GREATER:
- s = ">";
- break;
-
- case SL_PP_EQUAL:
- s = "==";
- break;
-
- case SL_PP_ASSIGN:
- s = "=";
- break;
-
- case SL_PP_AND:
- s = "&&";
- break;
-
- case SL_PP_BITANDASSIGN:
- s = "&=";
- break;
-
- case SL_PP_BITAND:
- s = "&";
- break;
-
- case SL_PP_XOR:
- s = "^^";
- break;
-
- case SL_PP_BITXORASSIGN:
- s = "^=";
- break;
-
- case SL_PP_BITXOR:
- s = "^";
- break;
-
- case SL_PP_OR:
- s = "||";
- break;
-
- case SL_PP_BITORASSIGN:
- s = "|=";
- break;
-
- case SL_PP_BITOR:
- s = "|";
- break;
-
- case SL_PP_QUESTION:
- s = "?";
- break;
-
- case SL_PP_COLON:
- s = ":";
- break;
-
- case SL_PP_IDENTIFIER:
- s = sl_pp_context_cstr(context, input[i].data.identifier);
- break;
-
- case SL_PP_UINT:
- s = sl_pp_context_cstr(context, input[i].data._uint);
- break;
-
- case SL_PP_FLOAT:
- s = sl_pp_context_cstr(context, input[i].data._float);
- break;
-
- case SL_PP_OTHER:
- buf[0] = input[i].data.other;
- buf[1] = '\0';
- s = buf;
- break;
-
- default:
- strcpy(context->error_msg, "internal error");
- return;
- }
-
- while (*s != '\0' && out_len < sizeof(context->error_msg) - 1) {
- context->error_msg[out_len++] = *s++;
- }
- }
-
- context->error_msg[out_len] = '\0';
-}
+++ /dev/null
-/**************************************************************************
- *
- * Copyright 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, 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 TUNGSTEN GRAPHICS AND/OR ITS 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.
- *
- **************************************************************************/
-
-#include <stdlib.h>
-#include <string.h>
-#include "sl_pp_context.h"
-#include "sl_pp_expression.h"
-#include "sl_pp_public.h"
-#include "sl_pp_token.h"
-
-
-struct parse_context {
- struct sl_pp_context *context;
- const struct sl_pp_token_info *input;
-};
-
-static int
-_parse_or(struct parse_context *ctx,
- int *result);
-
-static int
-_parse_primary(struct parse_context *ctx,
- int *result)
-{
- if (ctx->input->token == SL_PP_UINT) {
- *result = atoi(sl_pp_context_cstr(ctx->context, ctx->input->data._uint));
- ctx->input++;
- } else {
- if (ctx->input->token != SL_PP_LPAREN) {
- strcpy(ctx->context->error_msg, "expected `('");
- return -1;
- }
- ctx->input++;
- if (_parse_or(ctx, result)) {
- return -1;
- }
- if (ctx->input->token != SL_PP_RPAREN) {
- strcpy(ctx->context->error_msg, "expected `)'");
- return -1;
- }
- ctx->input++;
- }
- return 0;
-}
-
-static int
-_parse_unary(struct parse_context *ctx,
- int *result)
-{
- if (!_parse_primary(ctx, result)) {
- return 0;
- }
-
- switch (ctx->input->token) {
- case SL_PP_PLUS:
- ctx->input++;
- if (_parse_unary(ctx, result)) {
- return -1;
- }
- *result = +*result;
- break;
-
- case SL_PP_MINUS:
- ctx->input++;
- if (_parse_unary(ctx, result)) {
- return -1;
- }
- *result = -*result;
- break;
-
- case SL_PP_NOT:
- ctx->input++;
- if (_parse_unary(ctx, result)) {
- return -1;
- }
- *result = !*result;
- break;
-
- case SL_PP_BITNOT:
- ctx->input++;
- if (_parse_unary(ctx, result)) {
- return -1;
- }
- *result = ~*result;
- break;
-
- default:
- return -1;
- }
-
- return 0;
-}
-
-static int
-_parse_multiplicative(struct parse_context *ctx,
- int *result)
-{
- if (_parse_unary(ctx, result)) {
- return -1;
- }
- for (;;) {
- int right;
-
- switch (ctx->input->token) {
- case SL_PP_STAR:
- ctx->input++;
- if (_parse_unary(ctx, &right)) {
- return -1;
- }
- *result = *result * right;
- break;
-
- case SL_PP_SLASH:
- ctx->input++;
- if (_parse_unary(ctx, &right)) {
- return -1;
- }
- *result = *result / right;
- break;
-
- case SL_PP_MODULO:
- ctx->input++;
- if (_parse_unary(ctx, &right)) {
- return -1;
- }
- *result = *result % right;
- break;
-
- default:
- return 0;
- }
- }
-}
-
-static int
-_parse_additive(struct parse_context *ctx,
- int *result)
-{
- if (_parse_multiplicative(ctx, result)) {
- return -1;
- }
- for (;;) {
- int right;
-
- switch (ctx->input->token) {
- case SL_PP_PLUS:
- ctx->input++;
- if (_parse_multiplicative(ctx, &right)) {
- return -1;
- }
- *result = *result + right;
- break;
-
- case SL_PP_MINUS:
- ctx->input++;
- if (_parse_multiplicative(ctx, &right)) {
- return -1;
- }
- *result = *result - right;
- break;
-
- default:
- return 0;
- }
- }
-}
-
-static int
-_parse_shift(struct parse_context *ctx,
- int *result)
-{
- if (_parse_additive(ctx, result)) {
- return -1;
- }
- for (;;) {
- int right;
-
- switch (ctx->input->token) {
- case SL_PP_LSHIFT:
- ctx->input++;
- if (_parse_additive(ctx, &right)) {
- return -1;
- }
- *result = *result << right;
- break;
-
- case SL_PP_RSHIFT:
- ctx->input++;
- if (_parse_additive(ctx, &right)) {
- return -1;
- }
- *result = *result >> right;
- break;
-
- default:
- return 0;
- }
- }
-}
-
-static int
-_parse_relational(struct parse_context *ctx,
- int *result)
-{
- if (_parse_shift(ctx, result)) {
- return -1;
- }
- for (;;) {
- int right;
-
- switch (ctx->input->token) {
- case SL_PP_LESSEQUAL:
- ctx->input++;
- if (_parse_shift(ctx, &right)) {
- return -1;
- }
- *result = *result <= right;
- break;
-
- case SL_PP_GREATEREQUAL:
- ctx->input++;
- if (_parse_shift(ctx, &right)) {
- return -1;
- }
- *result = *result >= right;
- break;
-
- case SL_PP_LESS:
- ctx->input++;
- if (_parse_shift(ctx, &right)) {
- return -1;
- }
- *result = *result < right;
- break;
-
- case SL_PP_GREATER:
- ctx->input++;
- if (_parse_shift(ctx, &right)) {
- return -1;
- }
- *result = *result > right;
- break;
-
- default:
- return 0;
- }
- }
-}
-
-static int
-_parse_equality(struct parse_context *ctx,
- int *result)
-{
- if (_parse_relational(ctx, result)) {
- return -1;
- }
- for (;;) {
- int right;
-
- switch (ctx->input->token) {
- case SL_PP_EQUAL:
- ctx->input++;
- if (_parse_relational(ctx, &right)) {
- return -1;
- }
- *result = *result == right;
- break;
-
- case SL_PP_NOTEQUAL:
- ctx->input++;
- if (_parse_relational(ctx, &right)) {
- return -1;
- }
- *result = *result != right;
- break;
-
- default:
- return 0;
- }
- }
-}
-
-static int
-_parse_bitand(struct parse_context *ctx,
- int *result)
-{
- if (_parse_equality(ctx, result)) {
- return -1;
- }
- while (ctx->input->token == SL_PP_BITAND) {
- int right;
-
- ctx->input++;
- if (_parse_equality(ctx, &right)) {
- return -1;
- }
- *result = *result & right;
- }
- return 0;
-}
-
-static int
-_parse_xor(struct parse_context *ctx,
- int *result)
-{
- if (_parse_bitand(ctx, result)) {
- return -1;
- }
- while (ctx->input->token == SL_PP_XOR) {
- int right;
-
- ctx->input++;
- if (_parse_bitand(ctx, &right)) {
- return -1;
- }
- *result = *result ^ right;
- }
- return 0;
-}
-
-static int
-_parse_bitor(struct parse_context *ctx,
- int *result)
-{
- if (_parse_xor(ctx, result)) {
- return -1;
- }
- while (ctx->input->token == SL_PP_BITOR) {
- int right;
-
- ctx->input++;
- if (_parse_xor(ctx, &right)) {
- return -1;
- }
- *result = *result | right;
- }
- return 0;
-}
-
-static int
-_parse_and(struct parse_context *ctx,
- int *result)
-{
- if (_parse_bitor(ctx, result)) {
- return -1;
- }
- while (ctx->input->token == SL_PP_AND) {
- int right;
-
- ctx->input++;
- if (_parse_bitor(ctx, &right)) {
- return -1;
- }
- *result = *result && right;
- }
- return 0;
-}
-
-static int
-_parse_or(struct parse_context *ctx,
- int *result)
-{
- if (_parse_and(ctx, result)) {
- return -1;
- }
- while (ctx->input->token == SL_PP_OR) {
- int right;
-
- ctx->input++;
- if (_parse_and(ctx, &right)) {
- return -1;
- }
- *result = *result || right;
- }
- return 0;
-}
-
-int
-sl_pp_execute_expression(struct sl_pp_context *context,
- const struct sl_pp_token_info *input,
- int *result)
-{
- struct parse_context ctx;
-
- ctx.context = context;
- ctx.input = input;
-
- return _parse_or(&ctx, result);
-}
+++ /dev/null
-/**************************************************************************
- *
- * Copyright 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, 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 TUNGSTEN GRAPHICS AND/OR ITS 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.
- *
- **************************************************************************/
-
-#ifndef SL_PP_EXPRESSION_H
-#define SL_PP_EXPRESSION_H
-
-struct sl_pp_context;
-struct sl_pp_token_info;
-
-
-int
-sl_pp_execute_expression(struct sl_pp_context *context,
- const struct sl_pp_token_info *input,
- int *result);
-
-#endif /* SL_PP_EXPRESSION_H */
+++ /dev/null
-/**************************************************************************
- *
- * Copyright 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, 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 TUNGSTEN GRAPHICS AND/OR ITS 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.
- *
- **************************************************************************/
-
-#include <assert.h>
-#include <stdlib.h>
-#include <string.h>
-#include "sl_pp_context.h"
-#include "sl_pp_process.h"
-#include "sl_pp_public.h"
-#include "sl_pp_token.h"
-
-
-/**
- * Declare an extension to the preprocessor. This tells the preprocessor
- * which extensions are supported by Mesa.
- * The shader still needs to have a "#extension name: behavior" line to enable
- * the extension.
- */
-int
-sl_pp_context_add_extension(struct sl_pp_context *context,
- const char *name)
-{
- struct sl_pp_extension ext;
-
- if (context->num_extensions == SL_PP_MAX_EXTENSIONS) {
- return -1;
- }
-
- ext.name = sl_pp_context_add_unique_str(context, name);
- if (ext.name == -1) {
- return -1;
- }
-
- context->extensions[context->num_extensions++] = ext;
-
- assert(context->num_extensions <= sizeof(context->extensions));
-
- return 0;
-}
-
-
-/**
- * Process a "#extension name: behavior" directive.
- */
-int
-sl_pp_process_extension(struct sl_pp_context *context,
- const struct sl_pp_token_info *input,
- unsigned int first,
- unsigned int last,
- struct sl_pp_process_state *state)
-{
- int extension_name = -1;
- int behavior = -1;
- struct sl_pp_token_info out;
-
- /* Grab the extension name. */
- if (first < last && input[first].token == SL_PP_IDENTIFIER) {
- extension_name = input[first].data.identifier;
- first++;
- }
- if (extension_name == -1) {
- strcpy(context->error_msg, "expected identifier after `#extension'");
- return -1;
- }
-
- /* Make sure the extension is supported. */
- if (extension_name == context->dict.all) {
- out.data.extension = extension_name;
- } else {
- unsigned int i;
-
- out.data.extension = -1;
- for (i = 0; i < context->num_extensions; i++) {
- if (extension_name == context->extensions[i].name) {
- out.data.extension = extension_name;
- break;
- }
- }
- }
-
- /* Grab the colon separating the extension name and behavior. */
- while (first < last && input[first].token == SL_PP_WHITESPACE) {
- first++;
- }
- if (first < last && input[first].token == SL_PP_COLON) {
- first++;
- } else {
- strcpy(context->error_msg, "expected `:' after extension name");
- return -1;
- }
- while (first < last && input[first].token == SL_PP_WHITESPACE) {
- first++;
- }
-
- /* Grab the behavior name. */
- if (first < last && input[first].token == SL_PP_IDENTIFIER) {
- behavior = input[first].data.identifier;
- first++;
- }
- if (behavior == -1) {
- strcpy(context->error_msg, "expected identifier after `:'");
- return -1;
- }
-
- if (behavior == context->dict.require) {
- if (out.data.extension == -1) {
- strcpy(context->error_msg, "the required extension is not supported");
- return -1;
- }
- if (out.data.extension == context->dict.all) {
- strcpy(context->error_msg, "invalid behavior for `all' extension: `require'");
- return -1;
- }
- out.token = SL_PP_EXTENSION_REQUIRE;
- } else if (behavior == context->dict.enable) {
- if (out.data.extension == -1) {
- /* Warning: the extension cannot be enabled. */
- return 0;
- }
- if (out.data.extension == context->dict.all) {
- strcpy(context->error_msg, "invalid behavior for `all' extension: `enable'");
- return -1;
- }
- out.token = SL_PP_EXTENSION_ENABLE;
- } else if (behavior == context->dict.warn) {
- if (out.data.extension == -1) {
- /* Warning: the extension is not supported. */
- return 0;
- }
- out.token = SL_PP_EXTENSION_WARN;
- } else if (behavior == context->dict.disable) {
- if (out.data.extension == -1) {
- /* Warning: the extension is not supported. */
- return 0;
- }
- out.token = SL_PP_EXTENSION_DISABLE;
- } else {
- strcpy(context->error_msg, "unrecognised behavior name");
- return -1;
- }
-
- /* Grab the end of line. */
- while (first < last && input[first].token == SL_PP_WHITESPACE) {
- first++;
- }
- if (first < last) {
- strcpy(context->error_msg, "expected end of line after behavior name");
- return -1;
- }
-
- if (sl_pp_process_out(state, &out)) {
- return -1;
- }
-
- return 0;
-}
+++ /dev/null
-/**************************************************************************
- *
- * Copyright 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, 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 TUNGSTEN GRAPHICS AND/OR ITS 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.
- *
- **************************************************************************/
-
-#include <stdlib.h>
-#include <string.h>
-#include "sl_pp_context.h"
-#include "sl_pp_expression.h"
-#include "sl_pp_macro.h"
-#include "sl_pp_process.h"
-#include "sl_pp_token.h"
-
-
-static int
-_macro_is_defined(struct sl_pp_context *context,
- int macro_name)
-{
- unsigned int i;
- struct sl_pp_macro *macro;
-
- for (i = 0; i < context->num_extensions; i++) {
- if (macro_name == context->extensions[i].name) {
- return 1;
- }
- }
-
- for (macro = context->macro; macro; macro = macro->next) {
- if (macro_name == macro->name) {
- return 1;
- }
- }
-
- return 0;
-}
-
-static int
-_parse_defined(struct sl_pp_context *context,
- struct sl_pp_token_buffer *buffer,
- struct sl_pp_process_state *state)
-{
- struct sl_pp_token_info input;
- int parens = 0;
- int defined;
- struct sl_pp_token_info result;
-
- if (sl_pp_token_buffer_skip_white(buffer, &input)) {
- return -1;
- }
-
- if (input.token == SL_PP_LPAREN) {
- if (sl_pp_token_buffer_skip_white(buffer, &input)) {
- return -1;
- }
- parens = 1;
- }
-
- if (input.token != SL_PP_IDENTIFIER) {
- strcpy(context->error_msg, "expected an identifier");
- return -1;
- }
-
- defined = _macro_is_defined(context, input.data.identifier);
-
- if (parens) {
- if (sl_pp_token_buffer_skip_white(buffer, &input)) {
- return -1;
- }
- if (input.token != SL_PP_RPAREN) {
- strcpy(context->error_msg, "expected `)'");
- return -1;
- }
- }
-
- result.token = SL_PP_UINT;
- result.data._uint = (defined ? context->dict._1 : context->dict._0);
-
- if (sl_pp_process_out(state, &result)) {
- strcpy(context->error_msg, "out of memory");
- return -1;
- }
-
- return 0;
-}
-
-static unsigned int
-_evaluate_if_stack(struct sl_pp_context *context)
-{
- unsigned int i;
-
- for (i = context->if_ptr; i < SL_PP_MAX_IF_NESTING; i++) {
- if (!context->if_stack[i].u.condition) {
- return 0;
- }
- }
- return 1;
-}
-
-static int
-_parse_if(struct sl_pp_context *context,
- struct sl_pp_token_buffer *buffer)
-{
- struct sl_pp_process_state state;
- int found_end = 0;
- struct sl_pp_token_info eof;
- int result;
-
- if (!context->if_ptr) {
- strcpy(context->error_msg, "`#if' nesting too deep");
- return -1;
- }
-
- memset(&state, 0, sizeof(state));
- while (!found_end) {
- struct sl_pp_token_info input;
-
- sl_pp_token_buffer_get(buffer, &input);
- switch (input.token) {
- case SL_PP_WHITESPACE:
- break;
-
- case SL_PP_IDENTIFIER:
- if (input.data.identifier == context->dict.defined) {
- if (_parse_defined(context, buffer, &state)) {
- free(state.out);
- return -1;
- }
- } else {
- sl_pp_token_buffer_unget(buffer, &input);
- if (sl_pp_macro_expand(context, buffer, NULL, &state, sl_pp_macro_expand_unknown_to_0)) {
- free(state.out);
- return -1;
- }
- }
- break;
-
- case SL_PP_NEWLINE:
- case SL_PP_EOF:
- found_end = 1;
- break;
-
- default:
- if (sl_pp_process_out(&state, &input)) {
- strcpy(context->error_msg, "out of memory");
- free(state.out);
- return -1;
- }
- }
- }
-
- eof.token = SL_PP_EOF;
- if (sl_pp_process_out(&state, &eof)) {
- strcpy(context->error_msg, "out of memory");
- free(state.out);
- return -1;
- }
-
- if (sl_pp_execute_expression(context, state.out, &result)) {
- free(state.out);
- return -1;
- }
-
- free(state.out);
-
- context->if_ptr--;
- context->if_stack[context->if_ptr].value = 0;
- context->if_stack[context->if_ptr].u.condition = result ? 1 : 0;
- context->if_value = _evaluate_if_stack(context);
-
- return 0;
-}
-
-static int
-_parse_else(struct sl_pp_context *context)
-{
- union sl_pp_if_state *state = &context->if_stack[context->if_ptr];
-
- if (context->if_ptr == SL_PP_MAX_IF_NESTING) {
- strcpy(context->error_msg, "no matching `#if'");
- return -1;
- }
-
- if (state->u.went_thru_else) {
- strcpy(context->error_msg, "no matching `#if'");
- return -1;
- }
-
- /* Once we had a true condition, the subsequent #elifs should always be false. */
- state->u.had_true_cond |= state->u.condition;
-
- /* Update current condition value and mark that we are in the #else block. */
- state->u.condition = !(state->u.had_true_cond | state->u.condition);
- state->u.went_thru_else = 1;
- context->if_value = _evaluate_if_stack(context);
-
- return 0;
-}
-
-int
-sl_pp_process_if(struct sl_pp_context *context,
- struct sl_pp_token_buffer *buffer)
-{
- return _parse_if(context, buffer);
-}
-
-int
-sl_pp_process_ifdef(struct sl_pp_context *context,
- const struct sl_pp_token_info *input,
- unsigned int first,
- unsigned int last)
-{
- unsigned int i;
-
- if (!context->if_ptr) {
- strcpy(context->error_msg, "`#if' nesting too deep");
- return -1;
- }
-
- for (i = first; i < last; i++) {
- switch (input[i].token) {
- case SL_PP_IDENTIFIER:
- context->if_ptr--;
- context->if_stack[context->if_ptr].value = 0;
- context->if_stack[context->if_ptr].u.condition = _macro_is_defined(context, input[i].data.identifier);
- context->if_value = _evaluate_if_stack(context);
- return 0;
-
- case SL_PP_WHITESPACE:
- break;
-
- default:
- strcpy(context->error_msg, "expected an identifier");
- return -1;
- }
- }
-
- strcpy(context->error_msg, "expected an identifier");
- return -1;
-}
-
-int
-sl_pp_process_ifndef(struct sl_pp_context *context,
- const struct sl_pp_token_info *input,
- unsigned int first,
- unsigned int last)
-{
- unsigned int i;
-
- if (!context->if_ptr) {
- strcpy(context->error_msg, "`#if' nesting too deep");
- return -1;
- }
-
- for (i = first; i < last; i++) {
- switch (input[i].token) {
- case SL_PP_IDENTIFIER:
- context->if_ptr--;
- context->if_stack[context->if_ptr].value = 0;
- context->if_stack[context->if_ptr].u.condition = !_macro_is_defined(context, input[i].data.identifier);
- context->if_value = _evaluate_if_stack(context);
- return 0;
-
- case SL_PP_WHITESPACE:
- break;
-
- default:
- strcpy(context->error_msg, "expected an identifier");
- return -1;
- }
- }
-
- strcpy(context->error_msg, "expected an identifier");
- return -1;
-}
-
-int
-sl_pp_process_elif(struct sl_pp_context *context,
- struct sl_pp_token_buffer *buffer)
-{
- if (_parse_else(context)) {
- return -1;
- }
-
- if (context->if_stack[context->if_ptr].u.condition) {
- context->if_ptr++;
- if (_parse_if(context, buffer)) {
- return -1;
- }
- }
-
- /* We are still in the #if block. */
- context->if_stack[context->if_ptr].u.went_thru_else = 0;
-
- return 0;
-}
-
-int
-sl_pp_process_else(struct sl_pp_context *context,
- const struct sl_pp_token_info *input,
- unsigned int first,
- unsigned int last)
-{
- return _parse_else(context);
-}
-
-int
-sl_pp_process_endif(struct sl_pp_context *context,
- const struct sl_pp_token_info *input,
- unsigned int first,
- unsigned int last)
-{
- if (context->if_ptr == SL_PP_MAX_IF_NESTING) {
- strcpy(context->error_msg, "no matching `#if'");
- return -1;
- }
-
- context->if_ptr++;
- context->if_value = _evaluate_if_stack(context);
-
- return 0;
-}
+++ /dev/null
-/**************************************************************************
- *
- * Copyright 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, 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 TUNGSTEN GRAPHICS AND/OR ITS 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.
- *
- **************************************************************************/
-
-#include <stdlib.h>
-#include <string.h>
-#include "sl_pp_context.h"
-#include "sl_pp_macro.h"
-#include "sl_pp_public.h"
-#include "sl_pp_process.h"
-#include "sl_pp_token.h"
-
-
-int
-sl_pp_process_line(struct sl_pp_context *context,
- struct sl_pp_token_buffer *buffer,
- struct sl_pp_process_state *pstate)
-{
- struct sl_pp_process_state state;
- int found_end = 0;
- int line_number = -1;
- int file_number = -1;
- unsigned int line;
- unsigned int file;
-
- memset(&state, 0, sizeof(state));
- while (!found_end) {
- struct sl_pp_token_info input;
-
- sl_pp_token_buffer_get(buffer, &input);
- switch (input.token) {
- case SL_PP_WHITESPACE:
- break;
-
- case SL_PP_IDENTIFIER:
- sl_pp_token_buffer_unget(buffer, &input);
- if (sl_pp_macro_expand(context, buffer, NULL, &state, sl_pp_macro_expand_normal)) {
- free(state.out);
- return -1;
- }
- break;
-
- case SL_PP_NEWLINE:
- case SL_PP_EOF:
- found_end = 1;
- break;
-
- default:
- if (sl_pp_process_out(&state, &input)) {
- strcpy(context->error_msg, "out of memory");
- free(state.out);
- return -1;
- }
- }
- }
-
- if (state.out_len > 0 && state.out[0].token == SL_PP_UINT) {
- line_number = state.out[0].data._uint;
- } else {
- strcpy(context->error_msg, "expected a number after `#line'");
- free(state.out);
- return -1;
- }
-
- if (state.out_len > 1) {
- if (state.out[1].token == SL_PP_UINT) {
- file_number = state.out[1].data._uint;
- } else {
- strcpy(context->error_msg, "expected a number after line number");
- free(state.out);
- return -1;
- }
-
- if (state.out_len > 2) {
- strcpy(context->error_msg, "expected an end of line after file number");
- free(state.out);
- return -1;
- }
- }
-
- free(state.out);
-
- line = atoi(sl_pp_context_cstr(context, line_number));
- if (file_number != -1) {
- file = atoi(sl_pp_context_cstr(context, file_number));
- } else {
- file = context->file;
- }
-
- if (context->line != line || context->file != file) {
- struct sl_pp_token_info ti;
-
- ti.token = SL_PP_LINE;
- ti.data.line.lineno = line;
- ti.data.line.fileno = file;
- if (sl_pp_process_out(pstate, &ti)) {
- strcpy(context->error_msg, "out of memory");
- return -1;
- }
-
- context->line = line;
- context->file = file;
- }
-
- return 0;
-}
+++ /dev/null
-/**************************************************************************
- *
- * Copyright 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, 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 TUNGSTEN GRAPHICS AND/OR ITS 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.
- *
- **************************************************************************/
-
-#include <stdlib.h>
-#include <stdio.h>
-#include <string.h>
-#include "sl_pp_context.h"
-#include "sl_pp_public.h"
-#include "sl_pp_macro.h"
-#include "sl_pp_process.h"
-#include "sl_pp_token.h"
-
-
-static void
-_macro_init(struct sl_pp_macro *macro)
-{
- macro->name = -1;
- macro->num_args = -1;
- macro->arg = NULL;
- macro->body = NULL;
-}
-
-struct sl_pp_macro *
-sl_pp_macro_new(void)
-{
- struct sl_pp_macro *macro;
-
- macro = calloc(1, sizeof(struct sl_pp_macro));
- if (macro) {
- _macro_init(macro);
- }
- return macro;
-}
-
-static void
-_macro_destroy(struct sl_pp_macro *macro)
-{
- struct sl_pp_macro_formal_arg *arg = macro->arg;
-
- while (arg) {
- struct sl_pp_macro_formal_arg *next_arg = arg->next;
-
- free(arg);
- arg = next_arg;
- }
-
- free(macro->body);
-}
-
-void
-sl_pp_macro_free(struct sl_pp_macro *macro)
-{
- while (macro) {
- struct sl_pp_macro *next_macro = macro->next;
-
- _macro_destroy(macro);
- free(macro);
- macro = next_macro;
- }
-}
-
-void
-sl_pp_macro_reset(struct sl_pp_macro *macro)
-{
- _macro_destroy(macro);
- _macro_init(macro);
-}
-
-static int
-_out_number(struct sl_pp_context *context,
- struct sl_pp_process_state *state,
- unsigned int number)
-{
- char buf[32];
- struct sl_pp_token_info ti;
-
- sprintf(buf, "%u", number);
-
- ti.token = SL_PP_UINT;
- ti.data._uint = sl_pp_context_add_unique_str(context, buf);
- if (sl_pp_process_out(state, &ti)) {
- strcpy(context->error_msg, "out of memory");
- return -1;
- }
-
- return 0;
-}
-
-int
-sl_pp_macro_expand(struct sl_pp_context *context,
- struct sl_pp_token_buffer *tokens,
- struct sl_pp_macro *local,
- struct sl_pp_process_state *state,
- enum sl_pp_macro_expand_behaviour behaviour)
-{
- int mute = (behaviour == sl_pp_macro_expand_mute);
- struct sl_pp_token_info input;
- int macro_name;
- struct sl_pp_macro *macro = NULL;
- struct sl_pp_macro *actual_arg = NULL;
- unsigned int j;
-
- if (sl_pp_token_buffer_get(tokens, &input)) {
- return -1;
- }
-
- if (input.token != SL_PP_IDENTIFIER) {
- strcpy(context->error_msg, "expected an identifier");
- return -1;
- }
-
- macro_name = input.data.identifier;
-
- /* First look for predefined macros.
- */
-
- if (macro_name == context->dict.___LINE__) {
- if (!mute && _out_number(context, state, context->line)) {
- return -1;
- }
- return 0;
- }
- if (macro_name == context->dict.___FILE__) {
- if (!mute && _out_number(context, state, context->file)) {
- return -1;
- }
- return 0;
- }
- if (macro_name == context->dict.___VERSION__) {
- if (!mute && _out_number(context, state, 110)) {
- return -1;
- }
- return 0;
- }
-
- for (j = 0; j < context->num_predefined; j++) {
- if (macro_name == context->predefined[j].name) {
- if (!mute) {
- struct sl_pp_token_info ti;
-
- ti.token = SL_PP_UINT;
- ti.data._uint = context->predefined[j].value;
- if (sl_pp_process_out(state, &ti)) {
- strcpy(context->error_msg, "out of memory");
- return -1;
- }
- }
- return 0;
- }
- }
-
- /* Replace extension names with 1.
- */
- for (j = 0; j < context->num_extensions; j++) {
- if (macro_name == context->extensions[j].name) {
- if (!mute && _out_number(context, state, 1)) {
- return -1;
- }
- return 0;
- }
- }
-
- if (local) {
- for (macro = local; macro; macro = macro->next) {
- if (macro->name == macro_name) {
- break;
- }
- }
- }
-
- if (!macro) {
- for (macro = context->macro; macro; macro = macro->next) {
- if (macro->name == macro_name) {
- break;
- }
- }
- }
-
- if (!macro) {
- if (behaviour == sl_pp_macro_expand_unknown_to_0) {
- if (_out_number(context, state, 0)) {
- strcpy(context->error_msg, "out of memory");
- return -1;
- }
- } else if (!mute) {
- if (sl_pp_process_out(state, &input)) {
- strcpy(context->error_msg, "out of memory");
- return -1;
- }
- }
- return 0;
- }
-
- if (macro->num_args >= 0) {
- if (sl_pp_token_buffer_skip_white(tokens, &input)) {
- return -1;
- }
- if (input.token != SL_PP_LPAREN) {
- strcpy(context->error_msg, "expected `('");
- return -1;
- }
- if (sl_pp_token_buffer_skip_white(tokens, &input)) {
- return -1;
- }
- sl_pp_token_buffer_unget(tokens, &input);
- }
-
- if (macro->num_args > 0) {
- struct sl_pp_macro_formal_arg *formal_arg = macro->arg;
- struct sl_pp_macro **pmacro = &actual_arg;
-
- for (j = 0; j < (unsigned int)macro->num_args; j++) {
- struct sl_pp_process_state arg_state;
- int done = 0;
- unsigned int paren_nesting = 0;
- struct sl_pp_token_info eof;
-
- memset(&arg_state, 0, sizeof(arg_state));
-
- while (!done) {
- if (sl_pp_token_buffer_get(tokens, &input)) {
- goto fail_arg;
- }
- switch (input.token) {
- case SL_PP_WHITESPACE:
- break;
-
- case SL_PP_COMMA:
- if (!paren_nesting) {
- if (j < (unsigned int)macro->num_args - 1) {
- done = 1;
- } else {
- strcpy(context->error_msg, "too many actual macro arguments");
- goto fail_arg;
- }
- } else {
- if (sl_pp_process_out(&arg_state, &input)) {
- strcpy(context->error_msg, "out of memory");
- goto fail_arg;
- }
- }
- break;
-
- case SL_PP_LPAREN:
- paren_nesting++;
- if (sl_pp_process_out(&arg_state, &input)) {
- goto oom_arg;
- }
- break;
-
- case SL_PP_RPAREN:
- if (!paren_nesting) {
- if (j == (unsigned int)macro->num_args - 1) {
- done = 1;
- } else {
- strcpy(context->error_msg, "too few actual macro arguments");
- goto fail_arg;
- }
- } else {
- paren_nesting--;
- if (sl_pp_process_out(&arg_state, &input)) {
- goto oom_arg;
- }
- }
- break;
-
- case SL_PP_IDENTIFIER:
- sl_pp_token_buffer_unget(tokens, &input);
- if (sl_pp_macro_expand(context, tokens, local, &arg_state, sl_pp_macro_expand_normal)) {
- goto fail_arg;
- }
- break;
-
- case SL_PP_EOF:
- strcpy(context->error_msg, "too few actual macro arguments");
- goto fail_arg;
-
- default:
- if (sl_pp_process_out(&arg_state, &input)) {
- goto oom_arg;
- }
- }
- }
-
- eof.token = SL_PP_EOF;
- if (sl_pp_process_out(&arg_state, &eof)) {
- goto oom_arg;
- }
-
- *pmacro = sl_pp_macro_new();
- if (!*pmacro) {
- goto oom_arg;
- }
-
- (**pmacro).name = formal_arg->name;
- (**pmacro).body = arg_state.out;
-
- formal_arg = formal_arg->next;
- pmacro = &(**pmacro).next;
-
- continue;
-
-oom_arg:
- strcpy(context->error_msg, "out of memory");
-fail_arg:
- free(arg_state.out);
- goto fail;
- }
- }
-
- /* Right paren for non-empty argument list has already been eaten. */
- if (macro->num_args == 0) {
- if (sl_pp_token_buffer_skip_white(tokens, &input)) {
- goto fail;
- }
- if (input.token != SL_PP_RPAREN) {
- strcpy(context->error_msg, "expected `)'");
- goto fail;
- }
- }
-
- /* XXX: This is all wrong, we should be ungetting all tokens
- * back to the main token buffer.
- */
- {
- struct sl_pp_token_buffer buffer;
-
- /* Seek to the end.
- */
- for (j = 0; macro->body[j].token != SL_PP_EOF; j++) {
- }
- j++;
-
- /* Create a context-less token buffer since we are not going to underrun
- * its internal buffer.
- */
- if (sl_pp_token_buffer_init(&buffer, NULL)) {
- strcpy(context->error_msg, "out of memory");
- goto fail;
- }
-
- /* Unget the tokens in reverse order so later they will be fetched correctly.
- */
- for (; j > 0; j--) {
- sl_pp_token_buffer_unget(&buffer, ¯o->body[j - 1]);
- }
-
- /* Expand.
- */
- for (;;) {
- struct sl_pp_token_info input;
-
- sl_pp_token_buffer_get(&buffer, &input);
- switch (input.token) {
- case SL_PP_NEWLINE:
- if (sl_pp_process_out(state, &input)) {
- strcpy(context->error_msg, "out of memory");
- sl_pp_token_buffer_destroy(&buffer);
- goto fail;
- }
- break;
-
- case SL_PP_IDENTIFIER:
- sl_pp_token_buffer_unget(&buffer, &input);
- if (sl_pp_macro_expand(context, &buffer, actual_arg, state, behaviour)) {
- sl_pp_token_buffer_destroy(&buffer);
- goto fail;
- }
- break;
-
- case SL_PP_EOF:
- sl_pp_token_buffer_destroy(&buffer);
- sl_pp_macro_free(actual_arg);
- return 0;
-
- default:
- if (!mute) {
- if (sl_pp_process_out(state, &input)) {
- strcpy(context->error_msg, "out of memory");
- sl_pp_token_buffer_destroy(&buffer);
- goto fail;
- }
- }
- }
- }
- }
-
-fail:
- sl_pp_macro_free(actual_arg);
- return -1;
-}
+++ /dev/null
-/**************************************************************************
- *
- * Copyright 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, 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 TUNGSTEN GRAPHICS AND/OR ITS 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.
- *
- **************************************************************************/
-
-#ifndef SL_PP_MACRO_H
-#define SL_PP_MACRO_H
-
-struct sl_pp_context;
-struct sl_pp_process_state;
-struct sl_pp_token_buffer;
-
-struct sl_pp_macro_formal_arg {
- int name;
- struct sl_pp_macro_formal_arg *next;
-};
-
-struct sl_pp_macro {
- int name;
- int num_args; /* -1 means no args, 0 means `()' */
- struct sl_pp_macro_formal_arg *arg;
- struct sl_pp_token_info *body;
- struct sl_pp_macro *next;
-};
-
-struct sl_pp_macro *
-sl_pp_macro_new(void);
-
-void
-sl_pp_macro_free(struct sl_pp_macro *macro);
-
-void
-sl_pp_macro_reset(struct sl_pp_macro *macro);
-
-enum sl_pp_macro_expand_behaviour {
- sl_pp_macro_expand_normal,
- sl_pp_macro_expand_mute,
- sl_pp_macro_expand_unknown_to_0
-};
-
-int
-sl_pp_macro_expand(struct sl_pp_context *context,
- struct sl_pp_token_buffer *tokens,
- struct sl_pp_macro *local,
- struct sl_pp_process_state *state,
- enum sl_pp_macro_expand_behaviour behaviour);
-
-#endif /* SL_PP_MACRO_H */
+++ /dev/null
-/**************************************************************************
- *
- * Copyright 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, 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 TUNGSTEN GRAPHICS AND/OR ITS 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.
- *
- **************************************************************************/
-
-#include <stdlib.h>
-#include <string.h>
-#include "sl_pp_context.h"
-#include "sl_pp_process.h"
-#include "sl_pp_token.h"
-
-
-int
-sl_pp_process_pragma(struct sl_pp_context *context,
- const struct sl_pp_token_info *input,
- unsigned int first,
- unsigned int last,
- struct sl_pp_process_state *state)
-{
- int pragma_name = -1;
- struct sl_pp_token_info out;
- int arg_name = -1;
-
- if (first < last && input[first].token == SL_PP_IDENTIFIER) {
- pragma_name = input[first].data.identifier;
- first++;
- }
- if (pragma_name == -1) {
- return 0;
- }
-
- if (pragma_name == context->dict.optimize) {
- out.token = SL_PP_PRAGMA_OPTIMIZE;
- } else if (pragma_name == context->dict.debug) {
- out.token = SL_PP_PRAGMA_DEBUG;
- } else {
- return 0;
- }
-
- while (first < last && input[first].token == SL_PP_WHITESPACE) {
- first++;
- }
-
- if (first < last && input[first].token == SL_PP_LPAREN) {
- first++;
- } else {
- return 0;
- }
-
- while (first < last && input[first].token == SL_PP_WHITESPACE) {
- first++;
- }
-
- if (first < last && input[first].token == SL_PP_IDENTIFIER) {
- arg_name = input[first].data.identifier;
- first++;
- }
- if (arg_name == -1) {
- return 0;
- }
-
- if (arg_name == context->dict.off) {
- out.data.pragma = 0;
- } else if (arg_name == context->dict.on) {
- out.data.pragma = 1;
- } else {
- return 0;
- }
-
- while (first < last && input[first].token == SL_PP_WHITESPACE) {
- first++;
- }
-
- if (first < last && input[first].token == SL_PP_RPAREN) {
- first++;
- } else {
- return 0;
- }
-
- /* Ignore the tokens that follow. */
-
- if (sl_pp_process_out(state, &out)) {
- strcpy(context->error_msg, "out of memory");
- return -1;
- }
-
- return 0;
-}
+++ /dev/null
-/**************************************************************************
- *
- * Copyright 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, 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 TUNGSTEN GRAPHICS AND/OR ITS 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.
- *
- **************************************************************************/
-
-#include <assert.h>
-#include <stdlib.h>
-#include <string.h>
-#include "sl_pp_context.h"
-#include "sl_pp_macro.h"
-#include "sl_pp_process.h"
-#include "sl_pp_public.h"
-#include "sl_pp_token.h"
-
-
-int
-sl_pp_process_out(struct sl_pp_process_state *state,
- const struct sl_pp_token_info *token)
-{
- if (state->out_len >= state->out_max) {
- unsigned int new_max = state->out_max;
-
- if (new_max < 0x100) {
- new_max = 0x100;
- } else if (new_max < 0x10000) {
- new_max *= 2;
- } else {
- new_max += 0x10000;
- }
-
- state->out = realloc(state->out, new_max * sizeof(struct sl_pp_token_info));
- if (!state->out) {
- return -1;
- }
- state->out_max = new_max;
- }
-
- state->out[state->out_len++] = *token;
- return 0;
-}
-
-int
-sl_pp_process_get(struct sl_pp_context *context,
- struct sl_pp_token_info *output)
-{
- if (!context->process_state.out) {
- if (context->line > 1) {
- struct sl_pp_token_info ti;
-
- ti.token = SL_PP_LINE;
- ti.data.line.lineno = context->line - 1;
- ti.data.line.fileno = context->file;
- if (sl_pp_process_out(&context->process_state, &ti)) {
- strcpy(context->error_msg, "out of memory");
- return -1;
- }
-
- ti.token = SL_PP_NEWLINE;
- if (sl_pp_process_out(&context->process_state, &ti)) {
- strcpy(context->error_msg, "out of memory");
- return -1;
- }
- }
- }
-
- for (;;) {
- struct sl_pp_token_info input;
- int found_eof = 0;
-
- if (context->process_state.out_len) {
- assert(context->process_state.out);
- *output = context->process_state.out[0];
-
- if (context->process_state.out_len > 1) {
- unsigned int i;
-
- for (i = 1; i < context->process_state.out_len; i++) {
- context->process_state.out[i - 1] = context->process_state.out[i];
- }
- }
- context->process_state.out_len--;
-
- return 0;
- }
-
- if (sl_pp_token_buffer_skip_white(&context->tokens, &input)) {
- return -1;
- }
- if (input.token == SL_PP_HASH) {
- if (sl_pp_token_buffer_skip_white(&context->tokens, &input)) {
- return -1;
- }
- switch (input.token) {
- case SL_PP_IDENTIFIER:
- {
- int name;
- int found_eol = 0;
- struct sl_pp_token_info endof;
- struct sl_pp_token_peek peek;
- int result = 0;
-
- /* Directive name. */
- name = input.data.identifier;
-
- if (sl_pp_token_buffer_skip_white(&context->tokens, &input)) {
- return -1;
- }
- sl_pp_token_buffer_unget(&context->tokens, &input);
-
- if (sl_pp_token_peek_init(&peek, &context->tokens)) {
- return -1;
- }
-
- while (!found_eol) {
- if (sl_pp_token_peek_get(&peek, &input)) {
- sl_pp_token_peek_destroy(&peek);
- return -1;
- }
- switch (input.token) {
- case SL_PP_NEWLINE:
- /* Preserve newline just for the sake of line numbering. */
- endof = input;
- found_eol = 1;
- break;
-
- case SL_PP_EOF:
- endof = input;
- found_eof = 1;
- found_eol = 1;
- break;
-
- default:
- break;
- }
- }
-
- if (name == context->dict._if) {
- struct sl_pp_token_buffer buffer;
-
- result = sl_pp_token_peek_to_buffer(&peek, &buffer);
- if (result == 0) {
- result = sl_pp_process_if(context, &buffer);
- sl_pp_token_buffer_destroy(&buffer);
- }
- } else if (name == context->dict.ifdef) {
- result = sl_pp_process_ifdef(context, peek.tokens, 0, peek.size - 1);
- } else if (name == context->dict.ifndef) {
- result = sl_pp_process_ifndef(context, peek.tokens, 0, peek.size - 1);
- } else if (name == context->dict.elif) {
- struct sl_pp_token_buffer buffer;
-
- result = sl_pp_token_peek_to_buffer(&peek, &buffer);
- if (result == 0) {
- result = sl_pp_process_elif(context, &buffer);
- sl_pp_token_buffer_destroy(&buffer);
- }
- } else if (name == context->dict._else) {
- result = sl_pp_process_else(context, peek.tokens, 0, peek.size - 1);
- } else if (name == context->dict.endif) {
- result = sl_pp_process_endif(context, peek.tokens, 0, peek.size - 1);
- } else if (context->if_value) {
- if (name == context->dict.define) {
- result = sl_pp_process_define(context, peek.tokens, 0, peek.size - 1);
- } else if (name == context->dict.error) {
- sl_pp_process_error(context, peek.tokens, 0, peek.size - 1);
- result = -1;
- } else if (name == context->dict.extension) {
- result = sl_pp_process_extension(context, peek.tokens, 0, peek.size - 1, &context->process_state);
- } else if (name == context->dict.line) {
- struct sl_pp_token_buffer buffer;
-
- result = sl_pp_token_peek_to_buffer(&peek, &buffer);
- if (result == 0) {
- result = sl_pp_process_line(context, &buffer, &context->process_state);
- sl_pp_token_buffer_destroy(&buffer);
- }
- } else if (name == context->dict.pragma) {
- result = sl_pp_process_pragma(context, peek.tokens, 0, peek.size - 1, &context->process_state);
- } else if (name == context->dict.undef) {
- result = sl_pp_process_undef(context, peek.tokens, 0, peek.size - 1);
- } else {
- strcpy(context->error_msg, "unrecognised directive name");
- result = -1;
- }
- }
-
- sl_pp_token_peek_commit(&peek);
- sl_pp_token_peek_destroy(&peek);
-
- if (result) {
- return result;
- }
-
- if (sl_pp_process_out(&context->process_state, &endof)) {
- strcpy(context->error_msg, "out of memory");
- return -1;
- }
- context->line++;
- }
- break;
-
- case SL_PP_NEWLINE:
- /* Empty directive. */
- if (sl_pp_process_out(&context->process_state, &input)) {
- strcpy(context->error_msg, "out of memory");
- return -1;
- }
- context->line++;
- break;
-
- case SL_PP_EOF:
- /* Empty directive. */
- if (sl_pp_process_out(&context->process_state, &input)) {
- strcpy(context->error_msg, "out of memory");
- return -1;
- }
- found_eof = 1;
- break;
-
- default:
- strcpy(context->error_msg, "expected a directive name");
- return -1;
- }
- } else {
- int found_eol = 0;
-
- sl_pp_token_buffer_unget(&context->tokens, &input);
-
- while (!found_eol) {
- if (sl_pp_token_buffer_get(&context->tokens, &input)) {
- return -1;
- }
-
- switch (input.token) {
- case SL_PP_WHITESPACE:
- /* Drop whitespace all together at this point. */
- break;
-
- case SL_PP_NEWLINE:
- /* Preserve newline just for the sake of line numbering. */
- if (sl_pp_process_out(&context->process_state, &input)) {
- strcpy(context->error_msg, "out of memory");
- return -1;
- }
- context->line++;
- found_eol = 1;
- break;
-
- case SL_PP_EOF:
- if (sl_pp_process_out(&context->process_state, &input)) {
- strcpy(context->error_msg, "out of memory");
- return -1;
- }
- found_eof = 1;
- found_eol = 1;
- break;
-
- case SL_PP_IDENTIFIER:
- sl_pp_token_buffer_unget(&context->tokens, &input);
- if (sl_pp_macro_expand(context, &context->tokens, NULL, &context->process_state,
- context->if_value ? sl_pp_macro_expand_normal : sl_pp_macro_expand_mute)) {
- return -1;
- }
- break;
-
- default:
- if (context->if_value) {
- if (sl_pp_process_out(&context->process_state, &input)) {
- strcpy(context->error_msg, "out of memory");
- return -1;
- }
- }
- }
- }
- }
-
- if (found_eof) {
- if (context->if_ptr != SL_PP_MAX_IF_NESTING) {
- strcpy(context->error_msg, "expected `#endif' directive");
- return -1;
- }
- }
- }
-}
-
-int
-sl_pp_process(struct sl_pp_context *context,
- struct sl_pp_token_info **output)
-{
- struct sl_pp_process_state state;
-
- memset(&state, 0, sizeof(state));
- for (;;) {
- struct sl_pp_token_info input;
-
- if (sl_pp_process_get(context, &input)) {
- free(state.out);
- return -1;
- }
- if (sl_pp_process_out(&state, &input)) {
- free(state.out);
- return -1;
- }
- if (input.token == SL_PP_EOF) {
- *output = state.out;
- return 0;
- }
- }
-}
+++ /dev/null
-/**************************************************************************
- *
- * Copyright 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, 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 TUNGSTEN GRAPHICS AND/OR ITS 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.
- *
- **************************************************************************/
-
-#ifndef SL_PP_PROCESS_H
-#define SL_PP_PROCESS_H
-
-struct sl_pp_context;
-struct sl_pp_token_buffer;
-
-struct sl_pp_process_state {
- struct sl_pp_token_info *out;
- unsigned int out_len;
- unsigned int out_max;
-};
-
-int
-sl_pp_process_define(struct sl_pp_context *context,
- const struct sl_pp_token_info *input,
- unsigned int first,
- unsigned int last);
-
-int
-sl_pp_process_undef(struct sl_pp_context *context,
- const struct sl_pp_token_info *input,
- unsigned int first,
- unsigned int last);
-
-int
-sl_pp_process_if(struct sl_pp_context *context,
- struct sl_pp_token_buffer *input);
-
-int
-sl_pp_process_ifdef(struct sl_pp_context *context,
- const struct sl_pp_token_info *input,
- unsigned int first,
- unsigned int last);
-
-int
-sl_pp_process_ifndef(struct sl_pp_context *context,
- const struct sl_pp_token_info *input,
- unsigned int first,
- unsigned int last);
-
-int
-sl_pp_process_elif(struct sl_pp_context *context,
- struct sl_pp_token_buffer *buffer);
-
-int
-sl_pp_process_else(struct sl_pp_context *context,
- const struct sl_pp_token_info *input,
- unsigned int first,
- unsigned int last);
-
-int
-sl_pp_process_endif(struct sl_pp_context *context,
- const struct sl_pp_token_info *input,
- unsigned int first,
- unsigned int last);
-
-void
-sl_pp_process_error(struct sl_pp_context *context,
- const struct sl_pp_token_info *input,
- unsigned int first,
- unsigned int last);
-
-int
-sl_pp_process_pragma(struct sl_pp_context *context,
- const struct sl_pp_token_info *input,
- unsigned int first,
- unsigned int last,
- struct sl_pp_process_state *state);
-
-int
-sl_pp_process_extension(struct sl_pp_context *context,
- const struct sl_pp_token_info *input,
- unsigned int first,
- unsigned int last,
- struct sl_pp_process_state *state);
-
-int
-sl_pp_process_line(struct sl_pp_context *context,
- struct sl_pp_token_buffer *buffer,
- struct sl_pp_process_state *state);
-
-int
-sl_pp_process_out(struct sl_pp_process_state *state,
- const struct sl_pp_token_info *token);
-
-#endif /* SL_PP_PROCESS_H */
+++ /dev/null
-/**************************************************************************
- *
- * Copyright 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, 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 TUNGSTEN GRAPHICS AND/OR ITS 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.
- *
- **************************************************************************/
-
-#ifndef SL_PP_PUBLIC_H
-#define SL_PP_PUBLIC_H
-
-struct sl_pp_context;
-struct sl_pp_purify_options;
-struct sl_pp_token_info;
-
-struct sl_pp_context *
-sl_pp_context_create(const char *input,
- const struct sl_pp_purify_options *options);
-
-void
-sl_pp_context_destroy(struct sl_pp_context *context);
-
-const char *
-sl_pp_context_error_message(const struct sl_pp_context *context);
-
-void
-sl_pp_context_error_position(const struct sl_pp_context *context,
- unsigned int *file,
- unsigned int *line);
-
-int
-sl_pp_context_add_extension(struct sl_pp_context *context,
- const char *name);
-
-int
-sl_pp_context_add_predefined(struct sl_pp_context *context,
- const char *name,
- const char *value);
-
-int
-sl_pp_context_add_unique_str(struct sl_pp_context *context,
- const char *str);
-
-const char *
-sl_pp_context_cstr(const struct sl_pp_context *context,
- int offset);
-
-int
-sl_pp_version(struct sl_pp_context *context,
- unsigned int *version);
-
-int
-sl_pp_process_get(struct sl_pp_context *context,
- struct sl_pp_token_info *output);
-
-int
-sl_pp_process(struct sl_pp_context *context,
- struct sl_pp_token_info **output);
-
-#endif /* SL_PP_PUBLIC_H */
+++ /dev/null
-/**************************************************************************
- *
- * Copyright 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, 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 TUNGSTEN GRAPHICS AND/OR ITS 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.
- *
- **************************************************************************/
-
-#include <stdlib.h>
-#include <stdarg.h>
-#include <stdio.h>
-#include "sl_pp_purify.h"
-
-
-/*
- * Preprocessor purifier performs the following tasks.
- * - Convert all variants of newlines into a Unix newline.
- * - Merge continued lines into a single long line.
- * - Remove line comments and replace block comments with whitespace.
- */
-
-
-static unsigned int
-_purify_newline(const char *input,
- char *out,
- unsigned int *current_line)
-{
- if (input[0] == '\n') {
- *out = '\n';
- (*current_line)++;
- if (input[1] == '\r') {
- /*
- * The GLSL spec is not explicit about whether this
- * combination is a valid newline or not.
- * Let's assume it is acceptable.
- */
- return 2;
- }
- return 1;
- }
- if (input[0] == '\r') {
- *out = '\n';
- (*current_line)++;
- if (input[1] == '\n') {
- return 2;
- }
- return 1;
- }
- *out = input[0];
- return 1;
-}
-
-
-static unsigned int
-_purify_backslash(const char *input,
- char *out,
- unsigned int *current_line)
-{
- unsigned int eaten = 0;
-
- for (;;) {
- if (input[0] == '\\') {
- char next;
- unsigned int next_eaten;
- unsigned int next_line = *current_line;
-
- eaten++;
- input++;
-
- next_eaten = _purify_newline(input, &next, &next_line);
- if (next == '\n') {
- /*
- * If this is really a line continuation sequence, eat
- * it and do not exit the loop.
- */
- eaten += next_eaten;
- input += next_eaten;
- *current_line = next_line;
- } else {
- /*
- * It is an error to put anything between a backslash
- * and a newline and still expect it to behave like a line
- * continuation sequence.
- * Even if it is an innocent whitespace.
- */
- *out = '\\';
- break;
- }
- } else {
- eaten += _purify_newline(input, out, current_line);
- break;
- }
- }
- return eaten;
-}
-
-
-static void
-_report_error(char *buf,
- unsigned int cbbuf,
- const char *msg,
- ...)
-{
- va_list args;
-
- va_start(args, msg);
- vsnprintf(buf, cbbuf, msg, args);
- va_end(args);
-}
-
-
-void
-sl_pp_purify_state_init(struct sl_pp_purify_state *state,
- const char *input,
- const struct sl_pp_purify_options *options)
-{
- state->options = *options;
- state->input = input;
- state->current_line = 1;
- state->inside_c_comment = 0;
-}
-
-
-static unsigned int
-_purify_comment(struct sl_pp_purify_state *state,
- char *output,
- unsigned int *current_line,
- char *errormsg,
- unsigned int cberrormsg)
-{
- for (;;) {
- unsigned int eaten;
- char next;
-
- eaten = _purify_backslash(state->input, &next, current_line);
- state->input += eaten;
- while (next == '*') {
- eaten = _purify_backslash(state->input, &next, current_line);
- state->input += eaten;
- if (next == '/') {
- *output = ' ';
- state->inside_c_comment = 0;
- return 1;
- }
- }
- if (next == '\n') {
- *output = '\n';
- state->inside_c_comment = 1;
- return 1;
- }
- if (next == '\0') {
- _report_error(errormsg, cberrormsg, "expected `*/' but end of translation unit found");
- return 0;
- }
- }
-}
-
-
-unsigned int
-sl_pp_purify_getc(struct sl_pp_purify_state *state,
- char *output,
- unsigned int *current_line,
- char *errormsg,
- unsigned int cberrormsg)
-{
- unsigned int eaten;
-
- if (state->inside_c_comment) {
- return _purify_comment(state, output, current_line, errormsg, cberrormsg);
- }
-
- eaten = _purify_backslash(state->input, output, current_line);
- state->input += eaten;
- if (*output == '/') {
- char next;
- unsigned int next_line = *current_line;
-
- eaten = _purify_backslash(state->input, &next, &next_line);
- if (next == '/') {
- state->input += eaten;
- *current_line = next_line;
-
- /* Replace a line comment with either a newline or nil. */
- for (;;) {
- eaten = _purify_backslash(state->input, &next, current_line);
- state->input += eaten;
- if (next == '\n' || next == '\0') {
- *output = next;
- return eaten;
- }
- }
- } else if (next == '*') {
- state->input += eaten;
- *current_line = next_line;
-
- return _purify_comment(state, output, current_line, errormsg, cberrormsg);
- }
- }
- return eaten;
-}
-
-
-struct out_buf {
- char *out;
- unsigned int len;
- unsigned int capacity;
- unsigned int current_line;
- char *errormsg;
- unsigned int cberrormsg;
-};
-
-
-static int
-_out_buf_putc(struct out_buf *obuf,
- char c)
-{
- if (obuf->len >= obuf->capacity) {
- unsigned int new_max = obuf->capacity;
-
- if (new_max < 0x100) {
- new_max = 0x100;
- } else if (new_max < 0x10000) {
- new_max *= 2;
- } else {
- new_max += 0x10000;
- }
-
- obuf->out = realloc(obuf->out, new_max);
- if (!obuf->out) {
- _report_error(obuf->errormsg, obuf->cberrormsg, "out of memory");
- return -1;
- }
- obuf->capacity = new_max;
- }
-
- obuf->out[obuf->len++] = c;
-
- return 0;
-}
-
-
-int
-sl_pp_purify(const char *input,
- const struct sl_pp_purify_options *options,
- char **output,
- char *errormsg,
- unsigned int cberrormsg,
- unsigned int *errorline)
-{
- struct out_buf obuf;
- struct sl_pp_purify_state state;
-
- obuf.out = NULL;
- obuf.len = 0;
- obuf.capacity = 0;
- obuf.current_line = 1;
- obuf.errormsg = errormsg;
- obuf.cberrormsg = cberrormsg;
-
- sl_pp_purify_state_init(&state, input, options);
-
- for (;;) {
- unsigned int eaten;
- char c;
-
- eaten = sl_pp_purify_getc(&state, &c, &obuf.current_line, errormsg, cberrormsg);
- if (!eaten) {
- *errorline = obuf.current_line;
- return -1;
- }
- if (_out_buf_putc(&obuf, c)) {
- *errorline = obuf.current_line;
- return -1;
- }
-
- if (c == '\0') {
- break;
- }
- }
-
- *output = obuf.out;
- return 0;
-}
+++ /dev/null
-/**************************************************************************
- *
- * Copyright 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, 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 TUNGSTEN GRAPHICS AND/OR ITS 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.
- *
- **************************************************************************/
-
-#ifndef SL_PP_PURIFY_H
-#define SL_PP_PURIFY_H
-
-struct sl_pp_purify_options {
- unsigned int preserve_columns:1;
- unsigned int tab_width:4;
-};
-
-int
-sl_pp_purify(const char *input,
- const struct sl_pp_purify_options *options,
- char **output,
- char *errormsg,
- unsigned int cberrormsg,
- unsigned int *errorline);
-
-struct sl_pp_purify_state {
- struct sl_pp_purify_options options;
- const char *input;
- unsigned int current_line;
- unsigned int inside_c_comment:1;
-};
-
-void
-sl_pp_purify_state_init(struct sl_pp_purify_state *state,
- const char *input,
- const struct sl_pp_purify_options *options);
-
-unsigned int
-sl_pp_purify_getc(struct sl_pp_purify_state *state,
- char *output,
- unsigned int *current_line,
- char *errormsg,
- unsigned int cberrormsg);
-
-#endif /* SL_PP_PURIFY_H */
+++ /dev/null
-/**************************************************************************
- *
- * Copyright 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, 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 TUNGSTEN GRAPHICS AND/OR ITS 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.
- *
- **************************************************************************/
-
-#include <assert.h>
-#include <stdlib.h>
-#include <string.h>
-#include "sl_pp_public.h"
-#include "sl_pp_context.h"
-#include "sl_pp_token.h"
-
-
-#define PURE_ERROR 256
-
-static int
-_pure_getc(struct sl_pp_context *context)
-{
- char c;
-
- if (context->getc_buf_size) {
- return context->getc_buf[--context->getc_buf_size];
- }
-
- if (sl_pp_purify_getc(&context->pure, &c, &context->error_line, context->error_msg, sizeof(context->error_msg)) == 0) {
- return PURE_ERROR;
- }
- return c;
-}
-
-
-static void
-_pure_ungetc(struct sl_pp_context *context,
- int c)
-{
- assert(c != PURE_ERROR);
-
- if (context->getc_buf_size == context->getc_buf_capacity) {
- context->getc_buf_capacity += 64;
- context->getc_buf = realloc(context->getc_buf, context->getc_buf_capacity * sizeof(char));
- assert(context->getc_buf);
- }
-
- context->getc_buf[context->getc_buf_size++] = (char)c;
-}
-
-
-struct lookahead_state {
- char buf[256];
- unsigned int pos;
- struct sl_pp_context *context;
-};
-
-
-static void
-_lookahead_init(struct lookahead_state *lookahead,
- struct sl_pp_context *context)
-{
- lookahead->pos = 0;
- lookahead->context = context;
-}
-
-
-static unsigned int
-_lookahead_tell(const struct lookahead_state *lookahead)
-{
- return lookahead->pos;
-}
-
-
-static const void *
-_lookahead_buf(const struct lookahead_state *lookahead)
-{
- return lookahead->buf;
-}
-
-
-static void
-_lookahead_revert(struct lookahead_state *lookahead,
- unsigned int pos)
-{
- assert(pos <= lookahead->pos);
-
- while (lookahead->pos > pos) {
- _pure_ungetc(lookahead->context, lookahead->buf[--lookahead->pos]);
- }
-}
-
-
-static int
-_lookahead_getc(struct lookahead_state *lookahead)
-{
- int c;
-
- assert(lookahead->pos < sizeof(lookahead->buf) / sizeof(lookahead->buf[0]));
-
- c = _pure_getc(lookahead->context);
- if (c != PURE_ERROR) {
- lookahead->buf[lookahead->pos++] = (char)c;
- }
- return c;
-}
-
-
-static int
-_is_identifier_char(char c)
-{
- return (c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z') || (c >= '0' && c <= '9') || c == '_';
-}
-
-
-static int
-_tokenise_identifier(struct sl_pp_context *context,
- struct sl_pp_token_info *out)
-{
- int c;
- char identifier[256]; /* XXX: Remove this artifical limit. */
- unsigned int i = 0;
-
- out->token = SL_PP_IDENTIFIER;
- out->data.identifier = -1;
-
- c = _pure_getc(context);
- if (c == PURE_ERROR) {
- return -1;
- }
- identifier[i++] = (char)c;
- for (;;) {
- c = _pure_getc(context);
- if (c == PURE_ERROR) {
- return -1;
- }
-
- if (_is_identifier_char((char)c)) {
- if (i >= sizeof(identifier) / sizeof(char) - 1) {
- strcpy(context->error_msg, "out of memory");
- _pure_ungetc(context, c);
- while (i) {
- _pure_ungetc(context, identifier[--i]);
- }
- return -1;
- }
- identifier[i++] = (char)c;
- } else {
- _pure_ungetc(context, c);
- break;
- }
- }
- identifier[i] = '\0';
-
- out->data.identifier = sl_pp_context_add_unique_str(context, identifier);
- if (out->data.identifier == -1) {
- while (i) {
- _pure_ungetc(context, identifier[--i]);
- }
- return -1;
- }
-
- return 0;
-}
-
-
-/*
- * Return the number of consecutive decimal digits in the input stream.
- */
-static unsigned int
-_parse_float_digits(struct lookahead_state *lookahead)
-{
- unsigned int eaten;
-
- for (eaten = 0;; eaten++) {
- unsigned int pos = _lookahead_tell(lookahead);
- char c = _lookahead_getc(lookahead);
-
- if (c < '0' || c > '9') {
- _lookahead_revert(lookahead, pos);
- break;
- }
- }
- return eaten;
-}
-
-
-/*
- * Try to match one of the following patterns for the fractional part
- * of a floating point number.
- *
- * digits . [digits]
- * . digits
- *
- * Return 0 if the pattern could not be matched, otherwise the number
- * of eaten characters from the input stream.
- */
-static unsigned int
-_parse_float_frac(struct lookahead_state *lookahead)
-{
- unsigned int pos;
- int c;
- unsigned int eaten;
-
- pos = _lookahead_tell(lookahead);
- c = _lookahead_getc(lookahead);
- if (c == '.') {
- eaten = _parse_float_digits(lookahead);
- if (eaten) {
- return eaten + 1;
- }
- _lookahead_revert(lookahead, pos);
- return 0;
- }
-
- _lookahead_revert(lookahead, pos);
- eaten = _parse_float_digits(lookahead);
- if (eaten) {
- c = _lookahead_getc(lookahead);
- if (c == '.') {
- return eaten + 1 + _parse_float_digits(lookahead);
- }
- }
-
- _lookahead_revert(lookahead, pos);
- return 0;
-}
-
-
-/*
- * Try to match the following pattern for the exponential part
- * of a floating point number.
- *
- * (e|E) [(+|-)] digits
- *
- * Return 0 if the pattern could not be matched, otherwise the number
- * of eaten characters from the input stream.
- */
-static unsigned int
-_parse_float_exp(struct lookahead_state *lookahead)
-{
- unsigned int pos, pos2;
- int c;
- unsigned int eaten, digits;
-
- pos = _lookahead_tell(lookahead);
- c = _lookahead_getc(lookahead);
- if (c != 'e' && c != 'E') {
- _lookahead_revert(lookahead, pos);
- return 0;
- }
-
- pos2 = _lookahead_tell(lookahead);
- c = _lookahead_getc(lookahead);
- if (c == '-' || c == '+') {
- eaten = 2;
- } else {
- _lookahead_revert(lookahead, pos2);
- eaten = 1;
- }
-
- digits = _parse_float_digits(lookahead);
- if (!digits) {
- _lookahead_revert(lookahead, pos);
- return 0;
- }
-
- return eaten + digits;
-}
-
-
-/*
- * Try to match one of the following patterns for a floating point number.
- *
- * fract [exp] [(f|F)]
- * digits exp [(f|F)]
- *
- * Return 0 if the pattern could not be matched, otherwise the number
- * of eaten characters from the input stream.
- */
-static unsigned int
-_parse_float(struct lookahead_state *lookahead)
-{
- unsigned int eaten;
-
- eaten = _parse_float_frac(lookahead);
- if (eaten) {
- unsigned int pos;
- int c;
-
- eaten += _parse_float_exp(lookahead);
-
- pos = _lookahead_tell(lookahead);
- c = _lookahead_getc(lookahead);
- if (c == 'f' || c == 'F') {
- eaten++;
- } else {
- _lookahead_revert(lookahead, pos);
- }
-
- return eaten;
- }
-
- eaten = _parse_float_digits(lookahead);
- if (eaten) {
- unsigned int exponent;
-
- exponent = _parse_float_exp(lookahead);
- if (exponent) {
- unsigned int pos;
- int c;
-
- eaten += exponent;
-
- pos = _lookahead_tell(lookahead);
- c = _lookahead_getc(lookahead);
- if (c == 'f' || c == 'F') {
- eaten++;
- } else {
- _lookahead_revert(lookahead, pos);
- }
-
- return eaten;
- }
- }
-
- _lookahead_revert(lookahead, 0);
- return 0;
-}
-
-
-static unsigned int
-_parse_hex(struct lookahead_state *lookahead)
-{
- int c;
- unsigned int n;
-
- c = _lookahead_getc(lookahead);
- if (c != '0') {
- _lookahead_revert(lookahead, 0);
- return 0;
- }
-
- c = _lookahead_getc(lookahead);
- if (c != 'x' && c != 'X') {
- _lookahead_revert(lookahead, 0);
- return 0;
- }
-
- for (n = 2;;) {
- unsigned int pos = _lookahead_tell(lookahead);
-
- c = _lookahead_getc(lookahead);
- if ((c >= '0' && c <= '9') || (c >= 'a' && c <= 'f') || (c >= 'A' && c <= 'F')) {
- n++;
- } else {
- _lookahead_revert(lookahead, pos);
- break;
- }
- }
-
- if (n > 2) {
- return n;
- }
-
- _lookahead_revert(lookahead, 0);
- return 0;
-}
-
-
-static unsigned int
-_parse_oct(struct lookahead_state *lookahead)
-{
- int c;
- unsigned int n;
-
- c = _lookahead_getc(lookahead);
- if (c != '0') {
- _lookahead_revert(lookahead, 0);
- return 0;
- }
-
- for (n = 1;;) {
- unsigned int pos = _lookahead_tell(lookahead);
-
- c = _lookahead_getc(lookahead);
- if ((c >= '0' && c <= '7')) {
- n++;
- } else {
- _lookahead_revert(lookahead, pos);
- break;
- }
- }
-
- return n;
-}
-
-
-static unsigned int
-_parse_dec(struct lookahead_state *lookahead)
-{
- unsigned int n = 0;
-
- for (;;) {
- unsigned int pos = _lookahead_tell(lookahead);
- int c = _lookahead_getc(lookahead);
-
- if ((c >= '0' && c <= '9')) {
- n++;
- } else {
- _lookahead_revert(lookahead, pos);
- break;
- }
- }
-
- return n;
-}
-
-
-static int
-_tokenise_number(struct sl_pp_context *context,
- struct sl_pp_token_info *out)
-{
- struct lookahead_state lookahead;
- unsigned int eaten;
- unsigned int is_float = 0;
- unsigned int pos;
- int c;
- char number[256]; /* XXX: Remove this artifical limit. */
-
- _lookahead_init(&lookahead, context);
-
- eaten = _parse_float(&lookahead);
- if (!eaten) {
- eaten = _parse_hex(&lookahead);
- if (!eaten) {
- eaten = _parse_oct(&lookahead);
- if (!eaten) {
- eaten = _parse_dec(&lookahead);
- }
- }
- } else {
- is_float = 1;
- }
-
- if (!eaten) {
- strcpy(context->error_msg, "expected a number");
- return -1;
- }
-
- pos = _lookahead_tell(&lookahead);
- c = _lookahead_getc(&lookahead);
- _lookahead_revert(&lookahead, pos);
-
- if (_is_identifier_char(c)) {
- strcpy(context->error_msg, "expected a number");
- _lookahead_revert(&lookahead, 0);
- return -1;
- }
-
- if (eaten > sizeof(number) - 1) {
- strcpy(context->error_msg, "out of memory");
- _lookahead_revert(&lookahead, 0);
- return -1;
- }
-
- assert(_lookahead_tell(&lookahead) == eaten);
-
- memcpy(number, _lookahead_buf(&lookahead), eaten);
- number[eaten] = '\0';
-
- if (is_float) {
- out->token = SL_PP_FLOAT;
- out->data._float = sl_pp_context_add_unique_str(context, number);
- if (out->data._float == -1) {
- _lookahead_revert(&lookahead, 0);
- return -1;
- }
- } else {
- out->token = SL_PP_UINT;
- out->data._uint = sl_pp_context_add_unique_str(context, number);
- if (out->data._uint == -1) {
- _lookahead_revert(&lookahead, 0);
- return -1;
- }
- }
-
- return 0;
-}
-
-
-int
-sl_pp_token_get(struct sl_pp_context *context,
- struct sl_pp_token_info *out)
-{
- int c = _pure_getc(context);
-
- switch (c) {
- case ' ':
- case '\t':
- out->token = SL_PP_WHITESPACE;
- break;
-
- case '\n':
- out->token = SL_PP_NEWLINE;
- break;
-
- case '#':
- out->token = SL_PP_HASH;
- break;
-
- case ',':
- out->token = SL_PP_COMMA;
- break;
-
- case ';':
- out->token = SL_PP_SEMICOLON;
- break;
-
- case '{':
- out->token = SL_PP_LBRACE;
- break;
-
- case '}':
- out->token = SL_PP_RBRACE;
- break;
-
- case '(':
- out->token = SL_PP_LPAREN;
- break;
-
- case ')':
- out->token = SL_PP_RPAREN;
- break;
-
- case '[':
- out->token = SL_PP_LBRACKET;
- break;
-
- case ']':
- out->token = SL_PP_RBRACKET;
- break;
-
- case '.':
- {
- int c2 = _pure_getc(context);
-
- if (c2 == PURE_ERROR) {
- return -1;
- }
- if (c2 >= '0' && c2 <= '9') {
- _pure_ungetc(context, c2);
- _pure_ungetc(context, c);
- if (_tokenise_number(context, out)) {
- return -1;
- }
- } else {
- _pure_ungetc(context, c2);
- out->token = SL_PP_DOT;
- }
- }
- break;
-
- case '+':
- c = _pure_getc(context);
- if (c == PURE_ERROR) {
- return -1;
- }
- if (c == '+') {
- out->token = SL_PP_INCREMENT;
- } else if (c == '=') {
- out->token = SL_PP_ADDASSIGN;
- } else {
- _pure_ungetc(context, c);
- out->token = SL_PP_PLUS;
- }
- break;
-
- case '-':
- c = _pure_getc(context);
- if (c == PURE_ERROR) {
- return -1;
- }
- if (c == '-') {
- out->token = SL_PP_DECREMENT;
- } else if (c == '=') {
- out->token = SL_PP_SUBASSIGN;
- } else {
- _pure_ungetc(context, c);
- out->token = SL_PP_MINUS;
- }
- break;
-
- case '~':
- out->token = SL_PP_BITNOT;
- break;
-
- case '!':
- c = _pure_getc(context);
- if (c == PURE_ERROR) {
- return -1;
- }
- if (c == '=') {
- out->token = SL_PP_NOTEQUAL;
- } else {
- _pure_ungetc(context, c);
- out->token = SL_PP_NOT;
- }
- break;
-
- case '*':
- c = _pure_getc(context);
- if (c == PURE_ERROR) {
- return -1;
- }
- if (c == '=') {
- out->token = SL_PP_MULASSIGN;
- } else {
- _pure_ungetc(context, c);
- out->token = SL_PP_STAR;
- }
- break;
-
- case '/':
- c = _pure_getc(context);
- if (c == PURE_ERROR) {
- return -1;
- }
- if (c == '=') {
- out->token = SL_PP_DIVASSIGN;
- } else {
- _pure_ungetc(context, c);
- out->token = SL_PP_SLASH;
- }
- break;
-
- case '%':
- c = _pure_getc(context);
- if (c == PURE_ERROR) {
- return -1;
- }
- if (c == '=') {
- out->token = SL_PP_MODASSIGN;
- } else {
- _pure_ungetc(context, c);
- out->token = SL_PP_MODULO;
- }
- break;
-
- case '<':
- c = _pure_getc(context);
- if (c == PURE_ERROR) {
- return -1;
- }
- if (c == '<') {
- c = _pure_getc(context);
- if (c == PURE_ERROR) {
- return -1;
- }
- if (c == '=') {
- out->token = SL_PP_LSHIFTASSIGN;
- } else {
- _pure_ungetc(context, c);
- out->token = SL_PP_LSHIFT;
- }
- } else if (c == '=') {
- out->token = SL_PP_LESSEQUAL;
- } else {
- _pure_ungetc(context, c);
- out->token = SL_PP_LESS;
- }
- break;
-
- case '>':
- c = _pure_getc(context);
- if (c == PURE_ERROR) {
- return -1;
- }
- if (c == '>') {
- c = _pure_getc(context);
- if (c == PURE_ERROR) {
- return -1;
- }
- if (c == '=') {
- out->token = SL_PP_RSHIFTASSIGN;
- } else {
- _pure_ungetc(context, c);
- out->token = SL_PP_RSHIFT;
- }
- } else if (c == '=') {
- out->token = SL_PP_GREATEREQUAL;
- } else {
- _pure_ungetc(context, c);
- out->token = SL_PP_GREATER;
- }
- break;
-
- case '=':
- c = _pure_getc(context);
- if (c == PURE_ERROR) {
- return -1;
- }
- if (c == '=') {
- out->token = SL_PP_EQUAL;
- } else {
- _pure_ungetc(context, c);
- out->token = SL_PP_ASSIGN;
- }
- break;
-
- case '&':
- c = _pure_getc(context);
- if (c == PURE_ERROR) {
- return -1;
- }
- if (c == '&') {
- out->token = SL_PP_AND;
- } else if (c == '=') {
- out->token = SL_PP_BITANDASSIGN;
- } else {
- _pure_ungetc(context, c);
- out->token = SL_PP_BITAND;
- }
- break;
-
- case '^':
- c = _pure_getc(context);
- if (c == PURE_ERROR) {
- return -1;
- }
- if (c == '^') {
- out->token = SL_PP_XOR;
- } else if (c == '=') {
- out->token = SL_PP_BITXORASSIGN;
- } else {
- _pure_ungetc(context, c);
- out->token = SL_PP_BITXOR;
- }
- break;
-
- case '|':
- c = _pure_getc(context);
- if (c == PURE_ERROR) {
- return -1;
- }
- if (c == '|') {
- out->token = SL_PP_OR;
- } else if (c == '=') {
- out->token = SL_PP_BITORASSIGN;
- } else {
- _pure_ungetc(context, c);
- out->token = SL_PP_BITOR;
- }
- break;
-
- case '?':
- out->token = SL_PP_QUESTION;
- break;
-
- case ':':
- out->token = SL_PP_COLON;
- break;
-
- case '\0':
- out->token = SL_PP_EOF;
- break;
-
- case PURE_ERROR:
- return -1;
-
- default:
- if ((c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z') || c == '_') {
- _pure_ungetc(context, c);
- if (_tokenise_identifier(context, out)) {
- return -1;
- }
- } else if (c >= '0' && c <= '9') {
- _pure_ungetc(context, c);
- if (_tokenise_number(context, out)) {
- return -1;
- }
- } else {
- out->data.other = c;
- out->token = SL_PP_OTHER;
- }
- }
-
- return 0;
-}
-
-
-int
-sl_pp_tokenise(struct sl_pp_context *context,
- struct sl_pp_token_info **output)
-{
- struct sl_pp_token_info *out = NULL;
- unsigned int out_len = 0;
- unsigned int out_max = 0;
-
- for (;;) {
- struct sl_pp_token_info info;
-
- if (sl_pp_token_buffer_get(&context->tokens, &info)) {
- free(out);
- return -1;
- }
-
- if (out_len >= out_max) {
- unsigned int new_max = out_max;
-
- if (new_max < 0x100) {
- new_max = 0x100;
- } else if (new_max < 0x10000) {
- new_max *= 2;
- } else {
- new_max += 0x10000;
- }
-
- out = realloc(out, new_max * sizeof(struct sl_pp_token_info));
- if (!out) {
- strcpy(context->error_msg, "out of memory");
- return -1;
- }
- out_max = new_max;
- }
-
- out[out_len++] = info;
-
- if (info.token == SL_PP_EOF) {
- break;
- }
- }
-
- *output = out;
- return 0;
-}
+++ /dev/null
-/**************************************************************************
- *
- * Copyright 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, 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 TUNGSTEN GRAPHICS AND/OR ITS 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.
- *
- **************************************************************************/
-
-#ifndef SL_PP_TOKEN_H
-#define SL_PP_TOKEN_H
-
-
-struct sl_pp_context;
-
-enum sl_pp_token {
- SL_PP_WHITESPACE,
- SL_PP_NEWLINE,
- SL_PP_HASH, /* # */
-
- SL_PP_COMMA, /* , */
- SL_PP_SEMICOLON, /* ; */
- SL_PP_LBRACE, /* { */
- SL_PP_RBRACE, /* } */
- SL_PP_LPAREN, /* ( */
- SL_PP_RPAREN, /* ) */
- SL_PP_LBRACKET, /* [ */
- SL_PP_RBRACKET, /* ] */
- SL_PP_DOT, /* . */
- SL_PP_INCREMENT, /* ++ */
- SL_PP_ADDASSIGN, /* += */
- SL_PP_PLUS, /* + */
- SL_PP_DECREMENT, /* -- */
- SL_PP_SUBASSIGN, /* -= */
- SL_PP_MINUS, /* - */
- SL_PP_BITNOT, /* ~ */
- SL_PP_NOTEQUAL, /* != */
- SL_PP_NOT, /* ! */
- SL_PP_MULASSIGN, /* *= */
- SL_PP_STAR, /* * */
- SL_PP_DIVASSIGN, /* /= */
- SL_PP_SLASH, /* / */
- SL_PP_MODASSIGN, /* %= */
- SL_PP_MODULO, /* % */
- SL_PP_LSHIFTASSIGN, /* <<= */
- SL_PP_LSHIFT, /* << */
- SL_PP_LESSEQUAL, /* <= */
- SL_PP_LESS, /* < */
- SL_PP_RSHIFTASSIGN, /* >>= */
- SL_PP_RSHIFT, /* >> */
- SL_PP_GREATEREQUAL, /* >= */
- SL_PP_GREATER, /* > */
- SL_PP_EQUAL, /* == */
- SL_PP_ASSIGN, /* = */
- SL_PP_AND, /* && */
- SL_PP_BITANDASSIGN, /* &= */
- SL_PP_BITAND, /* & */
- SL_PP_XOR, /* ^^ */
- SL_PP_BITXORASSIGN, /* ^= */
- SL_PP_BITXOR, /* ^ */
- SL_PP_OR, /* || */
- SL_PP_BITORASSIGN, /* |= */
- SL_PP_BITOR, /* | */
- SL_PP_QUESTION, /* ? */
- SL_PP_COLON, /* : */
-
- SL_PP_IDENTIFIER,
-
- SL_PP_UINT,
- SL_PP_FLOAT,
-
- SL_PP_OTHER,
-
- SL_PP_PRAGMA_OPTIMIZE,
- SL_PP_PRAGMA_DEBUG,
-
- SL_PP_EXTENSION_REQUIRE,
- SL_PP_EXTENSION_ENABLE,
- SL_PP_EXTENSION_WARN,
- SL_PP_EXTENSION_DISABLE,
-
- SL_PP_LINE,
-
- SL_PP_EOF
-};
-
-union sl_pp_token_data {
- int identifier;
- int _uint;
- int _float;
- char other;
- int pragma;
- int extension;
- struct {
- unsigned int lineno: 24;
- unsigned int fileno: 8;
- } line;
-};
-
-struct sl_pp_token_info {
- enum sl_pp_token token;
- union sl_pp_token_data data;
-};
-
-struct sl_pp_purify_options;
-
-int
-sl_pp_token_get(struct sl_pp_context *context,
- struct sl_pp_token_info *out);
-
-int
-sl_pp_tokenise(struct sl_pp_context *context,
- struct sl_pp_token_info **output);
-
-#endif /* SL_PP_TOKEN_H */
+++ /dev/null
-/**************************************************************************
- *
- * Copyright 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, 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 TUNGSTEN GRAPHICS AND/OR ITS 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.
- *
- **************************************************************************/
-
-#include <assert.h>
-#include <stdlib.h>
-#include "sl_pp_token_util.h"
-#include "sl_pp_token.h"
-
-
-int
-sl_pp_token_buffer_init(struct sl_pp_token_buffer *buffer,
- struct sl_pp_context *context)
-{
- buffer->context = context;
- buffer->size = 0;
- buffer->capacity = 64;
- buffer->tokens = malloc(buffer->capacity * sizeof(struct sl_pp_token_info));
- if (!buffer->tokens) {
- return -1;
- }
- return 0;
-}
-
-void
-sl_pp_token_buffer_destroy(struct sl_pp_token_buffer *buffer)
-{
- free(buffer->tokens);
-}
-
-int
-sl_pp_token_buffer_get(struct sl_pp_token_buffer *buffer,
- struct sl_pp_token_info *out)
-{
- /* Pop from stack first if not empty. */
- if (buffer->size) {
- *out = buffer->tokens[--buffer->size];
- return 0;
- }
-
- assert(buffer->context);
- return sl_pp_token_get(buffer->context, out);
-}
-
-void
-sl_pp_token_buffer_unget(struct sl_pp_token_buffer *buffer,
- const struct sl_pp_token_info *in)
-{
- /* Resize if needed. */
- if (buffer->size == buffer->capacity) {
- buffer->capacity += 64;
- buffer->tokens = realloc(buffer->tokens,
- buffer->capacity * sizeof(struct sl_pp_token_info));
- assert(buffer->tokens);
- }
-
- /* Push token on stack. */
- buffer->tokens[buffer->size++] = *in;
-}
-
-int
-sl_pp_token_buffer_skip_white(struct sl_pp_token_buffer *buffer,
- struct sl_pp_token_info *out)
-{
- if (sl_pp_token_buffer_get(buffer, out)) {
- return -1;
- }
-
- while (out->token == SL_PP_WHITESPACE) {
- if (sl_pp_token_buffer_get(buffer, out)) {
- return -1;
- }
- }
-
- return 0;
-}
-
-
-
-int
-sl_pp_token_peek_init(struct sl_pp_token_peek *peek,
- struct sl_pp_token_buffer *buffer)
-{
- peek->buffer = buffer;
- peek->size = 0;
- peek->capacity = 64;
- peek->tokens = malloc(peek->capacity * sizeof(struct sl_pp_token_info));
- if (!peek->tokens) {
- return -1;
- }
- return 0;
-}
-
-void
-sl_pp_token_peek_destroy(struct sl_pp_token_peek *peek)
-{
- /* Abort. */
- while (peek->size) {
- sl_pp_token_buffer_unget(peek->buffer, &peek->tokens[--peek->size]);
- }
- free(peek->tokens);
-}
-
-int
-sl_pp_token_peek_get(struct sl_pp_token_peek *peek,
- struct sl_pp_token_info *out)
-{
- /* Get token from buffer. */
- if (sl_pp_token_buffer_get(peek->buffer, out)) {
- return -1;
- }
-
- /* Save it. */
- if (peek->size == peek->capacity) {
- peek->capacity += 64;
- peek->tokens = realloc(peek->tokens,
- peek->capacity * sizeof(struct sl_pp_token_info));
- assert(peek->tokens);
- }
- peek->tokens[peek->size++] = *out;
- return 0;
-}
-
-void
-sl_pp_token_peek_commit(struct sl_pp_token_peek *peek)
-{
- peek->size = 0;
-}
-
-int
-sl_pp_token_peek_to_buffer(const struct sl_pp_token_peek *peek,
- struct sl_pp_token_buffer *buffer)
-{
- unsigned int i;
-
- if (sl_pp_token_buffer_init(buffer, NULL)) {
- return -1;
- }
- for (i = peek->size; i > 0; i--) {
- sl_pp_token_buffer_unget(buffer, &peek->tokens[i - 1]);
- }
- return 0;
-}
-
-int
-sl_pp_token_peek_skip_white(struct sl_pp_token_peek *peek,
- struct sl_pp_token_info *out)
-{
- if (sl_pp_token_peek_get(peek, out)) {
- return -1;
- }
-
- while (out->token == SL_PP_WHITESPACE) {
- if (sl_pp_token_peek_get(peek, out)) {
- return -1;
- }
- }
-
- return 0;
-}
+++ /dev/null
-/**************************************************************************
- *
- * Copyright 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, 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 TUNGSTEN GRAPHICS AND/OR ITS 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.
- *
- **************************************************************************/
-
-#ifndef SL_PP_TOKEN_UTIL_H
-#define SL_PP_TOKEN_UTIL_H
-
-struct sl_pp_context;
-
-/*
- * A token buffer allows one to get and unget a token
- * from a preprocessor context.
- */
-struct sl_pp_token_buffer {
- struct sl_pp_context *context;
- unsigned int size;
- unsigned int capacity;
- struct sl_pp_token_info *tokens;
-};
-
-int
-sl_pp_token_buffer_init(struct sl_pp_token_buffer *buffer,
- struct sl_pp_context *context);
-
-void
-sl_pp_token_buffer_destroy(struct sl_pp_token_buffer *buffer);
-
-int
-sl_pp_token_buffer_get(struct sl_pp_token_buffer *buffer,
- struct sl_pp_token_info *out);
-
-void
-sl_pp_token_buffer_unget(struct sl_pp_token_buffer *buffer,
- const struct sl_pp_token_info *in);
-
-int
-sl_pp_token_buffer_skip_white(struct sl_pp_token_buffer *buffer,
- struct sl_pp_token_info *out);
-
-
-/*
- * A token peek allows one to get a number of tokens from a buffer
- * and then either commit the operation or abort it,
- * effectively ungetting the peeked tokens.
- */
-struct sl_pp_token_peek {
- struct sl_pp_token_buffer *buffer;
- unsigned int size;
- unsigned int capacity;
- struct sl_pp_token_info *tokens;
-};
-
-int
-sl_pp_token_peek_init(struct sl_pp_token_peek *peek,
- struct sl_pp_token_buffer *buffer);
-
-void
-sl_pp_token_peek_destroy(struct sl_pp_token_peek *peek);
-
-int
-sl_pp_token_peek_get(struct sl_pp_token_peek *peek,
- struct sl_pp_token_info *out);
-
-void
-sl_pp_token_peek_commit(struct sl_pp_token_peek *peek);
-
-int
-sl_pp_token_peek_to_buffer(const struct sl_pp_token_peek *peek,
- struct sl_pp_token_buffer *buffer);
-
-int
-sl_pp_token_peek_skip_white(struct sl_pp_token_peek *peek,
- struct sl_pp_token_info *out);
-
-#endif /* SL_PP_TOKEN_UTIL_H */
+++ /dev/null
-/**************************************************************************
- *
- * Copyright 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, 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 TUNGSTEN GRAPHICS AND/OR ITS 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.
- *
- **************************************************************************/
-
-#include <stdlib.h>
-#include <string.h>
-#include "sl_pp_public.h"
-#include "sl_pp_context.h"
-#include "sl_pp_token.h"
-
-
-int
-sl_pp_version(struct sl_pp_context *context,
- unsigned int *version)
-{
- struct sl_pp_token_peek peek;
- unsigned int line = context->line;
-
- /* Default values if `#version' is not present. */
- *version = 110;
-
- if (sl_pp_token_peek_init(&peek, &context->tokens)) {
- return -1;
- }
-
- /* There can be multiple `#version' directives present.
- * Accept the value of the last one.
- */
- for (;;) {
- struct sl_pp_token_info input;
- int found_hash = 0;
- int found_version = 0;
- int found_number = 0;
- int found_end = 0;
-
- /* Skip whitespace and newlines and seek for hash. */
- while (!found_hash) {
- if (sl_pp_token_peek_get(&peek, &input)) {
- sl_pp_token_peek_destroy(&peek);
- return -1;
- }
-
- switch (input.token) {
- case SL_PP_NEWLINE:
- line++;
- break;
-
- case SL_PP_WHITESPACE:
- break;
-
- case SL_PP_HASH:
- found_hash = 1;
- break;
-
- default:
- sl_pp_token_peek_destroy(&peek);
- return 0;
- }
- }
-
- /* Skip whitespace and seek for `version'. */
- while (!found_version) {
- if (sl_pp_token_peek_get(&peek, &input)) {
- sl_pp_token_peek_destroy(&peek);
- return -1;
- }
-
- switch (input.token) {
- case SL_PP_WHITESPACE:
- break;
-
- case SL_PP_IDENTIFIER:
- if (input.data.identifier != context->dict.version) {
- sl_pp_token_peek_destroy(&peek);
- return 0;
- }
- found_version = 1;
- break;
-
- default:
- sl_pp_token_peek_destroy(&peek);
- return 0;
- }
- }
-
- sl_pp_token_peek_commit(&peek);
-
- /* Skip whitespace and seek for version number. */
- while (!found_number) {
- if (sl_pp_token_buffer_get(&context->tokens, &input)) {
- sl_pp_token_peek_destroy(&peek);
- return -1;
- }
-
- switch (input.token) {
- case SL_PP_WHITESPACE:
- break;
-
- case SL_PP_UINT:
- *version = atoi(sl_pp_context_cstr(context, input.data._uint));
- found_number = 1;
- break;
-
- default:
- strcpy(context->error_msg, "expected version number after `#version'");
- sl_pp_token_peek_destroy(&peek);
- return -1;
- }
- }
-
- /* Skip whitespace and seek for either newline or eof. */
- while (!found_end) {
- if (sl_pp_token_buffer_get(&context->tokens, &input)) {
- sl_pp_token_peek_destroy(&peek);
- return -1;
- }
-
- switch (input.token) {
- case SL_PP_WHITESPACE:
- break;
-
- case SL_PP_NEWLINE:
- line++;
- /* pass thru */
- case SL_PP_EOF:
- context->line = line;
- found_end = 1;
- break;
-
- default:
- strcpy(context->error_msg, "expected end of line after version number");
- sl_pp_token_peek_destroy(&peek);
- return -1;
- }
- }
- }
-
- /* Should not get here. */
-}
+++ /dev/null
-# Makefile for stand-alone GL-SL compiler
-
-TOP = ../../../..
-
-include $(TOP)/configs/current
-
-
-PROGRAM = glslcompiler
-
-OBJECTS = \
- glslcompiler.o \
- ../common/driverfuncs.o \
- ../../libmesa.a \
- $(TOP)/src/mapi/glapi/libglapi.a
-
-INCLUDES = \
- -I$(TOP)/include \
- -I$(TOP)/include/GL/internal \
- -I$(TOP)/src/mapi \
- -I$(TOP)/src/mesa \
- -I$(TOP)/src/mesa/main \
- -I$(TOP)/src/mesa/glapi \
- -I$(TOP)/src/mesa/math \
- -I$(TOP)/src/mesa/transform \
- -I$(TOP)/src/mesa/shader \
- -I$(TOP)/src/mesa/swrast \
- -I$(TOP)/src/mesa/swrast_setup \
-
-
-default: $(PROGRAM)
- $(INSTALL) $(PROGRAM) $(TOP)/bin
-
-
-glslcompiler: $(OBJECTS)
- $(CC) $(OBJECTS) $(GL_LIB_DEPS) -o $@
-
-
-glslcompiler.o: glslcompiler.c
- $(CC) -c $(INCLUDES) $(CFLAGS) glslcompiler.c -o $@
-
-
-clean:
- -rm -f *.o *~ $(PROGRAM)
+++ /dev/null
-/*
- * Mesa 3-D graphics library
- * Version: 6.5.3
- *
- * Copyright (C) 1999-2007 Brian Paul, Tungsten Graphics, 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.
- */
-
-/**
- * \mainpage
- *
- * Stand-alone Shading Language compiler.
- * Basically, a command-line program which accepts GLSL shaders and emits
- * vertex/fragment programs (GPU instructions).
- *
- * This file is basically just a Mesa device driver but instead of building
- * a shared library we build an executable.
- *
- * We can emit programs in three different formats:
- * 1. ARB-style (GL_ARB_vertex/fragment_program)
- * 2. NV-style (GL_NV_vertex/fragment_program)
- * 3. debug-style (a slightly more sophisticated, internal format)
- *
- * Note that the ARB and NV program languages can't express all the
- * features that might be used by a fragment program (examples being
- * uniform and varying vars). So, the ARB/NV programs that are
- * emitted aren't always legal programs in those languages.
- */
-
-
-#include "main/imports.h"
-#include "main/context.h"
-#include "main/extensions.h"
-#include "main/framebuffer.h"
-#include "main/shaderapi.h"
-#include "main/shaderobj.h"
-#include "program/prog_print.h"
-#include "drivers/common/driverfuncs.h"
-#include "tnl/tnl.h"
-#include "tnl/t_context.h"
-#include "tnl/t_pipeline.h"
-#include "swrast/swrast.h"
-#include "swrast_setup/swrast_setup.h"
-#include "vbo/vbo.h"
-
-
-static const char *Prog = "glslcompiler";
-
-
-struct options {
- GLboolean LineNumbers;
- GLboolean Link;
- gl_prog_print_mode Mode;
- const char *VertFile;
- const char *FragFile;
- const char *GeoFile;
- const char *OutputFile;
- GLboolean Params;
- struct gl_sl_pragmas Pragmas;
-};
-
-static struct options Options;
-
-
-/**
- * GLSL compiler driver context. (kind of an artificial thing for now)
- */
-struct compiler_context
-{
- GLcontext MesaContext;
- int foo;
-};
-
-typedef struct compiler_context CompilerContext;
-
-
-
-static void
-UpdateState(GLcontext *ctx, GLuint new_state)
-{
- /* easy - just propogate */
- _swrast_InvalidateState( ctx, new_state );
- _swsetup_InvalidateState( ctx, new_state );
- _tnl_InvalidateState( ctx, new_state );
- _vbo_InvalidateState( ctx, new_state );
-}
-
-
-
-static GLboolean
-CreateContext(void)
-{
- struct dd_function_table ddFuncs;
- GLvisual *vis;
- GLframebuffer *buf;
- GLcontext *ctx;
- CompilerContext *cc;
-
- vis = _mesa_create_visual(GL_FALSE, GL_FALSE, /* RGB */
- 8, 8, 8, 8, /* color */
- 0, 0, /* z, stencil */
- 0, 0, 0, 0, 1); /* accum */
- buf = _mesa_create_framebuffer(vis);
-
- cc = calloc(1, sizeof(*cc));
- if (!vis || !buf || !cc) {
- if (vis)
- _mesa_destroy_visual(vis);
- if (buf)
- _mesa_destroy_framebuffer(buf);
- free(cc);
- return GL_FALSE;
- }
-
- _mesa_init_driver_functions(&ddFuncs);
- ddFuncs.GetString = NULL;/*get_string;*/
- ddFuncs.UpdateState = UpdateState;
- ddFuncs.GetBufferSize = NULL;
-
- ctx = &cc->MesaContext;
- _mesa_initialize_context(ctx, vis, NULL, &ddFuncs, cc);
- _mesa_enable_sw_extensions(ctx);
-
- if (!_swrast_CreateContext( ctx ) ||
- !_vbo_CreateContext( ctx ) ||
- !_tnl_CreateContext( ctx ) ||
- !_swsetup_CreateContext( ctx )) {
- _mesa_destroy_visual(vis);
- _mesa_destroy_framebuffer(buf);
- _mesa_free_context_data(ctx);
- free(cc);
- return GL_FALSE;
- }
- TNL_CONTEXT(ctx)->Driver.RunPipeline = _tnl_run_pipeline;
- _swsetup_Wakeup( ctx );
-
- /* Override the context's default pragma settings */
- ctx->Shader.DefaultPragmas = Options.Pragmas;
-
- _mesa_make_current(ctx, buf, buf);
-
- return GL_TRUE;
-}
-
-
-static void
-LoadAndCompileShader(GLuint shader, const char *text)
-{
- GLint stat;
- _mesa_ShaderSourceARB(shader, 1, (const GLchar **) &text, NULL);
- _mesa_CompileShaderARB(shader);
- _mesa_GetShaderiv(shader, GL_COMPILE_STATUS, &stat);
- if (!stat) {
- GLchar log[1000];
- GLsizei len;
- _mesa_GetShaderInfoLog(shader, 1000, &len, log);
- fprintf(stderr, "%s: problem compiling shader: %s\n", Prog, log);
- exit(1);
- }
- else {
- printf("Shader compiled OK\n");
- }
-}
-
-
-/**
- * Read a shader from a file.
- */
-static void
-ReadShader(GLuint shader, const char *filename)
-{
- const int max = 100*1000;
- int n;
- char *buffer = (char*) malloc(max);
- FILE *f = fopen(filename, "r");
- if (!f) {
- fprintf(stderr, "%s: Unable to open shader file %s\n", Prog, filename);
- exit(1);
- }
-
- n = fread(buffer, 1, max, f);
- /*
- printf("%s: read %d bytes from shader file %s\n", Prog, n, filename);
- */
- if (n > 0) {
- buffer[n] = 0;
- LoadAndCompileShader(shader, buffer);
- }
-
- fclose(f);
- free(buffer);
-}
-
-
-static void
-CheckLink(GLuint v_shader, GLuint f_shader)
-{
- GLuint prog;
- GLint stat;
-
- prog = _mesa_CreateProgram();
-
- _mesa_AttachShader(prog, v_shader);
- _mesa_AttachShader(prog, f_shader);
-
- _mesa_LinkProgramARB(prog);
- _mesa_GetProgramiv(prog, GL_LINK_STATUS, &stat);
- if (!stat) {
- GLchar log[1000];
- GLsizei len;
- _mesa_GetProgramInfoLog(prog, 1000, &len, log);
- fprintf(stderr, "Linker error:\n%s\n", log);
- }
- else {
- fprintf(stderr, "Link success!\n");
- }
-}
-
-
-static void
-PrintShaderInstructions(GLuint shader, FILE *f)
-{
- GET_CURRENT_CONTEXT(ctx);
- struct gl_shader *sh = _mesa_lookup_shader(ctx, shader);
- struct gl_program *prog = sh->Program;
- _mesa_fprint_program_opt(stdout, prog, Options.Mode, Options.LineNumbers);
- if (Options.Params)
- _mesa_print_program_parameters(ctx, prog);
-}
-
-
-static GLuint
-CompileShader(const char *filename, GLenum type)
-{
- GLuint shader;
-
- assert(type == GL_FRAGMENT_SHADER ||
- type == GL_VERTEX_SHADER ||
- type == GL_GEOMETRY_SHADER_ARB);
-
- shader = _mesa_CreateShader(type);
- ReadShader(shader, filename);
-
- return shader;
-}
-
-
-static void
-Usage(void)
-{
- printf("Mesa GLSL stand-alone compiler\n");
- printf("Usage:\n");
- printf(" --vs FILE vertex shader input filename\n");
- printf(" --fs FILE fragment shader input filename\n");
- printf(" --gs FILE geometry shader input filename\n");
- printf(" --arb emit ARB-style instructions\n");
- printf(" --nv emit NV-style instructions\n");
- printf(" --link run linker\n");
- printf(" --debug force #pragma debug(on)\n");
- printf(" --nodebug force #pragma debug(off)\n");
- printf(" --opt force #pragma optimize(on)\n");
- printf(" --noopt force #pragma optimize(off)\n");
- printf(" --number, -n emit line numbers (if --arb or --nv)\n");
- printf(" --output, -o FILE output filename\n");
- printf(" --params also emit program parameter info\n");
- printf(" --help display this information\n");
-}
-
-
-static void
-ParseOptions(int argc, char *argv[])
-{
- int i;
-
- Options.LineNumbers = GL_FALSE;
- Options.Mode = PROG_PRINT_DEBUG;
- Options.VertFile = NULL;
- Options.FragFile = NULL;
- Options.GeoFile = NULL;
- Options.OutputFile = NULL;
- Options.Params = GL_FALSE;
- Options.Pragmas.IgnoreOptimize = GL_FALSE;
- Options.Pragmas.IgnoreDebug = GL_FALSE;
- Options.Pragmas.Debug = GL_FALSE;
- Options.Pragmas.Optimize = GL_TRUE;
-
- if (argc == 1) {
- Usage();
- exit(0);
- }
-
- for (i = 1; i < argc; i++) {
- if (strcmp(argv[i], "--vs") == 0) {
- Options.VertFile = argv[i + 1];
- i++;
- }
- else if (strcmp(argv[i], "--fs") == 0) {
- Options.FragFile = argv[i + 1];
- i++;
- }
- else if (strcmp(argv[i], "--gs") == 0) {
- Options.GeoFile = argv[i + 1];
- i++;
- }
- else if (strcmp(argv[i], "--arb") == 0) {
- Options.Mode = PROG_PRINT_ARB;
- }
- else if (strcmp(argv[i], "--nv") == 0) {
- Options.Mode = PROG_PRINT_NV;
- }
- else if (strcmp(argv[i], "--link") == 0) {
- Options.Link = GL_TRUE;
- }
- else if (strcmp(argv[i], "--debug") == 0) {
- Options.Pragmas.IgnoreDebug = GL_TRUE;
- Options.Pragmas.Debug = GL_TRUE;
- }
- else if (strcmp(argv[i], "--nodebug") == 0) {
- Options.Pragmas.IgnoreDebug = GL_TRUE;
- Options.Pragmas.Debug = GL_FALSE;
- }
- else if (strcmp(argv[i], "--opt") == 0) {
- Options.Pragmas.IgnoreOptimize = GL_TRUE;
- Options.Pragmas.Optimize = GL_TRUE;
- }
- else if (strcmp(argv[i], "--noopt") == 0) {
- Options.Pragmas.IgnoreOptimize = GL_TRUE;
- Options.Pragmas.Optimize = GL_FALSE;
- }
- else if (strcmp(argv[i], "--number") == 0 ||
- strcmp(argv[i], "-n") == 0) {
- Options.LineNumbers = GL_TRUE;
- }
- else if (strcmp(argv[i], "--output") == 0 ||
- strcmp(argv[i], "-o") == 0) {
- Options.OutputFile = argv[i + 1];
- i++;
- }
- else if (strcmp(argv[i], "--params") == 0) {
- Options.Params = GL_TRUE;
- }
- else if (strcmp(argv[i], "--help") == 0) {
- Usage();
- exit(0);
- }
- else {
- printf("Unknown option: %s\n", argv[i]);
- Usage();
- exit(1);
- }
- }
-
- if (Options.Mode == PROG_PRINT_DEBUG) {
- /* always print line numbers when emitting debug-style output */
- Options.LineNumbers = GL_TRUE;
- }
-}
-
-
-int
-main(int argc, char *argv[])
-{
- GLuint v_shader = 0, f_shader = 0, g_shader = 0;
-
- ParseOptions(argc, argv);
-
- if (!CreateContext()) {
- fprintf(stderr, "%s: Failed to create compiler context\n", Prog);
- exit(1);
- }
-
- if (Options.VertFile) {
- v_shader = CompileShader(Options.VertFile, GL_VERTEX_SHADER);
- }
-
- if (Options.FragFile) {
- f_shader = CompileShader(Options.FragFile, GL_FRAGMENT_SHADER);
- }
-
- if (Options.GeoFile) {
- g_shader = CompileShader(Options.GeoFile, GL_GEOMETRY_SHADER_ARB);
- }
-
-
- if (v_shader || f_shader || g_shader) {
- if (Options.OutputFile) {
- FILE *f;
- fclose(stdout);
- /*stdout =*/ f = freopen(Options.OutputFile, "w", stdout);
- if (!f) {
- fprintf(stderr, "freopen error\n");
- }
- }
- if (stdout && v_shader) {
- PrintShaderInstructions(v_shader, stdout);
- }
- if (stdout && f_shader) {
- PrintShaderInstructions(f_shader, stdout);
- }
- if (stdout && g_shader) {
- PrintShaderInstructions(g_shader, stdout);
- }
- if (Options.OutputFile) {
- fclose(stdout);
- }
- }
-
- if (Options.Link) {
- if (!v_shader || !f_shader) {
- fprintf(stderr,
- "--link option requires both a vertex and fragment shader.\n");
- exit(1);
- }
-
- CheckLink(v_shader, f_shader);
- }
-
- return 0;
-}
+++ /dev/null
-# Makefile for core library for VMS
-# contributed by Jouk Jansen joukj@hrem.nano.tudelft.nl
-# Last revision : 3 October 2007
-
-.first
- define gl [----.include.gl]
- define math [--.math]
- define swrast [--.swrast]
- define array_cache [--.array_cache]
- define main [--.main]
- define glapi [--.glapi]
- define shader [--.shader]
-
-.include [----]mms-config.
-
-##### MACROS #####
-
-VPATH = RCS
-
-INCDIR = [----.include],[--.main],[--.glapi],[-.slang],[-]
-LIBDIR = [----.lib]
-CFLAGS = /include=($(INCDIR),[])/define=(PTHREADS=1)/name=(as_is,short)/float=ieee/ieee=denorm
-
-SOURCES = \
- slang_compile.c
-
-OBJECTS = slang_builtin.obj,slang_codegen.obj,slang_compile.obj,\
- slang_compile_function.obj,slang_compile_operation.obj,\
- slang_compile_struct.obj,slang_compile_variable.obj,slang_emit.obj,\
- slang_ir.obj,slang_label.obj,slang_library_noise.obj,slang_link.obj,\
- slang_log.obj,slang_mem.obj,slang_preprocess.obj,slang_print.obj,\
- slang_simplify.obj,slang_storage.obj,slang_typeinfo.obj,\
- slang_utility.obj,slang_vartable.obj
-
-##### RULES #####
-
-VERSION=Mesa V3.4
-
-##### TARGETS #####
-# Make the library
-$(LIBDIR)$(GL_LIB) : $(OBJECTS)
- @ library $(LIBDIR)$(GL_LIB) $(OBJECTS)
-
-clean :
- purge
- delete *.obj;*
-
-slang_builtin.obj : slang_builtin.c
-slang_codegen.obj : slang_codegen.c
-slang_compile.obj : slang_compile.c
-slang_compile_function.obj : slang_compile_function.c
-slang_compile_operation.obj : slang_compile_operation.c
-slang_compile_struct.obj : slang_compile_struct.c
-slang_compile_variable.obj : slang_compile_variable.c
-slang_emit.obj : slang_emit.c
-slang_ir.obj : slang_ir.c
-slang_label.obj : slang_label.c
-slang_library_noise.obj : slang_library_noise.c
-slang_link.obj : slang_link.c
-slang_log.obj : slang_log.c
-slang_mem.obj : slang_mem.c
-slang_print.obj : slang_print.c
-slang_simplify.obj : slang_simplify.c
-slang_storage.obj : slang_storage.c
-slang_typeinfo.obj : slang_typeinfo.c
-slang_utility.obj : slang_utility.c
-slang_vartable.obj : slang_vartable.c
+++ /dev/null
-# src/mesa/slang/library/Makefile
-
-TOP = ../../../..
-
-include $(TOP)/configs/current
-
-GLSL_CL = $(TOP)/src/glsl/apps/compile
-
-#
-# targets
-#
-
-.PHONY: default clean
-
-default: builtin
-
-clean:
- -rm -f *_gc.h
-
-builtin: builtin_110 builtin_120
-
-#
-# builtin library sources
-#
-
-builtin_110: slang_common_builtin_gc.h slang_core_gc.h slang_fragment_builtin_gc.h slang_vertex_builtin_gc.h slang_geometry_builtin_gc.h
-
-builtin_120: slang_120_core_gc.h slang_builtin_120_common_gc.h slang_builtin_120_fragment_gc.h
-
-
-slang_120_core_gc.h: slang_120_core.gc
- $(GLSL_CL) fragment slang_120_core.gc slang_120_core_gc.h
-
-slang_builtin_120_common_gc.h: slang_builtin_120_common.gc
- $(GLSL_CL) fragment slang_builtin_120_common.gc slang_builtin_120_common_gc.h
-
-slang_builtin_120_fragment_gc.h: slang_builtin_120_fragment.gc
- $(GLSL_CL) fragment slang_builtin_120_fragment.gc slang_builtin_120_fragment_gc.h
-
-slang_common_builtin_gc.h: slang_common_builtin.gc
- $(GLSL_CL) fragment slang_common_builtin.gc slang_common_builtin_gc.h
-
-slang_core_gc.h: slang_core.gc
- $(GLSL_CL) fragment slang_core.gc slang_core_gc.h
-
-slang_fragment_builtin_gc.h: slang_fragment_builtin.gc
- $(GLSL_CL) fragment slang_fragment_builtin.gc slang_fragment_builtin_gc.h
-
-slang_vertex_builtin_gc.h: slang_vertex_builtin.gc
- $(GLSL_CL) vertex slang_vertex_builtin.gc slang_vertex_builtin_gc.h
-
-slang_geometry_builtin_gc.h: slang_geometry_builtin.gc
- $(GLSL_CL) geometry slang_geometry_builtin.gc slang_geometry_builtin_gc.h
-
+++ /dev/null
-#######################################################################
-# SConscript for GLSL builtin library
-
-Import('*')
-
-env = env.Clone()
-
-# See also http://www.scons.org/wiki/UsingCodeGenerators
-
-def glsl_compile_emitter(target, source, env):
- env.Depends(target, glsl_compile)
- return (target, source)
-
-bld_frag = Builder(
- action = Action(glsl_compile[0].abspath + ' fragment $SOURCE $TARGET', '$CODEGENCODESTR'),
- emitter = glsl_compile_emitter,
- suffix = '.gc',
- src_suffix = '_gc.h')
-
-bld_vert = Builder(
- action = Action(glsl_compile[0].abspath + ' vertex $SOURCE $TARGET', '$CODEGENCODESTR'),
- emitter = glsl_compile_emitter,
- suffix = '.gc',
- src_suffix = '_gc.h')
-
-bld_geom = Builder(
- action = Action(glsl_compile[0].abspath + ' geometry $SOURCE $TARGET', '$CODEGENCODESTR'),
- emitter = glsl_compile_emitter,
- suffix = '.gc',
- src_suffix = '_gc.h')
-
-env['BUILDERS']['bld_frag'] = bld_frag
-env['BUILDERS']['bld_vert'] = bld_vert
-env['BUILDERS']['bld_geom'] = bld_geom
-
-# Generate GLSL builtin library binaries
-env.bld_frag(
- '#src/mesa/slang/library/slang_core_gc.h',
- '#src/mesa/slang/library/slang_core.gc')
-env.bld_frag(
- '#src/mesa/slang/library/slang_common_builtin_gc.h',
- '#src/mesa/slang/library/slang_common_builtin.gc')
-env.bld_frag(
- '#src/mesa/slang/library/slang_fragment_builtin_gc.h',
- '#src/mesa/slang/library/slang_fragment_builtin.gc')
-env.bld_vert(
- '#src/mesa/slang/library/slang_vertex_builtin_gc.h',
- '#src/mesa/slang/library/slang_vertex_builtin.gc')
-env.bld_geom(
- '#src/mesa/slang/library/slang_geometry_builtin_gc.h',
- '#src/mesa/slang/library/slang_geometry_builtin.gc')
-
-# Generate GLSL 1.20 builtin library binaries
-env.bld_frag(
- '#src/mesa/slang/library/slang_120_core_gc.h',
- '#src/mesa/slang/library/slang_120_core.gc')
-env.bld_frag(
- '#src/mesa/slang/library/slang_builtin_120_common_gc.h',
- '#src/mesa/slang/library/slang_builtin_120_common.gc')
-env.bld_frag(
- '#src/mesa/slang/library/slang_builtin_120_fragment_gc.h',
- '#src/mesa/slang/library/slang_builtin_120_fragment.gc')
+++ /dev/null
-/*
- * Mesa 3-D graphics library
- * Version: 6.5
- *
- * Copyright (C) 2006 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.
- */
-
-//
-// Constructors and operators introduced in GLSL 1.20 - mostly on new
-// (non-square) types of matrices.
-//
-// One important change in the language is that when a matrix is used
-// as an argument to a matrix constructor, it must be the only argument
-// for the constructor. The compiler takes care of it by itself and
-// here we only care to re-introduce constructors for old (square)
-// types of matrices.
-//
-
-//
-// From Shader Spec, ver. 1.20, rev. 6
-//
-
-//// mat2x3: 2 columns of vec3
-
-mat2x3 __constructor(const float f00, const float f10, const float f20,
- const float f01, const float f11, const float f21)
-{
- __retVal[0].x = f00;
- __retVal[0].y = f10;
- __retVal[0].z = f20;
- __retVal[1].x = f01;
- __retVal[1].y = f11;
- __retVal[1].z = f21;
-}
-
-mat2x3 __constructor(const float f)
-{
- __retVal = mat2x3( f, 0.0, 0.0,
- 0.0, f, 0.0);
-}
-
-mat2x3 __constructor(const int i)
-{
- const float f = float(i);
- __retVal = mat2x3(f);
-}
-
-mat2x3 __constructor(const bool b)
-{
- const float f = float(b);
- __retVal = mat2x3(f);
-}
-
-mat2x3 __constructor(const vec3 c0, const vec3 c1)
-{
- __retVal[0] = c0;
- __retVal[1] = c1;
-}
-
-
-
-//// mat2x4: 2 columns of vec4
-
-mat2x4 __constructor(const float f00, const float f10, const float f20, const float f30,
- const float f01, const float f11, const float f21, const float f31)
-{
- __retVal[0].x = f00;
- __retVal[0].y = f10;
- __retVal[0].z = f20;
- __retVal[0].w = f30;
- __retVal[1].x = f01;
- __retVal[1].y = f11;
- __retVal[1].z = f21;
- __retVal[1].w = f31;
-}
-
-mat2x4 __constructor(const float f)
-{
- __retVal = mat2x4( f, 0.0, 0.0, 0.0,
- 0.0, f, 0.0, 0.0);
-}
-
-mat2x4 __constructor(const int i)
-{
- const float f = float(i);
- __retVal = mat2x4(f);
-}
-
-mat2x4 __constructor(const bool b)
-{
- const float f = float(b);
- __retVal = mat2x4(f);
-}
-
-mat2x4 __constructor(const vec4 c0, const vec4 c1)
-{
- __retVal[0] = c0;
- __retVal[1] = c1;
-}
-
-
-
-//// mat3x2: 3 columns of vec2
-
-mat3x2 __constructor(const float f00, const float f10,
- const float f01, const float f11,
- const float f02, const float f12)
-{
- __retVal[0].x = f00;
- __retVal[0].y = f10;
- __retVal[1].x = f01;
- __retVal[1].y = f11;
- __retVal[2].x = f02;
- __retVal[2].y = f12;
-}
-
-mat3x2 __constructor(const float f)
-{
- __retVal = mat3x2( f, 0.0,
- 0.0, f,
- 0.0, 0.0);
-}
-
-mat3x2 __constructor(const int i)
-{
- const float f = float(i);
- __retVal = mat3x2(f);
-}
-
-mat3x2 __constructor(const bool b)
-{
- const float f = float(b);
- __retVal = mat3x2(f);
-}
-
-mat3x2 __constructor(const vec2 c0, const vec2 c1, const vec2 c2)
-{
- __retVal[0] = c0;
- __retVal[1] = c1;
- __retVal[2] = c2;
-}
-
-
-
-//// mat3x4: 3 columns of vec4
-
-mat3x4 __constructor(const float f00, const float f10, const float f20, const float f30,
- const float f01, const float f11, const float f21, const float f31,
- const float f02, const float f12, const float f22, const float f32)
-{
- __retVal[0].x = f00;
- __retVal[0].y = f10;
- __retVal[0].z = f20;
- __retVal[0].w = f30;
- __retVal[1].x = f01;
- __retVal[1].y = f11;
- __retVal[1].z = f21;
- __retVal[1].w = f31;
- __retVal[2].x = f02;
- __retVal[2].y = f12;
- __retVal[2].z = f22;
- __retVal[2].w = f32;
-}
-
-mat3x4 __constructor(const float f)
-{
- __retVal = mat3x4( f, 0.0, 0.0, 0.0,
- 0.0, f, 0.0, 0.0,
- 0.0, 0.0, f, 0.0);
-}
-
-mat3x4 __constructor(const int i)
-{
- const float f = float(i);
- __retVal = mat3x4(f);
-}
-
-mat3x4 __constructor(const bool b)
-{
- const float f = float(b);
- __retVal = mat3x4(f);
-}
-
-mat3x4 __constructor(const vec4 c0, const vec4 c1, const vec4 c2)
-{
- __retVal[0] = c0;
- __retVal[1] = c1;
- __retVal[2] = c2;
-}
-
-
-
-//// mat4x2: 4 columns of vec2
-
-mat4x2 __constructor(const float f00, const float f10,
- const float f01, const float f11,
- const float f02, const float f12,
- const float f03, const float f13)
-{
- __retVal[0].x = f00;
- __retVal[0].y = f10;
- __retVal[1].x = f01;
- __retVal[1].y = f11;
- __retVal[2].x = f02;
- __retVal[2].y = f12;
- __retVal[3].x = f03;
- __retVal[3].y = f13;
-}
-
-mat4x2 __constructor(const float f)
-{
- __retVal = mat4x2( f, 0.0,
- 0.0, 4,
- 0.0, 0.0,
- 0.0, 0.0);
-}
-
-mat4x2 __constructor(const int i)
-{
- const float f = float(i);
- __retVal = mat4x2(f);
-}
-
-mat4x2 __constructor(const bool b)
-{
- const float f = float(b);
- __retVal = mat4x2(f);
-}
-
-mat4x2 __constructor(const vec2 c0, const vec2 c1, const vec2 c2, const vec2 c3)
-{
- __retVal[0] = c0;
- __retVal[1] = c1;
- __retVal[2] = c2;
- __retVal[3] = c3;
-}
-
-
-
-//// mat4x3: 4 columns of vec3
-
-mat4x3 __constructor(const float f00, const float f10, const float f20,
- const float f01, const float f11, const float f21,
- const float f02, const float f12, const float f22,
- const float f03, const float f13, const float f23)
-{
- __retVal[0].x = f00;
- __retVal[0].y = f10;
- __retVal[0].z = f20;
- __retVal[1].x = f01;
- __retVal[1].y = f11;
- __retVal[1].z = f21;
- __retVal[2].x = f02;
- __retVal[2].y = f12;
- __retVal[2].z = f22;
- __retVal[3].x = f03;
- __retVal[3].y = f13;
- __retVal[3].z = f23;
-}
-
-mat4x3 __constructor(const float f)
-{
- __retVal = mat4x3( f, 0.0, 0.0,
- 0.0, f, 0.0,
- 0.0, 0.0, f,
- 0.0, 0.0, 0.0);
-}
-
-mat4x3 __constructor(const int i)
-{
- const float f = float(i);
- __retVal = mat4x3(f);
-}
-
-mat4x3 __constructor(const bool b)
-{
- const float f = float(b);
- __retVal = mat4x3(f);
-}
-
-mat4x3 __constructor(const vec3 c0, const vec3 c1, const vec3 c2, const vec3 c3)
-{
- __retVal[0] = c0;
- __retVal[1] = c1;
- __retVal[2] = c2;
- __retVal[3] = c3;
-}
-
-
-
-//// misc assorted matrix constructors
-
-mat2 __constructor(const mat2 m)
-{
- __retVal = m;
-}
-
-mat2 __constructor(const mat3x2 m)
-{
- __retVal = mat2(m[0], m[1]);
-}
-
-mat2 __constructor(const mat4x2 m)
-{
- __retVal = mat2(m[0], m[1]);
-}
-
-mat2 __constructor(const mat2x3 m)
-{
- __retVal = mat2(m[0].xy, m[1].xy);
-}
-
-mat2 __constructor(const mat2x4 m)
-{
- __retVal = mat2(m[0].xy, m[1].xy);
-}
-
-mat2 __constructor(const mat3 m)
-{
- __retVal = mat2(m[0].xy, m[1].xy);
-}
-
-mat2 __constructor(const mat3x4 m)
-{
- __retVal = mat2(m[0].xy, m[1].xy);
-}
-
-mat2 __constructor(const mat4x3 m)
-{
- __retVal = mat2(m[0].xy, m[1].xy);
-}
-
-mat2 __constructor(const mat4 m)
-{
- __retVal = mat2(m[0].xy, m[1].xy);
-}
-
-
-
-mat2x3 __constructor(const mat2x3 m)
-{
- __retVal = m;
-}
-
-mat2x3 __constructor(const mat3 m)
-{
- __retVal = mat2x3(m[0], m[1]);
-}
-
-mat2x3 __constructor(const mat4x3 m)
-{
- __retVal = mat2x3(m[0], m[1]);
-}
-
-mat2x3 __constructor(const mat2x4 m)
-{
- __retVal = mat2x3(m[0].xyz, m[1].xyz);
-}
-
-mat2x3 __constructor(const mat3x4 m)
-{
- __retVal = mat2x3(m[0].xyz, m[1].xyz);
-}
-
-mat2x3 __constructor(const mat4 m)
-{
- __retVal = mat2x3(m[0].xyz, m[1].xyz);
-}
-
-mat2x3 __constructor(const mat2 m)
-{
- __retVal = mat2x3(m[0].x, m[0].y, 0.0,
- m[1].x, m[1].y, 0.0);
-}
-
-mat2x3 __constructor(const mat3x2 m)
-{
- __retVal = mat2x3(m[0].x, m[0].y, 0.0,
- m[1].x, m[1].y, 0.0);
-}
-
-mat2x3 __constructor(const mat4x2 m)
-{
- __retVal = mat2x3(m[0].x, m[0].y, 0.0,
- m[1].x, m[1].y, 0.0);
-}
-
-
-
-mat2x4 __constructor(const mat2x4 m)
-{
- __retVal = m;
-}
-
-mat2x4 __constructor(const mat3x4 m)
-{
- __retVal = mat2x4(m[0], m[1]);
-}
-
-mat2x4 __constructor(const mat4 m)
-{
- __retVal = mat2x4(m[0], m[1]);
-}
-
-mat2x4 __constructor(const mat2x3 m)
-{
- __retVal = mat2x4(m[0].x, m[0].y, m[0].z, 0.0,
- m[1].x, m[1].y, m[1].z, 0.0);
-}
-
-mat2x4 __constructor(const mat3 m)
-{
- __retVal = mat2x4(m[0].x, m[0].y, m[0].z, 0.0,
- m[1].x, m[1].y, m[1].z, 0.0);
-}
-
-mat2x4 __constructor(const mat4x3 m)
-{
- __retVal = mat2x4(m[0].x, m[0].y, m[0].z, 0.0,
- m[1].x, m[1].y, m[1].z, 0.0);
-}
-
-mat2x4 __constructor(const mat2 m)
-{
- __retVal = mat2x4(m[0].x, m[1].y, 0.0, 0.0,
- m[1].x, m[1].y, 0.0, 0.0);
-}
-
-mat2x4 __constructor(const mat3x2 m)
-{
- __retVal = mat2x4(m[0].x, m[0].y, 0.0, 0.0,
- m[1].x, m[1].y, 0.0, 0.0);
-}
-
-mat2x4 __constructor(const mat4x2 m)
-{
- __retVal = mat2x4(m[0].x, m[0].y, 0.0, 0.0,
- m[1].x, m[1].y, 0.0, 0.0);
-}
-
-
-
-mat3x2 __constructor(const mat3x2 m)
-{
- __retVal = m;
-}
-
-mat3x2 __constructor(const mat4x2 m)
-{
- __retVal = mat3x2(m[0], m[1], m[2]);
-}
-
-mat3x2 __constructor(const mat3 m)
-{
- __retVal = mat3x2(m[0], m[1], m[2]);
-}
-
-mat3x2 __constructor(const mat3x4 m)
-{
- __retVal = mat3x2(m[0].x, m[0].y,
- m[1].x, m[1].y,
- m[2].x, m[2].y);
-}
-
-mat3x2 __constructor(const mat4x3 m)
-{
- __retVal = mat3x2(m[0].x, m[0].y,
- m[1].x, m[1].y,
- m[2].x, m[2].y);
-}
-
-mat3x2 __constructor(const mat4 m)
-{
- __retVal = mat3x2(m[0].x, m[0].y,
- m[1].x, m[1].y,
- 0.0, 0.0);
-}
-
-mat3x2 __constructor(const mat2 m)
-{
- __retVal = mat3x2(m[0], m[1], vec2(0.0));
-}
-
-mat3x2 __constructor(const mat2x3 m)
-{
- __retVal = mat3x2(m[0].x, m[0].y,
- m[1].x, m[1].y,
- 0.0, 0.0);
-}
-
-mat3x2 __constructor(const mat2x4 m)
-{
- __retVal = mat3x2(m[0].x, m[0].y,
- m[1].x, m[1].y,
- 0.0, 0.0);
-}
-
-
-
-
-mat3 __constructor(const mat3 m)
-{
- __retVal = m;
-}
-
-mat3 __constructor(const mat4x3 m)
-{
- __retVal = mat3 (
- m[0],
- m[1],
- m[2]
- );
-}
-
-mat3 __constructor(const mat3x4 m)
-{
- __retVal = mat3 (
- m[0].xyz,
- m[1].xyz,
- m[2].xyz
- );
-}
-
-mat3 __constructor(const mat4 m)
-{
- __retVal = mat3 (
- m[0].xyz,
- m[1].xyz,
- m[2].xyz
- );
-}
-
-mat3 __constructor(const mat2x3 m)
-{
- __retVal = mat3 (
- m[0],
- m[1],
- 0., 0., 1.
- );
-}
-
-mat3 __constructor(const mat2x4 m)
-{
- __retVal = mat3 (
- m[0].xyz,
- m[1].xyz,
- 0., 0., 1.
- );
-}
-
-mat3 __constructor(const mat3x2 m)
-{
- __retVal = mat3 (
- m[0], 0.,
- m[1], 0.,
- m[2], 1.
- );
-}
-
-mat3 __constructor(const mat4x2 m)
-{
- __retVal = mat3 (
- m[0], 0.,
- m[1], 0.,
- m[2], 1.
- );
-}
-
-mat3 __constructor(const mat2 m)
-{
- __retVal = mat3 (
- m[0], 0.,
- m[1], 0.,
- 0., 0., 1.
- );
-}
-
-
-mat3x4 __constructor(const mat3x4 m)
-{
- __retVal = m;
-}
-
-mat3x4 __constructor(const mat4 m)
-{
- __retVal = mat3x4 (
- m[0],
- m[1],
- m[2]
- );
-}
-
-mat3x4 __constructor(const mat3 m)
-{
- __retVal = mat3x4 (
- m[0], 0.,
- m[1], 0.,
- m[2], 0.
- );
-}
-
-mat3x4 __constructor(const mat4x3 m)
-{
- __retVal = mat3x4 (
- m[0], 0.,
- m[1], 0.,
- m[2], 0.
- );
-}
-
-mat3x4 __constructor(const mat2x4 m)
-{
- __retVal = mat3x4 (
- m[0],
- m[1],
- 0., 0., 1., 0.
- );
-}
-
-mat3x4 __constructor(const mat2x3 m)
-{
- __retVal = mat3x4 (
- m[0], 0.,
- m[1], 0.,
- 0., 0., 1., 0.
- );
-}
-
-mat3x4 __constructor(const mat3x2 m)
-{
- __retVal = mat3x4 (
- m[0], 0., 0.,
- m[1], 0., 0.,
- m[2], 1., 0.
- );
-}
-
-mat3x4 __constructor(const mat4x2 m)
-{
- __retVal = mat3x4 (
- m[0], 0., 0.,
- m[1], 0., 0.,
- m[2], 1., 0.
- );
-}
-
-mat3x4 __constructor(const mat2 m)
-{
- __retVal = mat3x4 (
- m[0], 0., 0.,
- m[1], 0., 0.,
- 0., 0., 1., 0.
- );
-}
-
-
-mat4x2 __constructor(const mat4x2 m)
-{
- __retVal = m;
-}
-
-mat4x2 __constructor(const mat4x3 m)
-{
- __retVal = mat4x2 (
- m[0].xy,
- m[1].xy,
- m[2].xy,
- m[3].xy
- );
-}
-
-mat4x2 __constructor(const mat4 m)
-{
- __retVal = mat4x2 (
- m[0].xy,
- m[1].xy,
- m[2].xy,
- m[3].xy
- );
-}
-
-mat4x2 __constructor(const mat3x2 m)
-{
- __retVal = mat4x2 (
- m[0],
- m[1],
- 0., 0.
- );
-}
-
-mat4x2 __constructor(const mat3 m)
-{
- __retVal = mat4x2 (
- m[0].xy,
- m[1].xy,
- m[2].xy,
- 0., 0.
- );
-}
-
-mat4x2 __constructor(const mat3x4 m)
-{
- __retVal = mat4x2 (
- m[0].xy,
- m[1].xy,
- m[2].xy,
- 0., 0.
- );
-}
-
-mat4x2 __constructor(const mat2 m)
-{
- __retVal = mat4x2 (
- m[0],
- m[1],
- 0., 0.,
- 0., 0.
- );
-}
-
-mat4x2 __constructor(const mat2x3 m)
-{
- __retVal = mat4x2 (
- m[0].xy,
- m[1].xy,
- 0., 0.,
- 0., 0.
- );
-}
-
-mat4x2 __constructor(const mat2x4 m)
-{
- __retVal = mat4x2 (
- m[0].xy,
- m[1].xy,
- 0., 0.,
- 0., 0.
- );
-}
-
-
-mat4x3 __constructor(const mat4x3 m)
-{
- __retVal = m;
-}
-
-mat4x3 __constructor(const mat4 m)
-{
- __retVal = mat4x3 (
- m[0].xyz,
- m[1].xyz,
- m[2].xyz,
- m[3].xyz
- );
-}
-
-mat4x3 __constructor(const mat3 m)
-{
- __retVal = mat4x3 (
- m[0],
- m[1],
- m[2],
- 0., 0., 0.
- );
-}
-
-mat4x3 __constructor(const mat3x4 m)
-{
- __retVal = mat4x3 (
- m[0].xyz,
- m[1].xyz,
- m[2].xyz,
- 0., 0., 0.
- );
-}
-
-mat4x3 __constructor(const mat4x2 m)
-{
- __retVal = mat4x3 (
- m[0], 0.,
- m[1], 0.,
- m[2], 1.,
- m[3], 0.
- );
-}
-
-mat4x3 __constructor(const mat2x3 m)
-{
- __retVal = mat4x3 (
- m[0],
- m[1],
- 0., 0., 1.,
- 0., 0., 0.
- );
-}
-
-mat4x3 __constructor(const mat3x2 m)
-{
- __retVal = mat4x3 (
- m[0], 0.,
- m[1], 0.,
- m[2], 1.,
- 0., 0., 0.
- );
-}
-
-mat4x3 __constructor(const mat2x4 m)
-{
- __retVal = mat4x3 (
- m[0].xyz,
- m[1].xyz,
- 0., 0., 1.,
- 0., 0., 0.
- );
-}
-
-mat4x3 __constructor(const mat2 m)
-{
- __retVal = mat4x3 (
- m[0], 0.,
- m[1], 0.,
- 0., 0., 1.,
- 0., 0., 0.
- );
-}
-
-
-mat4 __constructor(const mat4 m)
-{
- __retVal = m;
-}
-
-mat4 __constructor(const mat3x4 m)
-{
- __retVal = mat4 (
- m[0],
- m[1],
- m[2],
- 0., 0., 0., 1.
- );
-}
-
-mat4 __constructor(const mat4x3 m)
-{
- __retVal = mat4 (
- m[0], 0.,
- m[1], 0.,
- m[2], 0.,
- m[3], 1.
- );
-}
-
-mat4 __constructor(const mat2x4 m)
-{
- __retVal = mat4 (
- m[0],
- m[1],
- 0., 0., 1., 0.,
- 0., 0., 0., 1.
- );
-}
-
-mat4 __constructor(const mat4x2 m)
-{
- __retVal = mat4 (
- m[0], 0., 0.,
- m[1], 0., 0.,
- m[2], 1., 0.,
- m[3], 0., 1.
- );
-}
-
-mat4 __constructor(const mat3 m)
-{
- __retVal = mat4 (
- m[0], 0.,
- m[1], 0.,
- m[2], 0.,
- 0., 0., 0., 1.
- );
-}
-
-mat4 __constructor(const mat2x3 m)
-{
- __retVal = mat4 (
- m[0], 0.,
- m[1], 0.,
- 0., 0., 1., 0.,
- 0., 0., 0., 1.
- );
-}
-
-mat4 __constructor(const mat3x2 m)
-{
- __retVal = mat4 (
- m[0], 0., 0.,
- m[1], 0., 0.,
- m[2], 1., 0.,
- 0., 0., 0., 1.
- );
-}
-
-mat4 __constructor(const mat2 m)
-{
- __retVal = mat4 (
- m[0], 0., 0.,
- m[1], 0., 0.,
- 0., 0., 1., 0.,
- 0., 0., 0., 1.
- );
-}
-
-
-void __operator += (inout mat2x3 m, const mat2x3 n) {
- m[0] += n[0];
- m[1] += n[1];
-}
-
-void __operator += (inout mat2x4 m, const mat2x4 n) {
- m[0] += n[0];
- m[1] += n[1];
-}
-
-void __operator += (inout mat3x2 m, const mat3x2 n) {
- m[0] += n[0];
- m[1] += n[1];
- m[2] += n[2];
-}
-
-void __operator += (inout mat3x4 m, const mat3x4 n) {
- m[0] += n[0];
- m[1] += n[1];
- m[2] += n[2];
-}
-
-void __operator += (inout mat4x2 m, const mat4x2 n) {
- m[0] += n[0];
- m[1] += n[1];
- m[2] += n[2];
- m[3] += n[3];
-}
-
-void __operator += (inout mat4x3 m, const mat4x3 n) {
- m[0] += n[0];
- m[1] += n[1];
- m[2] += n[2];
- m[3] += n[3];
-}
-
-
-void __operator -= (inout mat2x3 m, const mat2x3 n) {
- m[0] -= n[0];
- m[1] -= n[1];
-}
-
-void __operator -= (inout mat2x4 m, const mat2x4 n) {
- m[0] -= n[0];
- m[1] -= n[1];
-}
-
-void __operator -= (inout mat3x2 m, const mat3x2 n) {
- m[0] -= n[0];
- m[1] -= n[1];
- m[2] -= n[2];
-}
-
-void __operator -= (inout mat3x4 m, const mat3x4 n) {
- m[0] -= n[0];
- m[1] -= n[1];
- m[2] -= n[2];
-}
-
-void __operator -= (inout mat4x2 m, const mat4x2 n) {
- m[0] -= n[0];
- m[1] -= n[1];
- m[2] -= n[2];
- m[3] -= n[3];
-}
-
-void __operator -= (inout mat4x3 m, const mat4x3 n) {
- m[0] -= n[0];
- m[1] -= n[1];
- m[2] -= n[2];
- m[3] -= n[3];
-}
-
-
-void __operator /= (inout mat2x3 m, const mat2x3 n) {
- m[0] /= n[0];
- m[1] /= n[1];
-}
-
-void __operator /= (inout mat2x4 m, const mat2x4 n) {
- m[0] /= n[0];
- m[1] /= n[1];
-}
-
-void __operator /= (inout mat3x2 m, const mat3x2 n) {
- m[0] /= n[0];
- m[1] /= n[1];
- m[2] /= n[2];
-}
-
-void __operator /= (inout mat3x4 m, const mat3x4 n) {
- m[0] /= n[0];
- m[1] /= n[1];
- m[2] /= n[2];
-}
-
-void __operator /= (inout mat4x2 m, const mat4x2 n) {
- m[0] /= n[0];
- m[1] /= n[1];
- m[2] /= n[2];
- m[3] /= n[3];
-}
-
-void __operator /= (inout mat4x3 m, const mat4x3 n) {
- m[0] /= n[0];
- m[1] /= n[1];
- m[2] /= n[2];
- m[3] /= n[3];
-}
-
-
-vec3 __operator * (const mat2x3 m, const vec2 v)
-{
- __retVal.x = v.x * m[0].x + v.y * m[1].x;
- __retVal.y = v.x * m[0].y + v.y * m[1].y;
- __retVal.z = v.x * m[0].z + v.y * m[1].z;
-}
-
-vec4 __operator * (const mat2x4 m, const vec2 v)
-{
- __retVal.x = v.x * m[0].x + v.y * m[1].x;
- __retVal.y = v.x * m[0].y + v.y * m[1].y;
- __retVal.z = v.x * m[0].z + v.y * m[1].z;
- __retVal.w = v.x * m[0].w + v.y * m[1].w;
-}
-
-vec2 __operator * (const mat3x2 m, const vec3 v)
-{
- __retVal.x = v.x * m[0].x + v.y * m[1].x + v.z * m[2].x;
- __retVal.y = v.x * m[0].y + v.y * m[1].y + v.z * m[2].y;
-}
-
-vec4 __operator * (const mat3x4 m, const vec3 v)
-{
- __retVal.x = v.x * m[0].x + v.y * m[1].x + v.z * m[2].x;
- __retVal.y = v.x * m[0].y + v.y * m[1].y + v.z * m[2].y;
- __retVal.z = v.x * m[0].z + v.y * m[1].z + v.z * m[2].z;
- __retVal.w = v.x * m[0].w + v.y * m[1].w + v.z * m[2].w;
-}
-
-vec2 __operator * (const mat4x2 m, const vec4 v)
-{
- __retVal.x = v.x * m[0].x + v.y * m[1].x + v.z * m[2].x + v.w * m[3].x;
- __retVal.y = v.x * m[0].y + v.y * m[1].y + v.z * m[2].y + v.w * m[3].y;
-}
-
-vec3 __operator * (const mat4x3 m, const vec4 v)
-{
- __retVal.x = v.x * m[0].x + v.y * m[1].x + v.z * m[2].x + v.w * m[3].x;
- __retVal.y = v.x * m[0].y + v.y * m[1].y + v.z * m[2].y + v.w * m[3].y;
- __retVal.z = v.x * m[0].z + v.y * m[1].z + v.z * m[2].z + v.w * m[3].z;
-}
-
-
-mat3x2 __operator * (const mat2 m, const mat3x2 n)
-{
- //return mat3x2 (m * n[0], m * n[1], m * n[2]);
- __retVal[0] = m * n[0];
- __retVal[1] = m * n[1];
- __retVal[2] = m * n[2];
-}
-
-mat4x2 __operator * (const mat2 m, const mat4x2 n)
-{
- //return mat4x2 (m * n[0], m * n[1], m * n[2], m * n[3]);
- __retVal[0] = m * n[0];
- __retVal[1] = m * n[1];
- __retVal[2] = m * n[2];
- __retVal[3] = m * n[3];
-}
-
-
-mat2x3 __operator * (const mat2x3 m, const mat2 n)
-{
- //return mat2x3 (m * n[0], m * n[1]);
- __retVal[0] = m * n[0];
- __retVal[1] = m * n[1];
-}
-
-mat3 __operator * (const mat2x3 m, const mat3x2 n)
-{
- //return mat3 (m * n[0], m * n[1], m * n[2]);
- __retVal[0] = m * n[0];
- __retVal[1] = m * n[1];
- __retVal[2] = m * n[2];
-}
-
-mat4x3 __operator * (const mat2x3 m, const mat4x2 n)
-{
- //return mat4x3 (m * n[0], m * n[1], m * n[2], m * n[3]);
- __retVal[0] = m * n[0];
- __retVal[1] = m * n[1];
- __retVal[2] = m * n[2];
- __retVal[3] = m * n[3];
-}
-
-
-mat2x4 __operator * (const mat2x4 m, const mat2 n)
-{
- //return mat2x4 (m * n[0], m * n[1]);
- __retVal[0] = m * n[0];
- __retVal[1] = m * n[1];
-}
-
-mat3x4 __operator * (const mat2x4 m, const mat3x2 n)
-{
- //return mat3x4 (m * n[0], m * n[1], m * n[2]);
- __retVal[0] = m * n[0];
- __retVal[1] = m * n[1];
- __retVal[2] = m * n[2];
-}
-
-mat4 __operator * (const mat2x4 m, const mat4x2 n)
-{
- //return mat4 (m * n[0], m * n[1], m * n[2], m * n[3]);
- __retVal[0] = m * n[0];
- __retVal[1] = m * n[1];
- __retVal[2] = m * n[2];
- __retVal[3] = m * n[3];
-}
-
-
-mat2 __operator * (const mat3x2 m, const mat2x3 n)
-{
- //return mat2 (m * n[0], m * n[1]);
- __retVal[0] = m * n[0];
- __retVal[1] = m * n[1];
-}
-
-mat3x2 __operator * (const mat3x2 m, const mat3 n)
-{
- //return mat3x2 (m * n[0], m * n[1], m * n[2]);
- __retVal[0] = m * n[0];
- __retVal[1] = m * n[1];
- __retVal[2] = m * n[2];
-}
-
-mat4x2 __operator * (const mat3x2 m, const mat4x3 n)
-{
- //return mat4x2 (m * n[0], m * n[1], m * n[2], m * n[3]);
- __retVal[0] = m * n[0];
- __retVal[1] = m * n[1];
- __retVal[2] = m * n[2];
- __retVal[3] = m * n[3];
-}
-
-
-mat2x3 __operator * (const mat3 m, const mat2x3 n)
-{
- //return mat2x3 (m * n[0], m * n[1]);
- __retVal[0] = m * n[0];
- __retVal[1] = m * n[1];
-}
-
-mat4x3 __operator * (const mat3 m, const mat4x3 n)
-{
- //return mat4x3 (m * n[0], m * n[1], m * n[2], m * n[3]);
- __retVal[0] = m * n[0];
- __retVal[1] = m * n[1];
- __retVal[2] = m * n[2];
- __retVal[3] = m * n[3];
-}
-
-
-mat2x4 __operator * (const mat3x4 m, const mat2x3 n)
-{
- //return mat2x4 (m * n[0], m * n[1]);
- __retVal[0] = m * n[0];
- __retVal[1] = m * n[1];
-}
-
-mat3x4 __operator * (const mat3x4 m, const mat3 n)
-{
- //return mat3x4 (m * n[0], m * n[1], m * n[2]);
- __retVal[0] = m * n[0];
- __retVal[1] = m * n[1];
- __retVal[2] = m * n[2];
-}
-
-mat4 __operator * (const mat3x4 m, const mat4x3 n)
-{
- //return mat4 (m * n[0], m * n[1], m * n[2], m * n[3]);
- __retVal[0] = m * n[0];
- __retVal[1] = m * n[1];
- __retVal[2] = m * n[2];
- __retVal[3] = m * n[3];
-}
-
-
-mat2 __operator * (const mat4x2 m, const mat2x4 n)
-{
- //return = mat2 (m * n[0], m * n[1]);
- __retVal[0] = m * n[0];
- __retVal[1] = m * n[1];
-}
-
-mat3x2 __operator * (const mat4x2 m, const mat3x4 n)
-{
- //return mat3x2 (m * n[0], m * n[1], m * n[2]);
- __retVal[0] = m * n[0];
- __retVal[1] = m * n[1];
- __retVal[2] = m * n[2];
-}
-
-mat4x2 __operator * (const mat4x2 m, const mat4 n)
-{
- //return mat4x2 (m * n[0], m * n[1], m * n[2], m * n[3]);
- __retVal[0] = m * n[0];
- __retVal[1] = m * n[1];
- __retVal[2] = m * n[2];
- __retVal[3] = m * n[3];
-}
-
-
-mat2x3 __operator * (const mat4x3 m, const mat2x4 n)
-{
- //return mat2x3 (m * n[0], m * n[1]);
- __retVal[0] = m * n[0];
- __retVal[1] = m * n[1];
-}
-
-mat3 __operator * (const mat4x3 m, const mat3x4 n)
-{
- //return mat3 (m * n[0], m * n[1], m * n[2]);
- __retVal[0] = m * n[0];
- __retVal[1] = m * n[1];
- __retVal[2] = m * n[2];
-}
-
-mat4x3 __operator * (const mat4x3 m, const mat4 n)
-{
- //return mat4x3 (m * n[0], m * n[1], m * n[2], m * n[3]);
- __retVal[0] = m * n[0];
- __retVal[1] = m * n[1];
- __retVal[2] = m * n[2];
- __retVal[3] = m * n[3];
-}
-
-
-mat2x4 __operator * (const mat4 m, const mat2x4 n)
-{
- //return mat2x4 (m * n[0], m * n[1]);
- __retVal[0] = m * n[0];
- __retVal[1] = m * n[1];
-}
-
-mat3x4 __operator * (const mat4 m, const mat3x4 n)
-{
- //return mat3x4 (m * n[0], m * n[1], m * n[2]);
- __retVal[0] = m * n[0];
- __retVal[1] = m * n[1];
- __retVal[2] = m * n[2];
-}
-
-
-void __operator *= (inout mat2x3 m, const mat2 n) {
- m = m * n;
-}
-
-void __operator *= (inout mat2x4 m, const mat2 n) {
- m = m * n;
-}
-
-void __operator *= (inout mat3x2 m, const mat3 n) {
- m = m * n;
-}
-
-void __operator *= (inout mat3x4 m, const mat3 n) {
- m = m * n;
-}
-
-void __operator *= (inout mat4x2 m, const mat4 n) {
- m = m * n;
-}
-
-void __operator *= (inout mat4x3 m, const mat4 n) {
- m = m * n;
-}
-
-
-vec3 __operator * (const vec2 v, const mat3x2 m)
-{
- __retVal.x = dot(v, m[0]);
- __retVal.y = dot(v, m[1]);
- __retVal.z = dot(v, m[2]);
-}
-
-vec4 __operator * (const vec2 v, const mat4x2 m)
-{
- __retVal.x = dot(v, m[0]);
- __retVal.y = dot(v, m[1]);
- __retVal.z = dot(v, m[2]);
- __retVal.w = dot(v, m[3]);
-}
-
-vec2 __operator * (const vec3 v, const mat2x3 m)
-{
- __retVal.x = dot(v, m[0]);
- __retVal.y = dot(v, m[1]);
-}
-
-vec4 __operator * (const vec3 v, const mat4x3 m)
-{
- __retVal.x = dot(v, m[0]);
- __retVal.y = dot(v, m[1]);
- __retVal.z = dot(v, m[2]);
- __retVal.w = dot(v, m[3]);
-}
-
-vec2 __operator * (const vec4 v, const mat2x4 m)
-{
- __retVal.x = dot(v, m[0]);
- __retVal.y = dot(v, m[1]);
-}
-
-vec3 __operator * (const vec4 v, const mat3x4 m)
-{
- __retVal.x = dot(v, m[0]);
- __retVal.y = dot(v, m[1]);
- __retVal.z = dot(v, m[2]);
-}
-
-
-void __operator += (inout mat2x3 m, const float a) {
- m[0] += a;
- m[1] += a;
-}
-
-void __operator += (inout mat2x4 m, const float a) {
- m[0] += a;
- m[1] += a;
-}
-
-void __operator += (inout mat3x2 m, const float a) {
- m[0] += a;
- m[1] += a;
- m[2] += a;
-}
-
-void __operator += (inout mat3x4 m, const float a) {
- m[0] += a;
- m[1] += a;
- m[2] += a;
-}
-
-void __operator += (inout mat4x2 m, const float a) {
- m[0] += a;
- m[1] += a;
- m[2] += a;
- m[3] += a;
-}
-
-void __operator += (inout mat4x3 m, const float a) {
- m[0] += a;
- m[1] += a;
- m[2] += a;
- m[3] += a;
-}
-
-
-void __operator -= (inout mat2x3 m, const float a) {
- m[0] -= a;
- m[1] -= a;
-}
-
-void __operator -= (inout mat2x4 m, const float a) {
- m[0] -= a;
- m[1] -= a;
-}
-
-void __operator -= (inout mat3x2 m, const float a) {
- m[0] -= a;
- m[1] -= a;
- m[2] -= a;
-}
-
-void __operator -= (inout mat3x4 m, const float a) {
- m[0] -= a;
- m[1] -= a;
- m[2] -= a;
-}
-
-void __operator -= (inout mat4x2 m, const float a) {
- m[0] -= a;
- m[1] -= a;
- m[2] -= a;
- m[3] -= a;
-}
-
-void __operator -= (inout mat4x3 m, const float a) {
- m[0] -= a;
- m[1] -= a;
- m[2] -= a;
- m[3] -= a;
-}
-
-
-void __operator *= (inout mat2x3 m, const float a) {
- m[0] *= a;
- m[1] *= a;
-}
-
-void __operator *= (inout mat2x4 m, const float a) {
- m[0] *= a;
- m[1] *= a;
-}
-
-void __operator *= (inout mat3x2 m, const float a) {
- m[0] *= a;
- m[1] *= a;
- m[2] *= a;
-}
-
-void __operator *= (inout mat3x4 m, const float a) {
- m[0] *= a;
- m[1] *= a;
- m[2] *= a;
-}
-
-void __operator *= (inout mat4x2 m, const float a) {
- m[0] *= a;
- m[1] *= a;
- m[2] *= a;
- m[3] *= a;
-}
-
-void __operator *= (inout mat4x3 m, const float a) {
- m[0] *= a;
- m[1] *= a;
- m[2] *= a;
- m[3] *= a;
-}
-
-
-void __operator /= (inout mat2x3 m, const float a) {
- m[0] /= a;
- m[1] /= a;
-}
-
-void __operator /= (inout mat2x4 m, const float a) {
- m[0] /= a;
- m[1] /= a;
-}
-
-void __operator /= (inout mat3x2 m, const float a) {
- m[0] /= a;
- m[1] /= a;
- m[2] /= a;
-}
-
-void __operator /= (inout mat3x4 m, const float a) {
- m[0] /= a;
- m[1] /= a;
- m[2] /= a;
-}
-
-void __operator /= (inout mat4x2 m, const float a) {
- m[0] /= a;
- m[1] /= a;
- m[2] /= a;
- m[3] /= a;
-}
-
-void __operator /= (inout mat4x3 m, const float a) {
- m[0] /= a;
- m[1] /= a;
- m[2] /= a;
- m[3] /= a;
-}
-
-
-mat2x3 __operator + (const mat2x3 m, const mat2x3 n) {
- return mat2x3 (m[0] + n[0], m[1] + n[1]);
-}
-
-mat2x4 __operator + (const mat2x4 m, const mat2x4 n) {
- return mat2x4 (m[0] + n[0], m[1] + n[1]);
-}
-
-mat3x2 __operator + (const mat3x2 m, const mat3x2 n) {
- return mat3x2 (m[0] + n[0], m[1] + n[1], m[2] + n[2]);
-}
-
-mat3x4 __operator + (const mat3x4 m, const mat3x4 n) {
- return mat3x4 (m[0] + n[0], m[1] + n[1], m[2] + n[2]);
-}
-
-mat4x2 __operator + (const mat4x2 m, const mat4x2 n) {
- return mat4x2 (m[0] + n[0], m[1] + n[1], m[2] + n[2], m[3] + n[3]);
-}
-
-mat4x3 __operator + (const mat4x3 m, const mat4x3 n) {
- return mat4x3 (m[0] + n[0], m[1] + n[1], m[2] + n[2], m[3] + n[3]);
-}
-
-
-mat2x3 __operator - (const mat2x3 m, const mat2x3 n) {
- return mat2x3 (m[0] - n[0], m[1] - n[1]);
-}
-
-mat2x4 __operator - (const mat2x4 m, const mat2x4 n) {
- return mat2x4 (m[0] - n[0], m[1] - n[1]);
-}
-
-mat3x2 __operator - (const mat3x2 m, const mat3x2 n) {
- return mat3x2 (m[0] - n[0], m[1] - n[1], m[2] - n[2]);
-}
-
-mat3x4 __operator - (const mat3x4 m, const mat3x4 n) {
- return mat3x4 (m[0] - n[0], m[1] - n[1], m[2] - n[2]);
-}
-
-mat4x2 __operator - (const mat4x2 m, const mat4x2 n) {
- return mat4x2 (m[0] - n[0], m[1] - n[1], m[2] - n[2], m[3] - n[3]);
-}
-
-mat4x3 __operator - (const mat4x3 m, const mat4x3 n) {
- return mat4x3 (m[0] - n[0], m[1] - n[1], m[2] - n[2], m[3] - n[3]);
-}
-
-
-mat2x3 __operator / (const mat2x3 m, const mat2x3 n) {
- return mat2x3 (m[0] / n[0], m[1] / n[1]);
-}
-
-mat2x4 __operator / (const mat2x4 m, const mat2x4 n) {
- return mat2x4 (m[0] / n[0], m[1] / n[1]);
-}
-
-mat3x2 __operator / (const mat3x2 m, const mat3x2 n) {
- return mat3x2 (m[0] / n[0], m[1] / n[1], m[2] / n[2]);
-}
-
-mat3x4 __operator / (const mat3x4 m, const mat3x4 n) {
- return mat3x4 (m[0] / n[0], m[1] / n[1], m[2] / n[2]);
-}
-
-mat4x2 __operator / (const mat4x2 m, const mat4x2 n) {
- return mat4x2 (m[0] / n[0], m[1] / n[1], m[2] / n[2], m[3] / n[3]);
-}
-
-mat4x3 __operator / (const mat4x3 m, const mat4x3 n) {
- return mat4x3 (m[0] / n[0], m[1] / n[1], m[2] / n[2], m[3] / n[3]);
-}
-
-
-mat2x3 __operator + (const float a, const mat2x3 n) {
- return mat2x3 (a + n[0], a + n[1]);
-}
-
-mat2x3 __operator + (const mat2x3 m, const float b) {
- return mat2x3 (m[0] + b, m[1] + b);
-}
-
-mat2x4 __operator + (const float a, const mat2x4 n) {
- return mat2x4 (a + n[0], a + n[1]);
-}
-
-mat2x4 __operator + (const mat2x4 m, const float b) {
- return mat2x4 (m[0] + b, m[1] + b);
-}
-
-mat3x2 __operator + (const float a, const mat3x2 n) {
- return mat3x2 (a + n[0], a + n[1], a + n[2]);
-}
-
-mat3x2 __operator + (const mat3x2 m, const float b) {
- return mat3x2 (m[0] + b, m[1] + b, m[2] + b);
-}
-
-mat3x4 __operator + (const float a, const mat3x4 n) {
- return mat3x4 (a + n[0], a + n[1], a + n[2]);
-}
-
-mat3x4 __operator + (const mat3x4 m, const float b) {
- return mat3x4 (m[0] + b, m[1] + b, m[2] + b);
-}
-
-mat4x2 __operator + (const mat4x2 m, const float b) {
- return mat4x2 (m[0] + b, m[1] + b, m[2] + b, m[3] + b);
-}
-
-mat4x2 __operator + (const float a, const mat4x2 n) {
- return mat4x2 (a + n[0], a + n[1], a + n[2], a + n[3]);
-}
-
-mat4x3 __operator + (const mat4x3 m, const float b) {
- return mat4x3 (m[0] + b, m[1] + b, m[2] + b, m[3] + b);
-}
-
-mat4x3 __operator + (const float a, const mat4x3 n) {
- return mat4x3 (a + n[0], a + n[1], a + n[2], a + n[3]);
-}
-
-
-mat2x3 __operator - (const float a, const mat2x3 n) {
- return mat2x3 (a - n[0], a - n[1]);
-}
-
-mat2x3 __operator - (const mat2x3 m, const float b) {
- return mat2x3 (m[0] - b, m[1] - b);
-}
-
-mat2x4 __operator - (const float a, const mat2x4 n) {
- return mat2x4 (a - n[0], a - n[1]);
-}
-
-mat2x4 __operator - (const mat2x4 m, const float b) {
- return mat2x4 (m[0] - b, m[1] - b);
-}
-
-mat3x2 __operator - (const float a, const mat3x2 n) {
- return mat3x2 (a - n[0], a - n[1], a - n[2]);
-}
-
-mat3x2 __operator - (const mat3x2 m, const float b) {
- return mat3x2 (m[0] - b, m[1] - b, m[2] - b);
-}
-
-mat3x4 __operator - (const float a, const mat3x4 n) {
- return mat3x4 (a - n[0], a - n[1], a - n[2]);
-}
-
-mat3x4 __operator - (const mat3x4 m, const float b) {
- return mat3x4 (m[0] - b, m[1] - b, m[2] - b);
-}
-
-mat4x2 __operator - (const mat4x2 m, const float b) {
- return mat4x2 (m[0] - b, m[1] - b, m[2] - b, m[3] - b);
-}
-
-mat4x2 __operator - (const float a, const mat4x2 n) {
- return mat4x2 (a - n[0], a - n[1], a - n[2], a - n[3]);
-}
-
-mat4x3 __operator - (const mat4x3 m, const float b) {
- return mat4x3 (m[0] - b, m[1] - b, m[2] - b, m[3] - b);
-}
-
-mat4x3 __operator - (const float a, const mat4x3 n) {
- return mat4x3 (a - n[0], a - n[1], a - n[2], a - n[3]);
-}
-
-
-mat2x3 __operator * (const float a, const mat2x3 n)
-{
- //return mat2x3 (a * n[0], a * n[1]);
- __retVal[0] = a * n[0];
- __retVal[1] = a * n[1];
-}
-
-mat2x3 __operator * (const mat2x3 m, const float b)
-{
- //return mat2x3 (m[0] * b, m[1] * b);
- __retVal[0] = m[0] * b;
- __retVal[1] = m[1] * b;
-}
-
-mat2x4 __operator * (const float a, const mat2x4 n)
-{
- //return mat2x4 (a * n[0], a * n[1]);
- __retVal[0] = a * n[0];
- __retVal[1] = a * n[1];
-}
-
-mat2x4 __operator * (const mat2x4 m, const float b)
-{
- //return mat2x4 (m[0] * b, m[1] * b);
- __retVal[0] = m[0] * b;
- __retVal[1] = m[1] * b;
-}
-
-mat3x2 __operator * (const float a, const mat3x2 n)
-{
- //return mat3x2 (a * n[0], a * n[1], a * n[2]);
- __retVal[0] = a * n[0];
- __retVal[1] = a * n[1];
- __retVal[2] = a * n[2];
-}
-
-mat3x2 __operator * (const mat3x2 m, const float b)
-{
- //return mat3x2 (m[0] * b, m[1] * b, m[2] * b);
- __retVal[0] = m[0] * b;
- __retVal[1] = m[1] * b;
- __retVal[2] = m[2] * b;
-}
-
-mat3x4 __operator * (const float a, const mat3x4 n)
-{
- //return mat3x4 (a * n[0], a * n[1], a * n[2]);
- __retVal[0] = a * n[0];
- __retVal[1] = a * n[1];
- __retVal[2] = a * n[2];
-}
-
-mat3x4 __operator * (const mat3x4 m, const float b)
-{
- //return mat3x4 (m[0] * b, m[1] * b, m[2] * b);
- __retVal[0] = m[0] * b;
- __retVal[1] = m[1] * b;
- __retVal[2] = m[2] * b;
-}
-
-mat4x2 __operator * (const mat4x2 m, const float b)
-{
- //return mat4x2 (m[0] * b, m[1] * b, m[2] * b, m[3] * b);
- __retVal[0] = m[0] * b;
- __retVal[1] = m[1] * b;
- __retVal[2] = m[2] * b;
- __retVal[3] = m[3] * b;
-}
-
-mat4x2 __operator * (const float a, const mat4x2 n)
-{
- //return mat4x2 (a * n[0], a * n[1], a * n[2], a * n[3]);
- __retVal[0] = a * n[0];
- __retVal[1] = a * n[1];
- __retVal[2] = a * n[2];
- __retVal[3] = a * n[3];
-}
-
-mat4x3 __operator * (const mat4x3 m, const float b)
-{
- //return mat4x3 (m[0] * b, m[1] * b, m[2] * b, m[3] * b);
- __retVal[0] = m[0] * b;
- __retVal[1] = m[1] * b;
- __retVal[2] = m[2] * b;
- __retVal[3] = m[3] * b;
-}
-
-mat4x3 __operator * (const float a, const mat4x3 n)
-{
- //return mat4x3 (a * n[0], a * n[1], a * n[2], a * n[3]);
- __retVal[0] = a * n[0];
- __retVal[1] = a * n[1];
- __retVal[2] = a * n[2];
- __retVal[3] = a * n[3];
-}
-
-
-mat2x3 __operator / (const float a, const mat2x3 n)
-{
- //return mat2x3 (a / n[0], a / n[1]);
- const float inv = 1.0 / a;
- __retVal[0] = inv * n[0];
- __retVal[1] = inv * n[1];
-}
-
-mat2x3 __operator / (const mat2x3 m, const float b)
-{
- //return mat2x3 (m[0] / b, m[1] / b);
- const float inv = 1.0 / b;
- __retVal[0] = m[0] * inv;
- __retVal[1] = m[1] * inv;
-}
-
-mat2x4 __operator / (const float a, const mat2x4 n)
-{
- //return mat2x4 (a / n[0], a / n[1]);
- const float inv = 1.0 / a;
- __retVal[0] = inv * n[0];
- __retVal[1] = inv * n[1];
-}
-
-mat2x4 __operator / (const mat2x4 m, const float b)
-{
- //return mat2x4 (m[0] / b, m[1] / b);
- const float inv = 1.0 / b;
- __retVal[0] = m[0] * inv;
- __retVal[1] = m[1] * inv;
-}
-
-mat3x2 __operator / (const float a, const mat3x2 n)
-{
- //return mat3x2 (a / n[0], a / n[1], a / n[2]);
- const float inv = 1.0 / a;
- __retVal[0] = inv * n[0];
- __retVal[1] = inv * n[1];
- __retVal[2] = inv * n[2];
-}
-
-mat3x2 __operator / (const mat3x2 m, const float b)
-{
- //return mat3x2 (m[0] / b, m[1] / b, m[2] / b);
- const float inv = 1.0 / b;
- __retVal[0] = m[0] * inv;
- __retVal[1] = m[1] * inv;
- __retVal[2] = m[2] * inv;
-}
-
-mat3x4 __operator / (const float a, const mat3x4 n)
-{
- //return mat3x4 (a / n[0], a / n[1], a / n[2]);
- const float inv = 1.0 / a;
- __retVal[0] = inv * n[0];
- __retVal[1] = inv * n[1];
- __retVal[2] = inv * n[2];
-}
-
-mat3x4 __operator / (const mat3x4 m, const float b)
-{
- //return mat3x4 (m[0] / b, m[1] / b, m[2] / b);
- const float inv = 1.0 / b;
- __retVal[0] = m[0] * inv;
- __retVal[1] = m[1] * inv;
- __retVal[2] = m[2] * inv;
-}
-
-mat4x2 __operator / (const mat4x2 m, const float b)
-{
- //return mat4x2 (m[0] / b, m[1] / b, m[2] / b, m[3] / b);
- const float inv = 1.0 / b;
- __retVal[0] = m[0] * inv;
- __retVal[1] = m[1] * inv;
- __retVal[2] = m[2] * inv;
- __retVal[3] = m[3] * inv;
-}
-
-mat4x2 __operator / (const float a, const mat4x2 n)
-{
- //return mat4x2 (a / n[0], a / n[1], a / n[2], a / n[3]);
- const float inv = 1.0 / a;
- __retVal[0] = inv * n[0];
- __retVal[1] = inv * n[1];
- __retVal[2] = inv * n[2];
- __retVal[3] = inv * n[3];
-}
-
-mat4x3 __operator / (const mat4x3 m, const float b)
-{
- //return mat4x3 (m[0] / b, m[1] / b, m[2] / b, m[3] / b);
- const float inv = 1.0 / b;
- __retVal[0] = m[0] * inv;
- __retVal[1] = m[1] * inv;
- __retVal[2] = m[2] * inv;
- __retVal[3] = m[3] * inv;
-}
-
-mat4x3 __operator / (const float a, const mat4x3 n)
-{
- //return mat4x3 (a / n[0], a / n[1], a / n[2], a / n[3]);
- const float inv = 1.0 / a;
- __retVal[0] = inv * n[0];
- __retVal[1] = inv * n[1];
- __retVal[2] = inv * n[2];
- __retVal[3] = inv * n[3];
-}
-
-
-mat2x3 __operator - (const mat2x3 m) {
- return mat2x3 (-m[0], -m[1]);
-}
-
-mat2x4 __operator - (const mat2x4 m) {
- return mat2x4 (-m[0], -m[1]);
-}
-
-mat3x2 __operator - (const mat3x2 m) {
- return mat3x2 (-m[0], -m[1], -m[2]);
-}
-
-mat3x4 __operator - (const mat3x4 m) {
- return mat3x4 (-m[0], -m[1], -m[2]);
-}
-
-mat4x2 __operator - (const mat4x2 m) {
- return mat4x2 (-m[0], -m[1], -m[2], -m[3]);
-}
-
-mat4x3 __operator - (const mat4x3 m) {
- return mat4x3 (-m[0], -m[1], -m[2], -m[3]);
-}
-
-
-void __operator -- (inout mat2x3 m) {
- --m[0];
- --m[1];
-}
-
-void __operator -- (inout mat2x4 m) {
- --m[0];
- --m[1];
-}
-
-void __operator -- (inout mat3x2 m) {
- --m[0];
- --m[1];
- --m[2];
-}
-
-void __operator -- (inout mat3x4 m) {
- --m[0];
- --m[1];
- --m[2];
-}
-
-void __operator -- (inout mat4x2 m) {
- --m[0];
- --m[1];
- --m[2];
- --m[3];
-}
-
-void __operator -- (inout mat4x3 m) {
- --m[0];
- --m[1];
- --m[2];
- --m[3];
-}
-
-
-void __operator ++ (inout mat2x3 m) {
- ++m[0];
- ++m[1];
-}
-
-void __operator ++ (inout mat2x4 m) {
- ++m[0];
- ++m[1];
-}
-
-void __operator ++ (inout mat3x2 m) {
- ++m[0];
- ++m[1];
- ++m[2];
-}
-
-void __operator ++ (inout mat3x4 m) {
- ++m[0];
- ++m[1];
- ++m[2];
-}
-
-void __operator ++ (inout mat4x2 m) {
- ++m[0];
- ++m[1];
- ++m[2];
- ++m[3];
-}
-
-void __operator ++ (inout mat4x3 m) {
- ++m[0];
- ++m[1];
- ++m[2];
- ++m[3];
-}
-
+++ /dev/null
-/*
- * Mesa 3-D graphics library
- * Version: 6.6
- *
- * Copyright (C) 2006 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.
- */
-
-//
-// From Shader Spec, ver. 1.20, rev. 6
-//
-
-//
-// 8.5 Matrix Functions
-//
-
-mat2x3 matrixCompMult (mat2x3 m, mat2x3 n) {
- return mat2x3 (m[0] * n[0], m[1] * n[1]);
-}
-
-mat2x4 matrixCompMult (mat2x4 m, mat2x4 n) {
- return mat2x4 (m[0] * n[0], m[1] * n[1]);
-}
-
-mat3x2 matrixCompMult (mat3x2 m, mat3x2 n) {
- return mat3x2 (m[0] * n[0], m[1] * n[1], m[2] * n[2]);
-}
-
-mat3x4 matrixCompMult (mat3x4 m, mat3x4 n) {
- return mat3x4 (m[0] * n[0], m[1] * n[1], m[2] * n[2]);
-}
-
-mat4x2 matrixCompMult (mat4x2 m, mat4x2 n) {
- return mat4x2 (m[0] * n[0], m[1] * n[1], m[2] * n[2], m[3] * n[3]);
-}
-
-mat4x3 matrixCompMult (mat4x3 m, mat4x3 n) {
- return mat4x3 (m[0] * n[0], m[1] * n[1], m[2] * n[2], m[3] * n[3]);
-}
-
-mat2 outerProduct (vec2 c, vec2 r) {
- return mat2 (
- c.x * r.x, c.y * r.x,
- c.x * r.y, c.y * r.y
- );
-}
-
-mat3 outerProduct (vec3 c, vec3 r) {
- return mat3 (
- c.x * r.x, c.y * r.x, c.z * r.x,
- c.x * r.y, c.y * r.y, c.z * r.y,
- c.x * r.z, c.y * r.z, c.z * r.z
- );
-}
-
-mat4 outerProduct (vec4 c, vec4 r) {
- return mat4 (
- c.x * r.x, c.y * r.x, c.z * r.x, c.w * r.x,
- c.x * r.y, c.y * r.y, c.z * r.y, c.w * r.y,
- c.x * r.z, c.y * r.z, c.z * r.z, c.w * r.z,
- c.x * r.w, c.y * r.w, c.z * r.w, c.w * r.w
- );
-}
-
-mat2x3 outerProduct (vec3 c, vec2 r) {
- return mat2x3 (
- c.x * r.x, c.y * r.x, c.z * r.x,
- c.x * r.y, c.y * r.y, c.z * r.y
- );
-}
-
-mat3x2 outerProduct (vec2 c, vec3 r) {
- return mat3x2 (
- c.x * r.x, c.y * r.x,
- c.x * r.y, c.y * r.y,
- c.x * r.z, c.y * r.z
- );
-}
-
-mat2x4 outerProduct (vec4 c, vec2 r) {
- return mat2x4 (
- c.x * r.x, c.y * r.x, c.z * r.x, c.w * r.x,
- c.x * r.y, c.y * r.y, c.z * r.y, c.w * r.y
- );
-}
-
-mat4x2 outerProduct (vec2 c, vec4 r) {
- return mat4x2 (
- c.x * r.x, c.y * r.x,
- c.x * r.y, c.y * r.y,
- c.x * r.z, c.y * r.z,
- c.x * r.w, c.y * r.w
- );
-}
-
-mat3x4 outerProduct (vec4 c, vec3 r) {
- return mat3x4 (
- c.x * r.x, c.y * r.x, c.z * r.x, c.w * r.x,
- c.x * r.y, c.y * r.y, c.z * r.y, c.w * r.y,
- c.x * r.z, c.y * r.z, c.z * r.z, c.w * r.z
- );
-}
-
-mat4x3 outerProduct (vec3 c, vec4 r) {
- return mat4x3 (
- c.x * r.x, c.y * r.x, c.z * r.x,
- c.x * r.y, c.y * r.y, c.z * r.y,
- c.x * r.z, c.y * r.z, c.z * r.z,
- c.x * r.w, c.y * r.w, c.z * r.w
- );
-}
-
-mat2 transpose (mat2 m) {
- return mat2 (
- m[0].x, m[1].x,
- m[0].y, m[1].y
- );
-}
-
-mat3 transpose (mat3 m) {
- return mat3 (
- m[0].x, m[1].x, m[2].x,
- m[0].y, m[1].y, m[2].y,
- m[0].z, m[1].z, m[2].z
- );
-}
-
-mat4 transpose (mat4 m) {
- return mat4 (
- m[0].x, m[1].x, m[2].x, m[3].x,
- m[0].y, m[1].y, m[2].y, m[3].y,
- m[0].z, m[1].z, m[2].z, m[3].z,
- m[0].w, m[1].w, m[2].w, m[3].w
- );
-}
-
-mat2x3 transpose (mat3x2 m) {
- return mat2x3 (
- m[0].x, m[1].x, m[2].x,
- m[0].y, m[1].y, m[2].y
- );
-}
-
-mat3x2 transpose (mat2x3 m) {
- return mat3x2 (
- m[0].x, m[1].x,
- m[0].y, m[1].y,
- m[0].z, m[1].z
- );
-}
-
-mat2x4 transpose (mat4x2 m) {
- return mat2x4 (
- m[0].x, m[1].x, m[2].x, m[3].x,
- m[0].y, m[1].y, m[2].y, m[3].y
- );
-}
-
-mat4x2 transpose (mat2x4 m) {
- return mat4x2 (
- m[0].x, m[1].x,
- m[0].y, m[1].y,
- m[0].z, m[1].z,
- m[0].w, m[1].w
- );
-}
-
-mat3x4 transpose (mat4x3 m) {
- return mat3x4 (
- m[0].x, m[1].x, m[2].x, m[3].x,
- m[0].y, m[1].y, m[2].y, m[3].y,
- m[0].z, m[1].z, m[2].z, m[3].z
- );
-}
-
-mat4x3 transpose (mat3x4 m) {
- return mat4x3 (
- m[0].x, m[1].x, m[2].x,
- m[0].y, m[1].y, m[2].y,
- m[0].z, m[1].z, m[2].z,
- m[0].w, m[1].w, m[2].w
- );
-}
-
+++ /dev/null
-/*
- * Mesa 3-D graphics library
- * Version: 6.5
- *
- * Copyright (C) 2006 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.
- */
-
-//
-// From Shader Spec, ver. 1.20, rev. 6
-//
-
-varying vec2 gl_PointCoord;
-
+++ /dev/null
-/*
- * Mesa 3-D graphics library
- * Version: 7.3
- *
- * Copyright (C) 2006 Brian Paul All Rights Reserved.
- * Copyright (C) 2008 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.
- */
-
-//
-// From Shader Spec, ver. 1.10, rev. 59
-//
-
-// Note: the values assigned to these constants here aren't actually used.
-// They're set by the compiler according to the GL context limits.
-// See slang_simplify.c
-const int gl_MaxLights = 8;
-const int gl_MaxClipPlanes = 6;
-const int gl_MaxTextureUnits = 8;
-const int gl_MaxTextureCoords = 8;
-const int gl_MaxVertexAttribs = 16;
-const int gl_MaxVertexUniformComponents = 512;
-const int gl_MaxVaryingFloats = 32;
-const int gl_MaxVertexTextureImageUnits = 0;
-const int gl_MaxCombinedTextureImageUnits = 2;
-const int gl_MaxTextureImageUnits = 2;
-const int gl_MaxFragmentUniformComponents = 64;
-const int gl_MaxDrawBuffers = 1;
-
-uniform mat4 gl_ModelViewMatrix;
-uniform mat4 gl_ProjectionMatrix;
-uniform mat4 gl_ModelViewProjectionMatrix;
-uniform mat4 gl_TextureMatrix[gl_MaxTextureCoords];
-
-uniform mat3 gl_NormalMatrix;
-
-uniform mat4 gl_ModelViewMatrixInverse;
-uniform mat4 gl_ProjectionMatrixInverse;
-uniform mat4 gl_ModelViewProjectionMatrixInverse;
-uniform mat4 gl_TextureMatrixInverse[gl_MaxTextureCoords];
-
-uniform mat4 gl_ModelViewMatrixTranspose;
-uniform mat4 gl_ProjectionMatrixTranspose;
-uniform mat4 gl_ModelViewProjectionMatrixTranspose;
-uniform mat4 gl_TextureMatrixTranspose[gl_MaxTextureCoords];
-
-uniform mat4 gl_ModelViewMatrixInverseTranspose;
-uniform mat4 gl_ProjectionMatrixInverseTranspose;
-uniform mat4 gl_ModelViewProjectionMatrixInverseTranspose;
-uniform mat4 gl_TextureMatrixInverseTranspose[gl_MaxTextureCoords];
-
-uniform float gl_NormalScale;
-
-struct gl_DepthRangeParameters {
- float near;
- float far;
- float diff;
-};
-
-uniform gl_DepthRangeParameters gl_DepthRange;
-
-uniform vec4 gl_ClipPlane[gl_MaxClipPlanes];
-
-struct gl_PointParameters {
- float size;
- float sizeMin;
- float sizeMax;
- float fadeThresholdSize;
- float distanceConstantAttenuation;
- float distanceLinearAttenuation;
- float distanceQuadraticAttenuation;
-};
-
-uniform gl_PointParameters gl_Point;
-
-struct gl_MaterialParameters {
- vec4 emission;
- vec4 ambient;
- vec4 diffuse;
- vec4 specular;
- float shininess;
-};
-
-uniform gl_MaterialParameters gl_FrontMaterial;
-uniform gl_MaterialParameters gl_BackMaterial;
-
-/* NOTE: the order of these fields is significant!
- * See the definition of the lighting state vars such as STATE_SPOT_DIRECTION.
- */
-struct gl_LightSourceParameters {
- vec4 ambient;
- vec4 diffuse;
- vec4 specular;
- vec4 position;
- vec4 halfVector;
- vec3 spotDirection;
- float spotCosCutoff;
-
- float constantAttenuation;
- float linearAttenuation;
- float quadraticAttenuation;
- float spotExponent;
-
- float spotCutoff;
-};
-
-uniform gl_LightSourceParameters gl_LightSource[gl_MaxLights];
-
-struct gl_LightModelParameters {
- vec4 ambient;
-};
-
-uniform gl_LightModelParameters gl_LightModel;
-
-struct gl_LightModelProducts {
- vec4 sceneColor;
-};
-
-uniform gl_LightModelProducts gl_FrontLightModelProduct;
-uniform gl_LightModelProducts gl_BackLightModelProduct;
-
-struct gl_LightProducts {
- vec4 ambient;
- vec4 diffuse;
- vec4 specular;
-};
-
-uniform gl_LightProducts gl_FrontLightProduct[gl_MaxLights];
-uniform gl_LightProducts gl_BackLightProduct[gl_MaxLights];
-
-uniform vec4 gl_TextureEnvColor[gl_MaxTextureImageUnits];
-uniform vec4 gl_EyePlaneS[gl_MaxTextureCoords];
-uniform vec4 gl_EyePlaneT[gl_MaxTextureCoords];
-uniform vec4 gl_EyePlaneR[gl_MaxTextureCoords];
-uniform vec4 gl_EyePlaneQ[gl_MaxTextureCoords];
-uniform vec4 gl_ObjectPlaneS[gl_MaxTextureCoords];
-uniform vec4 gl_ObjectPlaneT[gl_MaxTextureCoords];
-uniform vec4 gl_ObjectPlaneR[gl_MaxTextureCoords];
-uniform vec4 gl_ObjectPlaneQ[gl_MaxTextureCoords];
-
-struct gl_FogParameters {
- vec4 color;
- float density;
- float start;
- float end;
- float scale;
-};
-
-uniform gl_FogParameters gl_Fog;
-
-
-
-
-
-//
-// 8.1 Angle and Trigonometry Functions
-//
-
-//// radians
-
-float radians(const float deg)
-{
- const float c = 3.1415926 / 180.0;
- __asm vec4_multiply __retVal, deg, c;
-}
-
-vec2 radians(const vec2 deg)
-{
- const float c = 3.1415926 / 180.0;
- __asm vec4_multiply __retVal.xy, deg.xy, c.xx;
-}
-
-vec3 radians(const vec3 deg)
-{
- const float c = 3.1415926 / 180.0;
- __asm vec4_multiply __retVal.xyz, deg.xyz, c.xxx;
-}
-
-vec4 radians(const vec4 deg)
-{
- const float c = 3.1415926 / 180.0;
- __asm vec4_multiply __retVal, deg, c.xxxx;
-}
-
-
-//// degrees
-
-float degrees(const float rad)
-{
- const float c = 180.0 / 3.1415926;
- __asm vec4_multiply __retVal, rad, c;
-}
-
-vec2 degrees(const vec2 rad)
-{
- const float c = 180.0 / 3.1415926;
- __asm vec4_multiply __retVal.xy, rad.xy, c.xx;
-}
-
-vec3 degrees(const vec3 rad)
-{
- const float c = 180.0 / 3.1415926;
- __asm vec4_multiply __retVal.xyz, rad.xyz, c.xxx;
-}
-
-vec4 degrees(const vec4 rad)
-{
- const float c = 180.0 / 3.1415926;
- __asm vec4_multiply __retVal, rad, c.xxxx;
-}
-
-
-//// sin
-
-float sin(const float radians)
-{
- __asm float_sine __retVal, radians;
-}
-
-vec2 sin(const vec2 radians)
-{
- __asm float_sine __retVal.x, radians.x;
- __asm float_sine __retVal.y, radians.y;
-}
-
-vec3 sin(const vec3 radians)
-{
- __asm float_sine __retVal.x, radians.x;
- __asm float_sine __retVal.y, radians.y;
- __asm float_sine __retVal.z, radians.z;
-}
-
-vec4 sin(const vec4 radians)
-{
- __asm float_sine __retVal.x, radians.x;
- __asm float_sine __retVal.y, radians.y;
- __asm float_sine __retVal.z, radians.z;
- __asm float_sine __retVal.w, radians.w;
-}
-
-
-//// cos
-
-float cos(const float radians)
-{
- __asm float_cosine __retVal, radians;
-}
-
-vec2 cos(const vec2 radians)
-{
- __asm float_cosine __retVal.x, radians.x;
- __asm float_cosine __retVal.y, radians.y;
-}
-
-vec3 cos(const vec3 radians)
-{
- __asm float_cosine __retVal.x, radians.x;
- __asm float_cosine __retVal.y, radians.y;
- __asm float_cosine __retVal.z, radians.z;
-}
-
-vec4 cos(const vec4 radians)
-{
- __asm float_cosine __retVal.x, radians.x;
- __asm float_cosine __retVal.y, radians.y;
- __asm float_cosine __retVal.z, radians.z;
- __asm float_cosine __retVal.w, radians.w;
-}
-
-
-
-//// tan
-
-float tan(const float angle)
-{
- const float s = sin(angle);
- const float c = cos(angle);
- return s / c;
-}
-
-vec2 tan(const vec2 angle)
-{
- const vec2 s = sin(angle);
- const vec2 c = cos(angle);
- return s / c;
-}
-
-vec3 tan(const vec3 angle)
-{
- const vec3 s = sin(angle);
- const vec3 c = cos(angle);
- return s / c;
-}
-
-vec4 tan(const vec4 angle)
-{
- const vec4 s = sin(angle);
- const vec4 c = cos(angle);
- return s / c;
-}
-
-
-
-float asin(const float x)
-{
- const float a0 = 1.5707288; // PI/2?
- const float a1 = -0.2121144;
- const float a2 = 0.0742610;
- //const float a3 = -0.0187293;
- const float halfPi = 3.1415926 * 0.5;
- const float y = abs(x);
- // three terms seem to be enough:
- __retVal = (halfPi - sqrt(1.0 - y) * (a0 + y * (a1 + a2 * y))) * sign(x);
- // otherwise, try four:
- //__retVal = (halfPi - sqrt(1.0 - y) * (a0 + y * (a1 + y * (a2 + y * a3)))) * sign(x);
-}
-
-vec2 asin(const vec2 v)
-{
- __retVal.x = asin(v.x);
- __retVal.y = asin(v.y);
-}
-
-vec3 asin(const vec3 v)
-{
- __retVal.x = asin(v.x);
- __retVal.y = asin(v.y);
- __retVal.z = asin(v.z);
-}
-
-vec4 asin(const vec4 v)
-{
- __retVal.x = asin(v.x);
- __retVal.y = asin(v.y);
- __retVal.z = asin(v.z);
- __retVal.w = asin(v.w);
-}
-
-float acos(const float x)
-{
- const float halfPi = 3.1415926 * 0.5;
- __retVal = halfPi - asin(x);
-}
-
-vec2 acos(const vec2 v)
-{
- __retVal.x = acos(v.x);
- __retVal.y = acos(v.y);
-}
-
-vec3 acos(const vec3 v)
-{
- __retVal.x = acos(v.x);
- __retVal.y = acos(v.y);
- __retVal.z = acos(v.z);
-}
-
-vec4 acos(const vec4 v)
-{
- __retVal.x = acos(v.x);
- __retVal.y = acos(v.y);
- __retVal.z = acos(v.z);
- __retVal.w = acos(v.w);
-}
-
-float atan(const float x)
-{
- __retVal = asin(x * inversesqrt(x * x + 1.0));
-}
-
-vec2 atan(const vec2 y_over_x)
-{
- __retVal.x = atan(y_over_x.x);
- __retVal.y = atan(y_over_x.y);
-}
-
-vec3 atan(const vec3 y_over_x)
-{
- __retVal.x = atan(y_over_x.x);
- __retVal.y = atan(y_over_x.y);
- __retVal.z = atan(y_over_x.z);
-}
-
-vec4 atan(const vec4 y_over_x)
-{
- __retVal.x = atan(y_over_x.x);
- __retVal.y = atan(y_over_x.y);
- __retVal.z = atan(y_over_x.z);
- __retVal.w = atan(y_over_x.w);
-}
-
-float atan(const float y, const float x)
-{
- float r;
- if (abs(x) > 1.0e-4) {
- r = atan(y / x);
- if (x < 0.0) {
- r = r + 3.141593 - 6.283186 * float(y < 0.0);
- }
- }
- else {
- r = sign(y) * 1.5707965; // pi/2
- }
- return r;
-}
-
-vec2 atan(const vec2 u, const vec2 v)
-{
- __retVal.x = atan(u.x, v.x);
- __retVal.y = atan(u.y, v.y);
-}
-
-vec3 atan(const vec3 u, const vec3 v)
-{
- __retVal.x = atan(u.x, v.x);
- __retVal.y = atan(u.y, v.y);
- __retVal.z = atan(u.z, v.z);
-}
-
-vec4 atan(const vec4 u, const vec4 v)
-{
- __retVal.x = atan(u.x, v.x);
- __retVal.y = atan(u.y, v.y);
- __retVal.z = atan(u.z, v.z);
- __retVal.w = atan(u.w, v.w);
-}
-
-
-//
-// 8.2 Exponential Functions
-//
-
-//// pow
-
-float pow(const float a, const float b)
-{
- __asm float_power __retVal, a, b;
-}
-
-vec2 pow(const vec2 a, const vec2 b)
-{
- __asm float_power __retVal.x, a.x, b.x;
- __asm float_power __retVal.y, a.y, b.y;
-}
-
-vec3 pow(const vec3 a, const vec3 b)
-{
- __asm float_power __retVal.x, a.x, b.x;
- __asm float_power __retVal.y, a.y, b.y;
- __asm float_power __retVal.z, a.z, b.z;
-}
-
-vec4 pow(const vec4 a, const vec4 b)
-{
- __asm float_power __retVal.x, a.x, b.x;
- __asm float_power __retVal.y, a.y, b.y;
- __asm float_power __retVal.z, a.z, b.z;
- __asm float_power __retVal.w, a.w, b.w;
-}
-
-
-//// exp
-
-float exp(const float a)
-{
- // NOTE: log2(e) = 1.44269502
- float t = a * 1.44269502;
- __asm float_exp2 __retVal, t;
-}
-
-vec2 exp(const vec2 a)
-{
- vec2 t = a * 1.44269502;
- __asm float_exp2 __retVal.x, t.x;
- __asm float_exp2 __retVal.y, t.y;
-}
-
-vec3 exp(const vec3 a)
-{
- vec3 t = a * 1.44269502;
- __asm float_exp2 __retVal.x, t.x;
- __asm float_exp2 __retVal.y, t.y;
- __asm float_exp2 __retVal.z, t.z;
-}
-
-vec4 exp(const vec4 a)
-{
- vec4 t = a * 1.44269502;
- __asm float_exp2 __retVal.x, t.x;
- __asm float_exp2 __retVal.y, t.y;
- __asm float_exp2 __retVal.z, t.z;
- __asm float_exp2 __retVal.w, t.w;
-}
-
-
-
-//// log2
-
-float log2(const float x)
-{
- __asm float_log2 __retVal, x;
-}
-
-vec2 log2(const vec2 v)
-{
- __asm float_log2 __retVal.x, v.x;
- __asm float_log2 __retVal.y, v.y;
-}
-
-vec3 log2(const vec3 v)
-{
- __asm float_log2 __retVal.x, v.x;
- __asm float_log2 __retVal.y, v.y;
- __asm float_log2 __retVal.z, v.z;
-}
-
-vec4 log2(const vec4 v)
-{
- __asm float_log2 __retVal.x, v.x;
- __asm float_log2 __retVal.y, v.y;
- __asm float_log2 __retVal.z, v.z;
- __asm float_log2 __retVal.w, v.w;
-}
-
-
-//// log (natural log)
-
-float log(const float x)
-{
- // note: logBaseB(x) = logBaseN(x) / logBaseN(B)
- // compute log(x) = log2(x) / log2(e)
- // c = 1.0 / log2(e) = 0.693147181
- const float c = 0.693147181;
- return log2(x) * c;
-}
-
-vec2 log(const vec2 v)
-{
- const float c = 0.693147181;
- return log2(v) * c;
-}
-
-vec3 log(const vec3 v)
-{
- const float c = 0.693147181;
- return log2(v) * c;
-}
-
-vec4 log(const vec4 v)
-{
- const float c = 0.693147181;
- return log2(v) * c;
-}
-
-
-//// exp2
-
-float exp2(const float a)
-{
- __asm float_exp2 __retVal, a;
-}
-
-vec2 exp2(const vec2 a)
-{
- __asm float_exp2 __retVal.x, a.x;
- __asm float_exp2 __retVal.y, a.y;
-}
-
-vec3 exp2(const vec3 a)
-{
- __asm float_exp2 __retVal.x, a.x;
- __asm float_exp2 __retVal.y, a.y;
- __asm float_exp2 __retVal.z, a.z;
-}
-
-vec4 exp2(const vec4 a)
-{
- __asm float_exp2 __retVal.x, a.x;
- __asm float_exp2 __retVal.y, a.y;
- __asm float_exp2 __retVal.z, a.z;
- __asm float_exp2 __retVal.w, a.w;
-}
-
-
-//// sqrt
-
-float sqrt(const float x)
-{
- const float nx = -x;
- float r;
- __asm float_rsq r, x;
- r = r * x;
- __asm vec4_cmp __retVal, nx, r, 0.0;
-}
-
-vec2 sqrt(const vec2 x)
-{
- const vec2 nx = -x, zero = vec2(0.0);
- vec2 r;
- __asm float_rsq r.x, x.x;
- __asm float_rsq r.y, x.y;
- r = r * x;
- __asm vec4_cmp __retVal, nx, r, zero;
-}
-
-vec3 sqrt(const vec3 x)
-{
- const vec3 nx = -x, zero = vec3(0.0);
- vec3 r;
- __asm float_rsq r.x, x.x;
- __asm float_rsq r.y, x.y;
- __asm float_rsq r.z, x.z;
- r = r * x;
- __asm vec4_cmp __retVal, nx, r, zero;
-}
-
-vec4 sqrt(const vec4 x)
-{
- const vec4 nx = -x, zero = vec4(0.0);
- vec4 r;
- __asm float_rsq r.x, x.x;
- __asm float_rsq r.y, x.y;
- __asm float_rsq r.z, x.z;
- __asm float_rsq r.w, x.w;
- r = r * x;
- __asm vec4_cmp __retVal, nx, r, zero;
-}
-
-
-//// inversesqrt
-
-float inversesqrt(const float x)
-{
- __asm float_rsq __retVal.x, x;
-}
-
-vec2 inversesqrt(const vec2 v)
-{
- __asm float_rsq __retVal.x, v.x;
- __asm float_rsq __retVal.y, v.y;
-}
-
-vec3 inversesqrt(const vec3 v)
-{
- __asm float_rsq __retVal.x, v.x;
- __asm float_rsq __retVal.y, v.y;
- __asm float_rsq __retVal.z, v.z;
-}
-
-vec4 inversesqrt(const vec4 v)
-{
- __asm float_rsq __retVal.x, v.x;
- __asm float_rsq __retVal.y, v.y;
- __asm float_rsq __retVal.z, v.z;
- __asm float_rsq __retVal.w, v.w;
-}
-
-
-//// normalize
-
-float normalize(const float x)
-{
- __retVal = 1.0;
-}
-
-vec2 normalize(const vec2 v)
-{
- const float s = inversesqrt(dot(v, v));
- __asm vec4_multiply __retVal.xy, v, s;
-}
-
-vec3 normalize(const vec3 v)
-{
-// const float s = inversesqrt(dot(v, v));
-// __retVal = v * s;
-// XXX note, we _could_ use __retVal.w instead of tmp and save a
-// register, but that's actually a compilation error because v is a vec3
-// and the .w suffix is illegal. Oh well.
- float tmp;
- __asm vec3_dot tmp, v, v;
- __asm float_rsq tmp, tmp;
- __asm vec4_multiply __retVal.xyz, v, tmp;
-}
-
-vec4 normalize(const vec4 v)
-{
- float tmp;
- __asm vec4_dot tmp, v, v;
- __asm float_rsq tmp, tmp;
- __asm vec4_multiply __retVal.xyz, v, tmp;
-}
-
-
-
-//
-// 8.3 Common Functions
-//
-
-
-//// abs
-
-float abs(const float a)
-{
- __asm vec4_abs __retVal, a;
-}
-
-vec2 abs(const vec2 a)
-{
- __asm vec4_abs __retVal.xy, a;
-}
-
-vec3 abs(const vec3 a)
-{
- __asm vec4_abs __retVal.xyz, a;
-}
-
-vec4 abs(const vec4 a)
-{
- __asm vec4_abs __retVal, a;
-}
-
-
-//// sign
-
-float sign(const float x)
-{
- float p, n;
- __asm vec4_sgt p, x, 0.0; // p = (x > 0)
- __asm vec4_sgt n, 0.0, x; // n = (x < 0)
- __asm vec4_subtract __retVal, p, n; // sign = p - n
-}
-
-vec2 sign(const vec2 v)
-{
- vec2 p, n;
- __asm vec4_sgt p.xy, v, 0.0;
- __asm vec4_sgt n.xy, 0.0, v;
- __asm vec4_subtract __retVal.xy, p, n;
-}
-
-vec3 sign(const vec3 v)
-{
- vec3 p, n;
- __asm vec4_sgt p.xyz, v, 0.0;
- __asm vec4_sgt n.xyz, 0.0, v;
- __asm vec4_subtract __retVal.xyz, p, n;
-}
-
-vec4 sign(const vec4 v)
-{
- vec4 p, n;
- __asm vec4_sgt p, v, 0.0;
- __asm vec4_sgt n, 0.0, v;
- __asm vec4_subtract __retVal, p, n;
-}
-
-
-//// floor
-
-float floor(const float a)
-{
- __asm vec4_floor __retVal, a;
-}
-
-vec2 floor(const vec2 a)
-{
- __asm vec4_floor __retVal.xy, a;
-}
-
-vec3 floor(const vec3 a)
-{
- __asm vec4_floor __retVal.xyz, a;
-}
-
-vec4 floor(const vec4 a)
-{
- __asm vec4_floor __retVal, a;
-}
-
-
-//// ceil
-
-float ceil(const float a)
-{
- // XXX this could be improved
- float b = -a;
- __asm vec4_floor b, b;
- __retVal = -b;
-}
-
-vec2 ceil(const vec2 a)
-{
- vec2 b = -a;
- __asm vec4_floor b, b;
- __retVal.xy = -b;
-}
-
-vec3 ceil(const vec3 a)
-{
- vec3 b = -a;
- __asm vec4_floor b, b;
- __retVal.xyz = -b;
-}
-
-vec4 ceil(const vec4 a)
-{
- vec4 b = -a;
- __asm vec4_floor b, b;
- __retVal = -b;
-}
-
-
-//// fract
-
-float fract(const float a)
-{
- __asm vec4_frac __retVal, a;
-}
-
-vec2 fract(const vec2 a)
-{
- __asm vec4_frac __retVal.xy, a;
-}
-
-vec3 fract(const vec3 a)
-{
- __asm vec4_frac __retVal.xyz, a;
-}
-
-vec4 fract(const vec4 a)
-{
- __asm vec4_frac __retVal, a;
-}
-
-
-//// mod (very untested!)
-
-float mod(const float a, const float b)
-{
- float oneOverB;
- __asm float_rcp oneOverB, b;
- __retVal = a - b * floor(a * oneOverB);
-}
-
-vec2 mod(const vec2 a, const float b)
-{
- float oneOverB;
- __asm float_rcp oneOverB, b;
- __retVal.xy = a - b * floor(a * oneOverB);
-}
-
-vec3 mod(const vec3 a, const float b)
-{
- float oneOverB;
- __asm float_rcp oneOverB, b;
- __retVal.xyz = a - b * floor(a * oneOverB);
-}
-
-vec4 mod(const vec4 a, const float b)
-{
- float oneOverB;
- __asm float_rcp oneOverB, b;
- __retVal = a - b * floor(a * oneOverB);
-}
-
-vec2 mod(const vec2 a, const vec2 b)
-{
- vec2 oneOverB;
- __asm float_rcp oneOverB.x, b.x;
- __asm float_rcp oneOverB.y, b.y;
- __retVal = a - b * floor(a * oneOverB);
-}
-
-vec3 mod(const vec3 a, const vec3 b)
-{
- vec3 oneOverB;
- __asm float_rcp oneOverB.x, b.x;
- __asm float_rcp oneOverB.y, b.y;
- __asm float_rcp oneOverB.z, b.z;
- __retVal = a - b * floor(a * oneOverB);
-}
-
-vec4 mod(const vec4 a, const vec4 b)
-{
- vec4 oneOverB;
- __asm float_rcp oneOverB.x, b.x;
- __asm float_rcp oneOverB.y, b.y;
- __asm float_rcp oneOverB.z, b.z;
- __asm float_rcp oneOverB.w, b.w;
- __retVal = a - b * floor(a * oneOverB);
-}
-
-
-//// min
-
-float min(const float a, const float b)
-{
- __asm vec4_min __retVal, a, b;
-}
-
-vec2 min(const vec2 a, const vec2 b)
-{
- __asm vec4_min __retVal.xy, a.xy, b.xy;
-}
-
-vec3 min(const vec3 a, const vec3 b)
-{
- __asm vec4_min __retVal.xyz, a.xyz, b.xyz;
-}
-
-vec4 min(const vec4 a, const vec4 b)
-{
- __asm vec4_min __retVal, a, b;
-}
-
-vec2 min(const vec2 a, const float b)
-{
- __asm vec4_min __retVal, a.xy, b;
-}
-
-vec3 min(const vec3 a, const float b)
-{
- __asm vec4_min __retVal, a.xyz, b;
-}
-
-vec4 min(const vec4 a, const float b)
-{
- __asm vec4_min __retVal, a, b;
-}
-
-
-//// max
-
-float max(const float a, const float b)
-{
- __asm vec4_max __retVal, a, b;
-}
-
-vec2 max(const vec2 a, const vec2 b)
-{
- __asm vec4_max __retVal.xy, a.xy, b.xy;
-}
-
-vec3 max(const vec3 a, const vec3 b)
-{
- __asm vec4_max __retVal.xyz, a.xyz, b.xyz;
-}
-
-vec4 max(const vec4 a, const vec4 b)
-{
- __asm vec4_max __retVal, a, b;
-}
-
-vec2 max(const vec2 a, const float b)
-{
- __asm vec4_max __retVal, a.xy, b;
-}
-
-vec3 max(const vec3 a, const float b)
-{
- __asm vec4_max __retVal, a.xyz, b;
-}
-
-vec4 max(const vec4 a, const float b)
-{
- __asm vec4_max __retVal, a, b;
-}
-
-
-//// clamp
-
-float clamp(const float val, const float minVal, const float maxVal)
-{
- __asm vec4_clamp __retVal, val, minVal, maxVal;
-}
-
-vec2 clamp(const vec2 val, const float minVal, const float maxVal)
-{
- __asm vec4_clamp __retVal, val, minVal, maxVal;
-}
-
-vec3 clamp(const vec3 val, const float minVal, const float maxVal)
-{
- __asm vec4_clamp __retVal, val, minVal, maxVal;
-}
-
-vec4 clamp(const vec4 val, const float minVal, const float maxVal)
-{
- __asm vec4_clamp __retVal, val, minVal, maxVal;
-}
-
-vec2 clamp(const vec2 val, const vec2 minVal, const vec2 maxVal)
-{
- __asm vec4_clamp __retVal, val, minVal, maxVal;
-}
-
-vec3 clamp(const vec3 val, const vec3 minVal, const vec3 maxVal)
-{
- __asm vec4_clamp __retVal, val, minVal, maxVal;
-}
-
-vec4 clamp(const vec4 val, const vec4 minVal, const vec4 maxVal)
-{
- __asm vec4_clamp __retVal, val, minVal, maxVal;
-}
-
-
-//// mix
-
-float mix(const float x, const float y, const float a)
-{
- __asm vec4_lrp __retVal, a, y, x;
-}
-
-vec2 mix(const vec2 x, const vec2 y, const float a)
-{
- __asm vec4_lrp __retVal, a, y, x;
-}
-
-vec3 mix(const vec3 x, const vec3 y, const float a)
-{
- __asm vec4_lrp __retVal, a, y, x;
-}
-
-vec4 mix(const vec4 x, const vec4 y, const float a)
-{
- __asm vec4_lrp __retVal, a, y, x;
-}
-
-vec2 mix(const vec2 x, const vec2 y, const vec2 a)
-{
- __asm vec4_lrp __retVal, a, y, x;
-}
-
-vec3 mix(const vec3 x, const vec3 y, const vec3 a)
-{
- __asm vec4_lrp __retVal, a, y, x;
-}
-
-vec4 mix(const vec4 x, const vec4 y, const vec4 a)
-{
- __asm vec4_lrp __retVal, a, y, x;
-}
-
-
-//// step
-
-float step(const float edge, const float x)
-{
- __asm vec4_sge __retVal, x, edge;
-}
-
-vec2 step(const vec2 edge, const vec2 x)
-{
- __asm vec4_sge __retVal.xy, x, edge;
-}
-
-vec3 step(const vec3 edge, const vec3 x)
-{
- __asm vec4_sge __retVal.xyz, x, edge;
-}
-
-vec4 step(const vec4 edge, const vec4 x)
-{
- __asm vec4_sge __retVal, x, edge;
-}
-
-vec2 step(const float edge, const vec2 v)
-{
- __asm vec4_sge __retVal.xy, v, edge;
-}
-
-vec3 step(const float edge, const vec3 v)
-{
- __asm vec4_sge __retVal.xyz, v, edge;
-}
-
-vec4 step(const float edge, const vec4 v)
-{
- __asm vec4_sge __retVal, v, edge;
-}
-
-
-//// smoothstep
-
-float smoothstep(const float edge0, const float edge1, const float x)
-{
- float t = clamp((x - edge0) / (edge1 - edge0), 0.0, 1.0);
- return t * t * (3.0 - 2.0 * t);
-}
-
-vec2 smoothstep(const vec2 edge0, const vec2 edge1, const vec2 v)
-{
- vec2 t = clamp((v - edge0) / (edge1 - edge0), 0.0, 1.0);
- return t * t * (3.0 - 2.0 * t);
-}
-
-vec3 smoothstep(const vec3 edge0, const vec3 edge1, const vec3 v)
-{
- vec3 t = clamp((v - edge0) / (edge1 - edge0), 0.0, 1.0);
- return t * t * (3.0 - 2.0 * t);
-}
-
-vec4 smoothstep(const vec4 edge0, const vec4 edge1, const vec4 v)
-{
- vec4 t = clamp((v - edge0) / (edge1 - edge0), 0.0, 1.0);
- return t * t * (3.0 - 2.0 * t);
-}
-
-vec2 smoothstep(const float edge0, const float edge1, const vec2 v)
-{
- vec2 t = clamp((v - edge0) / (edge1 - edge0), 0.0, 1.0);
- return t * t * (3.0 - 2.0 * t);
-}
-
-vec3 smoothstep(const float edge0, const float edge1, const vec3 v)
-{
- vec3 t = clamp((v - edge0) / (edge1 - edge0), 0.0, 1.0);
- return t * t * (3.0 - 2.0 * t);
-}
-
-vec4 smoothstep(const float edge0, const float edge1, const vec4 v)
-{
- vec4 t = clamp((v - edge0) / (edge1 - edge0), 0.0, 1.0);
- return t * t * (3.0 - 2.0 * t);
-}
-
-
-
-//
-// 8.4 Geometric Functions
-//
-
-
-//// length
-
-float length(const float x)
-{
- return abs(x);
-}
-
-float length(const vec2 v)
-{
- float r;
- const float p = dot(v, v); // p = v.x * v.x + v.y * v.y
- __asm float_rsq r, p; // r = 1 / sqrt(p)
- __retVal = p * r; // p * r = sqrt(p);
-}
-
-float length(const vec3 v)
-{
- float r;
- const float p = dot(v, v); // p = v.x * v.x + v.y * v.y + v.z * v.z
- __asm float_rsq r, p; // r = 1 / sqrt(p)
- __retVal = p * r; // p * r = sqrt(p);
-}
-
-float length(const vec4 v)
-{
- float r;
- const float p = dot(v, v); // p = v.x * v.x + v.y * v.y + ...
- __asm float_rsq r, p; // r = 1 / sqrt(p)
- __retVal = p * r; // p * r = sqrt(p);
-}
-
-
-//// distance
-
-float distance(const float x, const float y)
-{
- const float d = x - y;
- __retVal = length(d);
-}
-
-float distance(const vec2 v, const vec2 u)
-{
- const vec2 d2 = v - u;
- __retVal = length(d2);
-}
-
-float distance(const vec3 v, const vec3 u)
-{
- const vec3 d3 = v - u;
- __retVal = length(d3);
-}
-
-float distance(const vec4 v, const vec4 u)
-{
- const vec4 d4 = v - u;
- __retVal = length(d4);
-}
-
-
-//// cross
-
-vec3 cross(const vec3 v, const vec3 u)
-{
- __asm vec3_cross __retVal.xyz, v, u;
-}
-
-
-//// faceforward
-
-float faceforward(const float N, const float I, const float Nref)
-{
- // this could probably be done better
- const float d = dot(Nref, I);
- float s;
- __asm vec4_sgt s, 0.0, d; // s = (0.0 > d) ? 1 : 0
- return mix(-N, N, s);
-}
-
-vec2 faceforward(const vec2 N, const vec2 I, const vec2 Nref)
-{
- // this could probably be done better
- const float d = dot(Nref, I);
- float s;
- __asm vec4_sgt s, 0.0, d; // s = (0.0 > d) ? 1 : 0
- return mix(-N, N, s);
-}
-
-vec3 faceforward(const vec3 N, const vec3 I, const vec3 Nref)
-{
- // this could probably be done better
- const float d = dot(Nref, I);
- float s;
- __asm vec4_sgt s, 0.0, d; // s = (0.0 > d) ? 1 : 0
- return mix(-N, N, s);
-}
-
-vec4 faceforward(const vec4 N, const vec4 I, const vec4 Nref)
-{
- // this could probably be done better
- const float d = dot(Nref, I);
- float s;
- __asm vec4_sgt s, 0.0, d; // s = (0.0 > d) ? 1 : 0
- return mix(-N, N, s);
-}
-
-
-//// reflect
-
-float reflect(const float I, const float N)
-{
- return I - 2.0 * dot(N, I) * N;
-}
-
-vec2 reflect(const vec2 I, const vec2 N)
-{
- return I - 2.0 * dot(N, I) * N;
-}
-
-vec3 reflect(const vec3 I, const vec3 N)
-{
- return I - 2.0 * dot(N, I) * N;
-}
-
-vec4 reflect(const vec4 I, const vec4 N)
-{
- return I - 2.0 * dot(N, I) * N;
-}
-
-//// refract
-
-float refract(const float I, const float N, const float eta)
-{
- float n_dot_i = dot(N, I);
- float k = 1.0 - eta * eta * (1.0 - n_dot_i * n_dot_i);
- float retval;
- if (k < 0.0)
- retval = 0.0;
- else
- retval = eta * I - (eta * n_dot_i + sqrt(k)) * N;
- return retval;
-}
-
-vec2 refract(const vec2 I, const vec2 N, const float eta)
-{
- float n_dot_i = dot(N, I);
- float k = 1.0 - eta * eta * (1.0 - n_dot_i * n_dot_i);
- vec2 retval;
- if (k < 0.0)
- retval = vec2(0.0);
- else
- retval = eta * I - (eta * n_dot_i + sqrt(k)) * N;
- return retval;
-}
-
-vec3 refract(const vec3 I, const vec3 N, const float eta)
-{
- float n_dot_i = dot(N, I);
- float k = 1.0 - eta * eta * (1.0 - n_dot_i * n_dot_i);
- vec3 retval;
- if (k < 0.0)
- retval = vec3(0.0);
- else
- retval = eta * I - (eta * n_dot_i + sqrt(k)) * N;
- return retval;
-}
-
-vec4 refract(const vec4 I, const vec4 N, const float eta)
-{
- float n_dot_i = dot(N, I);
- float k = 1.0 - eta * eta * (1.0 - n_dot_i * n_dot_i);
- vec4 retval;
- if (k < 0.0)
- retval = vec4(0.0);
- else
- retval = eta * I - (eta * n_dot_i + sqrt(k)) * N;
- return retval;
-}
-
-
-
-
-//
-// 8.5 Matrix Functions
-//
-
-mat2 matrixCompMult (mat2 m, mat2 n) {
- return mat2 (m[0] * n[0], m[1] * n[1]);
-}
-
-mat3 matrixCompMult (mat3 m, mat3 n) {
- return mat3 (m[0] * n[0], m[1] * n[1], m[2] * n[2]);
-}
-
-mat4 matrixCompMult (mat4 m, mat4 n) {
- return mat4 (m[0] * n[0], m[1] * n[1], m[2] * n[2], m[3] * n[3]);
-}
-
-
-
-
-//
-// 8.6 Vector Relational Functions
-//
-
-//// lessThan
-
-bvec2 lessThan(const vec2 u, const vec2 v)
-{
- __asm vec4_slt __retVal.xy, u, v;
-}
-
-bvec3 lessThan(const vec3 u, const vec3 v)
-{
- __asm vec4_slt __retVal.xyz, u, v;
-}
-
-bvec4 lessThan(const vec4 u, const vec4 v)
-{
- __asm vec4_slt __retVal, u, v;
-}
-
-bvec2 lessThan(const ivec2 u, const ivec2 v)
-{
- __asm vec4_slt __retVal.xy, u, v;
-}
-
-bvec3 lessThan(const ivec3 u, const ivec3 v)
-{
- __asm vec4_slt __retVal.xyz, u, v;
-}
-
-bvec4 lessThan(const ivec4 u, const ivec4 v)
-{
- __asm vec4_slt __retVal, u, v;
-}
-
-
-//// lessThanEqual
-
-bvec2 lessThanEqual(const vec2 u, const vec2 v)
-{
- __asm vec4_sle __retVal.xy, u, v;
-}
-
-bvec3 lessThanEqual(const vec3 u, const vec3 v)
-{
- __asm vec4_sle __retVal.xyz, u, v;
-}
-
-bvec4 lessThanEqual(const vec4 u, const vec4 v)
-{
- __asm vec4_sle __retVal, u, v;
-}
-
-bvec2 lessThanEqual(const ivec2 u, const ivec2 v)
-{
- __asm vec4_sle __retVal.xy, u, v;
-}
-
-bvec3 lessThanEqual(const ivec3 u, const ivec3 v)
-{
- __asm vec4_sle __retVal.xyz, u, v;
-}
-
-bvec4 lessThanEqual(const ivec4 u, const ivec4 v)
-{
- __asm vec4_sle __retVal, u, v;
-}
-
-
-//// greaterThan
-
-bvec2 greaterThan(const vec2 u, const vec2 v)
-{
- __asm vec4_sgt __retVal.xy, u, v;
-}
-
-bvec3 greaterThan(const vec3 u, const vec3 v)
-{
- __asm vec4_sgt __retVal.xyz, u, v;
-}
-
-bvec4 greaterThan(const vec4 u, const vec4 v)
-{
- __asm vec4_sgt __retVal, u, v;
-}
-
-bvec2 greaterThan(const ivec2 u, const ivec2 v)
-{
- __asm vec4_sgt __retVal.xy, u.xy, v.xy;
-}
-
-bvec3 greaterThan(const ivec3 u, const ivec3 v)
-{
- __asm vec4_sgt __retVal.xyz, u, v;
-}
-
-bvec4 greaterThan(const ivec4 u, const ivec4 v)
-{
- __asm vec4_sgt __retVal, u, v;
-}
-
-
-//// greaterThanEqual
-
-bvec2 greaterThanEqual(const vec2 u, const vec2 v)
-{
- __asm vec4_sge __retVal.xy, u, v;
-}
-
-bvec3 greaterThanEqual(const vec3 u, const vec3 v)
-{
- __asm vec4_sge __retVal.xyz, u, v;
-}
-
-bvec4 greaterThanEqual(const vec4 u, const vec4 v)
-{
- __asm vec4_sge __retVal, u, v;
-}
-
-bvec2 greaterThanEqual(const ivec2 u, const ivec2 v)
-{
- __asm vec4_sge __retVal.xy, u, v;
-}
-
-bvec3 greaterThanEqual(const ivec3 u, const ivec3 v)
-{
- __asm vec4_sge __retVal.xyz, u, v;
-}
-
-bvec4 greaterThanEqual(const ivec4 u, const ivec4 v)
-{
- __asm vec4_sge __retVal, u, v;
-}
-
-
-//// equal
-
-bvec2 equal(const vec2 u, const vec2 v)
-{
- __asm vec4_seq __retVal.xy, u, v;
-}
-
-bvec3 equal(const vec3 u, const vec3 v)
-{
- __asm vec4_seq __retVal.xyz, u, v;
-}
-
-bvec4 equal(const vec4 u, const vec4 v)
-{
- __asm vec4_seq __retVal, u, v;
-}
-
-bvec2 equal(const ivec2 u, const ivec2 v)
-{
- __asm vec4_seq __retVal.xy, u, v;
-}
-
-bvec3 equal(const ivec3 u, const ivec3 v)
-{
- __asm vec4_seq __retVal.xyz, u, v;
-}
-
-bvec4 equal(const ivec4 u, const ivec4 v)
-{
- __asm vec4_seq __retVal, u, v;
-}
-
-bvec2 equal(const bvec2 u, const bvec2 v)
-{
- __asm vec4_seq __retVal.xy, u, v;
-}
-
-bvec3 equal(const bvec3 u, const bvec3 v)
-{
- __asm vec4_seq __retVal.xyz, u, v;
-}
-
-bvec4 equal(const bvec4 u, const bvec4 v)
-{
- __asm vec4_seq __retVal, u, v;
-}
-
-
-
-
-//// notEqual
-
-bvec2 notEqual(const vec2 u, const vec2 v)
-{
- __asm vec4_sne __retVal.xy, u, v;
-}
-
-bvec3 notEqual(const vec3 u, const vec3 v)
-{
- __asm vec4_sne __retVal.xyz, u, v;
-}
-
-bvec4 notEqual(const vec4 u, const vec4 v)
-{
- __asm vec4_sne __retVal, u, v;
-}
-
-bvec2 notEqual(const ivec2 u, const ivec2 v)
-{
- __asm vec4_sne __retVal.xy, u, v;
-}
-
-bvec3 notEqual(const ivec3 u, const ivec3 v)
-{
- __asm vec4_sne __retVal.xyz, u, v;
-}
-
-bvec4 notEqual(const ivec4 u, const ivec4 v)
-{
- __asm vec4_sne __retVal, u, v;
-}
-
-bvec2 notEqual(const bvec2 u, const bvec2 v)
-{
- __asm vec4_sne __retVal.xy, u, v;
-}
-
-bvec3 notEqual(const bvec3 u, const bvec3 v)
-{
- __asm vec4_sne __retVal.xyz, u, v;
-}
-
-bvec4 notEqual(const bvec4 u, const bvec4 v)
-{
- __asm vec4_sne __retVal, u, v;
-}
-
-
-
-//// any
-
-bool any(const bvec2 v)
-{
- float sum;
- __asm vec4_add sum.x, v.x, v.y;
- __asm vec4_sne __retVal.x, sum.x, 0.0;
-}
-
-bool any(const bvec3 v)
-{
- float sum;
- __asm vec4_add sum.x, v.x, v.y;
- __asm vec4_add sum.x, sum.x, v.z;
- __asm vec4_sne __retVal.x, sum.x, 0.0;
-}
-
-bool any(const bvec4 v)
-{
- float sum;
- __asm vec4_add sum.x, v.x, v.y;
- __asm vec4_add sum.x, sum.x, v.z;
- __asm vec4_add sum.x, sum.x, v.w;
- __asm vec4_sne __retVal.x, sum.x, 0.0;
-}
-
-
-//// all
-
-bool all (const bvec2 v)
-{
- float prod;
- __asm vec4_multiply prod, v.x, v.y;
- __asm vec4_sne __retVal, prod, 0.0;
-}
-
-bool all (const bvec3 v)
-{
- float prod;
- __asm vec4_multiply prod, v.x, v.y;
- __asm vec4_multiply prod, prod, v.z;
- __asm vec4_sne __retVal, prod, 0.0;
-}
-
-bool all (const bvec4 v)
-{
- float prod;
- __asm vec4_multiply prod, v.x, v.y;
- __asm vec4_multiply prod, prod, v.z;
- __asm vec4_multiply prod, prod, v.w;
- __asm vec4_sne __retVal, prod, 0.0;
-}
-
-
-
-//// not
-
-bvec2 not (const bvec2 v)
-{
- __asm vec4_seq __retVal.xy, v, 0.0;
-}
-
-bvec3 not (const bvec3 v)
-{
- __asm vec4_seq __retVal.xyz, v, 0.0;
-}
-
-bvec4 not (const bvec4 v)
-{
- __asm vec4_seq __retVal, v, 0.0;
-}
-
-
-
-//// Texture Lookup Functions (for both fragment and vertex shaders)
-
-vec4 texture1D(const sampler1D sampler, const float coord)
-{
- __asm vec4_tex_1d __retVal, sampler, coord;
-}
-
-vec4 texture1DProj(const sampler1D sampler, const vec2 coord)
-{
- // need to swizzle .y into .w
- __asm vec4_tex_1d_proj __retVal, sampler, coord.xyyy;
-}
-
-vec4 texture1DProj(const sampler1D sampler, const vec4 coord)
-{
- __asm vec4_tex_1d_proj __retVal, sampler, coord;
-}
-
-
-vec4 texture2D(const sampler2D sampler, const vec2 coord)
-{
- __asm vec4_tex_2d __retVal, sampler, coord;
-}
-
-vec4 texture2DProj(const sampler2D sampler, const vec3 coord)
-{
- // need to swizzle 'z' into 'w'.
- __asm vec4_tex_2d_proj __retVal, sampler, coord.xyzz;
-}
-
-vec4 texture2DProj(const sampler2D sampler, const vec4 coord)
-{
- __asm vec4_tex_2d_proj __retVal, sampler, coord;
-}
-
-
-vec4 texture3D(const sampler3D sampler, const vec3 coord)
-{
- __asm vec4_tex_3d __retVal, sampler, coord;
-}
-
-vec4 texture3DProj(const sampler3D sampler, const vec4 coord)
-{
- __asm vec4_tex_3d_proj __retVal, sampler, coord;
-}
-
-
-vec4 textureCube(const samplerCube sampler, const vec3 coord)
-{
- __asm vec4_tex_cube __retVal, sampler, coord;
-}
-
-
-
-vec4 shadow1D(const sampler1DShadow sampler, const vec3 coord)
-{
- __asm vec4_tex_1d_shadow __retVal, sampler, coord;
-}
-
-vec4 shadow1DProj(const sampler1DShadow sampler, const vec4 coord)
-{
- // .s and .p will be divided by .q
- __asm vec4_tex_1d_proj_shadow __retVal, sampler, coord;
-}
-
-vec4 shadow2D(const sampler2DShadow sampler, const vec3 coord)
-{
- __asm vec4_tex_2d_shadow __retVal, sampler, coord;
-}
-
-vec4 shadow2DProj(const sampler2DShadow sampler, const vec4 coord)
-{
- // .s, .t and .p will be divided by .q
- __asm vec4_tex_2d_proj_shadow __retVal, sampler, coord;
-}
-
-
-//// GL_ARB_texture_rectangle:
-vec4 texture2DRect(const sampler2DRect sampler, const vec2 coord)
-{
- __asm vec4_tex_rect __retVal, sampler, coord;
-}
-
-vec4 texture2DRectProj(const sampler2DRect sampler, const vec3 coord)
-{
- // need to swizzle .y into .w
- __asm vec4_tex_rect_proj __retVal, sampler, coord.xyzz;
-}
-
-vec4 texture2DRectProj(const sampler2DRect sampler, const vec4 coord)
-{
- __asm vec4_tex_rect_proj __retVal, sampler, ccoord;
-}
-
-vec4 shadow2DRect(const sampler2DRectShadow sampler, const vec3 coord)
-{
- __asm vec4_tex_rect_shadow __retVal, sampler, coord;
-}
-
-vec4 shadow2DRectProj(const sampler2DRectShadow sampler, const vec4 coord)
-{
- __asm vec4_tex_rect_proj_shadow __retVal, sampler, coord;
-}
-
-
-
-//// GL_EXT_texture_array
-vec4 texture1DArray(const sampler1DArray sampler, const vec2 coord)
-{
- __asm vec4_tex_1d_array __retVal, sampler, coord;
-}
-
-vec4 texture2DArray(const sampler2DArray sampler, const vec3 coord)
-{
- __asm vec4_tex_2d_array __retVal, sampler, coord;
-}
-
-
-//
-// 8.9 Noise Functions
-//
-// AUTHOR: Stefan Gustavson (stegu@itn.liu.se), Nov 26, 2005
-//
-
-float noise1(const float x)
-{
- __asm float_noise1 __retVal, x;
-}
-
-
-float noise1(const vec2 x)
-{
- __asm float_noise2 __retVal, x;
-}
-
-float noise1(const vec3 x)
-{
- __asm float_noise3 __retVal, x;
-}
-
-float noise1(const vec4 x)
-{
- __asm float_noise4 __retVal, x;
-}
-
-vec2 noise2(const float x)
-{
- __retVal.x = noise1(x);
- __retVal.y = noise1(x + 19.34);
-}
-
-vec2 noise2(const vec2 x)
-{
- __retVal.x = noise1(x);
- __retVal.y = noise1(x + vec2(19.34, 7.66));
-}
-
-vec2 noise2(const vec3 x)
-{
- __retVal.x = noise1(x);
- __retVal.y = noise1(x + vec3(19.34, 7.66, 3.23));
-}
-
-vec2 noise2(const vec4 x)
-{
- __retVal.x = noise1(x);
- __retVal.y = noise1(x + vec4(19.34, 7.66, 3.23, 2.77));
-}
-
-vec3 noise3(const float x)
-{
- __retVal.x = noise1(x);
- __retVal.y = noise1(x + 19.34);
- __retVal.z = noise1(x + 5.47);
-}
-
-vec3 noise3(const vec2 x)
-{
- __retVal.x = noise1(x);
- __retVal.y = noise1(x + vec2(19.34, 7.66));
- __retVal.z = noise1(x + vec2(5.47, 17.85));
-}
-
-vec3 noise3(const vec3 x)
-{
- __retVal.x = noise1(x);
- __retVal.y = noise1(x + vec3(19.34, 7.66, 3.23));
- __retVal.z = noise1(x + vec3(5.47, 17.85, 11.04));
-}
-
-vec3 noise3(const vec4 x)
-{
- __retVal.x = noise1(x);
- __retVal.y = noise1(x + vec4(19.34, 7.66, 3.23, 2.77));
- __retVal.z = noise1(x + vec4(5.47, 17.85, 11.04, 13.19));
-}
-
-vec4 noise4(const float x)
-{
- __retVal.x = noise1(x);
- __retVal.y = noise1(x + 19.34);
- __retVal.z = noise1(x + 5.47);
- __retVal.w = noise1(x + 23.54);
-}
-
-vec4 noise4(const vec2 x)
-{
- __retVal.x = noise1(x);
- __retVal.y = noise1(x + vec2 (19.34, 7.66));
- __retVal.z = noise1(x + vec2 (5.47, 17.85));
- __retVal.w = noise1(x + vec2 (23.54, 29.11));
-}
-
-vec4 noise4(const vec3 x)
-{
- __retVal.x = noise1(x);
- __retVal.y = noise1(x + vec3(19.34, 7.66, 3.23));
- __retVal.z = noise1(x + vec3(5.47, 17.85, 11.04));
- __retVal.w = noise1(x + vec3(23.54, 29.11, 31.91));
-}
-
-vec4 noise4(const vec4 x)
-{
- __retVal.x = noise1(x);
- __retVal.y = noise1(x + vec4(19.34, 7.66, 3.23, 2.77));
- __retVal.z = noise1(x + vec4(5.47, 17.85, 11.04, 13.19));
- __retVal.w = noise1(x + vec4(23.54, 29.11, 31.91, 37.48));
-}
+++ /dev/null
-/*
- * Mesa 3-D graphics library
- * Version: 6.5
- *
- * Copyright (C) 2006 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.
- */
-
-//
-// This file defines nearly all constructors and operators for built-in data
-// types, using extended language syntax. In general, compiler treats
-// constructors and operators as ordinary functions with some exceptions.
-// For example, the language does not allow functions to be called in
-// constant expressions - here the exception is made to allow it.
-//
-// Each implementation provides its own version of this file. Each
-// implementation can define the required set of operators and constructors
-// in its own fashion.
-//
-// The extended language syntax is only present when compiling this file.
-// It is implicitly included at the very beginning of the compiled shader,
-// so no built-in functions can be used.
-//
-// To communicate with the implementation, a special extended "__asm" keyword
-// is used, followed by an instruction name (any valid identifier), a
-// destination variable identifier and a list of zero or more source
-// variable identifiers.
-//
-// A variable identifier is a variable name declared earlier in the code
-// (as a function parameter, local or global variable).
-//
-// An instruction name designates an instruction that must be exported
-// by the implementation. Each instruction receives data from source
-// variable identifiers and returns data in the destination variable
-// identifier.
-//
-// It is up to the implementation how to define a particular operator
-// or constructor. If it is expected to being used rarely, it can be
-// defined in terms of other operators and constructors,
-// for example:
-//
-// ivec2 __operator + (const ivec2 x, const ivec2 y) {
-// return ivec2 (x[0] + y[0], x[1] + y[1]);
-// }
-//
-// If a particular operator or constructor is expected to be used very
-// often or is an atomic operation (that is, an operation that cannot be
-// expressed in terms of other operations or would create a dependency
-// cycle) it must be defined using one or more __asm constructs.
-//
-// Each implementation must define constructors for all scalar types
-// (bool, float, int). There are 9 scalar-to-scalar constructors
-// (including identity constructors). However, since the language
-// introduces special constructors (like matrix constructor with a single
-// scalar value), implementations must also implement these cases.
-// The compiler provides the following algorithm when resolving a constructor:
-// - try to find a constructor with a prototype matching ours,
-// - if no constructor is found and this is a scalar-to-scalar constructor,
-// raise an error,
-// - if a constructor is found, execute it and return,
-// - count the size of the constructor parameter list - if it is less than
-// the size of our constructor's type, raise an error,
-// - for each parameter in the list do a recursive constructor matching for
-// appropriate scalar fields in the constructed variable,
-//
-// Each implementation must also define a set of operators that deal with
-// built-in data types.
-// There are four kinds of operators:
-// 1) Operators that are implemented only by the compiler: "()" (function
-// call), "," (sequence) and "?:" (selection).
-// 2) Operators that are implemented by the compiler by expressing it in
-// terms of other operators:
-// - "." (field selection) - translated to subscript access,
-// - "&&" (logical and) - translated to "<left_expr> ? <right_expr> :
-// false",
-// - "||" (logical or) - translated to "<left_expr> ? true : <right_expr>",
-// 3) Operators that can be defined by the implementation and if the required
-// prototype is not found, standard behaviour is used:
-// - "==", "!=", "=" (equality, assignment) - compare or assign
-// matching fields one-by-one;
-// note that at least operators for scalar data types must be defined
-// by the implementation to get it work,
-// 4) All other operators not mentioned above. If no required prototype is
-// found, an error is raised. An implementation must follow the language
-// specification to provide all valid operator prototypes.
-//
-
-
-
-//// Basic, scalar constructors/casts
-
-int __constructor(const float f)
-{
- __asm vec4_to_ivec4 __retVal, f;
-}
-
-int __constructor(const bool b)
-{
- __retVal = b;
-}
-
-int __constructor(const int i)
-{
- __retVal = i;
-}
-
-bool __constructor(const int i)
-{
- __asm vec4_sne __retVal, i, 0.0;
-}
-
-bool __constructor(const float f)
-{
- __asm vec4_sne __retVal, f, 0.0;
-}
-
-bool __constructor(const bool b)
-{
- __retVal = b;
-}
-
-float __constructor(const int i)
-{
- __asm ivec4_to_vec4 __retVal, i;
-}
-
-float __constructor(const bool b)
-{
- __asm ivec4_to_vec4 __retVal, b;
-}
-
-float __constructor(const float f)
-{
- __retVal = f;
-}
-
-
-//// vec2 constructors
-
-vec2 __constructor(const float x, const float y)
-{
- __retVal.x = x;
- __retVal.y = y;
-}
-
-vec2 __constructor(const float f)
-{
- __asm vec4_move __retVal.xy, f;
-}
-
-vec2 __constructor(const int i)
-{
- __asm ivec4_to_vec4 __retVal.xy, i;
-}
-
-vec2 __constructor(const bool b)
-{
- __asm ivec4_to_vec4 __retVal.xy, b;
-}
-
-vec2 __constructor(const bvec2 b)
-{
-// __retVal = b;
- __asm ivec4_to_vec4 __retVal.xy, b;
-}
-
-vec2 __constructor(const vec3 v)
-{
- __asm vec4_move __retVal.xy, v.xy;
-}
-
-vec2 __constructor(const vec4 v)
-{
- __asm vec4_move __retVal.xy, v.xy;
-}
-
-
-//// vec3 constructors
-
-vec3 __constructor(const float x, const float y, const float z)
-{
- __retVal.x = x;
- __retVal.y = y;
- __retVal.z = z;
-}
-
-vec3 __constructor(const float f)
-{
- // Note: this could be "__retVal.xyz = f" but that's an illegal assignment
- __asm vec4_move __retVal.xyz, f;
-}
-
-vec3 __constructor(const int i)
-{
- __asm ivec4_to_vec4 __retVal.xyz, i;
-}
-
-vec3 __constructor(const bool b)
-{
- __asm ivec4_to_vec4 __retVal.xyz, b;
-}
-
-vec3 __constructor(const bvec3 b)
-{
- __asm ivec4_to_vec4 __retVal.xyz, b;
-}
-
-vec3 __constructor(const vec4 v)
-{
- __asm vec4_move __retVal.xyz, v;
-}
-
-
-//// vec4 constructors
-
-vec4 __constructor(const float x, const float y, const float z, const float w)
-{
- __retVal.x = x;
- __retVal.y = y;
- __retVal.z = z;
- __retVal.w = w;
-}
-
-vec4 __constructor(const float f)
-{
- // Note: this could be "__retVal = f" but that's an illegal assignment
- __asm vec4_move __retVal, f;
-}
-
-vec4 __constructor(const int i)
-{
- __asm ivec4_to_vec4 __retVal, i;
-}
-
-vec4 __constructor(const bool b)
-{
- __asm ivec4_to_vec4 __retVal, b;
-}
-
-vec4 __constructor(const bvec4 b)
-{
- __asm ivec4_to_vec4 __retVal, b;
-}
-
-vec4 __constructor(const ivec4 i)
-{
- __asm ivec4_to_vec4 __retVal, i;
-}
-
-vec4 __constructor(const vec3 v3, const float f)
-{
- // XXX this constructor shouldn't be needed anymore
- __retVal.xyz = v3;
- __retVal.w = f;
-}
-
-vec4 __constructor(const vec2 v2, const float f1, const float f2)
-{
- // XXX this constructor shouldn't be needed anymore
- __retVal.xy = v2;
- __retVal.z = f1;
- __retVal.w = f2;
-}
-
-
-//// ivec2 constructors
-
-ivec2 __constructor(const int i, const int j)
-{
- __retVal.x = i;
- __retVal.y = j;
-}
-
-ivec2 __constructor(const int i)
-{
- __asm vec4_move __retVal.xy, i;
-}
-
-ivec2 __constructor(const float f)
-{
- __asm vec4_to_ivec4 __retVal.xy, f;
-}
-
-ivec2 __constructor(const bool b)
-{
- __asm vec4_to_ivec4 __retVal.xy, b;
-}
-
-
-//// ivec3 constructors
-
-ivec3 __constructor(const int i, const int j, const int k)
-{
- __retVal.x = i;
- __retVal.y = j;
- __retVal.z = k;
-}
-
-ivec3 __constructor(const int i)
-{
- __asm vec4_move __retVal.xyz, i;
-}
-
-ivec3 __constructor(const float f)
-{
- __asm vec4_to_ivec4 __retVal.xyz, f;
-}
-
-ivec3 __constructor(const bool b)
-{
- __asm vec4_move __retVal.xyz, b;
-}
-
-
-//// ivec4 constructors
-
-ivec4 __constructor(const int x, const int y, const int z, const int w)
-{
- __retVal.x = x;
- __retVal.y = y;
- __retVal.z = z;
- __retVal.w = w;
-}
-
-ivec4 __constructor(const int i)
-{
- __asm vec4_move __retVal, i;
-}
-
-ivec4 __constructor(const float f)
-{
- __asm vec4_to_ivec4 __retVal, f;
-}
-
-ivec4 __constructor(const bool b)
-{
- __asm vec4_to_ivec4 __retVal, b;
-}
-
-
-//// bvec2 constructors
-
-bvec2 __constructor(const bool b1, const bool b2)
-{
- __retVal.x = b1;
- __retVal.y = b2;
-}
-
-bvec2 __constructor(const int i1, const int i2)
-{
- __asm vec4_sne __retVal.x, i1, 0.0;
- __asm vec4_sne __retVal.y, i2, 0.0;
-}
-
-
-bvec2 __constructor(const bool b)
-{
- __asm vec4_move __retVal.xy, b;
-}
-
-bvec2 __constructor(const float f)
-{
- __asm vec4_sne __retVal.xy, f, 0.0;
-}
-
-bvec2 __constructor(const int i)
-{
- __asm vec4_sne __retVal.xy, i, 0.0;
-}
-
-bvec2 __constructor(const vec2 v)
-{
- __asm vec4_sne __retVal.xy, v, 0.0;
-}
-
-bvec2 __constructor(const ivec2 v)
-{
- __asm vec4_sne __retVal.xy, v, 0.0;
-}
-
-
-
-//// bvec3 constructors
-
-bvec3 __constructor(const bool b1, const bool b2, const bool b3)
-{
- __retVal.x = b1;
- __retVal.y = b2;
- __retVal.z = b3;
-}
-
-bvec3 __constructor(const float f1, const float f2, const float f3)
-{
- __asm vec4_sne __retVal.x, f1, 0.0;
- __asm vec4_sne __retVal.y, f2, 0.0;
- __asm vec4_sne __retVal.z, f3, 0.0;
-}
-
-bvec3 __constructor(const bool b)
-{
- __asm vec4_move __retVal.xyz, b;
-}
-
-bvec3 __constructor(const float f)
-{
- __asm vec4_sne __retVal.xyz, f, 0.0;
-}
-
-bvec3 __constructor(const int i)
-{
- __asm vec4_sne __retVal.xyz, i, 0.0;
-}
-
-bvec3 __constructor(const vec3 v)
-{
- __asm vec4_sne __retVal.xyz, v, 0.0;
-}
-
-bvec3 __constructor(const ivec3 v)
-{
- __asm vec4_sne __retVal.xyz, v, 0.0;
-}
-
-
-
-//// bvec4 constructors
-
-bvec4 __constructor(const bool b1, const bool b2, const bool b3, const bool b4)
-{
- __retVal.x = b1;
- __retVal.y = b2;
- __retVal.z = b3;
- __retVal.w = b4;
-}
-
-bvec4 __constructor(const float f1, const float f2, const float f3, const float f4)
-{
- const float zero = 0.0;
- __asm vec4_sne __retVal.x, f1, zero;
- __asm vec4_sne __retVal.y, f2, zero;
- __asm vec4_sne __retVal.z, f3, zero;
- __asm vec4_sne __retVal.w, f4, zero;
-}
-
-bvec4 __constructor(const bool b)
-{
- __asm vec4_move __retVal.xyzw, b;
-}
-
-bvec4 __constructor(const float f)
-{
- __asm vec4_sne __retVal.xyzw, f, 0.0;
-}
-
-bvec4 __constructor(const int i)
-{
- __asm vec4_sne __retVal.xyzw, i, 0.0;
-}
-
-bvec4 __constructor(const vec4 v)
-{
- __asm vec4_sne __retVal.xyzw, v, 0.0;
-}
-
-bvec4 __constructor(const ivec4 v)
-{
- __asm vec4_sne __retVal.xyzw, v, 0.0;
-}
-
-
-
-//// mat2 constructors
-
-mat2 __constructor(const float m00, const float m10,
- const float m01, const float m11)
-{
- __retVal[0].x = m00;
- __retVal[0].y = m10;
- __retVal[1].x = m01;
- __retVal[1].y = m11;
-}
-
-mat2 __constructor(const float f)
-{
- __retVal[0].x = f;
- __retVal[0].y = 0.0;
- __retVal[1].x = 0.0;
- __retVal[1].y = f;
-}
-
-mat2 __constructor(const int i)
-{
- return mat2(float(i));
-}
-
-mat2 __constructor(const bool b)
-{
- return mat2(float(b));
-}
-
-mat2 __constructor(const vec2 c0, const vec2 c1)
-{
- __retVal[0] = c0;
- __retVal[1] = c1;
-}
-
-
-//// mat3 constructors
-
-mat3 __constructor(const float m00, const float m10, const float m20,
- const float m01, const float m11, const float m21,
- const float m02, const float m12, const float m22)
-{
- __retVal[0].x = m00;
- __retVal[0].y = m10;
- __retVal[0].z = m20;
- __retVal[1].x = m01;
- __retVal[1].y = m11;
- __retVal[1].z = m21;
- __retVal[2].x = m02;
- __retVal[2].y = m12;
- __retVal[2].z = m22;
-}
-
-mat3 __constructor(const float f)
-{
- vec2 v = vec2(f, 0.0);
- __retVal[0] = v.xyy;
- __retVal[1] = v.yxy;
- __retVal[2] = v.yyx;
-}
-
-mat3 __constructor(const int i)
-{
- return mat3(float(i));
-}
-
-mat3 __constructor(const bool b)
-{
- return mat3(float(b));
-}
-
-mat3 __constructor(const vec3 c0, const vec3 c1, const vec3 c2)
-{
- __retVal[0] = c0;
- __retVal[1] = c1;
- __retVal[2] = c2;
-}
-
-
-//// mat4 constructors
-
-mat4 __constructor(const float m00, const float m10, const float m20, const float m30,
- const float m01, const float m11, const float m21, const float m31,
- const float m02, const float m12, const float m22, const float m32,
- const float m03, const float m13, const float m23, const float m33)
-{
- __retVal[0].x = m00;
- __retVal[0].y = m10;
- __retVal[0].z = m20;
- __retVal[0].w = m30;
- __retVal[1].x = m01;
- __retVal[1].y = m11;
- __retVal[1].z = m21;
- __retVal[1].w = m31;
- __retVal[2].x = m02;
- __retVal[2].y = m12;
- __retVal[2].z = m22;
- __retVal[2].w = m32;
- __retVal[3].x = m03;
- __retVal[3].y = m13;
- __retVal[3].z = m23;
- __retVal[3].w = m33;
-}
-
-
-mat4 __constructor(const float f)
-{
- vec2 v = vec2(f, 0.0);
- __retVal[0] = v.xyyy;
- __retVal[1] = v.yxyy;
- __retVal[2] = v.yyxy;
- __retVal[3] = v.yyyx;
-}
-
-mat4 __constructor(const int i)
-{
- return mat4(float(i));
-}
-
-mat4 __constructor(const bool b)
-{
- return mat4(float(b));
-}
-
-mat4 __constructor(const vec4 c0, const vec4 c1, const vec4 c2, const vec4 c3)
-{
- __retVal[0] = c0;
- __retVal[1] = c1;
- __retVal[2] = c2;
- __retVal[3] = c3;
-}
-
-
-
-//// Basic int operators
-
-int __operator + (const int a, const int b)
-{
- __asm vec4_add __retVal, a, b;
-}
-
-int __operator - (const int a, const int b)
-{
- __asm vec4_subtract __retVal, a, b;
-}
-
-int __operator * (const int a, const int b)
-{
- __asm vec4_multiply __retVal, a, b;
-}
-
-int __operator / (const int a, const int b)
-{
- float bInv, x;
- __asm float_rcp bInv, b;
- __asm vec4_multiply x, a, bInv;
- __asm vec4_to_ivec4 __retVal, x;
-}
-
-
-//// Basic ivec2 operators
-
-ivec2 __operator + (const ivec2 a, const ivec2 b)
-{
- __asm vec4_add __retVal, a, b;
-}
-
-ivec2 __operator - (const ivec2 a, const ivec2 b)
-{
- __asm vec4_subtract __retVal, a, b;
-}
-
-ivec2 __operator * (const ivec2 a, const ivec2 b)
-{
- __asm vec4_multiply __retVal, a, b;
-}
-
-ivec2 __operator / (const ivec2 a, const ivec2 b)
-{
- vec2 bInv, x;
- __asm float_rcp bInv.x, b.x;
- __asm float_rcp bInv.y, b.y;
- __asm vec4_multiply x, a, bInv;
- __asm vec4_to_ivec4 __retVal, x;
-}
-
-
-//// Basic ivec3 operators
-
-ivec3 __operator + (const ivec3 a, const ivec3 b)
-{
- __asm vec4_add __retVal, a, b;
-}
-
-ivec3 __operator - (const ivec3 a, const ivec3 b)
-{
- __asm vec4_subtract __retVal, a, b;
-}
-
-ivec3 __operator * (const ivec3 a, const ivec3 b)
-{
- __asm vec4_multiply __retVal, a, b;
-}
-
-ivec3 __operator / (const ivec3 a, const ivec3 b)
-{
- vec3 bInv, x;
- __asm float_rcp bInv.x, b.x;
- __asm float_rcp bInv.y, b.y;
- __asm float_rcp bInv.z, b.z;
- __asm vec4_multiply x, a, bInv;
- __asm vec4_to_ivec4 __retVal, x;
-}
-
-
-//// Basic ivec4 operators
-
-ivec4 __operator + (const ivec4 a, const ivec4 b)
-{
- __asm vec4_add __retVal, a, b;
-}
-
-ivec4 __operator - (const ivec4 a, const ivec4 b)
-{
- __asm vec4_subtract __retVal, a, b;
-}
-
-ivec4 __operator * (const ivec4 a, const ivec4 b)
-{
- __asm vec4_multiply __retVal, a, b;
-}
-
-ivec4 __operator / (const ivec4 a, const ivec4 b)
-{
- vec4 bInv, x;
- __asm float_rcp bInv.x, b.x;
- __asm float_rcp bInv.y, b.y;
- __asm float_rcp bInv.z, b.z;
- __asm float_rcp bInv.w, b.w;
- __asm vec4_multiply x, a, bInv;
- __asm vec4_to_ivec4 __retVal, x;
-}
-
-
-//// Basic float operators
-
-float __operator + (const float a, const float b)
-{
- __asm vec4_add __retVal, a, b;
-}
-
-float __operator - (const float a, const float b)
-{
- __asm vec4_subtract __retVal, a, b;
-}
-
-float __operator * (const float a, const float b)
-{
- __asm vec4_multiply __retVal, a, b;
-}
-
-float __operator / (const float a, const float b)
-{
- float bInv;
- __asm float_rcp bInv.x, b;
- __asm vec4_multiply __retVal, a, bInv;
-}
-
-
-//// Basic vec2 operators
-
-vec2 __operator + (const vec2 v, const vec2 u)
-{
- __asm vec4_add __retVal.xy, v, u;
-}
-
-vec2 __operator - (const vec2 v, const vec2 u)
-{
- __asm vec4_subtract __retVal.xy, v, u;
-}
-
-vec2 __operator * (const vec2 v, const vec2 u)
-{
- __asm vec4_multiply __retVal.xy, v, u;
-}
-
-vec2 __operator / (const vec2 v, const vec2 u)
-{
- vec2 w; // = 1 / u
- __asm float_rcp w.x, u.x;
- __asm float_rcp w.y, u.y;
- __asm vec4_multiply __retVal.xy, v, w;
-}
-
-
-//// Basic vec3 operators
-
-vec3 __operator + (const vec3 v, const vec3 u)
-{
- __asm vec4_add __retVal.xyz, v, u;
-}
-
-vec3 __operator - (const vec3 v, const vec3 u)
-{
- __asm vec4_subtract __retVal.xyz, v, u;
-}
-
-vec3 __operator * (const vec3 v, const vec3 u)
-{
- __asm vec4_multiply __retVal.xyz, v, u;
-}
-
-vec3 __operator / (const vec3 v, const vec3 u)
-{
- vec3 w; // = 1 / u
- __asm float_rcp w.x, u.x;
- __asm float_rcp w.y, u.y;
- __asm float_rcp w.z, u.z;
- __asm vec4_multiply __retVal.xyz, v, w;
-}
-
-
-//// Basic vec4 operators
-
-vec4 __operator + (const vec4 v, const vec4 u)
-{
- __asm vec4_add __retVal, v, u;
-}
-
-vec4 __operator - (const vec4 v, const vec4 u)
-{
- __asm vec4_subtract __retVal, v, u;
-}
-
-vec4 __operator * (const vec4 v, const vec4 u)
-{
- __asm vec4_multiply __retVal, v, u;
-}
-
-vec4 __operator / (const vec4 v, const vec4 u)
-{
- vec4 w; // = 1 / u
- __asm float_rcp w.x, u.x;
- __asm float_rcp w.y, u.y;
- __asm float_rcp w.z, u.z;
- __asm float_rcp w.w, u.w;
- __asm vec4_multiply __retVal, v, w;
-}
-
-
-
-
-//// Basic vec2/float operators
-
-vec2 __operator + (const float a, const vec2 u)
-{
- __asm vec4_add __retVal.xy, a, u.xy;
-}
-
-vec2 __operator + (const vec2 v, const float b)
-{
- __asm vec4_add __retVal.xy, v.xy, b;
-}
-
-vec2 __operator - (const float a, const vec2 u)
-{
- __asm vec4_subtract __retVal.xy, a, u.xy;
-}
-
-vec2 __operator - (const vec2 v, const float b)
-{
- __asm vec4_subtract __retVal.xy, v.xy, b;
-}
-
-vec2 __operator * (const float a, const vec2 u)
-{
- __asm vec4_multiply __retVal.xy, a, u.xy;
-}
-
-vec2 __operator * (const vec2 v, const float b)
-{
- __asm vec4_multiply __retVal.xy, v.xy, b;
-}
-
-vec2 __operator / (const float a, const vec2 u)
-{
- vec2 invU;
- __asm float_rcp invU.x, u.x;
- __asm float_rcp invU.y, u.y;
- __asm vec4_multiply __retVal.xy, a, invU.xy;
-}
-
-vec2 __operator / (const vec2 v, const float b)
-{
- float invB;
- __asm float_rcp invB, b;
- __asm vec4_multiply __retVal.xy, v.xy, invB;
-}
-
-
-//// Basic vec3/float operators
-
-vec3 __operator + (const float a, const vec3 u)
-{
- __asm vec4_add __retVal.xyz, a, u.xyz;
-}
-
-vec3 __operator + (const vec3 v, const float b)
-{
- __asm vec4_add __retVal.xyz, v.xyz, b;
-}
-
-vec3 __operator - (const float a, const vec3 u)
-{
- __asm vec4_subtract __retVal.xyz, a, u.xyz;
-}
-
-vec3 __operator - (const vec3 v, const float b)
-{
- __asm vec4_subtract __retVal.xyz, v.xyz, b;
-}
-
-vec3 __operator * (const float a, const vec3 u)
-{
- __asm vec4_multiply __retVal.xyz, a, u.xyz;
-}
-
-vec3 __operator * (const vec3 v, const float b)
-{
- __asm vec4_multiply __retVal.xyz, v.xyz, b;
-}
-
-vec3 __operator / (const float a, const vec3 u)
-{
- vec3 invU;
- __asm float_rcp invU.x, u.x;
- __asm float_rcp invU.y, u.y;
- __asm float_rcp invU.z, u.z;
- __asm vec4_multiply __retVal.xyz, a, invU.xyz;
-}
-
-vec3 __operator / (const vec3 v, const float b)
-{
- float invB;
- __asm float_rcp invB, b;
- __asm vec4_multiply __retVal.xyz, v.xyz, invB;
-}
-
-
-//// Basic vec4/float operators
-
-vec4 __operator + (const float a, const vec4 u)
-{
- __asm vec4_add __retVal, a, u;
-}
-
-vec4 __operator + (const vec4 v, const float b)
-{
- __asm vec4_add __retVal, v, b;
-}
-
-vec4 __operator - (const float a, const vec4 u)
-{
- __asm vec4_subtract __retVal, a, u;
-}
-
-vec4 __operator - (const vec4 v, const float b)
-{
- __asm vec4_subtract __retVal, v, b;
-}
-
-vec4 __operator * (const float a, const vec4 u)
-{
- __asm vec4_multiply __retVal, a, u;
-}
-
-vec4 __operator * (const vec4 v, const float b)
-{
- __asm vec4_multiply __retVal, v, b;
-}
-
-vec4 __operator / (const float a, const vec4 u)
-{
- vec4 invU;
- __asm float_rcp invU.x, u.x;
- __asm float_rcp invU.y, u.y;
- __asm float_rcp invU.z, u.z;
- __asm float_rcp invU.w, u.w;
- __asm vec4_multiply __retVal, a, invU;
-}
-
-vec4 __operator / (const vec4 v, const float b)
-{
- float invB;
- __asm float_rcp invB, b;
- __asm vec4_multiply __retVal, v, invB;
-}
-
-
-
-//// Basic ivec2/int operators
-
-ivec2 __operator + (const int a, const ivec2 u)
-{
- __retVal = ivec2(a) + u;
-}
-
-ivec2 __operator + (const ivec2 v, const int b)
-{
- __retVal = v + ivec2(b);
-}
-
-ivec2 __operator - (const int a, const ivec2 u)
-{
- __retVal = ivec2(a) - u;
-}
-
-ivec2 __operator - (const ivec2 v, const int b)
-{
- __retVal = v - ivec2(b);
-}
-
-ivec2 __operator * (const int a, const ivec2 u)
-{
- __retVal = ivec2(a) * u;
-}
-
-ivec2 __operator * (const ivec2 v, const int b)
-{
- __retVal = v * ivec2(b);
-}
-
-ivec2 __operator / (const int a, const ivec2 u)
-{
- __retVal = ivec2(a) / u;
-}
-
-ivec2 __operator / (const ivec2 v, const int b)
-{
- __retVal = v / ivec2(b);
-}
-
-
-//// Basic ivec3/int operators
-
-ivec3 __operator + (const int a, const ivec3 u)
-{
- __retVal = ivec3(a) + u;
-}
-
-ivec3 __operator + (const ivec3 v, const int b)
-{
- __retVal = v + ivec3(b);
-}
-
-ivec3 __operator - (const int a, const ivec3 u)
-{
- __retVal = ivec3(a) - u;
-}
-
-ivec3 __operator - (const ivec3 v, const int b)
-{
- __retVal = v - ivec3(b);
-}
-
-ivec3 __operator * (const int a, const ivec3 u)
-{
- __retVal = ivec3(a) * u;
-}
-
-ivec3 __operator * (const ivec3 v, const int b)
-{
- __retVal = v * ivec3(b);
-}
-
-ivec3 __operator / (const int a, const ivec3 u)
-{
- __retVal = ivec3(a) / u;
-}
-
-ivec3 __operator / (const ivec3 v, const int b)
-{
- __retVal = v / ivec3(b);
-}
-
-
-//// Basic ivec4/int operators
-
-ivec4 __operator + (const int a, const ivec4 u)
-{
- __retVal = ivec4(a) + u;
-}
-
-ivec4 __operator + (const ivec4 v, const int b)
-{
- __retVal = v + ivec4(b);
-}
-
-ivec4 __operator - (const int a, const ivec4 u)
-{
- __retVal = ivec4(a) - u;
-}
-
-ivec4 __operator - (const ivec4 v, const int b)
-{
- __retVal = v - ivec4(b);
-}
-
-ivec4 __operator * (const int a, const ivec4 u)
-{
- __retVal = ivec4(a) * u;
-}
-
-ivec4 __operator * (const ivec4 v, const int b)
-{
- __retVal = v * ivec4(b);
-}
-
-ivec4 __operator / (const int a, const ivec4 u)
-{
- __retVal = ivec4(a) / u;
-}
-
-ivec4 __operator / (const ivec4 v, const int b)
-{
- __retVal = v / ivec4(b);
-}
-
-
-
-
-//// Unary negation operator
-
-int __operator - (const int a)
-{
- __asm vec4_negate __retVal.x, a;
-}
-
-ivec2 __operator - (const ivec2 v)
-{
- __asm vec4_negate __retVal, v;
-}
-
-ivec3 __operator - (const ivec3 v)
-{
- __asm vec4_negate __retVal, v;
-}
-
-ivec4 __operator - (const ivec4 v)
-{
- __asm vec4_negate __retVal, v;
-}
-
-float __operator - (const float a)
-{
- __asm vec4_negate __retVal.x, a;
-}
-
-vec2 __operator - (const vec2 v)
-{
- __asm vec4_negate __retVal.xy, v.xy;
-}
-
-vec3 __operator - (const vec3 v)
-{
- __asm vec4_negate __retVal.xyz, v.xyz;
-}
-
-vec4 __operator - (const vec4 v)
-{
- __asm vec4_negate __retVal, v;
-}
-
-mat2 __operator - (const mat2 m)
-{
- __retVal[0] = -m[0];
- __retVal[1] = -m[1];
-}
-
-mat3 __operator - (const mat3 m)
-{
- __retVal[0] = -m[0];
- __retVal[1] = -m[1];
- __retVal[2] = -m[2];
-}
-
-mat4 __operator - (const mat4 m)
-{
- __retVal[0] = -m[0];
- __retVal[1] = -m[1];
- __retVal[2] = -m[2];
- __retVal[3] = -m[3];
-}
-
-
-
-//// dot product
-
-float dot(const float a, const float b)
-{
- __retVal = a * b;
-}
-
-float dot(const vec2 a, const vec2 b)
-{
- __retVal = a.x * b.x + a.y * b.y;
-}
-
-float dot(const vec3 a, const vec3 b)
-{
- __asm vec3_dot __retVal, a, b;
-}
-
-float dot(const vec4 a, const vec4 b)
-{
- __asm vec4_dot __retVal, a, b;
-}
-
-
-
-//// int assignment operators
-
-int __operator += (inout int a, const int b)
-{
- a = a + b;
- return a;
-}
-
-int __operator -= (inout int a, const int b)
-{
- a = a - b;
- return a;
-}
-
-int __operator *= (inout int a, const int b)
-{
- a = a * b;
- return a;
-}
-
-int __operator /= (inout int a, const int b)
-{
- a = a / b;
- return a;
-}
-
-
-//// ivec2 assignment operators
-
-ivec2 __operator += (inout ivec2 v, const ivec2 u)
-{
- v = v + u;
- return v;
-}
-
-ivec2 __operator -= (inout ivec2 v, const ivec2 u)
-{
- v = v - u;
- return v;
-}
-
-ivec2 __operator *= (inout ivec2 v, const ivec2 u)
-{
- v = v * u;
- return v;
-}
-
-ivec2 __operator /= (inout ivec2 v, const ivec2 u)
-{
- v = v / u;
- return v;
-}
-
-
-//// ivec3 assignment operators
-
-ivec3 __operator += (inout ivec3 v, const ivec3 u)
-{
- v = v + u;
- return v;
-}
-
-ivec3 __operator -= (inout ivec3 v, const ivec3 u)
-{
- v = v - u;
- return v;
-}
-
-ivec3 __operator *= (inout ivec3 v, const ivec3 u)
-{
- v = v * u;
- return v;
-}
-
-ivec3 __operator /= (inout ivec3 v, const ivec3 u)
-{
- v = v / u;
- return v;
-}
-
-
-//// ivec4 assignment operators
-
-ivec4 __operator += (inout ivec4 v, const ivec4 u)
-{
- v = v + u;
- return v;
-}
-
-ivec4 __operator -= (inout ivec4 v, const ivec4 u)
-{
- v = v - u;
- return v;
-}
-
-ivec4 __operator *= (inout ivec4 v, const ivec4 u)
-{
- v = v * u;
- return v;
-}
-
-ivec4 __operator /= (inout ivec4 v, const ivec4 u)
-{
- v = v / u;
- return v;
-}
-
-
-//// float assignment operators
-
-float __operator += (inout float a, const float b)
-{
- a = a + b;
- return a;
-}
-
-float __operator -= (inout float a, const float b)
-{
- a = a - b;
- return a;
-}
-
-float __operator *= (inout float a, const float b)
-{
- a = a * b;
- return a;
-}
-
-float __operator /= (inout float a, const float b)
-{
- a = a / b;
- return a;
-}
-
-
-//// vec2 assignment operators
-
-vec2 __operator += (inout vec2 v, const vec2 u)
-{
- v = v + u;
- return v;
-}
-
-vec2 __operator -= (inout vec2 v, const vec2 u)
-{
- v = v - u;
- return v;
-}
-
-vec2 __operator *= (inout vec2 v, const vec2 u)
-{
- v = v * u;
- return v;
-}
-
-vec2 __operator /= (inout vec2 v, const vec2 u)
-{
- v = v / u;
- return v;
-}
-
-
-//// vec3 assignment operators
-
-vec3 __operator += (inout vec3 v, const vec3 u)
-{
- v = v + u;
- return v;
-}
-
-vec3 __operator -= (inout vec3 v, const vec3 u)
-{
- v = v - u;
- return v;
-}
-
-vec3 __operator *= (inout vec3 v, const vec3 u)
-{
- v = v * u;
- return v;
-}
-
-vec3 __operator /= (inout vec3 v, const vec3 u)
-{
- v = v / u;
- return v;
-}
-
-
-//// vec4 assignment operators
-
-vec4 __operator += (inout vec4 v, const vec4 u)
-{
- v = v + u;
- return v;
-}
-
-vec4 __operator -= (inout vec4 v, const vec4 u)
-{
- v = v - u;
- return v;
-}
-
-vec4 __operator *= (inout vec4 v, const vec4 u)
-{
- v = v * u;
- return v;
-}
-
-vec4 __operator /= (inout vec4 v, const vec4 u)
-{
- v = v / u;
- return v;
-}
-
-
-
-//// ivec2/int assignment operators
-
-ivec2 __operator += (inout ivec2 v, const int a)
-{
- v = v + ivec2(a);
- return v;
-}
-
-ivec2 __operator -= (inout ivec2 v, const int a)
-{
- v = v - ivec2(a);
- return v;
-}
-
-ivec2 __operator *= (inout ivec2 v, const int a)
-{
- v = v * ivec2(a);
- return v;
-}
-
-ivec2 __operator /= (inout ivec2 v, const int a)
-{
- v = v / ivec2(a);
- return v;
-}
-
-
-//// ivec3/int assignment operators
-
-ivec3 __operator += (inout ivec3 v, const int a)
-{
- v = v + ivec3(a);
- return v;
-}
-
-ivec3 __operator -= (inout ivec3 v, const int a)
-{
- v = v - ivec3(a);
- return v;
-}
-
-ivec3 __operator *= (inout ivec3 v, const int a)
-{
- v = v * ivec3(a);
- return v;
-}
-
-ivec4 __operator /= (inout ivec3 v, const int a)
-{
- v = v / ivec3(a);
- return v;
-}
-
-
-//// ivec4/int assignment operators
-
-ivec4 __operator += (inout ivec4 v, const int a)
-{
- v = v + ivec4(a);
- return v;
-}
-
-ivec4 __operator -= (inout ivec4 v, const int a)
-{
- v = v - ivec4(a);
- return v;
-}
-
-ivec4 __operator *= (inout ivec4 v, const int a)
-{
- v = v * ivec4(a);
- return v;
-}
-
-ivec4 __operator /= (inout ivec4 v, const int a)
-{
- v = v / ivec4(a);
- return v;
-}
-
-
-
-//// vec2/float assignment operators
-
-vec2 __operator += (inout vec2 v, const float a)
-{
- v = v + vec2(a);
- return v;
-}
-
-vec2 __operator -= (inout vec2 v, const float a)
-{
- v = v - vec2(a);
- return v;
-}
-
-vec2 __operator *= (inout vec2 v, const float a)
-{
- v = v * vec2(a);
- return v;
-}
-
-vec2 __operator /= (inout vec2 v, const float a)
-{
- v = v / vec2(a);
- return v;
-}
-
-
-//// vec3/float assignment operators
-
-vec3 __operator += (inout vec3 v, const float a)
-{
- v = v + vec3(a);
- return v;
-}
-
-vec3 __operator -= (inout vec3 v, const float a)
-{
- v = v - vec3(a);
- return v;
-}
-
-vec3 __operator *= (inout vec3 v, const float a)
-{
- v = v * vec3(a);
- return v;
-}
-
-vec3 __operator /= (inout vec3 v, const float a)
-{
- v = v / vec3(a);
- return v;
-}
-
-
-//// vec4/float assignment operators
-
-vec4 __operator += (inout vec4 v, const float a)
-{
- v = v + vec4(a);
- return v;
-}
-
-vec4 __operator -= (inout vec4 v, const float a)
-{
- v = v - vec4(a);
- return v;
-}
-
-vec4 __operator *= (inout vec4 v, const float a)
-{
- v = v * vec4(a);
- return v;
-}
-
-vec4 __operator /= (inout vec4 v, const float a)
-{
- v = v / vec4(a);
- return v;
-}
-
-
-
-
-
-//// Basic mat2 operations
-
-mat2 __operator + (const mat2 m, const mat2 n)
-{
- __retVal[0] = m[0] + n[0];
- __retVal[1] = m[1] + n[1];
-}
-
-mat2 __operator - (const mat2 m, const mat2 n)
-{
- __retVal[0] = m[0] - n[0];
- __retVal[1] = m[1] - n[1];
-}
-
-mat2 __operator * (const mat2 m, const mat2 n)
-{
- __retVal[0] = m[0] * n[0].xx + m[1] * n[0].yy;
- __retVal[1] = m[0] * n[1].xx + m[1] * n[1].yy;
-}
-
-mat2 __operator / (const mat2 m, const mat2 n)
-{
- __retVal[0] = m[0] / n[0];
- __retVal[1] = m[1] / n[1];
-}
-
-
-//// Basic mat3 operations
-
-mat3 __operator + (const mat3 m, const mat3 n)
-{
- __retVal[0] = m[0] + n[0];
- __retVal[1] = m[1] + n[1];
- __retVal[2] = m[2] + n[2];
-}
-
-mat3 __operator - (const mat3 m, const mat3 n)
-{
- __retVal[0] = m[0] - n[0];
- __retVal[1] = m[1] - n[1];
- __retVal[2] = m[2] - n[2];
-}
-
-mat3 __operator * (const mat3 m, const mat3 n)
-{
- __retVal[0] = m[0] * n[0].xxx + m[1] * n[0].yyy + m[2] * n[0].zzz;
- __retVal[1] = m[0] * n[1].xxx + m[1] * n[1].yyy + m[2] * n[1].zzz;
- __retVal[2] = m[0] * n[2].xxx + m[1] * n[2].yyy + m[2] * n[2].zzz;
-}
-
-mat3 __operator / (const mat3 m, const mat3 n)
-{
- __retVal[0] = m[0] / n[0];
- __retVal[1] = m[1] / n[1];
- __retVal[2] = m[2] / n[2];
-}
-
-
-//// Basic mat4 operations
-
-mat4 __operator + (const mat4 m, const mat4 n)
-{
- __retVal[0] = m[0] + n[0];
- __retVal[1] = m[1] + n[1];
- __retVal[2] = m[2] + n[2];
- __retVal[3] = m[3] + n[3];
-}
-
-mat4 __operator - (const mat4 m, const mat4 n)
-{
- __retVal[0] = m[0] - n[0];
- __retVal[1] = m[1] - n[1];
- __retVal[2] = m[2] - n[2];
- __retVal[3] = m[3] - n[3];
-}
-
-mat4 __operator * (const mat4 m, const mat4 n)
-{
- __retVal[0] = m[0] * n[0].xxxx + m[1] * n[0].yyyy + m[2] * n[0].zzzz + m[3] * n[0].wwww;
- __retVal[1] = m[0] * n[1].xxxx + m[1] * n[1].yyyy + m[2] * n[1].zzzz + m[3] * n[1].wwww;
- __retVal[2] = m[0] * n[2].xxxx + m[1] * n[2].yyyy + m[2] * n[2].zzzz + m[3] * n[2].wwww;
- __retVal[3] = m[0] * n[3].xxxx + m[1] * n[3].yyyy + m[2] * n[3].zzzz + m[3] * n[3].wwww;
-}
-
-mat4 __operator / (const mat4 m, const mat4 n)
-{
- __retVal[0] = m[0] / n[0];
- __retVal[1] = m[1] / n[1];
- __retVal[2] = m[2] / n[2];
- __retVal[3] = m[3] / n[3];
-}
-
-
-//// mat2/float operations
-
-mat2 __operator + (const float a, const mat2 n)
-{
- __retVal[0] = a + n[0];
- __retVal[1] = a + n[1];
-}
-
-mat2 __operator + (const mat2 m, const float b)
-{
- __retVal[0] = m[0] + b;
- __retVal[1] = m[1] + b;
-}
-
-mat2 __operator - (const float a, const mat2 n)
-{
- __retVal[0] = a - n[0];
- __retVal[1] = a - n[1];
-}
-
-mat2 __operator - (const mat2 m, const float b)
-{
- __retVal[0] = m[0] - b;
- __retVal[1] = m[1] - b;
-}
-
-mat2 __operator * (const float a, const mat2 n)
-{
- __retVal[0] = a * n[0];
- __retVal[1] = a * n[1];
-}
-
-mat2 __operator * (const mat2 m, const float b)
-{
- __retVal[0] = m[0] * b;
- __retVal[1] = m[1] * b;
-}
-
-mat2 __operator / (const float a, const mat2 n)
-{
- __retVal[0] = a / n[0];
- __retVal[1] = a / n[1];
-}
-
-mat2 __operator / (const mat2 m, const float b)
-{
- __retVal[0] = m[0] / b;
- __retVal[1] = m[1] / b;
-}
-
-
-//// mat3/float operations
-
-mat3 __operator + (const float a, const mat3 n)
-{
- __retVal[0] = a + n[0];
- __retVal[1] = a + n[1];
- __retVal[2] = a + n[2];
-}
-
-mat3 __operator + (const mat3 m, const float b)
-{
- __retVal[0] = m[0] + b;
- __retVal[1] = m[1] + b;
- __retVal[2] = m[2] + b;
-}
-
-mat3 __operator - (const float a, const mat3 n)
-{
- __retVal[0] = a - n[0];
- __retVal[1] = a - n[1];
- __retVal[2] = a - n[2];
-}
-
-mat3 __operator - (const mat3 m, const float b)
-{
- __retVal[0] = m[0] - b;
- __retVal[1] = m[1] - b;
- __retVal[2] = m[2] - b;
-}
-
-mat3 __operator * (const float a, const mat3 n)
-{
- __retVal[0] = a * n[0];
- __retVal[1] = a * n[1];
- __retVal[2] = a * n[2];
-}
-
-mat3 __operator * (const mat3 m, const float b)
-{
- __retVal[0] = m[0] * b;
- __retVal[1] = m[1] * b;
- __retVal[2] = m[2] * b;
-}
-
-mat3 __operator / (const float a, const mat3 n)
-{
- __retVal[0] = a / n[0];
- __retVal[1] = a / n[1];
- __retVal[2] = a / n[2];
-}
-
-mat3 __operator / (const mat3 m, const float b)
-{
- __retVal[0] = m[0] / b;
- __retVal[1] = m[1] / b;
- __retVal[2] = m[2] / b;
-}
-
-
-//// mat4/float operations
-
-mat4 __operator + (const float a, const mat4 n)
-{
- __retVal[0] = a + n[0];
- __retVal[1] = a + n[1];
- __retVal[2] = a + n[2];
- __retVal[3] = a + n[3];
-}
-
-mat4 __operator + (const mat4 m, const float b)
-{
- __retVal[0] = m[0] + b;
- __retVal[1] = m[1] + b;
- __retVal[2] = m[2] + b;
- __retVal[3] = m[3] + b;
-}
-
-mat4 __operator - (const float a, const mat4 n)
-{
- __retVal[0] = a - n[0];
- __retVal[1] = a - n[1];
- __retVal[2] = a - n[2];
- __retVal[3] = a - n[3];
-}
-
-mat4 __operator - (const mat4 m, const float b)
-{
- __retVal[0] = m[0] - b;
- __retVal[1] = m[1] - b;
- __retVal[2] = m[2] - b;
- __retVal[3] = m[3] - b;
-}
-
-mat4 __operator * (const float a, const mat4 n)
-{
- __retVal[0] = a * n[0];
- __retVal[1] = a * n[1];
- __retVal[2] = a * n[2];
- __retVal[3] = a * n[3];
-}
-
-mat4 __operator * (const mat4 m, const float b)
-{
- __retVal[0] = m[0] * b;
- __retVal[1] = m[1] * b;
- __retVal[2] = m[2] * b;
- __retVal[3] = m[3] * b;
-}
-
-mat4 __operator / (const float a, const mat4 n)
-{
- __retVal[0] = a / n[0];
- __retVal[1] = a / n[1];
- __retVal[2] = a / n[2];
- __retVal[3] = a / n[3];
-}
-
-mat4 __operator / (const mat4 m, const float b)
-{
- __retVal[0] = m[0] / b;
- __retVal[1] = m[1] / b;
- __retVal[2] = m[2] / b;
- __retVal[3] = m[3] / b;
-}
-
-
-
-//// matrix / vector products
-
-vec2 __operator * (const mat2 m, const vec2 v)
-{
- __retVal = m[0] * v.xx
- + m[1] * v.yy;
-}
-
-vec2 __operator * (const vec2 v, const mat2 m)
-{
- __retVal.x = dot(v, m[0]);
- __retVal.y = dot(v, m[1]);
-}
-
-vec3 __operator * (const mat3 m, const vec3 v)
-{
- __retVal = m[0] * v.xxx
- + m[1] * v.yyy
- + m[2] * v.zzz;
-}
-
-vec3 __operator * (const vec3 v, const mat3 m)
-{
- __retVal.x = dot(v, m[0]);
- __retVal.y = dot(v, m[1]);
- __retVal.z = dot(v, m[2]);
-}
-
-vec4 __operator * (const mat4 m, const vec4 v)
-{
- __retVal = m[0] * v.xxxx
- + m[1] * v.yyyy
- + m[2] * v.zzzz
- + m[3] * v.wwww;
-}
-
-vec4 __operator * (const vec4 v, const mat4 m)
-{
- __retVal.x = dot(v, m[0]);
- __retVal.y = dot(v, m[1]);
- __retVal.z = dot(v, m[2]);
- __retVal.w = dot(v, m[3]);
-}
-
-
-
-//// mat2 assignment operators
-
-mat2 __operator += (inout mat2 m, const mat2 n)
-{
- m[0] = m[0] + n[0];
- m[1] = m[1] + n[1];
- return m;
-}
-
-mat2 __operator -= (inout mat2 m, const mat2 n)
-{
- m[0] = m[0] - n[0];
- m[1] = m[1] - n[1];
- return m;
-}
-
-mat2 __operator *= (inout mat2 m, const mat2 n)
-{
- m = m * n;
- return m;
-}
-
-mat2 __operator /= (inout mat2 m, const mat2 n)
-{
- m[0] = m[0] / n[0];
- m[1] = m[1] / n[1];
- return m;
-}
-
-
-//// mat3 assignment operators
-
-mat3 __operator += (inout mat3 m, const mat3 n)
-{
- m[0] = m[0] + n[0];
- m[1] = m[1] + n[1];
- m[2] = m[2] + n[2];
- return m;
-}
-
-mat3 __operator -= (inout mat3 m, const mat3 n)
-{
- m[0] = m[0] - n[0];
- m[1] = m[1] - n[1];
- m[2] = m[2] - n[2];
- return m;
-}
-
-mat3 __operator *= (inout mat3 m, const mat3 n)
-{
- m = m * n;
- return m;
-}
-
-mat3 __operator /= (inout mat3 m, const mat3 n)
-{
- m[0] = m[0] / n[0];
- m[1] = m[1] / n[1];
- m[2] = m[2] / n[2];
- return m;
-}
-
-
-// mat4 assignment operators
-
-mat4 __operator += (inout mat4 m, const mat4 n)
-{
- m[0] = m[0] + n[0];
- m[1] = m[1] + n[1];
- m[2] = m[2] + n[2];
- m[3] = m[3] + n[3];
- return m;
-}
-
-mat4 __operator -= (inout mat4 m, const mat4 n)
-{
- m[0] = m[0] - n[0];
- m[1] = m[1] - n[1];
- m[2] = m[2] - n[2];
- m[3] = m[3] - n[3];
- return m;
-}
-
-mat4 __operator *= (inout mat4 m, const mat4 n)
-{
- m = m * n;
- return m;
-}
-
-mat4 __operator /= (inout mat4 m, const mat4 n)
-{
- m[0] = m[0] / n[0];
- m[1] = m[1] / n[1];
- m[2] = m[2] / n[2];
- m[3] = m[3] / n[3];
- return m;
-}
-
-
-//// mat2/float assignment operators
-
-mat2 __operator += (inout mat2 m, const float a)
-{
- vec2 v = vec2(a);
- m[0] = m[0] + v;
- m[1] = m[1] + v;
- return m;
-}
-
-mat2 __operator -= (inout mat2 m, const float a)
-{
- vec2 v = vec2(a);
- m[0] = m[0] - v;
- m[1] = m[1] - v;
- return m;
-}
-
-mat2 __operator *= (inout mat2 m, const float a)
-{
- vec2 v = vec2(a);
- m[0] = m[0] * v;
- m[1] = m[1] * v;
- return m;
-}
-
-mat2 __operator /= (inout mat2 m, const float a)
-{
- vec2 v = vec2(1.0 / a);
- m[0] = m[0] * v;
- m[1] = m[1] * v;
- return m;
-}
-
-
-//// mat3/float assignment operators
-
-mat3 __operator += (inout mat3 m, const float a)
-{
- vec3 v = vec3(a);
- m[0] = m[0] + v;
- m[1] = m[1] + v;
- m[2] = m[2] + v;
- return m;
-}
-
-mat3 __operator -= (inout mat3 m, const float a)
-{
- vec3 v = vec3(a);
- m[0] = m[0] - v;
- m[1] = m[1] - v;
- m[2] = m[2] - v;
- return m;
-}
-
-mat3 __operator *= (inout mat3 m, const float a)
-{
- vec3 v = vec3(a);
- m[0] = m[0] * v;
- m[1] = m[1] * v;
- m[2] = m[2] * v;
- return m;
-}
-
-mat3 __operator /= (inout mat3 m, const float a)
-{
- vec3 v = vec3(1.0 / a);
- m[0] = m[0] * v;
- m[1] = m[1] * v;
- m[2] = m[2] * v;
- return m;
-}
-
-
-//// mat4/float assignment operators
-
-mat4 __operator += (inout mat4 m, const float a)
-{
- vec4 v = vec4(a);
- m[0] = m[0] + v;
- m[1] = m[1] + v;
- m[2] = m[2] + v;
- m[3] = m[3] + v;
- return m;
-}
-
-mat4 __operator -= (inout mat4 m, const float a)
-{
- vec4 v = vec4(a);
- m[0] = m[0] - v;
- m[1] = m[1] - v;
- m[2] = m[2] - v;
- m[3] = m[3] - v;
- return m;
-}
-
-mat4 __operator *= (inout mat4 m, const float a)
-{
- vec4 v = vec4(a);
- m[0] = m[0] * v;
- m[1] = m[1] * v;
- m[2] = m[2] * v;
- m[3] = m[3] * v;
- return m;
-}
-
-mat4 __operator /= (inout mat4 m, const float a)
-{
- vec4 v = vec4(1.0 / a);
- m[0] = m[0] * v;
- m[1] = m[1] * v;
- m[2] = m[2] * v;
- m[3] = m[3] * v;
- return m;
-}
-
-
-
-//// vec/mat assignment operators
-
-vec2 __operator *= (inout vec2 v, const mat2 m)
-{
- v = v * m;
- return v;
-}
-
-vec3 __operator *= (inout vec3 v, const mat3 m)
-{
- v = v * m;
- return v;
-}
-
-vec4 __operator *= (inout vec4 v, const mat4 m)
-{
- v = v * m;
- return v;
-}
-
-
-
-//// pre-decrement operators
-
-int __operator --(inout int a)
-{
- a = a - 1;
- __retVal = a;
-}
-
-ivec2 __operator --(inout ivec2 v)
-{
- v = v - ivec2(1);
- __retVal = v;
-}
-
-ivec3 __operator --(inout ivec3 v)
-{
- v = v - ivec3(1);
- __retVal = v;
-}
-
-ivec4 __operator --(inout ivec4 v)
-{
- v = v - ivec4(1);
- __retVal = v;
-}
-
-
-float __operator --(inout float a)
-{
- a = a - 1.0;
- __retVal = a;
-}
-
-vec2 __operator --(inout vec2 v)
-{
- v = v - vec2(1.0);
- __retVal = v;
-}
-
-vec3 __operator --(inout vec3 v)
-{
- v = v - vec3(1.0);
- __retVal = v;
-}
-
-vec4 __operator --(inout vec4 v)
-{
- v = v - vec4(1.0);
- __retVal = v;
-}
-
-
-mat2 __operator --(inout mat2 m)
-{
- m[0] = m[0] - vec2(1.0);
- m[1] = m[1] - vec2(1.0);
- __retVal = m;
-}
-
-mat3 __operator --(inout mat3 m)
-{
- m[0] = m[0] - vec3(1.0);
- m[1] = m[1] - vec3(1.0);
- m[2] = m[2] - vec3(1.0);
- __retVal = m;
-}
-
-mat4 __operator --(inout mat4 m)
-{
- m[0] = m[0] - vec4(1.0);
- m[1] = m[1] - vec4(1.0);
- m[2] = m[2] - vec4(1.0);
- m[3] = m[3] - vec4(1.0);
- __retVal = m;
-}
-
-
-//// pre-increment operators
-
-int __operator ++(inout int a)
-{
- a = a + 1;
- __retVal = a;
-}
-
-ivec2 __operator ++(inout ivec2 v)
-{
- v = v + ivec2(1);
- __retVal = v;
-}
-
-ivec3 __operator ++(inout ivec3 v)
-{
- v = v + ivec3(1);
- __retVal = v;
-}
-
-ivec4 __operator ++(inout ivec4 v)
-{
- v = v + ivec4(1);
- __retVal = v;
-}
-
-
-float __operator ++(inout float a)
-{
- a = a + 1.0;
- __retVal = a;
-}
-
-vec2 __operator ++(inout vec2 v)
-{
- v = v + vec2(1.0);
- __retVal = v;
-}
-
-vec3 __operator ++(inout vec3 v)
-{
- v = v + vec3(1.0);
- __retVal = v;
-}
-
-vec4 __operator ++(inout vec4 v)
-{
- v = v + vec4(1.0);
- __retVal = v;
-}
-
-
-mat2 __operator ++(inout mat2 m)
-{
- m[0] = m[0] + vec2(1.0);
- m[1] = m[1] + vec2(1.0);
- __retVal = m;
-}
-
-mat3 __operator ++(inout mat3 m)
-{
- m[0] = m[0] + vec3(1.0);
- m[1] = m[1] + vec3(1.0);
- m[2] = m[2] + vec3(1.0);
- __retVal = m;
-}
-
-mat4 __operator ++(inout mat4 m)
-{
- m[0] = m[0] + vec4(1.0);
- m[1] = m[1] + vec4(1.0);
- m[2] = m[2] + vec4(1.0);
- m[3] = m[3] + vec4(1.0);
- __retVal = m;
-}
-
-
-
-//// post-decrement
-
-int __postDecr(inout int a)
-{
- __retVal = a;
- a = a - 1;
-}
-
-ivec2 __postDecr(inout ivec2 v)
-{
- __retVal = v;
- v = v - ivec2(1);
-}
-
-ivec3 __postDecr(inout ivec3 v)
-{
- __retVal = v;
- v = v - ivec3(1);
-}
-
-ivec4 __postDecr(inout ivec4 v)
-{
- __retVal = v;
- v = v - ivec4(1);
-}
-
-
-float __postDecr(inout float a)
-{
- __retVal = a;
- a = a - 1.0;
-}
-
-vec2 __postDecr(inout vec2 v)
-{
- __retVal = v;
- v = v - vec2(1.0);
-}
-
-vec3 __postDecr(inout vec3 v)
-{
- __retVal = v;
- v = v - vec3(1.0);
-}
-
-vec4 __postDecr(inout vec4 v)
-{
- __retVal = v;
- v = v - vec4(1.0);
-}
-
-
-mat2 __postDecr(inout mat2 m)
-{
- __retVal = m;
- m[0] = m[0] - vec2(1.0);
- m[1] = m[1] - vec2(1.0);
-}
-
-mat3 __postDecr(inout mat3 m)
-{
- __retVal = m;
- m[0] = m[0] - vec3(1.0);
- m[1] = m[1] - vec3(1.0);
- m[2] = m[2] - vec3(1.0);
-}
-
-mat4 __postDecr(inout mat4 m)
-{
- __retVal = m;
- m[0] = m[0] - vec4(1.0);
- m[1] = m[1] - vec4(1.0);
- m[2] = m[2] - vec4(1.0);
- m[3] = m[3] - vec4(1.0);
-}
-
-
-//// post-increment
-
-float __postIncr(inout float a)
-{
- __retVal = a;
- a = a + 1;
-}
-
-vec2 __postIncr(inout vec2 v)
-{
- __retVal = v;
- v = v + vec2(1.0);
-}
-
-vec3 __postIncr(inout vec3 v)
-{
- __retVal = v;
- v = v + vec3(1.0);
-}
-
-vec4 __postIncr(inout vec4 v)
-{
- __retVal = v;
- v = v + vec4(1.0);
-}
-
-
-int __postIncr(inout int a)
-{
- __retVal = a;
- a = a + 1;
-}
-
-ivec2 __postIncr(inout ivec2 v)
-{
- __retVal = v;
- v = v + ivec2(1);
-}
-
-ivec3 __postIncr(inout ivec3 v)
-{
- __retVal = v;
- v = v + ivec3(1);
-}
-
-ivec4 __postIncr(inout ivec4 v)
-{
- __retVal = v;
- v = v + ivec3(1);
-}
-
-
-mat2 __postIncr(inout mat2 m)
-{
- mat2 n = m;
- m[0] = m[0] + vec2(1.0);
- m[1] = m[1] + vec2(1.0);
- return n;
-}
-
-mat3 __postIncr(inout mat3 m)
-{
- mat3 n = m;
- m[0] = m[0] + vec3(1.0);
- m[1] = m[1] + vec3(1.0);
- m[2] = m[2] + vec3(1.0);
- return n;
-}
-
-mat4 __postIncr(inout mat4 m)
-{
- mat4 n = m;
- m[0] = m[0] + vec4(1.0);
- m[1] = m[1] + vec4(1.0);
- m[2] = m[2] + vec4(1.0);
- m[3] = m[3] + vec4(1.0);
- return n;
-}
-
-
-
-//// inequality operators
-
-
-// XXX are the inequality operators for floats/ints really needed????
-bool __operator < (const float a, const float b)
-{
- __asm vec4_sgt __retVal.x, b, a;
-}
-
-
-bool __operator < (const int a, const int b) {
- return float (a) < float (b);
-}
-
-bool __operator > (const float a, const float b) {
- bool c;
- __asm float_less c, b, a;
- return c;
-}
-
-bool __operator > (const int a, const int b) {
- return float (a) > float (b);
-}
-
-bool __operator >= (const float a, const float b) {
- bool g, e;
- __asm float_less g, b, a;
- __asm float_equal e, a, b;
- return g || e;
-}
-
-bool __operator >= (const int a, const int b) {
- return float (a) >= float (b);
-}
-
-bool __operator <= (const float a, const float b) {
- bool g, e;
- __asm float_less g, a, b;
- __asm float_equal e, a, b;
- return g || e;
-}
-
-bool __operator <= (const int a, const int b) {
- return float (a) <= float (b);
-}
-
-
-
-//
-// MESA-specific extension functions.
-//
-
-void printMESA (const float f) {
- __asm float_print f;
-}
-
-void printMESA (const int i) {
- __asm int_print i;
-}
-
-void printMESA (const bool b) {
- __asm bool_print b;
-}
-
-void printMESA (const vec2 v) {
- printMESA (v.x);
- printMESA (v.y);
-}
-
-void printMESA (const vec3 v) {
- printMESA (v.x);
- printMESA (v.y);
- printMESA (v.z);
-}
-
-void printMESA (const vec4 v) {
- printMESA (v.x);
- printMESA (v.y);
- printMESA (v.z);
- printMESA (v.w);
-}
-
-void printMESA (const ivec2 v) {
- printMESA (v.x);
- printMESA (v.y);
-}
-
-void printMESA (const ivec3 v) {
- printMESA (v.x);
- printMESA (v.y);
- printMESA (v.z);
-}
-
-void printMESA (const ivec4 v) {
- printMESA (v.x);
- printMESA (v.y);
- printMESA (v.z);
- printMESA (v.w);
-}
-
-void printMESA (const bvec2 v) {
- printMESA (v.x);
- printMESA (v.y);
-}
-
-void printMESA (const bvec3 v) {
- printMESA (v.x);
- printMESA (v.y);
- printMESA (v.z);
-}
-
-void printMESA (const bvec4 v) {
- printMESA (v.x);
- printMESA (v.y);
- printMESA (v.z);
- printMESA (v.w);
-}
-
-void printMESA (const mat2 m) {
- printMESA (m[0]);
- printMESA (m[1]);
-}
-
-void printMESA (const mat3 m) {
- printMESA (m[0]);
- printMESA (m[1]);
- printMESA (m[2]);
-}
-
-void printMESA (const mat4 m) {
- printMESA (m[0]);
- printMESA (m[1]);
- printMESA (m[2]);
- printMESA (m[3]);
-}
-
-void printMESA (const sampler1D e) {
- __asm int_print e;
-}
-
-void printMESA (const sampler2D e) {
- __asm int_print e;
-}
-
-void printMESA (const sampler3D e) {
- __asm int_print e;
-}
-
-void printMESA (const samplerCube e) {
- __asm int_print e;
-}
-
-void printMESA (const sampler1DShadow e) {
- __asm int_print e;
-}
-
-void printMESA (const sampler2DShadow e) {
- __asm int_print e;
-}
-
+++ /dev/null
-/*
- * Mesa 3-D graphics library
- * Version: 6.5
- *
- * Copyright (C) 2006 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.
- */
-
-//
-// From Shader Spec, ver. 1.10, rev. 59
-//
-
-__fixed_input vec4 gl_FragCoord;
-__fixed_input bool gl_FrontFacing;
-__fixed_output vec4 gl_FragColor;
-__fixed_output vec4 gl_FragData[gl_MaxDrawBuffers];
-__fixed_output float gl_FragDepth;
-
-varying vec4 gl_Color;
-varying vec4 gl_SecondaryColor;
-varying vec4 gl_TexCoord[gl_MaxTextureCoords];
-varying float gl_FogFragCoord;
-
-
-
-//// 8.7 Texture Lookup Functions (with bias)
-
-vec4 texture1D(const sampler1D sampler, const float coord, const float bias)
-{
- vec4 coord4;
- coord4.x = coord;
- coord4.w = bias;
- __asm vec4_tex_1d_bias __retVal, sampler, coord4;
-}
-
-vec4 texture1DProj(const sampler1D sampler, const vec2 coord, const float bias)
-{
- // do projection here (there's no vec4_texbp1d instruction)
- vec4 pcoord;
- pcoord.x = coord.x / coord.y;
- pcoord.w = bias;
- __asm vec4_tex_1d_bias __retVal, sampler, pcoord;
-}
-
-vec4 texture1DProj(const sampler1D sampler, const vec4 coord, const float bias)
-{
- // do projection here (there's no vec4_texbp1d instruction)
- vec4 pcoord;
- pcoord.x = coord.x / coord.z;
- pcoord.w = bias;
- __asm vec4_tex_1d_bias __retVal, sampler, pcoord;
-}
-
-
-
-
-vec4 texture2D(const sampler2D sampler, const vec2 coord, const float bias)
-{
- vec4 coord4;
- coord4.xy = coord.xy;
- coord4.w = bias;
- __asm vec4_tex_2d_bias __retVal, sampler, coord4;
-}
-
-vec4 texture2DProj(const sampler2D sampler, const vec3 coord, const float bias)
-{
- // do projection here (there's no vec4_texbp2d instruction)
- vec4 pcoord;
- pcoord.xy = coord.xy / coord.z;
- pcoord.w = bias;
- __asm vec4_tex_2d_bias __retVal, sampler, pcoord;
-}
-
-vec4 texture2DProj(const sampler2D sampler, const vec4 coord, const float bias)
-{
- // do projection here (there's no vec4_texbp2d instruction)
- vec4 pcoord;
- pcoord.xy = coord.xy / coord.w;
- pcoord.w = bias;
- __asm vec4_tex_2d_bias __retVal, sampler, pcoord;
-}
-
-
-
-
-vec4 texture3D(const sampler3D sampler, const vec3 coord, const float bias)
-{
- vec4 coord4;
- coord4.xyz = coord.xyz;
- coord4.w = bias;
- __asm vec4_tex_3d_bias __retVal, sampler, coord4;
-}
-
-vec4 texture3DProj(const sampler3D sampler, const vec4 coord, const float bias)
-{
- // do projection here (there's no vec4_texbp3d instruction)
- vec4 pcoord;
- pcoord.xyz = coord.xyz / coord.w;
- pcoord.w = bias;
- __asm vec4_tex_3d_bias __retVal, sampler, pcoord;
-}
-
-
-
-
-vec4 textureCube(const samplerCube sampler, const vec3 coord, const float bias)
-{
- vec4 coord4;
- coord4.xyz = coord;
- coord4.w = bias;
- __asm vec4_tex_cube __retVal, sampler, coord4;
-}
-
-
-
-vec4 shadow1D(const sampler1DShadow sampler, const vec3 coord, const float bias)
-{
- vec4 coord4;
- coord4.xyz = coord;
- coord4.w = bias;
- __asm vec4_tex_1d_bias_shadow __retVal, sampler, coord4;
-}
-
-vec4 shadow1DProj(const sampler1DShadow sampler, const vec4 coord, const float bias)
-{
- vec4 pcoord;
- pcoord.x = coord.x / coord.w;
- pcoord.z = coord.z;
- pcoord.w = bias;
- __asm vec4_tex_1d_bias_shadow __retVal, sampler, pcoord;
-}
-
-vec4 shadow2D(const sampler2DShadow sampler, const vec3 coord, const float bias)
-{
- vec4 coord4;
- coord4.xyz = coord;
- coord4.w = bias;
- __asm vec4_tex_2d_bias_shadow __retVal, sampler, coord4;
-}
-
-vec4 shadow2DProj(const sampler2DShadow sampler, const vec4 coord, const float bias)
-{
- vec4 pcoord;
- pcoord.xy = coord.xy / coord.w;
- pcoord.z = coord.z;
- pcoord.w = bias;
- __asm vec4_tex_2d_bias_shadow __retVal, sampler, pcoord;
-}
-
-
-
-//// GL_EXT_texture_array
-
-vec4 texture1DArray(const sampler1DArray sampler, const vec2 coord)
-{
- vec4 coord4;
- coord4.xy = coord;
- __asm vec4_tex_1d_array __retVal, sampler, coord4;
-}
-
-vec4 texture1DArray(const sampler1DArray sampler, const vec2 coord, const float bias)
-{
- vec4 coord4;
- coord4.xy = coord;
- coord4.w = bias;
- __asm vec4_tex_1d_array_bias __retVal, sampler, coord4;
-}
-
-vec4 texure2DArray(const sampler2DArray sampler, const vec3 coord)
-{
- vec4 coord4;
- coord4.xyz = coord;
- __asm vec4_tex_2d_array __retVal, sampler, coord4;
-}
-
-vec4 texture2DArray(const sampler2DArray sampler, const vec3 coord, const float bias)
-{
- vec4 coord4;
- coord4.xyz = coord;
- coord4.w = bias;
- __asm vec4_tex_2d_array_bias __retVal, sampler, coord4;
-}
-
-vec4 shadow1DArray(const sampler1DArrayShadow sampler, const vec2 coord)
-{
- vec4 coord4;
- coord4.xy = coord;
- __asm vec4_tex_1d_array_shadow __retVal, sampler, coord4;
-}
-
-vec4 shadow1DArray(const sampler1DArrayShadow sampler, const vec2 coord, const float bias)
-{
- vec4 coord4;
- coord4.xy = coord;
- coord4.w = bias;
- __asm vec4_tex_1d_array_bias_shadow __retVal, sampler, coord4;
-}
-
-vec4 shadow2DArray(const sampler2DArrayShadow sampler, const vec3 coord)
-{
- vec4 coord4;
- coord4.xyz = coord;
- __asm vec4_tex_2d_array_shadow __retVal, sampler, coord4;
-}
-
-vec4 shadow2DArray(const sampler2DArrayShadow sampler, const vec3 coord, const float bias)
-{
- vec4 coord4;
- coord4.xyz = coord;
- coord4.w = bias;
- __asm vec4_tex_2d_array_bias_shadow __retVal, sampler, coord4;
-}
-
-
-
-//
-// 8.8 Fragment Processing Functions
-//
-
-float dFdx(const float p)
-{
- __asm vec4_ddx __retVal.x, p.xxxx;
-}
-
-vec2 dFdx(const vec2 p)
-{
- __asm vec4_ddx __retVal.xy, p.xyyy;
-}
-
-vec3 dFdx(const vec3 p)
-{
- __asm vec4_ddx __retVal.xyz, p.xyzz;
-}
-
-vec4 dFdx(const vec4 p)
-{
- __asm vec4_ddx __retVal, p;
-}
-
-float dFdy(const float p)
-{
- __asm vec4_ddy __retVal.x, p.xxxx;
-}
-
-vec2 dFdy(const vec2 p)
-{
- __asm vec4_ddy __retVal.xy, p.xyyy;
-}
-
-vec3 dFdy(const vec3 p)
-{
- __asm vec4_ddy __retVal.xyz, p.xyzz;
-}
-
-vec4 dFdy(const vec4 p)
-{
- __asm vec4_ddy __retVal, p;
-}
-
-float fwidth (const float p)
-{
- // XXX hand-write with __asm
- return abs(dFdx(p)) + abs(dFdy(p));
-}
-
-vec2 fwidth(const vec2 p)
-{
- // XXX hand-write with __asm
- return abs(dFdx(p)) + abs(dFdy(p));
-}
-
-vec3 fwidth(const vec3 p)
-{
- // XXX hand-write with __asm
- return abs(dFdx(p)) + abs(dFdy(p));
-}
-
-vec4 fwidth(const vec4 p)
-{
- // XXX hand-write with __asm
- return abs(dFdx(p)) + abs(dFdy(p));
-}
-
+++ /dev/null
-/*
- * Mesa 3-D graphics library
- *
- * 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.
- */
-
-const int _mesa_VerticesInMax = 6;
-
-__fixed_input int gl_PrimitiveIDIn;
-__fixed_output int gl_PrimitiveID;
-__fixed_output int gl_Layer;
-
-
-varying in vec4 gl_FrontColorIn[_mesa_VerticesInMax];
-varying in vec4 gl_BackColorIn[_mesa_VerticesInMax];
-varying in vec4 gl_FrontSecondaryColorIn[_mesa_VerticesInMax];
-varying in vec4 gl_BackSecondaryColorIn[_mesa_VerticesInMax];
-/*varying in vec4 gl_TexCoordIn[_mesa_VerticesInMax][gl_MaxTextureCoords];*/
-varying in float gl_FogFragCoordIn[_mesa_VerticesInMax];
-varying in vec4 gl_PositionIn[_mesa_VerticesInMax];
-varying in float gl_PointSizeIn[_mesa_VerticesInMax];
-varying in vec4 gl_ClipVertexIn[_mesa_VerticesInMax];
-
-varying out vec4 gl_Position;
-varying out vec4 gl_FrontColor;
-varying out vec4 gl_BackColor;
-varying out vec4 gl_FrontSecondaryColor;
-varying out vec4 gl_BackSecondaryColor;
-varying out vec4 gl_TexCoord[gl_MaxTextureCoords];
-varying out float gl_FogFragCoord;
-
-void EmitVertex()
-{
- __asm emit_vertex;
-}
-
-void EndPrimitive()
-{
- __asm end_primitive;
-}
+++ /dev/null
-/*
- * Mesa 3-D graphics library
- * Version: 6.5
- *
- * Copyright (C) 2006 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.
- */
-
-//
-// From Shader Spec, ver. 1.10, rev. 59
-//
-
-__fixed_output vec4 gl_Position;
-__fixed_output float gl_PointSize;
-__fixed_output vec4 gl_ClipVertex;
-
-attribute vec4 gl_Color;
-attribute vec4 gl_SecondaryColor;
-attribute vec3 gl_Normal;
-attribute vec4 gl_Vertex;
-attribute vec4 gl_MultiTexCoord0;
-attribute vec4 gl_MultiTexCoord1;
-attribute vec4 gl_MultiTexCoord2;
-attribute vec4 gl_MultiTexCoord3;
-attribute vec4 gl_MultiTexCoord4;
-attribute vec4 gl_MultiTexCoord5;
-attribute vec4 gl_MultiTexCoord6;
-attribute vec4 gl_MultiTexCoord7;
-attribute float gl_FogCoord;
-
-varying vec4 gl_FrontColor;
-varying vec4 gl_BackColor;
-varying vec4 gl_FrontSecondaryColor;
-varying vec4 gl_BackSecondaryColor;
-varying vec4 gl_TexCoord[gl_MaxTextureCoords];
-varying float gl_FogFragCoord;
-
-//
-// Geometric Functions
-//
-
-vec4 ftransform()
-{
- __retVal = gl_ModelViewProjectionMatrix[0] * gl_Vertex.xxxx
- + gl_ModelViewProjectionMatrix[1] * gl_Vertex.yyyy
- + gl_ModelViewProjectionMatrix[2] * gl_Vertex.zzzz
- + gl_ModelViewProjectionMatrix[3] * gl_Vertex.wwww;
-}
-
-
-
-//
-// 8.7 Texture Lookup Functions
-// These are pretty much identical to the ones in slang_fragment_builtin.gc
-// When used in a vertex program, the texture sample instructions should not
-// be using a LOD term so it's effectively zero. Adding 'lod' to that does
-// what we want.
-//
-
-vec4 texture1DLod(const sampler1D sampler, const float coord, const float lod)
-{
- vec4 coord4;
- coord4.x = coord;
- coord4.w = lod;
- __asm vec4_tex_1d_bias __retVal, sampler, coord4;
-}
-
-vec4 texture1DProjLod(const sampler1D sampler, const vec2 coord, const float lod)
-{
- vec4 pcoord;
- pcoord.x = coord.x / coord.y;
- pcoord.w = lod;
- __asm vec4_tex_1d_bias __retVal, sampler, pcoord;
-}
-
-vec4 texture1DProjLod(const sampler1D sampler, const vec4 coord, const float lod)
-{
- vec4 pcoord;
- pcoord.x = coord.x / coord.z;
- pcoord.w = lod;
- __asm vec4_tex_1d_bias __retVal, sampler, pcoord;
-}
-
-
-
-vec4 texture2DLod(const sampler2D sampler, const vec2 coord, const float lod)
-{
- vec4 coord4;
- coord4.xy = coord.xy;
- coord4.w = lod;
- __asm vec4_tex_2d_bias __retVal, sampler, coord4;
-}
-
-vec4 texture2DProjLod(const sampler2D sampler, const vec3 coord, const float lod)
-{
- vec4 pcoord;
- pcoord.xy = coord.xy / coord.z;
- pcoord.w = lod;
- __asm vec4_tex_2d_bias __retVal, sampler, pcoord;
-}
-
-vec4 texture2DProjLod(const sampler2D sampler, const vec4 coord, const float lod)
-{
- vec4 pcoord;
- pcoord.xy = coord.xy / coord.z;
- pcoord.w = lod;
- __asm vec4_tex_2d_bias __retVal, sampler, pcoord;
-}
-
-
-vec4 texture3DLod(const sampler3D sampler, const vec3 coord, const float lod)
-{
- vec4 coord4;
- coord4.xyz = coord.xyz;
- coord4.w = lod;
- __asm vec4_tex_3d_bias __retVal, sampler, coord4;
-}
-
-vec4 texture3DProjLod(const sampler3D sampler, const vec4 coord, const float lod)
-{
- // do projection here (there's no vec4_tex_3d_bias_proj instruction)
- vec4 pcoord;
- pcoord.xyz = coord.xyz / coord.w;
- pcoord.w = lod;
- __asm vec4_tex_3d_bias __retVal, sampler, pcoord;
-}
-
-
-vec4 textureCubeLod(const samplerCube sampler, const vec3 coord, const float lod)
-{
- vec4 coord4;
- coord4.xyz = coord;
- coord4.w = lod;
- __asm vec4_tex_cube __retVal, sampler, coord4;
-}
-
-
-vec4 shadow1DLod(const sampler1DShadow sampler, const vec3 coord, const float lod)
-{
- vec4 coord4;
- coord4.xyz = coord;
- coord4.w = lod;
- __asm vec4_tex_1d_bias_shadow __retVal, sampler, coord4;
-}
-
-vec4 shadow1DProjLod(const sampler1DShadow sampler, const vec4 coord,
- const float lod)
-{
- vec4 pcoord;
- pcoord.x = coord.x / coord.w;
- pcoord.z = coord.z;
- pcoord.w = lod;
- __asm vec4_tex_1d_bias_shadow __retVal, sampler, pcoord;
-}
-
-
-vec4 shadow2DLod(const sampler2DShadow sampler, const vec3 coord, const float lod)
-{
- vec4 coord4;
- coord4.xyz = coord;
- coord4.w = lod;
- __asm vec4_tex_2d_bias_shadow __retVal, sampler, coord4;
-}
-
-vec4 shadow2DProjLod(const sampler2DShadow sampler, const vec4 coord,
- const float lod)
-{
- vec4 pcoord;
- pcoord.xy = coord.xy / coord.w;
- pcoord.z = coord.z;
- pcoord.w = lod;
- __asm vec4_tex_2d_bias_shadow __retVal, sampler, pcoord;
-}
-
-
-//// GL_EXT_texture_array
-
-vec4 texture1DArrayLod(const sampler1DArray sampler, const vec2 coord, const float lod)
-{
- vec4 coord4;
- coord4.xy = coord;
- coord4.w = lod;
- __asm vec4_tex_1d_array_bias __retVal, sampler, coord4;
-}
-
-
-vec4 texture2DArrayLod(const sampler2DArray sampler, const vec3 coord, const float lod)
-{
- vec4 coord4;
- coord4.xyz = coord;
- coord4.w = lod;
- __asm vec4_tex_2d_array_bias __retVal, sampler, coord4;
-}
-
+++ /dev/null
-/*
- * Mesa 3-D graphics library
- * Version: 7.3
- *
- * Copyright (C) 2005-2007 Brian Paul All Rights Reserved.
- * Copyright (C) 2008 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 slang_builtin.c
- * Resolve built-in uniform vars.
- * \author Brian Paul
- */
-
-#include "main/imports.h"
-#include "main/mtypes.h"
-#include "program/program.h"
-#include "program/prog_instruction.h"
-#include "program/prog_parameter.h"
-#include "program/prog_statevars.h"
-#include "slang/slang_builtin.h"
-#include "slang/slang_compile_struct.h"
-#include "slang/slang_ir.h"
-#include "slang/slang_typeinfo.h"
-
-
-/** special state token (see below) */
-#define STATE_ARRAY ((gl_state_index) 0xfffff)
-
-
-/**
- * Lookup GL state given a variable name, 0, 1 or 2 indexes and a field.
- * Allocate room for the state in the given param list and return position
- * in the list.
- * Yes, this is kind of ugly, but it works.
- */
-static GLint
-lookup_statevar(const char *var, GLint index1, GLint index2, const char *field,
- GLuint *swizzleOut,
- struct gl_program_parameter_list *paramList)
-{
- /*
- * NOTE: The ARB_vertex_program extension specified that matrices get
- * loaded in registers in row-major order. With GLSL, we want column-
- * major order. So, we need to transpose all matrices here...
- */
- static const struct {
- const char *name;
- gl_state_index matrix;
- gl_state_index modifier;
- } matrices[] = {
- { "gl_ModelViewMatrix", STATE_MODELVIEW_MATRIX, STATE_MATRIX_TRANSPOSE },
- { "gl_ModelViewMatrixInverse", STATE_MODELVIEW_MATRIX, STATE_MATRIX_INVTRANS },
- { "gl_ModelViewMatrixTranspose", STATE_MODELVIEW_MATRIX, 0 },
- { "gl_ModelViewMatrixInverseTranspose", STATE_MODELVIEW_MATRIX, STATE_MATRIX_INVERSE },
-
- { "gl_ProjectionMatrix", STATE_PROJECTION_MATRIX, STATE_MATRIX_TRANSPOSE },
- { "gl_ProjectionMatrixInverse", STATE_PROJECTION_MATRIX, STATE_MATRIX_INVTRANS },
- { "gl_ProjectionMatrixTranspose", STATE_PROJECTION_MATRIX, 0 },
- { "gl_ProjectionMatrixInverseTranspose", STATE_PROJECTION_MATRIX, STATE_MATRIX_INVERSE },
-
- { "gl_ModelViewProjectionMatrix", STATE_MVP_MATRIX, STATE_MATRIX_TRANSPOSE },
- { "gl_ModelViewProjectionMatrixInverse", STATE_MVP_MATRIX, STATE_MATRIX_INVTRANS },
- { "gl_ModelViewProjectionMatrixTranspose", STATE_MVP_MATRIX, 0 },
- { "gl_ModelViewProjectionMatrixInverseTranspose", STATE_MVP_MATRIX, STATE_MATRIX_INVERSE },
-
- { "gl_TextureMatrix", STATE_TEXTURE_MATRIX, STATE_MATRIX_TRANSPOSE },
- { "gl_TextureMatrixInverse", STATE_TEXTURE_MATRIX, STATE_MATRIX_INVTRANS },
- { "gl_TextureMatrixTranspose", STATE_TEXTURE_MATRIX, 0 },
- { "gl_TextureMatrixInverseTranspose", STATE_TEXTURE_MATRIX, STATE_MATRIX_INVERSE },
-
- { "gl_NormalMatrix", STATE_MODELVIEW_MATRIX, STATE_MATRIX_INVERSE },
-
- { NULL, 0, 0 }
- };
- gl_state_index tokens[STATE_LENGTH];
- GLuint i;
- GLboolean isMatrix = GL_FALSE;
-
- for (i = 0; i < STATE_LENGTH; i++) {
- tokens[i] = 0;
- }
- *swizzleOut = SWIZZLE_NOOP;
-
- /* first, look if var is a pre-defined matrix */
- for (i = 0; matrices[i].name; i++) {
- if (strcmp(var, matrices[i].name) == 0) {
- tokens[0] = matrices[i].matrix;
- /* tokens[1], [2] and [3] filled below */
- tokens[4] = matrices[i].modifier;
- isMatrix = GL_TRUE;
- break;
- }
- }
-
- if (isMatrix) {
- if (tokens[0] == STATE_TEXTURE_MATRIX) {
- /* texture_matrix[index1][index2] */
- tokens[1] = index1 >= 0 ? index1 : 0; /* which texture matrix */
- index1 = index2; /* move matrix row value to index1 */
- }
- if (index1 < 0) {
- /* index1 is unused: prevent extra addition at end of function */
- index1 = 0;
- }
- }
- else if (strcmp(var, "gl_DepthRange") == 0) {
- tokens[0] = STATE_DEPTH_RANGE;
- assert(field);
- if (strcmp(field, "near") == 0) {
- *swizzleOut = SWIZZLE_XXXX;
- }
- else if (strcmp(field, "far") == 0) {
- *swizzleOut = SWIZZLE_YYYY;
- }
- else if (strcmp(field, "diff") == 0) {
- *swizzleOut = SWIZZLE_ZZZZ;
- }
- else {
- return -1;
- }
- }
- else if (strcmp(var, "gl_ClipPlane") == 0) {
- if (index1 < 0)
- return -1;
- tokens[0] = STATE_CLIPPLANE;
- tokens[1] = index1;
- }
- else if (strcmp(var, "gl_Point") == 0) {
- assert(field);
- if (strcmp(field, "size") == 0) {
- tokens[0] = STATE_POINT_SIZE;
- *swizzleOut = SWIZZLE_XXXX;
- }
- else if (strcmp(field, "sizeMin") == 0) {
- tokens[0] = STATE_POINT_SIZE;
- *swizzleOut = SWIZZLE_YYYY;
- }
- else if (strcmp(field, "sizeMax") == 0) {
- tokens[0] = STATE_POINT_SIZE;
- *swizzleOut = SWIZZLE_ZZZZ;
- }
- else if (strcmp(field, "fadeThresholdSize") == 0) {
- tokens[0] = STATE_POINT_SIZE;
- *swizzleOut = SWIZZLE_WWWW;
- }
- else if (strcmp(field, "distanceConstantAttenuation") == 0) {
- tokens[0] = STATE_POINT_ATTENUATION;
- *swizzleOut = SWIZZLE_XXXX;
- }
- else if (strcmp(field, "distanceLinearAttenuation") == 0) {
- tokens[0] = STATE_POINT_ATTENUATION;
- *swizzleOut = SWIZZLE_YYYY;
- }
- else if (strcmp(field, "distanceQuadraticAttenuation") == 0) {
- tokens[0] = STATE_POINT_ATTENUATION;
- *swizzleOut = SWIZZLE_ZZZZ;
- }
- else {
- return -1;
- }
- }
- else if (strcmp(var, "gl_FrontMaterial") == 0 ||
- strcmp(var, "gl_BackMaterial") == 0) {
- tokens[0] = STATE_MATERIAL;
- if (strcmp(var, "gl_FrontMaterial") == 0)
- tokens[1] = 0;
- else
- tokens[1] = 1;
- assert(field);
- if (strcmp(field, "emission") == 0) {
- tokens[2] = STATE_EMISSION;
- }
- else if (strcmp(field, "ambient") == 0) {
- tokens[2] = STATE_AMBIENT;
- }
- else if (strcmp(field, "diffuse") == 0) {
- tokens[2] = STATE_DIFFUSE;
- }
- else if (strcmp(field, "specular") == 0) {
- tokens[2] = STATE_SPECULAR;
- }
- else if (strcmp(field, "shininess") == 0) {
- tokens[2] = STATE_SHININESS;
- *swizzleOut = SWIZZLE_XXXX;
- }
- else {
- return -1;
- }
- }
- else if (strcmp(var, "gl_LightSource") == 0) {
- if (!field || index1 < 0)
- return -1;
-
- tokens[0] = STATE_LIGHT;
- tokens[1] = index1;
-
- if (strcmp(field, "ambient") == 0) {
- tokens[2] = STATE_AMBIENT;
- }
- else if (strcmp(field, "diffuse") == 0) {
- tokens[2] = STATE_DIFFUSE;
- }
- else if (strcmp(field, "specular") == 0) {
- tokens[2] = STATE_SPECULAR;
- }
- else if (strcmp(field, "position") == 0) {
- tokens[2] = STATE_POSITION;
- }
- else if (strcmp(field, "halfVector") == 0) {
- tokens[2] = STATE_HALF_VECTOR;
- }
- else if (strcmp(field, "spotDirection") == 0) {
- tokens[2] = STATE_SPOT_DIRECTION;
- }
- else if (strcmp(field, "spotCosCutoff") == 0) {
- tokens[2] = STATE_SPOT_DIRECTION;
- *swizzleOut = SWIZZLE_WWWW;
- }
- else if (strcmp(field, "spotCutoff") == 0) {
- tokens[2] = STATE_SPOT_CUTOFF;
- *swizzleOut = SWIZZLE_XXXX;
- }
- else if (strcmp(field, "spotExponent") == 0) {
- tokens[2] = STATE_ATTENUATION;
- *swizzleOut = SWIZZLE_WWWW;
- }
- else if (strcmp(field, "constantAttenuation") == 0) {
- tokens[2] = STATE_ATTENUATION;
- *swizzleOut = SWIZZLE_XXXX;
- }
- else if (strcmp(field, "linearAttenuation") == 0) {
- tokens[2] = STATE_ATTENUATION;
- *swizzleOut = SWIZZLE_YYYY;
- }
- else if (strcmp(field, "quadraticAttenuation") == 0) {
- tokens[2] = STATE_ATTENUATION;
- *swizzleOut = SWIZZLE_ZZZZ;
- }
- else {
- return -1;
- }
- }
- else if (strcmp(var, "gl_LightModel") == 0) {
- if (strcmp(field, "ambient") == 0) {
- tokens[0] = STATE_LIGHTMODEL_AMBIENT;
- }
- else {
- return -1;
- }
- }
- else if (strcmp(var, "gl_FrontLightModelProduct") == 0) {
- if (strcmp(field, "sceneColor") == 0) {
- tokens[0] = STATE_LIGHTMODEL_SCENECOLOR;
- tokens[1] = 0;
- }
- else {
- return -1;
- }
- }
- else if (strcmp(var, "gl_BackLightModelProduct") == 0) {
- if (strcmp(field, "sceneColor") == 0) {
- tokens[0] = STATE_LIGHTMODEL_SCENECOLOR;
- tokens[1] = 1;
- }
- else {
- return -1;
- }
- }
- else if (strcmp(var, "gl_FrontLightProduct") == 0 ||
- strcmp(var, "gl_BackLightProduct") == 0) {
- if (index1 < 0 || !field)
- return -1;
-
- tokens[0] = STATE_LIGHTPROD;
- tokens[1] = index1; /* light number */
- if (strcmp(var, "gl_FrontLightProduct") == 0) {
- tokens[2] = 0; /* front */
- }
- else {
- tokens[2] = 1; /* back */
- }
- if (strcmp(field, "ambient") == 0) {
- tokens[3] = STATE_AMBIENT;
- }
- else if (strcmp(field, "diffuse") == 0) {
- tokens[3] = STATE_DIFFUSE;
- }
- else if (strcmp(field, "specular") == 0) {
- tokens[3] = STATE_SPECULAR;
- }
- else {
- return -1;
- }
- }
- else if (strcmp(var, "gl_TextureEnvColor") == 0) {
- if (index1 < 0)
- return -1;
- tokens[0] = STATE_TEXENV_COLOR;
- tokens[1] = index1;
- }
- else if (strcmp(var, "gl_EyePlaneS") == 0) {
- if (index1 < 0)
- return -1;
- tokens[0] = STATE_TEXGEN;
- tokens[1] = index1; /* tex unit */
- tokens[2] = STATE_TEXGEN_EYE_S;
- }
- else if (strcmp(var, "gl_EyePlaneT") == 0) {
- if (index1 < 0)
- return -1;
- tokens[0] = STATE_TEXGEN;
- tokens[1] = index1; /* tex unit */
- tokens[2] = STATE_TEXGEN_EYE_T;
- }
- else if (strcmp(var, "gl_EyePlaneR") == 0) {
- if (index1 < 0)
- return -1;
- tokens[0] = STATE_TEXGEN;
- tokens[1] = index1; /* tex unit */
- tokens[2] = STATE_TEXGEN_EYE_R;
- }
- else if (strcmp(var, "gl_EyePlaneQ") == 0) {
- if (index1 < 0)
- return -1;
- tokens[0] = STATE_TEXGEN;
- tokens[1] = index1; /* tex unit */
- tokens[2] = STATE_TEXGEN_EYE_Q;
- }
- else if (strcmp(var, "gl_ObjectPlaneS") == 0) {
- if (index1 < 0)
- return -1;
- tokens[0] = STATE_TEXGEN;
- tokens[1] = index1; /* tex unit */
- tokens[2] = STATE_TEXGEN_OBJECT_S;
- }
- else if (strcmp(var, "gl_ObjectPlaneT") == 0) {
- if (index1 < 0)
- return -1;
- tokens[0] = STATE_TEXGEN;
- tokens[1] = index1; /* tex unit */
- tokens[2] = STATE_TEXGEN_OBJECT_T;
- }
- else if (strcmp(var, "gl_ObjectPlaneR") == 0) {
- if (index1 < 0)
- return -1;
- tokens[0] = STATE_TEXGEN;
- tokens[1] = index1; /* tex unit */
- tokens[2] = STATE_TEXGEN_OBJECT_R;
- }
- else if (strcmp(var, "gl_ObjectPlaneQ") == 0) {
- if (index1 < 0)
- return -1;
- tokens[0] = STATE_TEXGEN;
- tokens[1] = index1; /* tex unit */
- tokens[2] = STATE_TEXGEN_OBJECT_Q;
- }
- else if (strcmp(var, "gl_Fog") == 0) {
- if (strcmp(field, "color") == 0) {
- tokens[0] = STATE_FOG_COLOR;
- }
- else if (strcmp(field, "density") == 0) {
- tokens[0] = STATE_FOG_PARAMS;
- *swizzleOut = SWIZZLE_XXXX;
- }
- else if (strcmp(field, "start") == 0) {
- tokens[0] = STATE_FOG_PARAMS;
- *swizzleOut = SWIZZLE_YYYY;
- }
- else if (strcmp(field, "end") == 0) {
- tokens[0] = STATE_FOG_PARAMS;
- *swizzleOut = SWIZZLE_ZZZZ;
- }
- else if (strcmp(field, "scale") == 0) {
- tokens[0] = STATE_FOG_PARAMS;
- *swizzleOut = SWIZZLE_WWWW;
- }
- else {
- return -1;
- }
- }
- else {
- return -1;
- }
-
- if (isMatrix) {
- /* load all four rows (or columns) of matrix */
- GLint pos[4];
- GLuint j;
- for (j = 0; j < 4; j++) {
- tokens[2] = tokens[3] = j; /* jth row of matrix */
- pos[j] = _mesa_add_state_reference(paramList, tokens);
- assert(pos[j] >= 0);
- ASSERT(pos[j] >= 0);
- }
- return pos[0] + index1;
- }
- else {
- /* allocate a single register */
- GLint pos = _mesa_add_state_reference(paramList, tokens);
- ASSERT(pos >= 0);
- return pos;
- }
-}
-
-
-
-/**
- * Given a variable name and datatype, emit uniform/constant buffer
- * entries which will store that state variable.
- * For example, if name="gl_LightSource" we'll emit 64 state variable
- * vectors/references and return position where that data starts. This will
- * allow run-time array indexing into the light source array.
- *
- * Note that this is a recursive function.
- *
- * \return -1 if error, else index of start of data in the program parameter list
- */
-static GLint
-emit_statevars(const char *name, int array_len,
- const slang_type_specifier *type,
- gl_state_index tokens[STATE_LENGTH],
- struct gl_program_parameter_list *paramList)
-{
- if (type->type == SLANG_SPEC_ARRAY) {
- GLint i, pos = -1;
- assert(array_len > 0);
- if (strcmp(name, "gl_ClipPlane") == 0) {
- tokens[0] = STATE_CLIPPLANE;
- }
- else if (strcmp(name, "gl_LightSource") == 0) {
- tokens[0] = STATE_LIGHT;
- }
- else if (strcmp(name, "gl_FrontLightProduct") == 0) {
- tokens[0] = STATE_LIGHTPROD;
- tokens[2] = 0; /* front */
- }
- else if (strcmp(name, "gl_BackLightProduct") == 0) {
- tokens[0] = STATE_LIGHTPROD;
- tokens[2] = 1; /* back */
- }
- else if (strcmp(name, "gl_TextureEnvColor") == 0) {
- tokens[0] = STATE_TEXENV_COLOR;
- }
- else if (strcmp(name, "gl_EyePlaneS") == 0) {
- tokens[0] = STATE_TEXGEN;
- tokens[2] = STATE_TEXGEN_EYE_S;
- }
- else if (strcmp(name, "gl_EyePlaneT") == 0) {
- tokens[0] = STATE_TEXGEN;
- tokens[2] = STATE_TEXGEN_EYE_T;
- }
- else if (strcmp(name, "gl_EyePlaneR") == 0) {
- tokens[0] = STATE_TEXGEN;
- tokens[2] = STATE_TEXGEN_EYE_R;
- }
- else if (strcmp(name, "gl_EyePlaneQ") == 0) {
- tokens[0] = STATE_TEXGEN;
- tokens[2] = STATE_TEXGEN_EYE_Q;
- }
- else if (strcmp(name, "gl_ObjectPlaneS") == 0) {
- tokens[0] = STATE_TEXGEN;
- tokens[2] = STATE_TEXGEN_OBJECT_S;
- }
- else if (strcmp(name, "gl_ObjectPlaneT") == 0) {
- tokens[0] = STATE_TEXGEN;
- tokens[2] = STATE_TEXGEN_OBJECT_T;
- }
- else if (strcmp(name, "gl_ObjectPlaneR") == 0) {
- tokens[0] = STATE_TEXGEN;
- tokens[2] = STATE_TEXGEN_OBJECT_R;
- }
- else if (strcmp(name, "gl_ObjectPlaneQ") == 0) {
- tokens[0] = STATE_TEXGEN;
- tokens[2] = STATE_TEXGEN_OBJECT_Q;
- }
- else if (strcmp(name, "gl_TextureMatrix") == 0) {
- tokens[0] = STATE_TEXTURE_MATRIX;
- tokens[4] = STATE_MATRIX_TRANSPOSE;
- }
- else if (strcmp(name, "gl_TextureMatrixInverse") == 0) {
- tokens[0] = STATE_TEXTURE_MATRIX;
- tokens[4] = STATE_MATRIX_INVTRANS;
- }
- else if (strcmp(name, "gl_TextureMatrixTranspose") == 0) {
- tokens[0] = STATE_TEXTURE_MATRIX;
- tokens[4] = 0;
- }
- else if (strcmp(name, "gl_TextureMatrixInverseTranspose") == 0) {
- tokens[0] = STATE_TEXTURE_MATRIX;
- tokens[4] = STATE_MATRIX_INVERSE;
- }
- else {
- return -1; /* invalid array name */
- }
- /* emit state vars for each array element */
- for (i = 0; i < array_len; i++) {
- GLint p;
- tokens[1] = i;
- p = emit_statevars(NULL, 0, type->_array, tokens, paramList);
- if (i == 0)
- pos = p;
- }
- return pos;
- }
- else if (type->type == SLANG_SPEC_STRUCT) {
- const slang_variable_scope *fields = type->_struct->fields;
- GLuint i, pos = 0;
- for (i = 0; i < fields->num_variables; i++) {
- const slang_variable *var = fields->variables[i];
- GLint p = emit_statevars(var->a_name, 0, &var->type.specifier,
- tokens, paramList);
- if (i == 0)
- pos = p;
- }
- return pos;
- }
- else if (type->type == SLANG_SPEC_MAT4) {
- /* unroll/emit 4 array rows (or columns) */
- slang_type_specifier vec4;
- GLint i, p, pos = -1;
- vec4.type = SLANG_SPEC_VEC4;
- for (i = 0; i < 4; i++) {
- tokens[2] = tokens[3] = i; /* row[i] (or column[i]) of matrix */
- p = emit_statevars(NULL, 0, &vec4, tokens, paramList);
- if (pos == -1)
- pos = p;
- }
- return pos;
- }
- else {
- GLint pos;
- assert(type->type == SLANG_SPEC_VEC4 ||
- type->type == SLANG_SPEC_VEC3 ||
- type->type == SLANG_SPEC_VEC2 ||
- type->type == SLANG_SPEC_FLOAT ||
- type->type == SLANG_SPEC_IVEC4 ||
- type->type == SLANG_SPEC_IVEC3 ||
- type->type == SLANG_SPEC_IVEC2 ||
- type->type == SLANG_SPEC_INT);
- if (name) {
- GLint t;
-
- if (tokens[0] == STATE_LIGHT)
- t = 2;
- else if (tokens[0] == STATE_LIGHTPROD)
- t = 3;
- else
- return -1; /* invalid array name */
-
- if (strcmp(name, "ambient") == 0) {
- tokens[t] = STATE_AMBIENT;
- }
- else if (strcmp(name, "diffuse") == 0) {
- tokens[t] = STATE_DIFFUSE;
- }
- else if (strcmp(name, "specular") == 0) {
- tokens[t] = STATE_SPECULAR;
- }
- else if (strcmp(name, "position") == 0) {
- tokens[t] = STATE_POSITION;
- }
- else if (strcmp(name, "halfVector") == 0) {
- tokens[t] = STATE_HALF_VECTOR;
- }
- else if (strcmp(name, "spotDirection") == 0) {
- tokens[t] = STATE_SPOT_DIRECTION; /* xyz components */
- }
- else if (strcmp(name, "spotCosCutoff") == 0) {
- tokens[t] = STATE_SPOT_DIRECTION; /* w component */
- }
-
- else if (strcmp(name, "constantAttenuation") == 0) {
- tokens[t] = STATE_ATTENUATION; /* x component */
- }
- else if (strcmp(name, "linearAttenuation") == 0) {
- tokens[t] = STATE_ATTENUATION; /* y component */
- }
- else if (strcmp(name, "quadraticAttenuation") == 0) {
- tokens[t] = STATE_ATTENUATION; /* z component */
- }
- else if (strcmp(name, "spotExponent") == 0) {
- tokens[t] = STATE_ATTENUATION; /* w = spot exponent */
- }
-
- else if (strcmp(name, "spotCutoff") == 0) {
- tokens[t] = STATE_SPOT_CUTOFF; /* x component */
- }
-
- else {
- return -1; /* invalid field name */
- }
- }
-
- pos = _mesa_add_state_reference(paramList, tokens);
- return pos;
- }
-
- return 1;
-}
-
-
-/**
- * Unroll the named built-in uniform variable into a sequence of state
- * vars in the given parameter list.
- */
-static GLint
-alloc_state_var_array(const slang_variable *var,
- struct gl_program_parameter_list *paramList)
-{
- gl_state_index tokens[STATE_LENGTH];
- GLuint i;
- GLint pos;
-
- /* Initialize the state tokens array. This is very important.
- * When we call _mesa_add_state_reference() it'll searches the parameter
- * list to see if the given statevar token sequence is already present.
- * This is normally a good thing since it prevents redundant values in the
- * constant buffer.
- *
- * But when we're building arrays of state this can be bad. For example,
- * consider this fragment of GLSL code:
- * foo = gl_LightSource[3].diffuse;
- * ...
- * bar = gl_LightSource[i].diffuse;
- *
- * When we unroll the gl_LightSource array (for "bar") we want to re-emit
- * gl_LightSource[3].diffuse and not re-use the first instance (from "foo")
- * since that would upset the array layout. We handle this situation by
- * setting the last token in the state var token array to the special
- * value STATE_ARRAY.
- * This token will only be set for array state. We can hijack the last
- * element in the array for this since it's never used for light, clipplane
- * or texture env array state.
- */
- for (i = 0; i < STATE_LENGTH; i++)
- tokens[i] = 0;
- tokens[STATE_LENGTH - 1] = STATE_ARRAY;
-
- pos = emit_statevars(var->a_name, var->array_len, &var->type.specifier,
- tokens, paramList);
-
- return pos;
-}
-
-
-
-/**
- * Allocate storage for a pre-defined uniform (a GL state variable).
- * As a memory-saving optimization, we try to only allocate storage for
- * state vars that are actually used.
- *
- * Arrays such as gl_LightSource are handled specially. For an expression
- * like "gl_LightSource[2].diffuse", we can allocate a single uniform/constant
- * slot and return the index. In this case, we return direct=TRUE.
- *
- * Buf for something like "gl_LightSource[i].diffuse" we don't know the value
- * of 'i' at compile time so we need to "unroll" the gl_LightSource array
- * into a consecutive sequence of uniform/constant slots so it can be indexed
- * at runtime. In this case, we return direct=FALSE.
- *
- * Currently, all pre-defined uniforms are in one of these forms:
- * var
- * var[i]
- * var.field
- * var[i].field
- * var[i][j]
- *
- * \return -1 upon error, else position in paramList of the state variable/data
- */
-GLint
-_slang_alloc_statevar(slang_ir_node *n,
- struct gl_program_parameter_list *paramList,
- GLboolean *direct)
-{
- slang_ir_node *n0 = n;
- const char *field = NULL;
- GLint index1 = -1, index2 = -1;
- GLuint swizzle;
-
- *direct = GL_TRUE;
-
- if (n->Opcode == IR_FIELD) {
- field = n->Field;
- n = n->Children[0];
- }
-
- if (n->Opcode == IR_ELEMENT) {
- if (n->Children[1]->Opcode == IR_FLOAT) {
- index1 = (GLint) n->Children[1]->Value[0];
- }
- else {
- *direct = GL_FALSE;
- }
- n = n->Children[0];
- }
-
- if (n->Opcode == IR_ELEMENT) {
- /* XXX can only handle constant indexes for now */
- if (n->Children[1]->Opcode == IR_FLOAT) {
- /* two-dimensional array index: mat[i][j] */
- index2 = index1;
- index1 = (GLint) n->Children[1]->Value[0];
- }
- else {
- *direct = GL_FALSE;
- }
- n = n->Children[0];
- }
-
- assert(n->Opcode == IR_VAR);
-
- if (*direct) {
- const char *var = (const char *) n->Var->a_name;
- GLint pos =
- lookup_statevar(var, index1, index2, field, &swizzle, paramList);
- if (pos >= 0) {
- /* newly resolved storage for the statevar/constant/uniform */
- n0->Store->File = PROGRAM_STATE_VAR;
- n0->Store->Index = pos;
- n0->Store->Swizzle = swizzle;
- n0->Store->Parent = NULL;
- return pos;
- }
- }
-
- *direct = GL_FALSE;
- return alloc_state_var_array(n->Var, paramList);
-}
-
-
-
-
-#define SWIZZLE_ZWWW MAKE_SWIZZLE4(SWIZZLE_Z, SWIZZLE_W, SWIZZLE_W, SWIZZLE_W)
-
-
-/** Predefined shader inputs */
-struct input_info
-{
- const char *Name;
- GLuint Attrib;
- GLenum Type;
- GLuint Swizzle;
- GLboolean Array;
-};
-
-/** Predefined vertex shader inputs/attributes */
-static const struct input_info vertInputs[] = {
- { "gl_Vertex", VERT_ATTRIB_POS, GL_FLOAT_VEC4, SWIZZLE_NOOP, GL_FALSE },
- { "gl_Normal", VERT_ATTRIB_NORMAL, GL_FLOAT_VEC3, SWIZZLE_NOOP, GL_FALSE },
- { "gl_Color", VERT_ATTRIB_COLOR0, GL_FLOAT_VEC4, SWIZZLE_NOOP, GL_FALSE },
- { "gl_SecondaryColor", VERT_ATTRIB_COLOR1, GL_FLOAT_VEC4, SWIZZLE_NOOP, GL_FALSE },
- { "gl_FogCoord", VERT_ATTRIB_FOG, GL_FLOAT, SWIZZLE_XXXX, GL_FALSE },
- { "gl_MultiTexCoord0", VERT_ATTRIB_TEX0, GL_FLOAT_VEC4, SWIZZLE_NOOP, GL_FALSE },
- { "gl_MultiTexCoord1", VERT_ATTRIB_TEX1, GL_FLOAT_VEC4, SWIZZLE_NOOP, GL_FALSE },
- { "gl_MultiTexCoord2", VERT_ATTRIB_TEX2, GL_FLOAT_VEC4, SWIZZLE_NOOP, GL_FALSE },
- { "gl_MultiTexCoord3", VERT_ATTRIB_TEX3, GL_FLOAT_VEC4, SWIZZLE_NOOP, GL_FALSE },
- { "gl_MultiTexCoord4", VERT_ATTRIB_TEX4, GL_FLOAT_VEC4, SWIZZLE_NOOP, GL_FALSE },
- { "gl_MultiTexCoord5", VERT_ATTRIB_TEX5, GL_FLOAT_VEC4, SWIZZLE_NOOP, GL_FALSE },
- { "gl_MultiTexCoord6", VERT_ATTRIB_TEX6, GL_FLOAT_VEC4, SWIZZLE_NOOP, GL_FALSE },
- { "gl_MultiTexCoord7", VERT_ATTRIB_TEX7, GL_FLOAT_VEC4, SWIZZLE_NOOP, GL_FALSE }
-};
-
-static const struct input_info geomInputs[] = {
- { "gl_PrimitiveIDIn", GEOM_ATTRIB_PRIMITIVE_ID, GL_FLOAT, SWIZZLE_NOOP, GL_FALSE },
- { "gl_FrontColorIn", GEOM_ATTRIB_COLOR0, GL_FLOAT_VEC4, SWIZZLE_NOOP, GL_TRUE },
- { "gl_BackColorIn", GEOM_ATTRIB_COLOR1, GL_FLOAT_VEC4, SWIZZLE_NOOP, GL_TRUE },
- { "gl_FrontSecondaryColorIn", GEOM_ATTRIB_SECONDARY_COLOR0, GL_FLOAT_VEC4, SWIZZLE_NOOP, GL_TRUE },
- { "gl_BackSecondaryColorIn", GEOM_ATTRIB_SECONDARY_COLOR1, GL_FLOAT_VEC4, SWIZZLE_NOOP, GL_TRUE },
- { "gl_TexCoordIn", GEOM_ATTRIB_TEX_COORD, GL_FLOAT_VEC4, SWIZZLE_NOOP, GL_TRUE },
- { "gl_FogFragCoordIn", GEOM_ATTRIB_FOG_FRAG_COORD, GL_FLOAT, SWIZZLE_NOOP, GL_TRUE },
- { "gl_PositionIn", GEOM_ATTRIB_POSITION, GL_FLOAT_VEC4, SWIZZLE_NOOP, GL_TRUE },
- { "gl_ClipVertexIn", GEOM_ATTRIB_CLIP_VERTEX, GL_FLOAT_VEC4, SWIZZLE_NOOP, GL_TRUE },
- { "gl_PointSizeIn", GEOM_ATTRIB_POINT_SIZE, GL_FLOAT, SWIZZLE_NOOP, GL_TRUE }
-};
-
-/** Predefined fragment shader inputs */
-static const struct input_info fragInputs[] = {
- { "gl_FragCoord", FRAG_ATTRIB_WPOS, GL_FLOAT_VEC4, SWIZZLE_NOOP, GL_FALSE },
- { "gl_Color", FRAG_ATTRIB_COL0, GL_FLOAT_VEC4, SWIZZLE_NOOP, GL_FALSE },
- { "gl_SecondaryColor", FRAG_ATTRIB_COL1, GL_FLOAT_VEC4, SWIZZLE_NOOP, GL_FALSE },
- { "gl_TexCoord", FRAG_ATTRIB_TEX0, GL_FLOAT_VEC4, SWIZZLE_NOOP, GL_FALSE },
- { "gl_FogFragCoord", FRAG_ATTRIB_FOGC, GL_FLOAT, SWIZZLE_XXXX, GL_FALSE },
- { "gl_FrontFacing", FRAG_ATTRIB_FACE, GL_FLOAT, SWIZZLE_XXXX, GL_FALSE },
- { "gl_PointCoord", FRAG_ATTRIB_PNTC, GL_FLOAT_VEC2, SWIZZLE_XYZW, GL_FALSE }
-};
-
-
-/**
- * Return the VERT_ATTRIB_* or FRAG_ATTRIB_* value that corresponds to
- * a vertex or fragment program input variable. Return -1 if the input
- * name is invalid.
- * XXX return size too
- */
-GLint
-_slang_input_index(const char *name, GLenum target, GLuint *swizzleOut,
- GLboolean *is_array)
-{
- const struct input_info *inputs;
- GLuint i, n;
-
- switch (target) {
- case GL_VERTEX_PROGRAM_ARB:
- inputs = vertInputs;
- n = Elements(vertInputs);
- break;
- case GL_FRAGMENT_PROGRAM_ARB:
- inputs = fragInputs;
- n = Elements(fragInputs);
- break;
- case MESA_GEOMETRY_PROGRAM:
- inputs = geomInputs;
- n = Elements(geomInputs);
- break;
- default:
- _mesa_problem(NULL, "bad target in _slang_input_index");
- return -1;
- }
-
- ASSERT(MAX_TEXTURE_COORD_UNITS == 8); /* if this fails, fix vertInputs above */
-
- for (i = 0; i < n; i++) {
- if (strcmp(inputs[i].Name, name) == 0) {
- /* found */
- *swizzleOut = inputs[i].Swizzle;
- if (is_array)
- *is_array = inputs[i].Array;
- return inputs[i].Attrib;
- }
- }
- return -1;
-}
-
-
-/**
- * Return name of the given vertex attribute (VERT_ATTRIB_x).
- */
-const char *
-_slang_vert_attrib_name(GLuint attrib)
-{
- GLuint i;
- assert(attrib < VERT_ATTRIB_GENERIC0);
- for (i = 0; Elements(vertInputs); i++) {
- if (vertInputs[i].Attrib == attrib)
- return vertInputs[i].Name;
- }
- return NULL;
-}
-
-
-/**
- * Return type (GL_FLOAT, GL_FLOAT_VEC2, etc) of the given vertex
- * attribute (VERT_ATTRIB_x).
- */
-GLenum
-_slang_vert_attrib_type(GLuint attrib)
-{
- GLuint i;
- assert(attrib < VERT_ATTRIB_GENERIC0);
- for (i = 0; Elements(vertInputs); i++) {
- if (vertInputs[i].Attrib == attrib)
- return vertInputs[i].Type;
- }
- return GL_NONE;
-}
-
-
-
-
-
-/** Predefined shader output info */
-struct output_info
-{
- const char *Name;
- GLuint Attrib;
- GLenum Type;
-};
-
-/** Predefined vertex shader outputs */
-static const struct output_info vertOutputs[] = {
- { "gl_Position", VERT_RESULT_HPOS, GL_FLOAT_VEC4 },
- { "gl_FrontColor", VERT_RESULT_COL0, GL_FLOAT_VEC4 },
- { "gl_BackColor", VERT_RESULT_BFC0, GL_FLOAT_VEC4 },
- { "gl_FrontSecondaryColor", VERT_RESULT_COL1, GL_FLOAT_VEC4 },
- { "gl_BackSecondaryColor", VERT_RESULT_BFC1, GL_FLOAT_VEC4 },
- { "gl_TexCoord", VERT_RESULT_TEX0, GL_FLOAT_VEC4 },
- { "gl_FogFragCoord", VERT_RESULT_FOGC, GL_FLOAT },
- { "gl_PointSize", VERT_RESULT_PSIZ, GL_FLOAT }
-};
-
-/** Predefined geometry shader outputs */
-static const struct output_info geomOutputs[] = {
- { "gl_Position", GEOM_RESULT_POS, GL_FLOAT_VEC4 },
- { "gl_FrontColor", GEOM_RESULT_COL0, GL_FLOAT_VEC4 },
- { "gl_BackColor", GEOM_RESULT_COL1, GL_FLOAT_VEC4 },
- { "gl_FrontSecondaryColor", GEOM_RESULT_SCOL0, GL_FLOAT_VEC4 },
- { "gl_BackSecondaryColor", GEOM_RESULT_SCOL1, GL_FLOAT_VEC4 },
- { "gl_TexCoord", GEOM_RESULT_TEX0, GL_FLOAT_VEC4 },
- { "gl_FogFragCoord", GEOM_RESULT_FOGC, GL_FLOAT },
- { "gl_ClipVertex", GEOM_RESULT_CLPV, GL_FLOAT_VEC4 },
- { "gl_PointSize", GEOM_RESULT_PSIZ, GL_FLOAT },
- { "gl_PrimitiveID", GEOM_RESULT_PRID, GL_FLOAT },
- { "gl_Layer", GEOM_RESULT_LAYR, GL_FLOAT }
-};
-
-/** Predefined fragment shader outputs */
-static const struct output_info fragOutputs[] = {
- { "gl_FragColor", FRAG_RESULT_COLOR, GL_FLOAT_VEC4 },
- { "gl_FragDepth", FRAG_RESULT_DEPTH, GL_FLOAT },
- { "gl_FragData", FRAG_RESULT_DATA0, GL_FLOAT_VEC4 }
-};
-
-
-/**
- * Return the VERT_RESULT_*, GEOM_RESULT_* or FRAG_RESULT_* value that corresponds
- * to a vertex or fragment program output variable. Return -1 for an invalid
- * output name.
- */
-GLint
-_slang_output_index(const char *name, GLenum target)
-{
- const struct output_info *outputs;
- GLuint i, n;
-
- switch (target) {
- case GL_VERTEX_PROGRAM_ARB:
- outputs = vertOutputs;
- n = Elements(vertOutputs);
- break;
- case GL_FRAGMENT_PROGRAM_ARB:
- outputs = fragOutputs;
- n = Elements(fragOutputs);
- break;
- case MESA_GEOMETRY_PROGRAM:
- outputs = geomOutputs;
- n = Elements(geomOutputs);
- break;
- default:
- _mesa_problem(NULL, "bad target in _slang_output_index");
- return -1;
- }
-
- for (i = 0; i < n; i++) {
- if (strcmp(outputs[i].Name, name) == 0) {
- /* found */
- return outputs[i].Attrib;
- }
- }
- return -1;
-}
-
-
-/**
- * Given a VERT_RESULT_x index, return the corresponding string name.
- */
-const char *
-_slang_vertex_output_name(gl_vert_result index)
-{
- if (index < Elements(vertOutputs))
- return vertOutputs[index].Name;
- else
- return NULL;
-}
-
-
-/**
- * Given a GEOM_RESULT_x index, return the corresponding string name.
- */
-const char *
-_slang_geometry_output_name(gl_geom_result index)
-{
- if (index < Elements(geomOutputs))
- return geomOutputs[index].Name;
- else
- return NULL;
-}
-
-
-/**
- * Given a FRAG_RESULT_x index, return the corresponding string name.
- */
-const char *
-_slang_fragment_output_name(gl_frag_result index)
-{
- if (index < Elements(fragOutputs))
- return fragOutputs[index].Name;
- else
- return NULL;
-}
-
-
-/**
- * Given a VERT_RESULT_x index, return the corresponding varying
- * var's datatype.
- */
-GLenum
-_slang_vertex_output_type(gl_vert_result index)
-{
- if (index < Elements(vertOutputs))
- return vertOutputs[index].Type;
- else
- return GL_NONE;
-}
+++ /dev/null
-/*
- * Mesa 3-D graphics library
- * Version: 6.5.3
- *
- * Copyright (C) 2005-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 SLANG_BUILTIN_H
-#define SLANG_BUILTIN_H
-
-#include "main/glheader.h"
-#include "main/mtypes.h"
-#include "slang_ir.h"
-
-
-extern GLint
-_slang_alloc_statevar(slang_ir_node *n,
- struct gl_program_parameter_list *paramList,
- GLboolean *direct);
-
-
-extern GLint
-_slang_input_index(const char *name, GLenum target, GLuint *swizzleOut,
- GLboolean *is_array);
-
-extern GLint
-_slang_output_index(const char *name, GLenum target);
-
-
-extern const char *
-_slang_vert_attrib_name(GLuint attrib);
-
-extern GLenum
-_slang_vert_attrib_type(GLuint attrib);
-
-
-const char *
-_slang_vertex_output_name(gl_vert_result index);
-
-const char *
-_slang_fragment_output_name(gl_frag_result index);
-
-const char *
-_slang_geometry_output_name(gl_geom_result index);
-
-GLenum
-_slang_vertex_output_type(gl_vert_result index);
-
-
-#endif /* SLANG_BUILTIN_H */
+++ /dev/null
-/*
- * Mesa 3-D graphics library
- *
- * Copyright (C) 2005-2007 Brian Paul All Rights Reserved.
- * Copyright (C) 2008 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 slang_codegen.c
- * Generate IR tree from AST.
- * \author Brian Paul
- */
-
-
-/***
- *** NOTES:
- *** The new_() functions return a new instance of a simple IR node.
- *** The gen_() functions generate larger IR trees from the simple nodes.
- ***/
-
-
-
-#include "main/imports.h"
-#include "main/macros.h"
-#include "main/mtypes.h"
-#include "program/program.h"
-#include "program/prog_instruction.h"
-#include "program/prog_parameter.h"
-#include "program/prog_print.h"
-#include "program/prog_statevars.h"
-#include "slang_typeinfo.h"
-#include "slang_builtin.h"
-#include "slang_codegen.h"
-#include "slang_compile.h"
-#include "slang_label.h"
-#include "slang_mem.h"
-#include "slang_simplify.h"
-#include "slang_emit.h"
-#include "slang_vartable.h"
-#include "slang_ir.h"
-#include "slang_print.h"
-
-
-/** Max iterations to unroll */
-const GLuint MAX_FOR_LOOP_UNROLL_ITERATIONS = 32;
-
-/** Max for-loop body size (in slang operations) to unroll */
-const GLuint MAX_FOR_LOOP_UNROLL_BODY_SIZE = 50;
-
-/** Max for-loop body complexity to unroll.
- * We'll compute complexity as the product of the number of iterations
- * and the size of the body. So long-ish loops with very simple bodies
- * can be unrolled, as well as short loops with larger bodies.
- */
-const GLuint MAX_FOR_LOOP_UNROLL_COMPLEXITY = 256;
-
-
-
-static slang_ir_node *
-_slang_gen_operation(slang_assemble_ctx * A, slang_operation *oper);
-
-static void
-slang_substitute(slang_assemble_ctx *A, slang_operation *oper,
- GLuint substCount, slang_variable **substOld,
- slang_operation **substNew, GLboolean isLHS);
-
-
-/**
- * Retrieves type information about an operation.
- * Returns GL_TRUE on success.
- * Returns GL_FALSE otherwise.
- */
-static GLboolean
-typeof_operation(const struct slang_assemble_ctx_ *A,
- slang_operation *op,
- slang_typeinfo *ti)
-{
- return _slang_typeof_operation(op, &A->space, ti, A->atoms, A->log);
-}
-
-
-static GLboolean
-is_sampler_type(const slang_fully_specified_type *t)
-{
- switch (t->specifier.type) {
- case SLANG_SPEC_SAMPLER_1D:
- case SLANG_SPEC_SAMPLER_2D:
- case SLANG_SPEC_SAMPLER_3D:
- case SLANG_SPEC_SAMPLER_CUBE:
- case SLANG_SPEC_SAMPLER_1D_SHADOW:
- case SLANG_SPEC_SAMPLER_2D_SHADOW:
- case SLANG_SPEC_SAMPLER_RECT:
- case SLANG_SPEC_SAMPLER_RECT_SHADOW:
- case SLANG_SPEC_SAMPLER_1D_ARRAY:
- case SLANG_SPEC_SAMPLER_2D_ARRAY:
- case SLANG_SPEC_SAMPLER_1D_ARRAY_SHADOW:
- case SLANG_SPEC_SAMPLER_2D_ARRAY_SHADOW:
- return GL_TRUE;
- default:
- return GL_FALSE;
- }
-}
-
-
-/**
- * Return the offset (in floats or ints) of the named field within
- * the given struct. Return -1 if field not found.
- * If field is NULL, return the size of the struct instead.
- */
-static GLint
-_slang_field_offset(const slang_type_specifier *spec, slang_atom field)
-{
- GLint offset = 0;
- GLuint i;
- for (i = 0; i < spec->_struct->fields->num_variables; i++) {
- const slang_variable *v = spec->_struct->fields->variables[i];
- const GLuint sz = _slang_sizeof_type_specifier(&v->type.specifier);
- if (sz > 1) {
- /* types larger than 1 float are register (4-float) aligned */
- offset = (offset + 3) & ~3;
- }
- if (field && v->a_name == field) {
- return offset;
- }
- offset += sz;
- }
- if (field)
- return -1; /* field not found */
- else
- return offset; /* struct size */
-}
-
-
-/**
- * Return the size (in floats) of the given type specifier.
- * If the size is greater than 4, the size should be a multiple of 4
- * so that the correct number of 4-float registers are allocated.
- * For example, a mat3x2 is size 12 because we want to store the
- * 3 columns in 3 float[4] registers.
- */
-GLuint
-_slang_sizeof_type_specifier(const slang_type_specifier *spec)
-{
- GLuint sz;
- switch (spec->type) {
- case SLANG_SPEC_VOID:
- sz = 0;
- break;
- case SLANG_SPEC_BOOL:
- sz = 1;
- break;
- case SLANG_SPEC_BVEC2:
- sz = 2;
- break;
- case SLANG_SPEC_BVEC3:
- sz = 3;
- break;
- case SLANG_SPEC_BVEC4:
- sz = 4;
- break;
- case SLANG_SPEC_INT:
- sz = 1;
- break;
- case SLANG_SPEC_IVEC2:
- sz = 2;
- break;
- case SLANG_SPEC_IVEC3:
- sz = 3;
- break;
- case SLANG_SPEC_IVEC4:
- sz = 4;
- break;
- case SLANG_SPEC_FLOAT:
- sz = 1;
- break;
- case SLANG_SPEC_VEC2:
- sz = 2;
- break;
- case SLANG_SPEC_VEC3:
- sz = 3;
- break;
- case SLANG_SPEC_VEC4:
- sz = 4;
- break;
- case SLANG_SPEC_MAT2:
- sz = 2 * 4; /* 2 columns (regs) */
- break;
- case SLANG_SPEC_MAT3:
- sz = 3 * 4;
- break;
- case SLANG_SPEC_MAT4:
- sz = 4 * 4;
- break;
- case SLANG_SPEC_MAT23:
- sz = 2 * 4; /* 2 columns (regs) */
- break;
- case SLANG_SPEC_MAT32:
- sz = 3 * 4; /* 3 columns (regs) */
- break;
- case SLANG_SPEC_MAT24:
- sz = 2 * 4;
- break;
- case SLANG_SPEC_MAT42:
- sz = 4 * 4; /* 4 columns (regs) */
- break;
- case SLANG_SPEC_MAT34:
- sz = 3 * 4;
- break;
- case SLANG_SPEC_MAT43:
- sz = 4 * 4; /* 4 columns (regs) */
- break;
- case SLANG_SPEC_SAMPLER_1D:
- case SLANG_SPEC_SAMPLER_2D:
- case SLANG_SPEC_SAMPLER_3D:
- case SLANG_SPEC_SAMPLER_CUBE:
- case SLANG_SPEC_SAMPLER_1D_SHADOW:
- case SLANG_SPEC_SAMPLER_2D_SHADOW:
- case SLANG_SPEC_SAMPLER_RECT:
- case SLANG_SPEC_SAMPLER_RECT_SHADOW:
- case SLANG_SPEC_SAMPLER_1D_ARRAY:
- case SLANG_SPEC_SAMPLER_2D_ARRAY:
- case SLANG_SPEC_SAMPLER_1D_ARRAY_SHADOW:
- case SLANG_SPEC_SAMPLER_2D_ARRAY_SHADOW:
- sz = 1; /* a sampler is basically just an integer index */
- break;
- case SLANG_SPEC_STRUCT:
- sz = _slang_field_offset(spec, 0); /* special use */
- if (sz == 1) {
- /* 1-float structs are actually troublesome to deal with since they
- * might get placed at R.x, R.y, R.z or R.z. Return size=2 to
- * ensure the object is placed at R.x
- */
- sz = 2;
- }
- else if (sz > 4) {
- sz = (sz + 3) & ~0x3; /* round up to multiple of four */
- }
- break;
- case SLANG_SPEC_ARRAY:
- sz = _slang_sizeof_type_specifier(spec->_array);
- break;
- default:
- _mesa_problem(NULL, "Unexpected type in _slang_sizeof_type_specifier()");
- sz = 0;
- }
-
- if (sz > 4) {
- /* if size is > 4, it should be a multiple of four */
- assert((sz & 0x3) == 0);
- }
- return sz;
-}
-
-
-/**
- * Query variable/array length (number of elements).
- * This is slightly non-trivial because there are two ways to express
- * arrays: "float x[3]" vs. "float[3] x".
- * \return the length of the array for the given variable, or 0 if not an array
- */
-static GLint
-_slang_array_length(const slang_variable *var)
-{
- if (var->type.array_len > 0) {
- /* Ex: float[4] x; */
- return var->type.array_len;
- }
- if (var->array_len > 0) {
- /* Ex: float x[4]; */
- return var->array_len;
- }
- return 0;
-}
-
-
-/**
- * Compute total size of array give size of element, number of elements.
- * \return size in floats
- */
-static GLint
-_slang_array_size(GLint elemSize, GLint arrayLen)
-{
- GLint total;
- assert(elemSize > 0);
- if (arrayLen > 1) {
- /* round up base type to multiple of 4 */
- total = ((elemSize + 3) & ~0x3) * MAX2(arrayLen, 1);
- }
- else {
- total = elemSize;
- }
- return total;
-}
-
-
-/**
- * Return the TEXTURE_*_INDEX value that corresponds to a sampler type,
- * or -1 if the type is not a sampler.
- */
-static GLint
-sampler_to_texture_index(const slang_type_specifier_type type)
-{
- switch (type) {
- case SLANG_SPEC_SAMPLER_1D:
- return TEXTURE_1D_INDEX;
- case SLANG_SPEC_SAMPLER_2D:
- return TEXTURE_2D_INDEX;
- case SLANG_SPEC_SAMPLER_3D:
- return TEXTURE_3D_INDEX;
- case SLANG_SPEC_SAMPLER_CUBE:
- return TEXTURE_CUBE_INDEX;
- case SLANG_SPEC_SAMPLER_1D_SHADOW:
- return TEXTURE_1D_INDEX; /* XXX fix */
- case SLANG_SPEC_SAMPLER_2D_SHADOW:
- return TEXTURE_2D_INDEX; /* XXX fix */
- case SLANG_SPEC_SAMPLER_RECT:
- return TEXTURE_RECT_INDEX;
- case SLANG_SPEC_SAMPLER_RECT_SHADOW:
- return TEXTURE_RECT_INDEX; /* XXX fix */
- case SLANG_SPEC_SAMPLER_1D_ARRAY:
- return TEXTURE_1D_ARRAY_INDEX;
- case SLANG_SPEC_SAMPLER_2D_ARRAY:
- return TEXTURE_2D_ARRAY_INDEX;
- case SLANG_SPEC_SAMPLER_1D_ARRAY_SHADOW:
- return TEXTURE_1D_ARRAY_INDEX;
- case SLANG_SPEC_SAMPLER_2D_ARRAY_SHADOW:
- return TEXTURE_2D_ARRAY_INDEX;
- default:
- return -1;
- }
-}
-
-
-/** helper to build a SLANG_OPER_IDENTIFIER node */
-static void
-slang_operation_identifier(slang_operation *oper,
- slang_assemble_ctx *A,
- const char *name)
-{
- oper->type = SLANG_OPER_IDENTIFIER;
- oper->a_id = slang_atom_pool_atom(A->atoms, name);
-}
-
-
-/**
- * Called when we begin code/IR generation for a new while/do/for loop.
- */
-static void
-push_loop(slang_assemble_ctx *A, slang_operation *loopOper, slang_ir_node *loopIR)
-{
- A->LoopOperStack[A->LoopDepth] = loopOper;
- A->LoopIRStack[A->LoopDepth] = loopIR;
- A->LoopDepth++;
-}
-
-
-/**
- * Called when we end code/IR generation for a new while/do/for loop.
- */
-static void
-pop_loop(slang_assemble_ctx *A)
-{
- assert(A->LoopDepth > 0);
- A->LoopDepth--;
-}
-
-
-/**
- * Return pointer to slang_operation for the loop we're currently inside,
- * or NULL if not in a loop.
- */
-static const slang_operation *
-current_loop_oper(const slang_assemble_ctx *A)
-{
- if (A->LoopDepth > 0)
- return A->LoopOperStack[A->LoopDepth - 1];
- else
- return NULL;
-}
-
-
-/**
- * Return pointer to slang_ir_node for the loop we're currently inside,
- * or NULL if not in a loop.
- */
-static slang_ir_node *
-current_loop_ir(const slang_assemble_ctx *A)
-{
- if (A->LoopDepth > 0)
- return A->LoopIRStack[A->LoopDepth - 1];
- else
- return NULL;
-}
-
-
-/**********************************************************************/
-
-
-/**
- * Map "_asm foo" to IR_FOO, etc.
- */
-typedef struct
-{
- const char *Name;
- slang_ir_opcode Opcode;
- GLuint HaveRetValue, NumParams;
-} slang_asm_info;
-
-
-static slang_asm_info AsmInfo[] = {
- /* vec4 binary op */
- { "vec4_add", IR_ADD, 1, 2 },
- { "vec4_subtract", IR_SUB, 1, 2 },
- { "vec4_multiply", IR_MUL, 1, 2 },
- { "vec4_dot", IR_DOT4, 1, 2 },
- { "vec3_dot", IR_DOT3, 1, 2 },
- { "vec2_dot", IR_DOT2, 1, 2 },
- { "vec3_nrm", IR_NRM3, 1, 1 },
- { "vec4_nrm", IR_NRM4, 1, 1 },
- { "vec3_cross", IR_CROSS, 1, 2 },
- { "vec4_lrp", IR_LRP, 1, 3 },
- { "vec4_min", IR_MIN, 1, 2 },
- { "vec4_max", IR_MAX, 1, 2 },
- { "vec4_cmp", IR_CMP, 1, 3 },
- { "vec4_clamp", IR_CLAMP, 1, 3 },
- { "vec4_seq", IR_SEQUAL, 1, 2 },
- { "vec4_sne", IR_SNEQUAL, 1, 2 },
- { "vec4_sge", IR_SGE, 1, 2 },
- { "vec4_sgt", IR_SGT, 1, 2 },
- { "vec4_sle", IR_SLE, 1, 2 },
- { "vec4_slt", IR_SLT, 1, 2 },
- /* vec4 unary */
- { "vec4_move", IR_MOVE, 1, 1 },
- { "vec4_floor", IR_FLOOR, 1, 1 },
- { "vec4_frac", IR_FRAC, 1, 1 },
- { "vec4_abs", IR_ABS, 1, 1 },
- { "vec4_negate", IR_NEG, 1, 1 },
- { "vec4_ddx", IR_DDX, 1, 1 },
- { "vec4_ddy", IR_DDY, 1, 1 },
- /* float binary op */
- { "float_power", IR_POW, 1, 2 },
- /* texture / sampler */
- { "vec4_tex_1d", IR_TEX, 1, 2 },
- { "vec4_tex_1d_bias", IR_TEXB, 1, 2 }, /* 1d w/ bias */
- { "vec4_tex_1d_proj", IR_TEXP, 1, 2 }, /* 1d w/ projection */
- { "vec4_tex_2d", IR_TEX, 1, 2 },
- { "vec4_tex_2d_bias", IR_TEXB, 1, 2 }, /* 2d w/ bias */
- { "vec4_tex_2d_proj", IR_TEXP, 1, 2 }, /* 2d w/ projection */
- { "vec4_tex_3d", IR_TEX, 1, 2 },
- { "vec4_tex_3d_bias", IR_TEXB, 1, 2 }, /* 3d w/ bias */
- { "vec4_tex_3d_proj", IR_TEXP, 1, 2 }, /* 3d w/ projection */
- { "vec4_tex_cube", IR_TEX, 1, 2 }, /* cubemap */
- { "vec4_tex_rect", IR_TEX, 1, 2 }, /* rectangle */
- { "vec4_tex_rect_bias", IR_TEX, 1, 2 }, /* rectangle w/ projection */
- { "vec4_tex_1d_array", IR_TEX, 1, 2 },
- { "vec4_tex_1d_array_bias", IR_TEXB, 1, 2 },
- { "vec4_tex_1d_array_shadow", IR_TEX, 1, 2 },
- { "vec4_tex_1d_array_bias_shadow", IR_TEXB, 1, 2 },
- { "vec4_tex_2d_array", IR_TEX, 1, 2 },
- { "vec4_tex_2d_array_bias", IR_TEXB, 1, 2 },
- { "vec4_tex_2d_array_shadow", IR_TEX, 1, 2 },
- { "vec4_tex_2d_array_bias_shadow", IR_TEXB, 1, 2 },
-
- /* texture / sampler but with shadow comparison */
- { "vec4_tex_1d_shadow", IR_TEX_SH, 1, 2 },
- { "vec4_tex_1d_bias_shadow", IR_TEXB_SH, 1, 2 },
- { "vec4_tex_1d_proj_shadow", IR_TEXP_SH, 1, 2 },
- { "vec4_tex_2d_shadow", IR_TEX_SH, 1, 2 },
- { "vec4_tex_2d_bias_shadow", IR_TEXB_SH, 1, 2 },
- { "vec4_tex_2d_proj_shadow", IR_TEXP_SH, 1, 2 },
- { "vec4_tex_rect_shadow", IR_TEX_SH, 1, 2 },
- { "vec4_tex_rect_proj_shadow", IR_TEXP_SH, 1, 2 },
-
- /* unary op */
- { "ivec4_to_vec4", IR_I_TO_F, 1, 1 }, /* int[4] to float[4] */
- { "vec4_to_ivec4", IR_F_TO_I, 1, 1 }, /* float[4] to int[4] */
- { "float_exp", IR_EXP, 1, 1 },
- { "float_exp2", IR_EXP2, 1, 1 },
- { "float_log2", IR_LOG2, 1, 1 },
- { "float_rsq", IR_RSQ, 1, 1 },
- { "float_rcp", IR_RCP, 1, 1 },
- { "float_sine", IR_SIN, 1, 1 },
- { "float_cosine", IR_COS, 1, 1 },
- { "float_noise1", IR_NOISE1, 1, 1},
- { "float_noise2", IR_NOISE2, 1, 1},
- { "float_noise3", IR_NOISE3, 1, 1},
- { "float_noise4", IR_NOISE4, 1, 1},
-
- { "emit_vertex", IR_EMIT_VERTEX, 0, 0},
- { "end_primitive", IR_END_PRIMITIVE, 0, 0},
-
- { NULL, IR_NOP, 0, 0 }
-};
-
-
-static slang_ir_node *
-new_node3(slang_ir_opcode op,
- slang_ir_node *c0, slang_ir_node *c1, slang_ir_node *c2)
-{
- slang_ir_node *n = (slang_ir_node *) _slang_alloc(sizeof(slang_ir_node));
- if (n) {
- n->Opcode = op;
- n->Children[0] = c0;
- n->Children[1] = c1;
- n->Children[2] = c2;
- n->InstLocation = -1;
- }
- return n;
-}
-
-static slang_ir_node *
-new_node2(slang_ir_opcode op, slang_ir_node *c0, slang_ir_node *c1)
-{
- return new_node3(op, c0, c1, NULL);
-}
-
-static slang_ir_node *
-new_node1(slang_ir_opcode op, slang_ir_node *c0)
-{
- return new_node3(op, c0, NULL, NULL);
-}
-
-static slang_ir_node *
-new_node0(slang_ir_opcode op)
-{
- return new_node3(op, NULL, NULL, NULL);
-}
-
-
-/**
- * Create sequence of two nodes.
- */
-static slang_ir_node *
-new_seq(slang_ir_node *left, slang_ir_node *right)
-{
- if (!left)
- return right;
- if (!right)
- return left;
- return new_node2(IR_SEQ, left, right);
-}
-
-static slang_ir_node *
-new_label(slang_label *label)
-{
- slang_ir_node *n = new_node0(IR_LABEL);
- assert(label);
- if (n)
- n->Label = label;
- return n;
-}
-
-static slang_ir_node *
-new_float_literal(const float v[4], GLuint size)
-{
- slang_ir_node *n = new_node0(IR_FLOAT);
- assert(size <= 4);
- COPY_4V(n->Value, v);
- /* allocate a storage object, but compute actual location (Index) later */
- n->Store = _slang_new_ir_storage(PROGRAM_CONSTANT, -1, size);
- return n;
-}
-
-
-static slang_ir_node *
-new_not(slang_ir_node *n)
-{
- return new_node1(IR_NOT, n);
-}
-
-
-/**
- * Non-inlined function call.
- */
-static slang_ir_node *
-new_function_call(slang_ir_node *code, slang_label *name)
-{
- slang_ir_node *n = new_node1(IR_CALL, code);
- assert(name);
- if (n)
- n->Label = name;
- return n;
-}
-
-
-/**
- * Unconditional jump.
- */
-static slang_ir_node *
-new_return(slang_label *dest)
-{
- slang_ir_node *n = new_node0(IR_RETURN);
- assert(dest);
- if (n)
- n->Label = dest;
- return n;
-}
-
-
-static slang_ir_node *
-new_loop(slang_ir_node *body)
-{
- return new_node1(IR_LOOP, body);
-}
-
-
-static slang_ir_node *
-new_break(slang_ir_node *loopNode)
-{
- slang_ir_node *n = new_node0(IR_BREAK);
- assert(loopNode);
- assert(loopNode->Opcode == IR_LOOP);
- if (n) {
- /* insert this node at head of linked list of cont/break instructions */
- n->List = loopNode->List;
- loopNode->List = n;
- }
- return n;
-}
-
-
-/**
- * Make new IR_BREAK_IF_TRUE.
- */
-static slang_ir_node *
-new_break_if_true(slang_assemble_ctx *A, slang_ir_node *cond)
-{
- slang_ir_node *loopNode = current_loop_ir(A);
- slang_ir_node *n;
- assert(loopNode);
- assert(loopNode->Opcode == IR_LOOP);
- n = new_node1(IR_BREAK_IF_TRUE, cond);
- if (n) {
- /* insert this node at head of linked list of cont/break instructions */
- n->List = loopNode->List;
- loopNode->List = n;
- }
- return n;
-}
-
-
-/**
- * Make new IR_CONT_IF_TRUE node.
- */
-static slang_ir_node *
-new_cont_if_true(slang_assemble_ctx *A, slang_ir_node *cond)
-{
- slang_ir_node *loopNode = current_loop_ir(A);
- slang_ir_node *n;
- assert(loopNode);
- assert(loopNode->Opcode == IR_LOOP);
- n = new_node1(IR_CONT_IF_TRUE, cond);
- if (n) {
- n->Parent = loopNode; /* pointer to containing loop */
- /* insert this node at head of linked list of cont/break instructions */
- n->List = loopNode->List;
- loopNode->List = n;
- }
- return n;
-}
-
-
-static slang_ir_node *
-new_cond(slang_ir_node *n)
-{
- slang_ir_node *c = new_node1(IR_COND, n);
- return c;
-}
-
-
-static slang_ir_node *
-new_if(slang_ir_node *cond, slang_ir_node *ifPart, slang_ir_node *elsePart)
-{
- return new_node3(IR_IF, cond, ifPart, elsePart);
-}
-
-
-/**
- * New IR_VAR node - a reference to a previously declared variable.
- */
-static slang_ir_node *
-new_var(slang_assemble_ctx *A, slang_variable *var)
-{
- slang_ir_node *n = new_node0(IR_VAR);
- if (n) {
- ASSERT(var);
- ASSERT(var->store);
- ASSERT(!n->Store);
- ASSERT(!n->Var);
-
- /* Set IR node's Var and Store pointers */
- n->Var = var;
- n->Store = var->store;
- }
- return n;
-}
-
-
-/**
- * Check if the given function is really just a wrapper for a
- * basic assembly instruction.
- */
-static GLboolean
-slang_is_asm_function(const slang_function *fun)
-{
- if (fun->body->type == SLANG_OPER_BLOCK_NO_NEW_SCOPE &&
- fun->body->num_children == 1 &&
- fun->body->children[0].type == SLANG_OPER_ASM) {
- return GL_TRUE;
- }
- return GL_FALSE;
-}
-
-
-static GLboolean
-_slang_is_noop(const slang_operation *oper)
-{
- if (!oper ||
- oper->type == SLANG_OPER_VOID ||
- (oper->num_children == 1 && oper->children[0].type == SLANG_OPER_VOID))
- return GL_TRUE;
- else
- return GL_FALSE;
-}
-
-
-/**
- * Recursively search tree for a node of the given type.
- */
-#if 0
-static slang_operation *
-_slang_find_node_type(slang_operation *oper, slang_operation_type type)
-{
- GLuint i;
- if (oper->type == type)
- return oper;
- for (i = 0; i < oper->num_children; i++) {
- slang_operation *p = _slang_find_node_type(&oper->children[i], type);
- if (p)
- return p;
- }
- return NULL;
-}
-#endif
-
-
-/**
- * Count the number of operations of the given time rooted at 'oper'.
- */
-static GLuint
-_slang_count_node_type(const slang_operation *oper, slang_operation_type type)
-{
- GLuint i, count = 0;
- if (oper->type == type) {
- return 1;
- }
- for (i = 0; i < oper->num_children; i++) {
- count += _slang_count_node_type(&oper->children[i], type);
- }
- return count;
-}
-
-
-/**
- * Check if the 'return' statement found under 'oper' is a "tail return"
- * that can be no-op'd. For example:
- *
- * void func(void)
- * {
- * .. do something ..
- * return; // this is a no-op
- * }
- *
- * This is used when determining if a function can be inlined. If the
- * 'return' is not the last statement, we can't inline the function since
- * we still need the semantic behaviour of the 'return' but we don't want
- * to accidentally return from the _calling_ function. We'd need to use an
- * unconditional branch, but we don't have such a GPU instruction (not
- * always, at least).
- */
-static GLboolean
-_slang_is_tail_return(const slang_operation *oper)
-{
- GLuint k = oper->num_children;
-
- while (k > 0) {
- const slang_operation *last = &oper->children[k - 1];
- if (last->type == SLANG_OPER_RETURN)
- return GL_TRUE;
- else if (last->type == SLANG_OPER_IDENTIFIER ||
- last->type == SLANG_OPER_LABEL)
- k--; /* try prev child */
- else if (last->type == SLANG_OPER_BLOCK_NO_NEW_SCOPE ||
- last->type == SLANG_OPER_BLOCK_NEW_SCOPE)
- /* try sub-children */
- return _slang_is_tail_return(last);
- else
- break;
- }
-
- return GL_FALSE;
-}
-
-
-/**
- * Generate a variable declaration opeartion.
- * I.e.: generate AST code for "bool flag = false;"
- */
-static void
-slang_generate_declaration(slang_assemble_ctx *A,
- slang_variable_scope *scope,
- slang_operation *decl,
- slang_type_specifier_type type,
- const char *name,
- GLint initValue)
-{
- slang_variable *var;
-
- assert(type == SLANG_SPEC_BOOL ||
- type == SLANG_SPEC_INT);
-
- decl->type = SLANG_OPER_VARIABLE_DECL;
-
- var = slang_variable_scope_grow(scope);
-
- slang_fully_specified_type_construct(&var->type);
-
- var->type.specifier.type = type;
- var->a_name = slang_atom_pool_atom(A->atoms, name);
- decl->a_id = var->a_name;
- var->initializer = slang_operation_new(1);
- slang_operation_literal_bool(var->initializer, initValue);
-}
-
-
-static void
-slang_resolve_variable(slang_operation *oper)
-{
- if (oper->type == SLANG_OPER_IDENTIFIER && !oper->var) {
- oper->var = _slang_variable_locate(oper->locals, oper->a_id, GL_TRUE);
- }
-}
-
-
-/**
- * Rewrite AST code for "return expression;".
- *
- * We return values from functions by assinging the returned value to
- * the hidden __retVal variable which is an extra 'out' parameter we add
- * to the function signature.
- * This code basically converts "return expr;" into "__retVal = expr; return;"
- *
- * \return the new AST code.
- */
-static slang_operation *
-gen_return_with_expression(slang_assemble_ctx *A, slang_operation *oper)
-{
- slang_operation *blockOper, *assignOper;
-
- assert(oper->type == SLANG_OPER_RETURN);
-
- if (A->CurFunction->header.type.specifier.type == SLANG_SPEC_VOID) {
- slang_info_log_error(A->log, "illegal return expression");
- return NULL;
- }
-
- blockOper = slang_operation_new(1);
- blockOper->type = SLANG_OPER_BLOCK_NO_NEW_SCOPE;
- blockOper->locals->outer_scope = oper->locals->outer_scope;
- slang_operation_add_children(blockOper, 2);
-
- if (A->UseReturnFlag) {
- /* Emit:
- * {
- * if (__notRetFlag)
- * __retVal = expr;
- * __notRetFlag = 0;
- * }
- */
- {
- slang_operation *ifOper = slang_oper_child(blockOper, 0);
- ifOper->type = SLANG_OPER_IF;
- slang_operation_add_children(ifOper, 3);
- {
- slang_operation *cond = slang_oper_child(ifOper, 0);
- cond->type = SLANG_OPER_IDENTIFIER;
- cond->a_id = slang_atom_pool_atom(A->atoms, "__notRetFlag");
- }
- {
- slang_operation *elseOper = slang_oper_child(ifOper, 2);
- elseOper->type = SLANG_OPER_VOID;
- }
- assignOper = slang_oper_child(ifOper, 1);
- }
- {
- slang_operation *setOper = slang_oper_child(blockOper, 1);
- setOper->type = SLANG_OPER_ASSIGN;
- slang_operation_add_children(setOper, 2);
- {
- slang_operation *lhs = slang_oper_child(setOper, 0);
- lhs->type = SLANG_OPER_IDENTIFIER;
- lhs->a_id = slang_atom_pool_atom(A->atoms, "__notRetFlag");
- }
- {
- slang_operation *rhs = slang_oper_child(setOper, 1);
- slang_operation_literal_bool(rhs, GL_FALSE);
- }
- }
- }
- else {
- /* Emit:
- * {
- * __retVal = expr;
- * return_inlined;
- * }
- */
- assignOper = slang_oper_child(blockOper, 0);
- {
- slang_operation *returnOper = slang_oper_child(blockOper, 1);
- returnOper->type = SLANG_OPER_RETURN_INLINED;
- assert(returnOper->num_children == 0);
- }
- }
-
- /* __retVal = expression; */
- assignOper->type = SLANG_OPER_ASSIGN;
- slang_operation_add_children(assignOper, 2);
- {
- slang_operation *lhs = slang_oper_child(assignOper, 0);
- lhs->type = SLANG_OPER_IDENTIFIER;
- lhs->a_id = slang_atom_pool_atom(A->atoms, "__retVal");
- }
- {
- slang_operation *rhs = slang_oper_child(assignOper, 1);
- slang_operation_copy(rhs, &oper->children[0]);
- }
-
- /*blockOper->locals->outer_scope = oper->locals->outer_scope;*/
-
- /*slang_print_tree(blockOper, 0);*/
-
- return blockOper;
-}
-
-
-/**
- * Rewrite AST code for "return;" (no expression).
- */
-static slang_operation *
-gen_return_without_expression(slang_assemble_ctx *A, slang_operation *oper)
-{
- slang_operation *newRet;
-
- assert(oper->type == SLANG_OPER_RETURN);
-
- if (A->CurFunction->header.type.specifier.type != SLANG_SPEC_VOID) {
- slang_info_log_error(A->log, "return statement requires an expression");
- return NULL;
- }
-
- if (A->UseReturnFlag) {
- /* Emit:
- * __notRetFlag = 0;
- */
- {
- newRet = slang_operation_new(1);
- newRet->locals->outer_scope = oper->locals->outer_scope;
- newRet->type = SLANG_OPER_ASSIGN;
- slang_operation_add_children(newRet, 2);
- {
- slang_operation *lhs = slang_oper_child(newRet, 0);
- lhs->type = SLANG_OPER_IDENTIFIER;
- lhs->a_id = slang_atom_pool_atom(A->atoms, "__notRetFlag");
- }
- {
- slang_operation *rhs = slang_oper_child(newRet, 1);
- slang_operation_literal_bool(rhs, GL_FALSE);
- }
- }
- }
- else {
- /* Emit:
- * return_inlined;
- */
- newRet = slang_operation_new(1);
- newRet->locals->outer_scope = oper->locals->outer_scope;
- newRet->type = SLANG_OPER_RETURN_INLINED;
- }
-
- /*slang_print_tree(newRet, 0);*/
-
- return newRet;
-}
-
-
-
-
-/**
- * Replace particular variables (SLANG_OPER_IDENTIFIER) with new expressions.
- */
-static void
-slang_substitute(slang_assemble_ctx *A, slang_operation *oper,
- GLuint substCount, slang_variable **substOld,
- slang_operation **substNew, GLboolean isLHS)
-{
- switch (oper->type) {
- case SLANG_OPER_VARIABLE_DECL:
- {
- slang_variable *v = _slang_variable_locate(oper->locals,
- oper->a_id, GL_TRUE);
- assert(v);
- if (v->initializer && oper->num_children == 0) {
- /* set child of oper to copy of initializer */
- oper->num_children = 1;
- oper->children = slang_operation_new(1);
- slang_operation_copy(&oper->children[0], v->initializer);
- }
- if (oper->num_children == 1) {
- /* the initializer */
- slang_substitute(A, &oper->children[0], substCount,
- substOld, substNew, GL_FALSE);
- }
- }
- break;
- case SLANG_OPER_IDENTIFIER:
- assert(oper->num_children == 0);
- if (1/**!isLHS XXX FIX */) {
- slang_atom id = oper->a_id;
- slang_variable *v;
- GLuint i;
- v = _slang_variable_locate(oper->locals, id, GL_TRUE);
- if (!v) {
-#if 0
- if (strcmp((char *) oper->a_id, "__notRetFlag"))
- _mesa_problem(NULL, "var %s not found!\n", (char *) oper->a_id);
-#endif
- return;
- }
-
- /* look for a substitution */
- for (i = 0; i < substCount; i++) {
- if (v == substOld[i]) {
- /* OK, replace this SLANG_OPER_IDENTIFIER with a new expr */
-#if 0 /* DEBUG only */
- if (substNew[i]->type == SLANG_OPER_IDENTIFIER) {
- assert(substNew[i]->var);
- assert(substNew[i]->var->a_name);
- printf("Substitute %s with %s in id node %p\n",
- (char*)v->a_name, (char*) substNew[i]->var->a_name,
- (void*) oper);
- }
- else {
- printf("Substitute %s with %f in id node %p\n",
- (char*)v->a_name, substNew[i]->literal[0],
- (void*) oper);
- }
-#endif
- slang_operation_copy(oper, substNew[i]);
- break;
- }
- }
- }
- break;
-
- case SLANG_OPER_RETURN:
- {
- slang_operation *newReturn;
- /* generate new 'return' code' */
- if (slang_oper_child(oper, 0)->type == SLANG_OPER_VOID)
- newReturn = gen_return_without_expression(A, oper);
- else
- newReturn = gen_return_with_expression(A, oper);
-
- if (!newReturn)
- return;
-
- /* do substitutions on the new 'return' code */
- slang_substitute(A, newReturn,
- substCount, substOld, substNew, GL_FALSE);
-
- /* install new 'return' code */
- slang_operation_copy(oper, newReturn);
- slang_operation_destruct(newReturn);
- }
- break;
-
- case SLANG_OPER_ASSIGN:
- case SLANG_OPER_SUBSCRIPT:
- /* special case:
- * child[0] can't have substitutions but child[1] can.
- */
- slang_substitute(A, &oper->children[0],
- substCount, substOld, substNew, GL_TRUE);
- slang_substitute(A, &oper->children[1],
- substCount, substOld, substNew, GL_FALSE);
- break;
- case SLANG_OPER_FIELD:
- /* XXX NEW - test */
- slang_substitute(A, &oper->children[0],
- substCount, substOld, substNew, GL_TRUE);
- break;
- default:
- {
- GLuint i;
- for (i = 0; i < oper->num_children; i++)
- slang_substitute(A, &oper->children[i],
- substCount, substOld, substNew, GL_FALSE);
- }
- }
-}
-
-
-/**
- * Produce inline code for a call to an assembly instruction.
- * This is typically used to compile a call to a built-in function like this:
- *
- * vec4 mix(const vec4 x, const vec4 y, const vec4 a)
- * {
- * __asm vec4_lrp __retVal, a, y, x;
- * }
- *
- *
- * A call to
- * r = mix(p1, p2, p3);
- *
- * Becomes:
- *
- * mov
- * / \
- * r vec4_lrp
- * / | \
- * p3 p2 p1
- *
- * We basically translate a SLANG_OPER_CALL into a SLANG_OPER_ASM.
- */
-static slang_operation *
-slang_inline_asm_function(slang_assemble_ctx *A,
- slang_function *fun, slang_operation *oper)
-{
- const GLuint numArgs = oper->num_children;
- GLuint i;
- slang_operation *inlined;
- const GLboolean haveRetValue = _slang_function_has_return_value(fun);
- slang_variable **substOld;
- slang_operation **substNew;
-
- ASSERT(slang_is_asm_function(fun));
- ASSERT(fun->param_count == numArgs + haveRetValue);
-
- /*
- printf("Inline %s as %s\n",
- (char*) fun->header.a_name,
- (char*) fun->body->children[0].a_id);
- */
-
- /*
- * We'll substitute formal params with actual args in the asm call.
- */
- substOld = (slang_variable **)
- _slang_alloc(numArgs * sizeof(slang_variable *));
- substNew = (slang_operation **)
- _slang_alloc(numArgs * sizeof(slang_operation *));
- for (i = 0; i < numArgs; i++) {
- substOld[i] = fun->parameters->variables[i];
- substNew[i] = oper->children + i;
- }
-
- /* make a copy of the code to inline */
- inlined = slang_operation_new(1);
- slang_operation_copy(inlined, &fun->body->children[0]);
- if (haveRetValue) {
- /* get rid of the __retVal child */
- inlined->num_children--;
- for (i = 0; i < inlined->num_children; i++) {
- inlined->children[i] = inlined->children[i + 1];
- }
- }
-
- /* now do formal->actual substitutions */
- slang_substitute(A, inlined, numArgs, substOld, substNew, GL_FALSE);
-
- _slang_free(substOld);
- _slang_free(substNew);
-
-#if 0
- printf("+++++++++++++ inlined asm function %s +++++++++++++\n",
- (char *) fun->header.a_name);
- slang_print_tree(inlined, 3);
- printf("+++++++++++++++++++++++++++++++++++++++++++++++++++\n");
-#endif
-
- return inlined;
-}
-
-
-/**
- * Inline the given function call operation.
- * Return a new slang_operation that corresponds to the inlined code.
- */
-static slang_operation *
-slang_inline_function_call(slang_assemble_ctx * A, slang_function *fun,
- slang_operation *oper, slang_operation *returnOper)
-{
- typedef enum {
- SUBST = 1,
- COPY_IN,
- COPY_OUT
- } ParamMode;
- ParamMode *paramMode;
- const GLboolean haveRetValue = _slang_function_has_return_value(fun);
- const GLuint numArgs = oper->num_children;
- const GLuint totalArgs = numArgs + haveRetValue;
- slang_operation *args = oper->children;
- slang_operation *inlined, *top;
- slang_variable **substOld;
- slang_operation **substNew;
- GLuint substCount, numCopyIn, i;
- slang_function *prevFunction;
- slang_variable_scope *newScope = NULL;
-
- /* save / push */
- prevFunction = A->CurFunction;
- A->CurFunction = fun;
-
- /*assert(oper->type == SLANG_OPER_CALL); (or (matrix) multiply, etc) */
- assert(fun->param_count == totalArgs);
-
- /* allocate temporary arrays */
- paramMode = (ParamMode *)
- _slang_alloc(totalArgs * sizeof(ParamMode));
- substOld = (slang_variable **)
- _slang_alloc(totalArgs * sizeof(slang_variable *));
- substNew = (slang_operation **)
- _slang_alloc(totalArgs * sizeof(slang_operation *));
-
-#if 0
- printf("\nInline call to %s (total vars=%d nparams=%d)\n",
- (char *) fun->header.a_name,
- fun->parameters->num_variables, numArgs);
-#endif
-
- if (haveRetValue && !returnOper) {
- /* Create 3-child comma sequence for inlined code:
- * child[0]: declare __resultTmp
- * child[1]: inlined function body
- * child[2]: __resultTmp
- */
- slang_operation *commaSeq;
- slang_operation *declOper = NULL;
- slang_variable *resultVar;
-
- commaSeq = slang_operation_new(1);
- commaSeq->type = SLANG_OPER_SEQUENCE;
- assert(commaSeq->locals);
- commaSeq->locals->outer_scope = oper->locals->outer_scope;
- commaSeq->num_children = 3;
- commaSeq->children = slang_operation_new(3);
- /* allocate the return var */
- resultVar = slang_variable_scope_grow(commaSeq->locals);
- /*
- printf("Alloc __resultTmp in scope %p for retval of calling %s\n",
- (void*)commaSeq->locals, (char *) fun->header.a_name);
- */
-
- resultVar->a_name = slang_atom_pool_atom(A->atoms, "__resultTmp");
- resultVar->type = fun->header.type; /* XXX copy? */
- resultVar->isTemp = GL_TRUE;
-
- /* child[0] = __resultTmp declaration */
- declOper = &commaSeq->children[0];
- declOper->type = SLANG_OPER_VARIABLE_DECL;
- declOper->a_id = resultVar->a_name;
- declOper->locals->outer_scope = commaSeq->locals;
-
- /* child[1] = function body */
- inlined = &commaSeq->children[1];
- inlined->locals->outer_scope = commaSeq->locals;
-
- /* child[2] = __resultTmp reference */
- returnOper = &commaSeq->children[2];
- returnOper->type = SLANG_OPER_IDENTIFIER;
- returnOper->a_id = resultVar->a_name;
- returnOper->locals->outer_scope = commaSeq->locals;
-
- top = commaSeq;
- }
- else {
- top = inlined = slang_operation_new(1);
- /* XXXX this may be inappropriate!!!! */
- inlined->locals->outer_scope = oper->locals->outer_scope;
- }
-
-
- assert(inlined->locals);
-
- /* Examine the parameters, look for inout/out params, look for possible
- * substitutions, etc:
- * param type behaviour
- * in copy actual to local
- * const in substitute param with actual
- * out copy out
- */
- substCount = 0;
- for (i = 0; i < totalArgs; i++) {
- slang_variable *p = fun->parameters->variables[i];
- /*
- printf("Param %d: %s %s \n", i,
- slang_type_qual_string(p->type.qualifier),
- (char *) p->a_name);
- */
- if (p->type.qualifier == SLANG_QUAL_INOUT ||
- p->type.qualifier == SLANG_QUAL_OUT) {
- /* an output param */
- slang_operation *arg;
- if (i < numArgs)
- arg = &args[i];
- else
- arg = returnOper;
- paramMode[i] = SUBST;
-
- if (arg->type == SLANG_OPER_IDENTIFIER)
- slang_resolve_variable(arg);
-
- /* replace parameter 'p' with argument 'arg' */
- substOld[substCount] = p;
- substNew[substCount] = arg; /* will get copied */
- substCount++;
- }
- else if (p->type.qualifier == SLANG_QUAL_CONST) {
- /* a constant input param */
- if (args[i].type == SLANG_OPER_IDENTIFIER ||
- args[i].type == SLANG_OPER_LITERAL_FLOAT ||
- args[i].type == SLANG_OPER_SUBSCRIPT) {
- /* replace all occurances of this parameter variable with the
- * actual argument variable or a literal.
- */
- paramMode[i] = SUBST;
- slang_resolve_variable(&args[i]);
- substOld[substCount] = p;
- substNew[substCount] = &args[i]; /* will get copied */
- substCount++;
- }
- else {
- paramMode[i] = COPY_IN;
- }
- }
- else {
- paramMode[i] = COPY_IN;
- }
- assert(paramMode[i]);
- }
-
- /* actual code inlining: */
- slang_operation_copy(inlined, fun->body);
-
- /*** XXX review this */
- assert(inlined->type == SLANG_OPER_BLOCK_NO_NEW_SCOPE ||
- inlined->type == SLANG_OPER_BLOCK_NEW_SCOPE);
- inlined->type = SLANG_OPER_BLOCK_NEW_SCOPE;
-
-#if 0
- printf("======================= orig body code ======================\n");
- printf("=== params scope = %p\n", (void*) fun->parameters);
- slang_print_tree(fun->body, 8);
- printf("======================= copied code =========================\n");
- slang_print_tree(inlined, 8);
-#endif
-
- /* do parameter substitution in inlined code: */
- slang_substitute(A, inlined, substCount, substOld, substNew, GL_FALSE);
-
-#if 0
- printf("======================= subst code ==========================\n");
- slang_print_tree(inlined, 8);
- printf("=============================================================\n");
-#endif
-
- /* New prolog statements: (inserted before the inlined code)
- * Copy the 'in' arguments.
- */
- numCopyIn = 0;
- for (i = 0; i < numArgs; i++) {
- if (paramMode[i] == COPY_IN) {
- slang_variable *p = fun->parameters->variables[i];
- /* declare parameter 'p' */
- slang_operation *decl = slang_operation_insert(&inlined->num_children,
- &inlined->children,
- numCopyIn);
-
- decl->type = SLANG_OPER_VARIABLE_DECL;
- assert(decl->locals);
- decl->locals->outer_scope = inlined->locals;
- decl->a_id = p->a_name;
- decl->num_children = 1;
- decl->children = slang_operation_new(1);
-
- /* child[0] is the var's initializer */
- slang_operation_copy(&decl->children[0], args + i);
-
- /* add parameter 'p' to the local variable scope here */
- {
- slang_variable *pCopy = slang_variable_scope_grow(inlined->locals);
- pCopy->type = p->type;
- pCopy->a_name = p->a_name;
- pCopy->array_len = p->array_len;
- }
-
- newScope = inlined->locals;
- numCopyIn++;
- }
- }
-
- /* Now add copies of the function's local vars to the new variable scope */
- for (i = totalArgs; i < fun->parameters->num_variables; i++) {
- slang_variable *p = fun->parameters->variables[i];
- slang_variable *pCopy = slang_variable_scope_grow(inlined->locals);
- pCopy->type = p->type;
- pCopy->a_name = p->a_name;
- pCopy->array_len = p->array_len;
- }
-
-
- /* New epilog statements:
- * 1. Create end of function label to jump to from return statements.
- * 2. Copy the 'out' parameter vars
- */
- {
- slang_operation *lab = slang_operation_insert(&inlined->num_children,
- &inlined->children,
- inlined->num_children);
- lab->type = SLANG_OPER_LABEL;
- lab->label = A->curFuncEndLabel;
- }
-
- for (i = 0; i < totalArgs; i++) {
- if (paramMode[i] == COPY_OUT) {
- const slang_variable *p = fun->parameters->variables[i];
- /* actualCallVar = outParam */
- /*if (i > 0 || !haveRetValue)*/
- slang_operation *ass = slang_operation_insert(&inlined->num_children,
- &inlined->children,
- inlined->num_children);
- ass->type = SLANG_OPER_ASSIGN;
- ass->num_children = 2;
- ass->locals->outer_scope = inlined->locals;
- ass->children = slang_operation_new(2);
- ass->children[0] = args[i]; /*XXX copy */
- ass->children[1].type = SLANG_OPER_IDENTIFIER;
- ass->children[1].a_id = p->a_name;
- ass->children[1].locals->outer_scope = ass->locals;
- }
- }
-
- _slang_free(paramMode);
- _slang_free(substOld);
- _slang_free(substNew);
-
- /* Update scoping to use the new local vars instead of the
- * original function's vars. This is especially important
- * for nested inlining.
- */
- if (newScope)
- slang_replace_scope(inlined, fun->parameters, newScope);
-
-#if 0
- printf("Done Inline call to %s (total vars=%d nparams=%d)\n\n",
- (char *) fun->header.a_name,
- fun->parameters->num_variables, numArgs);
- slang_print_tree(top, 0);
-#endif
-
- /* pop */
- A->CurFunction = prevFunction;
-
- return top;
-}
-
-
-/**
- * Insert declaration for "bool __notRetFlag" in given block operation.
- * This is used when we can't emit "early" return statements in subroutines.
- */
-static void
-declare_return_flag(slang_assemble_ctx *A, slang_operation *oper)
-{
- slang_operation *decl;
-
- assert(oper->type == SLANG_OPER_BLOCK_NEW_SCOPE ||
- oper->type == SLANG_OPER_SEQUENCE);
-
- decl = slang_operation_insert_child(oper, 1);
-
- slang_generate_declaration(A, oper->locals, decl,
- SLANG_SPEC_BOOL, "__notRetFlag", GL_TRUE);
-
- /*slang_print_tree(oper, 0);*/
-}
-
-
-/**
- * Recursively replace instances of the old node type with the new type.
- */
-static void
-replace_node_type(slang_operation *oper, slang_operation_type oldType,
- slang_operation_type newType)
-{
- GLuint i;
-
- if (oper->type == oldType)
- oper->type = newType;
-
- for (i = 0; i < slang_oper_num_children(oper); i++) {
- replace_node_type(slang_oper_child(oper, i), oldType, newType);
- }
-}
-
-
-
-/**
- * Test if the given function body has an "early return". That is, there's
- * a 'return' statement that's not the very last instruction in the body.
- */
-static GLboolean
-has_early_return(const slang_operation *funcBody)
-{
- GLuint retCount = _slang_count_node_type(funcBody, SLANG_OPER_RETURN);
- if (retCount == 0)
- return GL_FALSE;
- else if (retCount == 1 && _slang_is_tail_return(funcBody))
- return GL_FALSE;
- else
- return GL_TRUE;
-}
-
-
-/**
- * Emit IR code for a function call. This does one of two things:
- * 1. Inline the function's code
- * 2. Create an IR for the function's body and create a real call to it.
- */
-static slang_ir_node *
-_slang_gen_function_call(slang_assemble_ctx *A, slang_function *fun,
- slang_operation *oper, slang_operation *dest)
-{
- slang_ir_node *n;
- slang_operation *instance;
- slang_label *prevFuncEndLabel;
- char name[200];
-
- prevFuncEndLabel = A->curFuncEndLabel;
- _mesa_snprintf(name, sizeof(name), "__endOfFunc_%s_", (char *) fun->header.a_name);
- A->curFuncEndLabel = _slang_label_new(name);
- assert(A->curFuncEndLabel);
-
- /*
- * 'instance' is basically a copy of the function's body with various
- * transformations.
- */
-
- if (slang_is_asm_function(fun) && !dest) {
- /* assemble assembly function - tree style */
- instance = slang_inline_asm_function(A, fun, oper);
- }
- else {
- /* non-assembly function */
- /* We always generate an "inline-able" block of code here.
- * We may either:
- * 1. insert the inline code
- * 2. Generate a call to the "inline" code as a subroutine
- */
- const GLboolean earlyReturn = has_early_return(fun->body);
-
- if (earlyReturn && !A->EmitContReturn) {
- A->UseReturnFlag = GL_TRUE;
- }
-
- instance = slang_inline_function_call(A, fun, oper, dest);
- if (!instance)
- return NULL;
-
- if (earlyReturn) {
- /* The function we're calling has one or more 'return' statements
- * that prevent us from inlining the function's code.
- *
- * In this case, change the function's body type from
- * SLANG_OPER_BLOCK_NEW_SCOPE to SLANG_OPER_NON_INLINED_CALL.
- * During code emit this will result in a true subroutine call.
- *
- * Also, convert SLANG_OPER_RETURN_INLINED nodes to SLANG_OPER_RETURN.
- */
- slang_operation *callOper;
-
- assert(instance->type == SLANG_OPER_BLOCK_NEW_SCOPE ||
- instance->type == SLANG_OPER_SEQUENCE);
-
- if (_slang_function_has_return_value(fun) && !dest) {
- assert(instance->children[0].type == SLANG_OPER_VARIABLE_DECL);
- assert(instance->children[2].type == SLANG_OPER_IDENTIFIER);
- callOper = &instance->children[1];
- }
- else {
- callOper = instance;
- }
-
- if (A->UseReturnFlag) {
- /* Early returns not supported. Create a _returnFlag variable
- * that's set upon 'return' and tested elsewhere to no-op any
- * remaining instructions in the subroutine.
- */
- assert(callOper->type == SLANG_OPER_BLOCK_NEW_SCOPE ||
- callOper->type == SLANG_OPER_SEQUENCE);
- declare_return_flag(A, callOper);
- }
- else {
- /* We can emit real 'return' statements. If we generated any
- * 'inline return' statements during function instantiation,
- * change them back to regular 'return' statements.
- */
- replace_node_type(instance, SLANG_OPER_RETURN_INLINED,
- SLANG_OPER_RETURN);
- }
-
- callOper->type = SLANG_OPER_NON_INLINED_CALL;
- callOper->fun = fun;
- callOper->label = _slang_label_new_unique((char*) fun->header.a_name);
- }
- else {
- /* If there are any 'return' statements remaining, they're at the
- * very end of the function and can effectively become no-ops.
- */
- replace_node_type(instance, SLANG_OPER_RETURN_INLINED,
- SLANG_OPER_VOID);
- }
- }
-
- if (!instance)
- return NULL;
-
- /* Replace the function call with the instance block (or new CALL stmt) */
- slang_operation_destruct(oper);
- *oper = *instance;
- _slang_free(instance);
-
-#if 0
- assert(instance->locals);
- printf("*** Inlined code for call to %s:\n", (char*) fun->header.a_name);
- slang_print_tree(oper, 10);
- printf("\n");
-#endif
-
- n = _slang_gen_operation(A, oper);
-
- /*_slang_label_delete(A->curFuncEndLabel);*/
- A->curFuncEndLabel = prevFuncEndLabel;
-
- if (A->pragmas->Debug) {
- char s[1000];
- _mesa_snprintf(s, sizeof(s), "Call/inline %s()", (char *) fun->header.a_name);
- n->Comment = _slang_strdup(s);
- }
-
- A->UseReturnFlag = GL_FALSE;
-
- return n;
-}
-
-
-static slang_asm_info *
-slang_find_asm_info(const char *name)
-{
- GLuint i;
- for (i = 0; AsmInfo[i].Name; i++) {
- if (strcmp(AsmInfo[i].Name, name) == 0) {
- return AsmInfo + i;
- }
- }
- return NULL;
-}
-
-
-/**
- * Some write-masked assignments are simple, but others are hard.
- * Simple example:
- * vec3 v;
- * v.xy = vec2(a, b);
- * Hard example:
- * vec3 v;
- * v.zy = vec2(a, b);
- * this gets transformed/swizzled into:
- * v.zy = vec2(a, b).*yx* (* = don't care)
- * This function helps to determine simple vs. non-simple.
- */
-static GLboolean
-_slang_simple_writemask(GLuint writemask, GLuint swizzle)
-{
- switch (writemask) {
- case WRITEMASK_X:
- return GET_SWZ(swizzle, 0) == SWIZZLE_X;
- case WRITEMASK_Y:
- return GET_SWZ(swizzle, 1) == SWIZZLE_Y;
- case WRITEMASK_Z:
- return GET_SWZ(swizzle, 2) == SWIZZLE_Z;
- case WRITEMASK_W:
- return GET_SWZ(swizzle, 3) == SWIZZLE_W;
- case WRITEMASK_XY:
- return (GET_SWZ(swizzle, 0) == SWIZZLE_X)
- && (GET_SWZ(swizzle, 1) == SWIZZLE_Y);
- case WRITEMASK_XYZ:
- return (GET_SWZ(swizzle, 0) == SWIZZLE_X)
- && (GET_SWZ(swizzle, 1) == SWIZZLE_Y)
- && (GET_SWZ(swizzle, 2) == SWIZZLE_Z);
- case WRITEMASK_XYZW:
- return swizzle == SWIZZLE_NOOP;
- default:
- return GL_FALSE;
- }
-}
-
-
-/**
- * Convert the given swizzle into a writemask. In some cases this
- * is trivial, in other cases, we'll need to also swizzle the right
- * hand side to put components in the right places.
- * See comment above for more info.
- * XXX this function could be simplified and should probably be renamed.
- * \param swizzle the incoming swizzle
- * \param writemaskOut returns the writemask
- * \param swizzleOut swizzle to apply to the right-hand-side
- * \return GL_FALSE for simple writemasks, GL_TRUE for non-simple
- */
-static GLboolean
-swizzle_to_writemask(slang_assemble_ctx *A, GLuint swizzle,
- GLuint *writemaskOut, GLuint *swizzleOut)
-{
- GLuint mask = 0x0, newSwizzle[4];
- GLint i, size;
-
- /* make new dst writemask, compute size */
- for (i = 0; i < 4; i++) {
- const GLuint swz = GET_SWZ(swizzle, i);
- if (swz == SWIZZLE_NIL) {
- /* end */
- break;
- }
- assert(swz <= 3);
-
- if (swizzle != SWIZZLE_XXXX &&
- swizzle != SWIZZLE_YYYY &&
- swizzle != SWIZZLE_ZZZZ &&
- swizzle != SWIZZLE_WWWW &&
- (mask & (1 << swz))) {
- /* a channel can't be specified twice (ex: ".xyyz") */
- slang_info_log_error(A->log, "Invalid writemask '%s'",
- _mesa_swizzle_string(swizzle, 0, 0));
- return GL_FALSE;
- }
-
- mask |= (1 << swz);
- }
- assert(mask <= 0xf);
- size = i; /* number of components in mask/swizzle */
-
- *writemaskOut = mask;
-
- /* make new src swizzle, by inversion */
- for (i = 0; i < 4; i++) {
- newSwizzle[i] = i; /*identity*/
- }
- for (i = 0; i < size; i++) {
- const GLuint swz = GET_SWZ(swizzle, i);
- newSwizzle[swz] = i;
- }
- *swizzleOut = MAKE_SWIZZLE4(newSwizzle[0],
- newSwizzle[1],
- newSwizzle[2],
- newSwizzle[3]);
-
- if (_slang_simple_writemask(mask, *swizzleOut)) {
- if (size >= 1)
- assert(GET_SWZ(*swizzleOut, 0) == SWIZZLE_X);
- if (size >= 2)
- assert(GET_SWZ(*swizzleOut, 1) == SWIZZLE_Y);
- if (size >= 3)
- assert(GET_SWZ(*swizzleOut, 2) == SWIZZLE_Z);
- if (size >= 4)
- assert(GET_SWZ(*swizzleOut, 3) == SWIZZLE_W);
- return GL_TRUE;
- }
- else
- return GL_FALSE;
-}
-
-
-#if 0 /* not used, but don't remove just yet */
-/**
- * Recursively traverse 'oper' to produce a swizzle mask in the event
- * of any vector subscripts and swizzle suffixes.
- * Ex: for "vec4 v", "v[2].x" resolves to v.z
- */
-static GLuint
-resolve_swizzle(const slang_operation *oper)
-{
- if (oper->type == SLANG_OPER_FIELD) {
- /* writemask from .xyzw suffix */
- slang_swizzle swz;
- if (_slang_is_swizzle((char*) oper->a_id, 4, &swz)) {
- GLuint swizzle = MAKE_SWIZZLE4(swz.swizzle[0],
- swz.swizzle[1],
- swz.swizzle[2],
- swz.swizzle[3]);
- GLuint child_swizzle = resolve_swizzle(&oper->children[0]);
- GLuint s = _slang_swizzle_swizzle(child_swizzle, swizzle);
- return s;
- }
- else
- return SWIZZLE_XYZW;
- }
- else if (oper->type == SLANG_OPER_SUBSCRIPT &&
- oper->children[1].type == SLANG_OPER_LITERAL_INT) {
- /* writemask from [index] */
- GLuint child_swizzle = resolve_swizzle(&oper->children[0]);
- GLuint i = (GLuint) oper->children[1].literal[0];
- GLuint swizzle;
- GLuint s;
- switch (i) {
- case 0:
- swizzle = SWIZZLE_XXXX;
- break;
- case 1:
- swizzle = SWIZZLE_YYYY;
- break;
- case 2:
- swizzle = SWIZZLE_ZZZZ;
- break;
- case 3:
- swizzle = SWIZZLE_WWWW;
- break;
- default:
- swizzle = SWIZZLE_XYZW;
- }
- s = _slang_swizzle_swizzle(child_swizzle, swizzle);
- return s;
- }
- else {
- return SWIZZLE_XYZW;
- }
-}
-#endif
-
-
-#if 0
-/**
- * Recursively descend through swizzle nodes to find the node's storage info.
- */
-static slang_ir_storage *
-get_store(const slang_ir_node *n)
-{
- if (n->Opcode == IR_SWIZZLE) {
- return get_store(n->Children[0]);
- }
- return n->Store;
-}
-#endif
-
-
-/**
- * Generate IR tree for an asm instruction/operation such as:
- * __asm vec4_dot __retVal.x, v1, v2;
- */
-static slang_ir_node *
-_slang_gen_asm(slang_assemble_ctx *A, slang_operation *oper,
- slang_operation *dest)
-{
- const slang_asm_info *info;
- slang_ir_node *kids[3], *n;
- GLuint j, firstOperand;
-
- assert(oper->type == SLANG_OPER_ASM);
-
- info = slang_find_asm_info((char *) oper->a_id);
- if (!info) {
- _mesa_problem(NULL, "undefined __asm function %s\n",
- (char *) oper->a_id);
- assert(info);
- return NULL;
- }
- assert(info->NumParams <= 3);
-
- if (info->NumParams == oper->num_children) {
- /* Storage for result is not specified.
- * Children[0], [1], [2] are the operands.
- */
- firstOperand = 0;
- }
- else {
- /* Storage for result (child[0]) is specified.
- * Children[1], [2], [3] are the operands.
- */
- firstOperand = 1;
- }
-
- /* assemble child(ren) */
- kids[0] = kids[1] = kids[2] = NULL;
- for (j = 0; j < info->NumParams; j++) {
- kids[j] = _slang_gen_operation(A, &oper->children[firstOperand + j]);
- if (!kids[j])
- return NULL;
- }
-
- n = new_node3(info->Opcode, kids[0], kids[1], kids[2]);
-
- if (firstOperand) {
- /* Setup n->Store to be a particular location. Otherwise, storage
- * for the result (a temporary) will be allocated later.
- */
- slang_operation *dest_oper;
- slang_ir_node *n0;
-
- dest_oper = &oper->children[0];
-
- n0 = _slang_gen_operation(A, dest_oper);
- if (!n0)
- return NULL;
-
- assert(!n->Store);
- n->Store = n0->Store;
-
- assert(n->Store->File != PROGRAM_UNDEFINED || n->Store->Parent);
-
- _slang_free(n0);
- }
-
- return n;
-}
-
-
-#if 0
-static void
-print_funcs(struct slang_function_scope_ *scope, const char *name)
-{
- GLuint i;
- for (i = 0; i < scope->num_functions; i++) {
- slang_function *f = &scope->functions[i];
- if (!name || strcmp(name, (char*) f->header.a_name) == 0)
- printf(" %s (%d args)\n", name, f->param_count);
-
- }
- if (scope->outer_scope)
- print_funcs(scope->outer_scope, name);
-}
-#endif
-
-
-/**
- * Find a function of the given name, taking 'numArgs' arguments.
- * This is the function we'll try to call when there is no exact match
- * between function parameters and call arguments.
- *
- * XXX we should really create a list of candidate functions and try
- * all of them...
- */
-static slang_function *
-_slang_find_function_by_argc(slang_function_scope *scope,
- const char *name, int numArgs)
-{
- while (scope) {
- GLuint i;
- for (i = 0; i < scope->num_functions; i++) {
- slang_function *f = &scope->functions[i];
- if (strcmp(name, (char*) f->header.a_name) == 0) {
- int haveRetValue = _slang_function_has_return_value(f);
- if (numArgs == f->param_count - haveRetValue)
- return f;
- }
- }
- scope = scope->outer_scope;
- }
-
- return NULL;
-}
-
-
-static slang_function *
-_slang_find_function_by_max_argc(slang_function_scope *scope,
- const char *name)
-{
- slang_function *maxFunc = NULL;
- GLuint maxArgs = 0;
-
- while (scope) {
- GLuint i;
- for (i = 0; i < scope->num_functions; i++) {
- slang_function *f = &scope->functions[i];
- if (strcmp(name, (char*) f->header.a_name) == 0) {
- if (f->param_count > maxArgs) {
- maxArgs = f->param_count;
- maxFunc = f;
- }
- }
- }
- scope = scope->outer_scope;
- }
-
- return maxFunc;
-}
-
-
-/**
- * Generate a new slang_function which is a constructor for a user-defined
- * struct type.
- */
-static slang_function *
-_slang_make_struct_constructor(slang_assemble_ctx *A, slang_struct *str)
-{
- const GLint numFields = str->fields->num_variables;
- slang_function *fun = slang_function_new(SLANG_FUNC_CONSTRUCTOR);
-
- /* function header (name, return type) */
- fun->header.a_name = str->a_name;
- fun->header.type.qualifier = SLANG_QUAL_NONE;
- fun->header.type.specifier.type = SLANG_SPEC_STRUCT;
- fun->header.type.specifier._struct = str;
-
- /* function parameters (= struct's fields) */
- {
- GLint i;
- for (i = 0; i < numFields; i++) {
- /*
- printf("Field %d: %s\n", i, (char*) str->fields->variables[i]->a_name);
- */
- slang_variable *p = slang_variable_scope_grow(fun->parameters);
- *p = *str->fields->variables[i]; /* copy the variable and type */
- p->type.qualifier = SLANG_QUAL_CONST;
- }
- fun->param_count = fun->parameters->num_variables;
- }
-
- /* Add __retVal to params */
- {
- slang_variable *p = slang_variable_scope_grow(fun->parameters);
- slang_atom a_retVal = slang_atom_pool_atom(A->atoms, "__retVal");
- assert(a_retVal);
- p->a_name = a_retVal;
- p->type = fun->header.type;
- p->type.qualifier = SLANG_QUAL_OUT;
- fun->param_count++;
- }
-
- /* function body is:
- * block:
- * declare T;
- * T.f1 = p1;
- * T.f2 = p2;
- * ...
- * T.fn = pn;
- * return T;
- */
- {
- slang_variable_scope *scope;
- slang_variable *var;
- GLint i;
-
- fun->body = slang_operation_new(1);
- fun->body->type = SLANG_OPER_BLOCK_NEW_SCOPE;
- fun->body->num_children = numFields + 2;
- fun->body->children = slang_operation_new(numFields + 2);
-
- scope = fun->body->locals;
- scope->outer_scope = fun->parameters;
-
- /* create local var 't' */
- var = slang_variable_scope_grow(scope);
- var->a_name = slang_atom_pool_atom(A->atoms, "t");
- var->type = fun->header.type;
-
- /* declare t */
- {
- slang_operation *decl;
-
- decl = &fun->body->children[0];
- decl->type = SLANG_OPER_VARIABLE_DECL;
- decl->locals = _slang_variable_scope_new(scope);
- decl->a_id = var->a_name;
- }
-
- /* assign params to fields of t */
- for (i = 0; i < numFields; i++) {
- slang_operation *assign = &fun->body->children[1 + i];
-
- assign->type = SLANG_OPER_ASSIGN;
- assign->locals = _slang_variable_scope_new(scope);
- assign->num_children = 2;
- assign->children = slang_operation_new(2);
-
- {
- slang_operation *lhs = &assign->children[0];
-
- lhs->type = SLANG_OPER_FIELD;
- lhs->locals = _slang_variable_scope_new(scope);
- lhs->num_children = 1;
- lhs->children = slang_operation_new(1);
- lhs->a_id = str->fields->variables[i]->a_name;
-
- lhs->children[0].type = SLANG_OPER_IDENTIFIER;
- lhs->children[0].a_id = var->a_name;
- lhs->children[0].locals = _slang_variable_scope_new(scope);
-
-#if 0
- lhs->children[1].num_children = 1;
- lhs->children[1].children = slang_operation_new(1);
- lhs->children[1].children[0].type = SLANG_OPER_IDENTIFIER;
- lhs->children[1].children[0].a_id = str->fields->variables[i]->a_name;
- lhs->children[1].children->locals = _slang_variable_scope_new(scope);
-#endif
- }
-
- {
- slang_operation *rhs = &assign->children[1];
-
- rhs->type = SLANG_OPER_IDENTIFIER;
- rhs->locals = _slang_variable_scope_new(scope);
- rhs->a_id = str->fields->variables[i]->a_name;
- }
- }
-
- /* return t; */
- {
- slang_operation *ret = &fun->body->children[numFields + 1];
-
- ret->type = SLANG_OPER_RETURN;
- ret->locals = _slang_variable_scope_new(scope);
- ret->num_children = 1;
- ret->children = slang_operation_new(1);
- ret->children[0].type = SLANG_OPER_IDENTIFIER;
- ret->children[0].a_id = var->a_name;
- ret->children[0].locals = _slang_variable_scope_new(scope);
- }
- }
- /*
- slang_print_function(fun, 1);
- */
- return fun;
-}
-
-
-/**
- * Find/create a function (constructor) for the given structure name.
- */
-static slang_function *
-_slang_locate_struct_constructor(slang_assemble_ctx *A, const char *name)
-{
- unsigned int i;
- for (i = 0; i < A->space.structs->num_structs; i++) {
- slang_struct *str = &A->space.structs->structs[i];
- if (strcmp(name, (const char *) str->a_name) == 0) {
- /* found a structure type that matches the function name */
- if (!str->constructor) {
- /* create the constructor function now */
- str->constructor = _slang_make_struct_constructor(A, str);
- }
- return str->constructor;
- }
- }
- return NULL;
-}
-
-
-/**
- * Generate a new slang_function to satisfy a call to an array constructor.
- * Ex: float[3](1., 2., 3.)
- */
-static slang_function *
-_slang_make_array_constructor(slang_assemble_ctx *A, slang_operation *oper)
-{
- slang_type_specifier_type baseType;
- slang_function *fun;
- int num_elements;
-
- fun = slang_function_new(SLANG_FUNC_CONSTRUCTOR);
- if (!fun)
- return NULL;
-
- baseType = slang_type_specifier_type_from_string((char *) oper->a_id);
-
- num_elements = oper->num_children;
-
- /* function header, return type */
- {
- fun->header.a_name = oper->a_id;
- fun->header.type.qualifier = SLANG_QUAL_NONE;
- fun->header.type.specifier.type = SLANG_SPEC_ARRAY;
- fun->header.type.specifier._array =
- slang_type_specifier_new(baseType, NULL, NULL);
- fun->header.type.array_len = num_elements;
- }
-
- /* function parameters (= number of elements) */
- {
- GLint i;
- for (i = 0; i < num_elements; i++) {
- /*
- printf("Field %d: %s\n", i, (char*) str->fields->variables[i]->a_name);
- */
- slang_variable *p = slang_variable_scope_grow(fun->parameters);
- char name[10];
- _mesa_snprintf(name, sizeof(name), "p%d", i);
- p->a_name = slang_atom_pool_atom(A->atoms, name);
- p->type.qualifier = SLANG_QUAL_CONST;
- p->type.specifier.type = baseType;
- }
- fun->param_count = fun->parameters->num_variables;
- }
-
- /* Add __retVal to params */
- {
- slang_variable *p = slang_variable_scope_grow(fun->parameters);
- slang_atom a_retVal = slang_atom_pool_atom(A->atoms, "__retVal");
- assert(a_retVal);
- p->a_name = a_retVal;
- p->type = fun->header.type;
- p->type.qualifier = SLANG_QUAL_OUT;
- p->type.specifier.type = baseType;
- fun->param_count++;
- }
-
- /* function body is:
- * block:
- * declare T;
- * T[0] = p0;
- * T[1] = p1;
- * ...
- * T[n] = pn;
- * return T;
- */
- {
- slang_variable_scope *scope;
- slang_variable *var;
- GLint i;
-
- fun->body = slang_operation_new(1);
- fun->body->type = SLANG_OPER_BLOCK_NEW_SCOPE;
- fun->body->num_children = num_elements + 2;
- fun->body->children = slang_operation_new(num_elements + 2);
-
- scope = fun->body->locals;
- scope->outer_scope = fun->parameters;
-
- /* create local var 't' */
- var = slang_variable_scope_grow(scope);
- var->a_name = slang_atom_pool_atom(A->atoms, "ttt");
- var->type = fun->header.type;/*XXX copy*/
-
- /* declare t */
- {
- slang_operation *decl;
-
- decl = &fun->body->children[0];
- decl->type = SLANG_OPER_VARIABLE_DECL;
- decl->locals = _slang_variable_scope_new(scope);
- decl->a_id = var->a_name;
- }
-
- /* assign params to elements of t */
- for (i = 0; i < num_elements; i++) {
- slang_operation *assign = &fun->body->children[1 + i];
-
- assign->type = SLANG_OPER_ASSIGN;
- assign->locals = _slang_variable_scope_new(scope);
- assign->num_children = 2;
- assign->children = slang_operation_new(2);
-
- {
- slang_operation *lhs = &assign->children[0];
-
- lhs->type = SLANG_OPER_SUBSCRIPT;
- lhs->locals = _slang_variable_scope_new(scope);
- lhs->num_children = 2;
- lhs->children = slang_operation_new(2);
-
- lhs->children[0].type = SLANG_OPER_IDENTIFIER;
- lhs->children[0].a_id = var->a_name;
- lhs->children[0].locals = _slang_variable_scope_new(scope);
-
- lhs->children[1].type = SLANG_OPER_LITERAL_INT;
- lhs->children[1].literal[0] = (GLfloat) i;
- }
-
- {
- slang_operation *rhs = &assign->children[1];
-
- rhs->type = SLANG_OPER_IDENTIFIER;
- rhs->locals = _slang_variable_scope_new(scope);
- rhs->a_id = fun->parameters->variables[i]->a_name;
- }
- }
-
- /* return t; */
- {
- slang_operation *ret = &fun->body->children[num_elements + 1];
-
- ret->type = SLANG_OPER_RETURN;
- ret->locals = _slang_variable_scope_new(scope);
- ret->num_children = 1;
- ret->children = slang_operation_new(1);
- ret->children[0].type = SLANG_OPER_IDENTIFIER;
- ret->children[0].a_id = var->a_name;
- ret->children[0].locals = _slang_variable_scope_new(scope);
- }
- }
-
- /*
- slang_print_function(fun, 1);
- */
-
- return fun;
-}
-
-
-static GLboolean
-_slang_is_vec_mat_type(const char *name)
-{
- static const char *vecmat_types[] = {
- "float", "int", "bool",
- "vec2", "vec3", "vec4",
- "ivec2", "ivec3", "ivec4",
- "bvec2", "bvec3", "bvec4",
- "mat2", "mat3", "mat4",
- "mat2x3", "mat2x4", "mat3x2", "mat3x4", "mat4x2", "mat4x3",
- NULL
- };
- int i;
- for (i = 0; vecmat_types[i]; i++)
- if (strcmp(name, vecmat_types[i]) == 0)
- return GL_TRUE;
- return GL_FALSE;
-}
-
-
-/**
- * Assemble a function call, given a particular function name.
- * \param name the function's name (operators like '*' are possible).
- */
-static slang_ir_node *
-_slang_gen_function_call_name(slang_assemble_ctx *A, const char *name,
- slang_operation *oper, slang_operation *dest)
-{
- slang_operation *params = oper->children;
- const GLuint param_count = oper->num_children;
- slang_atom atom;
- slang_function *fun;
- slang_ir_node *n;
-
- atom = slang_atom_pool_atom(A->atoms, name);
- if (atom == SLANG_ATOM_NULL)
- return NULL;
-
- if (oper->array_constructor) {
- /* this needs special handling */
- fun = _slang_make_array_constructor(A, oper);
- }
- else {
- /* Try to find function by name and exact argument type matching */
- GLboolean error = GL_FALSE;
- fun = _slang_function_locate(A->space.funcs, atom, params, param_count,
- &A->space, A->atoms, A->log, &error);
- if (error) {
- slang_info_log_error(A->log,
- "Function '%s' not found (check argument types)",
- name);
- return NULL;
- }
- }
-
- if (!fun) {
- /* Next, try locating a constructor function for a user-defined type */
- fun = _slang_locate_struct_constructor(A, name);
- }
-
- /*
- * At this point, some heuristics are used to try to find a function
- * that matches the calling signature by means of casting or "unrolling"
- * of constructors.
- */
-
- if (!fun && _slang_is_vec_mat_type(name)) {
- /* Next, if this call looks like a vec() or mat() constructor call,
- * try "unwinding" the args to satisfy a constructor.
- */
- fun = _slang_find_function_by_max_argc(A->space.funcs, name);
- if (fun) {
- if (!_slang_adapt_call(oper, fun, &A->space, A->atoms, A->log)) {
- slang_info_log_error(A->log,
- "Function '%s' not found (check argument types)",
- name);
- return NULL;
- }
- }
- }
-
- if (!fun && _slang_is_vec_mat_type(name)) {
- /* Next, try casting args to the types of the formal parameters */
- int numArgs = oper->num_children;
- fun = _slang_find_function_by_argc(A->space.funcs, name, numArgs);
- if (!fun || !_slang_cast_func_params(oper, fun, &A->space, A->atoms, A->log)) {
- slang_info_log_error(A->log,
- "Function '%s' not found (check argument types)",
- name);
- return NULL;
- }
- assert(fun);
- }
-
- if (!fun) {
- slang_info_log_error(A->log,
- "Function '%s' not found (check argument types)",
- name);
- return NULL;
- }
-
- if (!fun->body) {
- /* The function body may be in another compilation unit.
- * We'll try concatenating the shaders and recompile at link time.
- */
- A->UnresolvedRefs = GL_TRUE;
- return new_node1(IR_NOP, NULL);
- }
-
- /* type checking to be sure function's return type matches 'dest' type */
- if (dest) {
- slang_typeinfo t0;
-
- slang_typeinfo_construct(&t0);
- typeof_operation(A, dest, &t0);
-
- if (!slang_type_specifier_equal(&t0.spec, &fun->header.type.specifier)) {
- slang_info_log_error(A->log,
- "Incompatible type returned by call to '%s'",
- name);
- return NULL;
- }
- }
-
- n = _slang_gen_function_call(A, fun, oper, dest);
-
- if (n && !n->Store && !dest
- && fun->header.type.specifier.type != SLANG_SPEC_VOID) {
- /* setup n->Store for the result of the function call */
- GLint size = _slang_sizeof_type_specifier(&fun->header.type.specifier);
- n->Store = _slang_new_ir_storage(PROGRAM_TEMPORARY, -1, size);
- /*printf("Alloc storage for function result, size %d \n", size);*/
- }
-
- if (oper->array_constructor) {
- /* free the temporary array constructor function now */
- slang_function_destruct(fun);
- }
-
- return n;
-}
-
-
-static slang_ir_node *
-_slang_gen_method_call(slang_assemble_ctx *A, slang_operation *oper)
-{
- slang_atom *a_length = slang_atom_pool_atom(A->atoms, "length");
- slang_ir_node *n;
- slang_variable *var;
-
- /* NOTE: In GLSL 1.20, there's only one kind of method
- * call: array.length(). Anything else is an error.
- */
- if (oper->a_id != a_length) {
- slang_info_log_error(A->log,
- "Undefined method call '%s'", (char *) oper->a_id);
- return NULL;
- }
-
- /* length() takes no arguments */
- if (oper->num_children > 0) {
- slang_info_log_error(A->log, "Invalid arguments to length() method");
- return NULL;
- }
-
- /* lookup the object/variable */
- var = _slang_variable_locate(oper->locals, oper->a_obj, GL_TRUE);
- if (!var || var->type.specifier.type != SLANG_SPEC_ARRAY) {
- slang_info_log_error(A->log,
- "Undefined object '%s'", (char *) oper->a_obj);
- return NULL;
- }
-
- /* Create a float/literal IR node encoding the array length */
- n = new_node0(IR_FLOAT);
- if (n) {
- n->Value[0] = (float) _slang_array_length(var);
- n->Store = _slang_new_ir_storage(PROGRAM_CONSTANT, -1, 1);
- }
- return n;
-}
-
-
-static GLboolean
-_slang_is_constant_cond(const slang_operation *oper, GLboolean *value)
-{
- if (oper->type == SLANG_OPER_LITERAL_FLOAT ||
- oper->type == SLANG_OPER_LITERAL_INT ||
- oper->type == SLANG_OPER_LITERAL_BOOL) {
- if (oper->literal[0])
- *value = GL_TRUE;
- else
- *value = GL_FALSE;
- return GL_TRUE;
- }
- else if (oper->type == SLANG_OPER_EXPRESSION &&
- oper->num_children == 1) {
- return _slang_is_constant_cond(&oper->children[0], value);
- }
- return GL_FALSE;
-}
-
-
-/**
- * Test if an operation is a scalar or boolean.
- */
-static GLboolean
-_slang_is_scalar_or_boolean(slang_assemble_ctx *A, slang_operation *oper)
-{
- slang_typeinfo type;
- GLint size;
-
- slang_typeinfo_construct(&type);
- typeof_operation(A, oper, &type);
- size = _slang_sizeof_type_specifier(&type.spec);
- slang_typeinfo_destruct(&type);
- return size == 1;
-}
-
-
-/**
- * Test if an operation is boolean.
- */
-static GLboolean
-_slang_is_boolean(slang_assemble_ctx *A, slang_operation *oper)
-{
- slang_typeinfo type;
- GLboolean isBool;
-
- slang_typeinfo_construct(&type);
- typeof_operation(A, oper, &type);
- isBool = (type.spec.type == SLANG_SPEC_BOOL);
- slang_typeinfo_destruct(&type);
- return isBool;
-}
-
-
-/**
- * Check if a loop contains a 'continue' statement.
- * Stop looking if we find a nested loop.
- */
-static GLboolean
-_slang_loop_contains_continue(const slang_operation *oper)
-{
- switch (oper->type) {
- case SLANG_OPER_CONTINUE:
- return GL_TRUE;
- case SLANG_OPER_FOR:
- case SLANG_OPER_DO:
- case SLANG_OPER_WHILE:
- /* stop upon finding a nested loop */
- return GL_FALSE;
- default:
- /* recurse */
- {
- GLuint i;
- for (i = 0; i < oper->num_children; i++) {
- const slang_operation *child = slang_oper_child_const(oper, i);
- if (_slang_loop_contains_continue(child))
- return GL_TRUE;
- }
- }
- return GL_FALSE;
- }
-}
-
-
-/**
- * Check if a loop contains a 'continue' or 'break' statement.
- * Stop looking if we find a nested loop.
- */
-static GLboolean
-_slang_loop_contains_continue_or_break(const slang_operation *oper)
-{
- switch (oper->type) {
- case SLANG_OPER_CONTINUE:
- case SLANG_OPER_BREAK:
- return GL_TRUE;
- case SLANG_OPER_FOR:
- case SLANG_OPER_DO:
- case SLANG_OPER_WHILE:
- /* stop upon finding a nested loop */
- return GL_FALSE;
- default:
- /* recurse */
- {
- GLuint i;
- for (i = 0; i < oper->num_children; i++) {
- const slang_operation *child = slang_oper_child_const(oper, i);
- if (_slang_loop_contains_continue_or_break(child))
- return GL_TRUE;
- }
- }
- return GL_FALSE;
- }
-}
-
-
-/**
- * Replace 'break' and 'continue' statements inside a do and while loops.
- * This is a recursive helper function used by
- * _slang_gen_do/while_without_continue().
- */
-static void
-replace_break_and_cont(slang_assemble_ctx *A, slang_operation *oper)
-{
- switch (oper->type) {
- case SLANG_OPER_BREAK:
- /* replace 'break' with "_notBreakFlag = false; break" */
- {
- slang_operation *block = oper;
- block->type = SLANG_OPER_BLOCK_NEW_SCOPE;
- slang_operation_add_children(block, 2);
- {
- slang_operation *assign = slang_oper_child(block, 0);
- assign->type = SLANG_OPER_ASSIGN;
- slang_operation_add_children(assign, 2);
- {
- slang_operation *lhs = slang_oper_child(assign, 0);
- slang_operation_identifier(lhs, A, "_notBreakFlag");
- }
- {
- slang_operation *rhs = slang_oper_child(assign, 1);
- slang_operation_literal_bool(rhs, GL_FALSE);
- }
- }
- {
- slang_operation *brk = slang_oper_child(block, 1);
- brk->type = SLANG_OPER_BREAK;
- assert(!brk->children);
- }
- }
- break;
- case SLANG_OPER_CONTINUE:
- /* convert continue into a break */
- oper->type = SLANG_OPER_BREAK;
- break;
- case SLANG_OPER_FOR:
- case SLANG_OPER_DO:
- case SLANG_OPER_WHILE:
- /* stop upon finding a nested loop */
- break;
- default:
- /* recurse */
- {
- GLuint i;
- for (i = 0; i < oper->num_children; i++) {
- replace_break_and_cont(A, slang_oper_child(oper, i));
- }
- }
- }
-}
-
-
-/**
- * Transform a while-loop so that continue statements are converted to breaks.
- * Then do normal IR code generation.
- *
- * Before:
- *
- * while (LOOPCOND) {
- * A;
- * if (IFCOND)
- * continue;
- * B;
- * break;
- * C;
- * }
- *
- * After:
- *
- * {
- * bool _notBreakFlag = 1;
- * while (_notBreakFlag && LOOPCOND) {
- * do {
- * A;
- * if (IFCOND) {
- * break; // was continue
- * }
- * B;
- * _notBreakFlag = 0; // was
- * break; // break
- * C;
- * } while (0)
- * }
- * }
- */
-static slang_ir_node *
-_slang_gen_while_without_continue(slang_assemble_ctx *A, slang_operation *oper)
-{
- slang_operation *top;
- slang_operation *innerBody;
-
- assert(oper->type == SLANG_OPER_WHILE);
-
- top = slang_operation_new(1);
- top->type = SLANG_OPER_BLOCK_NEW_SCOPE;
- top->locals->outer_scope = oper->locals->outer_scope;
- slang_operation_add_children(top, 2);
-
- /* declare: bool _notBreakFlag = true */
- {
- slang_operation *condDecl = slang_oper_child(top, 0);
- slang_generate_declaration(A, top->locals, condDecl,
- SLANG_SPEC_BOOL, "_notBreakFlag", GL_TRUE);
- }
-
- /* build outer while-loop: while (_notBreakFlag && LOOPCOND) { ... } */
- {
- slang_operation *outerWhile = slang_oper_child(top, 1);
- outerWhile->type = SLANG_OPER_WHILE;
- slang_operation_add_children(outerWhile, 2);
-
- /* _notBreakFlag && LOOPCOND */
- {
- slang_operation *cond = slang_oper_child(outerWhile, 0);
- cond->type = SLANG_OPER_LOGICALAND;
- slang_operation_add_children(cond, 2);
- {
- slang_operation *notBreak = slang_oper_child(cond, 0);
- slang_operation_identifier(notBreak, A, "_notBreakFlag");
- }
- {
- slang_operation *origCond = slang_oper_child(cond, 1);
- slang_operation_copy(origCond, slang_oper_child(oper, 0));
- }
- }
-
- /* inner loop */
- {
- slang_operation *innerDo = slang_oper_child(outerWhile, 1);
- innerDo->type = SLANG_OPER_DO;
- slang_operation_add_children(innerDo, 2);
-
- /* copy original do-loop body into inner do-loop's body */
- innerBody = slang_oper_child(innerDo, 0);
- slang_operation_copy(innerBody, slang_oper_child(oper, 1));
- innerBody->locals->outer_scope = innerDo->locals;
-
- /* inner do-loop's condition is constant/false */
- {
- slang_operation *constFalse = slang_oper_child(innerDo, 1);
- slang_operation_literal_bool(constFalse, GL_FALSE);
- }
- }
- }
-
- /* Finally, in innerBody,
- * replace "break" with "_notBreakFlag = 0; break"
- * replace "continue" with "break"
- */
- replace_break_and_cont(A, innerBody);
-
- /*slang_print_tree(top, 0);*/
-
- return _slang_gen_operation(A, top);
-
- return NULL;
-}
-
-
-/**
- * Generate loop code using high-level IR_LOOP instruction
- */
-static slang_ir_node *
-_slang_gen_while(slang_assemble_ctx * A, slang_operation *oper)
-{
- /*
- * LOOP:
- * BREAK if !expr (child[0])
- * body code (child[1])
- */
- slang_ir_node *loop, *breakIf, *body;
- GLboolean isConst, constTrue = GL_FALSE;
-
- if (!A->EmitContReturn) {
- /* We don't want to emit CONT instructions. If this while-loop has
- * a continue, translate it away.
- */
- if (_slang_loop_contains_continue(slang_oper_child(oper, 1))) {
- return _slang_gen_while_without_continue(A, oper);
- }
- }
-
- /* type-check expression */
- if (!_slang_is_boolean(A, &oper->children[0])) {
- slang_info_log_error(A->log, "scalar/boolean expression expected for 'while'");
- return NULL;
- }
-
- /* Check if loop condition is a constant */
- isConst = _slang_is_constant_cond(&oper->children[0], &constTrue);
-
- if (isConst && !constTrue) {
- /* loop is never executed! */
- return new_node0(IR_NOP);
- }
-
- /* Begin new loop */
- loop = new_loop(NULL);
-
- /* save loop state */
- push_loop(A, oper, loop);
-
- if (isConst && constTrue) {
- /* while(nonzero constant), no conditional break */
- breakIf = NULL;
- }
- else {
- slang_ir_node *cond
- = new_cond(new_not(_slang_gen_operation(A, &oper->children[0])));
- breakIf = new_break_if_true(A, cond);
- }
- body = _slang_gen_operation(A, &oper->children[1]);
- loop->Children[0] = new_seq(breakIf, body);
-
- /* Do infinite loop detection */
- /* loop->List is head of linked list of break/continue nodes */
- if (!loop->List && isConst && constTrue) {
- /* infinite loop detected */
- pop_loop(A);
- slang_info_log_error(A->log, "Infinite loop detected!");
- return NULL;
- }
-
- /* restore loop state */
- pop_loop(A);
-
- return loop;
-}
-
-
-/**
- * Transform a do-while-loop so that continue statements are converted to breaks.
- * Then do normal IR code generation.
- *
- * Before:
- *
- * do {
- * A;
- * if (IFCOND)
- * continue;
- * B;
- * break;
- * C;
- * } while (LOOPCOND);
- *
- * After:
- *
- * {
- * bool _notBreakFlag = 1;
- * do {
- * do {
- * A;
- * if (IFCOND) {
- * break; // was continue
- * }
- * B;
- * _notBreakFlag = 0; // was
- * break; // break
- * C;
- * } while (0)
- * } while (_notBreakFlag && LOOPCOND);
- * }
- */
-static slang_ir_node *
-_slang_gen_do_without_continue(slang_assemble_ctx *A, slang_operation *oper)
-{
- slang_operation *top;
- slang_operation *innerBody;
-
- assert(oper->type == SLANG_OPER_DO);
-
- top = slang_operation_new(1);
- top->type = SLANG_OPER_BLOCK_NEW_SCOPE;
- top->locals->outer_scope = oper->locals->outer_scope;
- slang_operation_add_children(top, 2);
-
- /* declare: bool _notBreakFlag = true */
- {
- slang_operation *condDecl = slang_oper_child(top, 0);
- slang_generate_declaration(A, top->locals, condDecl,
- SLANG_SPEC_BOOL, "_notBreakFlag", GL_TRUE);
- }
-
- /* build outer do-loop: do { ... } while (_notBreakFlag && LOOPCOND) */
- {
- slang_operation *outerDo = slang_oper_child(top, 1);
- outerDo->type = SLANG_OPER_DO;
- slang_operation_add_children(outerDo, 2);
-
- /* inner do-loop */
- {
- slang_operation *innerDo = slang_oper_child(outerDo, 0);
- innerDo->type = SLANG_OPER_DO;
- slang_operation_add_children(innerDo, 2);
-
- /* copy original do-loop body into inner do-loop's body */
- innerBody = slang_oper_child(innerDo, 0);
- slang_operation_copy(innerBody, slang_oper_child(oper, 0));
- innerBody->locals->outer_scope = innerDo->locals;
-
- /* inner do-loop's condition is constant/false */
- {
- slang_operation *constFalse = slang_oper_child(innerDo, 1);
- slang_operation_literal_bool(constFalse, GL_FALSE);
- }
- }
-
- /* _notBreakFlag && LOOPCOND */
- {
- slang_operation *cond = slang_oper_child(outerDo, 1);
- cond->type = SLANG_OPER_LOGICALAND;
- slang_operation_add_children(cond, 2);
- {
- slang_operation *notBreak = slang_oper_child(cond, 0);
- slang_operation_identifier(notBreak, A, "_notBreakFlag");
- }
- {
- slang_operation *origCond = slang_oper_child(cond, 1);
- slang_operation_copy(origCond, slang_oper_child(oper, 1));
- }
- }
- }
-
- /* Finally, in innerBody,
- * replace "break" with "_notBreakFlag = 0; break"
- * replace "continue" with "break"
- */
- replace_break_and_cont(A, innerBody);
-
- /*slang_print_tree(top, 0);*/
-
- return _slang_gen_operation(A, top);
-}
-
-
-/**
- * Generate IR tree for a do-while loop using high-level LOOP, IF instructions.
- */
-static slang_ir_node *
-_slang_gen_do(slang_assemble_ctx * A, slang_operation *oper)
-{
- /*
- * LOOP:
- * body code (child[0])
- * tail code:
- * BREAK if !expr (child[1])
- */
- slang_ir_node *loop;
- GLboolean isConst, constTrue;
-
- if (!A->EmitContReturn) {
- /* We don't want to emit CONT instructions. If this do-loop has
- * a continue, translate it away.
- */
- if (_slang_loop_contains_continue(slang_oper_child(oper, 0))) {
- return _slang_gen_do_without_continue(A, oper);
- }
- }
-
- /* type-check expression */
- if (!_slang_is_boolean(A, &oper->children[1])) {
- slang_info_log_error(A->log, "scalar/boolean expression expected for 'do/while'");
- return NULL;
- }
-
- loop = new_loop(NULL);
-
- /* save loop state */
- push_loop(A, oper, loop);
-
- /* loop body: */
- loop->Children[0] = _slang_gen_operation(A, &oper->children[0]);
-
- /* Check if loop condition is a constant */
- isConst = _slang_is_constant_cond(&oper->children[1], &constTrue);
- if (isConst && constTrue) {
- /* do { } while(1) ==> no conditional break */
- loop->Children[1] = NULL; /* no tail code */
- }
- else {
- slang_ir_node *cond
- = new_cond(new_not(_slang_gen_operation(A, &oper->children[1])));
- loop->Children[1] = new_break_if_true(A, cond);
- }
-
- /* XXX we should do infinite loop detection, as above */
-
- /* restore loop state */
- pop_loop(A);
-
- return loop;
-}
-
-
-/**
- * Recursively count the number of operations rooted at 'oper'.
- * This gives some kind of indication of the size/complexity of an operation.
- */
-static GLuint
-sizeof_operation(const slang_operation *oper)
-{
- if (oper) {
- GLuint count = 1; /* me */
- GLuint i;
- for (i = 0; i < oper->num_children; i++) {
- count += sizeof_operation(&oper->children[i]);
- }
- return count;
- }
- else {
- return 0;
- }
-}
-
-
-/**
- * Determine if a for-loop can be unrolled.
- * At this time, only a rather narrow class of for loops can be unrolled.
- * See code for details.
- * When a loop can't be unrolled because it's too large we'll emit a
- * message to the log.
- */
-static GLboolean
-_slang_can_unroll_for_loop(slang_assemble_ctx * A, const slang_operation *oper)
-{
- GLuint bodySize;
- GLint start, end;
- const char *varName;
- slang_atom varId;
-
- if (oper->type != SLANG_OPER_FOR)
- return GL_FALSE;
-
- assert(oper->num_children == 4);
-
- if (_slang_loop_contains_continue_or_break(slang_oper_child_const(oper, 3)))
- return GL_FALSE;
-
- /* children[0] must be either "int i=constant" or "i=constant" */
- if (oper->children[0].type == SLANG_OPER_BLOCK_NO_NEW_SCOPE) {
- slang_variable *var;
-
- if (oper->children[0].children[0].type != SLANG_OPER_VARIABLE_DECL)
- return GL_FALSE;
-
- varId = oper->children[0].children[0].a_id;
-
- var = _slang_variable_locate(oper->children[0].children[0].locals,
- varId, GL_TRUE);
- if (!var)
- return GL_FALSE;
- if (!var->initializer)
- return GL_FALSE;
- if (var->initializer->type != SLANG_OPER_LITERAL_INT)
- return GL_FALSE;
- start = (GLint) var->initializer->literal[0];
- }
- else if (oper->children[0].type == SLANG_OPER_EXPRESSION) {
- if (oper->children[0].children[0].type != SLANG_OPER_ASSIGN)
- return GL_FALSE;
- if (oper->children[0].children[0].children[0].type != SLANG_OPER_IDENTIFIER)
- return GL_FALSE;
- if (oper->children[0].children[0].children[1].type != SLANG_OPER_LITERAL_INT)
- return GL_FALSE;
-
- varId = oper->children[0].children[0].children[0].a_id;
-
- start = (GLint) oper->children[0].children[0].children[1].literal[0];
- }
- else {
- return GL_FALSE;
- }
-
- /* children[1] must be "i<constant" */
- if (oper->children[1].type != SLANG_OPER_EXPRESSION)
- return GL_FALSE;
- if (oper->children[1].children[0].type != SLANG_OPER_LESS)
- return GL_FALSE;
- if (oper->children[1].children[0].children[0].type != SLANG_OPER_IDENTIFIER)
- return GL_FALSE;
- if (oper->children[1].children[0].children[1].type != SLANG_OPER_LITERAL_INT)
- return GL_FALSE;
-
- end = (GLint) oper->children[1].children[0].children[1].literal[0];
-
- /* children[2] must be "i++" or "++i" */
- if (oper->children[2].type != SLANG_OPER_POSTINCREMENT &&
- oper->children[2].type != SLANG_OPER_PREINCREMENT)
- return GL_FALSE;
- if (oper->children[2].children[0].type != SLANG_OPER_IDENTIFIER)
- return GL_FALSE;
-
- /* make sure the same variable name is used in all places */
- if ((oper->children[1].children[0].children[0].a_id != varId) ||
- (oper->children[2].children[0].a_id != varId))
- return GL_FALSE;
-
- varName = (const char *) varId;
-
- /* children[3], the loop body, can't be too large */
- bodySize = sizeof_operation(&oper->children[3]);
- if (bodySize > MAX_FOR_LOOP_UNROLL_BODY_SIZE) {
- slang_info_log_print(A->log,
- "Note: 'for (%s ... )' body is too large/complex"
- " to unroll",
- varName);
- return GL_FALSE;
- }
-
- if (start >= end)
- return GL_FALSE; /* degenerate case */
-
- if ((GLuint)(end - start) > MAX_FOR_LOOP_UNROLL_ITERATIONS) {
- slang_info_log_print(A->log,
- "Note: 'for (%s=%d; %s<%d; ++%s)' is too"
- " many iterations to unroll",
- varName, start, varName, end, varName);
- return GL_FALSE;
- }
-
- if ((end - start) * bodySize > MAX_FOR_LOOP_UNROLL_COMPLEXITY) {
- slang_info_log_print(A->log,
- "Note: 'for (%s=%d; %s<%d; ++%s)' will generate"
- " too much code to unroll",
- varName, start, varName, end, varName);
- return GL_FALSE;
- }
-
- return GL_TRUE; /* we can unroll the loop */
-}
-
-
-/**
- * Unroll a for-loop.
- * First we determine the number of iterations to unroll.
- * Then for each iteration:
- * make a copy of the loop body
- * replace instances of the loop variable with the current iteration value
- * generate IR code for the body
- * \return pointer to generated IR code or NULL if error, out of memory, etc.
- */
-static slang_ir_node *
-_slang_unroll_for_loop(slang_assemble_ctx * A, const slang_operation *oper)
-{
- GLint start, end, iter;
- slang_ir_node *n, *root = NULL;
- slang_atom varId;
-
- if (oper->children[0].type == SLANG_OPER_BLOCK_NO_NEW_SCOPE) {
- /* for (int i=0; ... */
- slang_variable *var;
-
- varId = oper->children[0].children[0].a_id;
- var = _slang_variable_locate(oper->children[0].children[0].locals,
- varId, GL_TRUE);
- assert(var);
- start = (GLint) var->initializer->literal[0];
- }
- else {
- /* for (i=0; ... */
- varId = oper->children[0].children[0].children[0].a_id;
- start = (GLint) oper->children[0].children[0].children[1].literal[0];
- }
-
- end = (GLint) oper->children[1].children[0].children[1].literal[0];
-
- for (iter = start; iter < end; iter++) {
- slang_operation *body;
-
- /* make a copy of the loop body */
- body = slang_operation_new(1);
- if (!body)
- return NULL;
-
- if (!slang_operation_copy(body, &oper->children[3]))
- return NULL;
-
- /* in body, replace instances of 'varId' with literal 'iter' */
- {
- slang_variable *oldVar;
- slang_operation *newOper;
-
- oldVar = _slang_variable_locate(oper->locals, varId, GL_TRUE);
- if (!oldVar) {
- /* undeclared loop variable */
- slang_operation_delete(body);
- return NULL;
- }
-
- newOper = slang_operation_new(1);
- newOper->type = SLANG_OPER_LITERAL_INT;
- newOper->literal_size = 1;
- newOper->literal[0] = (GLfloat) iter;
-
- /* replace instances of the loop variable with newOper */
- slang_substitute(A, body, 1, &oldVar, &newOper, GL_FALSE);
- }
-
- /* do IR codegen for body */
- n = _slang_gen_operation(A, body);
- if (!n)
- return NULL;
-
- root = new_seq(root, n);
-
- slang_operation_delete(body);
- }
-
- return root;
-}
-
-
-/**
- * Replace 'continue' statement with 'break' inside a for-loop.
- * This is a recursive helper function used by _slang_gen_for_without_continue().
- */
-static void
-replace_continue_with_break(slang_assemble_ctx *A, slang_operation *oper)
-{
- switch (oper->type) {
- case SLANG_OPER_CONTINUE:
- oper->type = SLANG_OPER_BREAK;
- break;
- case SLANG_OPER_FOR:
- case SLANG_OPER_DO:
- case SLANG_OPER_WHILE:
- /* stop upon finding a nested loop */
- break;
- default:
- /* recurse */
- {
- GLuint i;
- for (i = 0; i < oper->num_children; i++) {
- replace_continue_with_break(A, slang_oper_child(oper, i));
- }
- }
- }
-}
-
-
-/**
- * Transform a for-loop so that continue statements are converted to breaks.
- * Then do normal IR code generation.
- *
- * Before:
- *
- * for (INIT; LOOPCOND; INCR) {
- * A;
- * if (IFCOND) {
- * continue;
- * }
- * B;
- * }
- *
- * After:
- *
- * {
- * bool _condFlag = 1;
- * for (INIT; _condFlag; ) {
- * for ( ; _condFlag = LOOPCOND; INCR) {
- * A;
- * if (IFCOND) {
- * break;
- * }
- * B;
- * }
- * if (_condFlag)
- * INCR;
- * }
- * }
- */
-static slang_ir_node *
-_slang_gen_for_without_continue(slang_assemble_ctx *A, slang_operation *oper)
-{
- slang_operation *top;
- slang_operation *outerFor, *innerFor, *init, *cond, *incr;
- slang_operation *lhs, *rhs;
-
- assert(oper->type == SLANG_OPER_FOR);
-
- top = slang_operation_new(1);
- top->type = SLANG_OPER_BLOCK_NEW_SCOPE;
- top->locals->outer_scope = oper->locals->outer_scope;
- slang_operation_add_children(top, 2);
-
- /* declare: bool _condFlag = true */
- {
- slang_operation *condDecl = slang_oper_child(top, 0);
- slang_generate_declaration(A, top->locals, condDecl,
- SLANG_SPEC_BOOL, "_condFlag", GL_TRUE);
- }
-
- /* build outer loop: for (INIT; _condFlag; ) { */
- outerFor = slang_oper_child(top, 1);
- outerFor->type = SLANG_OPER_FOR;
- slang_operation_add_children(outerFor, 4);
-
- init = slang_oper_child(outerFor, 0);
- slang_operation_copy(init, slang_oper_child(oper, 0));
-
- cond = slang_oper_child(outerFor, 1);
- cond->type = SLANG_OPER_IDENTIFIER;
- cond->a_id = slang_atom_pool_atom(A->atoms, "_condFlag");
-
- incr = slang_oper_child(outerFor, 2);
- incr->type = SLANG_OPER_VOID;
-
- /* body of the outer loop */
- {
- slang_operation *block = slang_oper_child(outerFor, 3);
-
- slang_operation_add_children(block, 2);
- block->type = SLANG_OPER_BLOCK_NO_NEW_SCOPE;
-
- /* build inner loop: for ( ; _condFlag = LOOPCOND; INCR) { */
- {
- innerFor = slang_oper_child(block, 0);
-
- /* make copy of orig loop */
- slang_operation_copy(innerFor, oper);
- assert(innerFor->type == SLANG_OPER_FOR);
- innerFor->locals->outer_scope = block->locals;
-
- init = slang_oper_child(innerFor, 0);
- init->type = SLANG_OPER_VOID; /* leak? */
-
- cond = slang_oper_child(innerFor, 1);
- slang_operation_destruct(cond);
- cond->type = SLANG_OPER_ASSIGN;
- cond->locals = _slang_variable_scope_new(innerFor->locals);
- slang_operation_add_children(cond, 2);
-
- lhs = slang_oper_child(cond, 0);
- lhs->type = SLANG_OPER_IDENTIFIER;
- lhs->a_id = slang_atom_pool_atom(A->atoms, "_condFlag");
-
- rhs = slang_oper_child(cond, 1);
- slang_operation_copy(rhs, slang_oper_child(oper, 1));
- }
-
- /* if (_condFlag) INCR; */
- {
- slang_operation *ifop = slang_oper_child(block, 1);
- ifop->type = SLANG_OPER_IF;
- slang_operation_add_children(ifop, 2);
-
- /* re-use cond node build above */
- slang_operation_copy(slang_oper_child(ifop, 0), cond);
-
- /* incr node from original for-loop operation */
- slang_operation_copy(slang_oper_child(ifop, 1),
- slang_oper_child(oper, 2));
- }
-
- /* finally, replace "continue" with "break" in the inner for-loop */
- replace_continue_with_break(A, slang_oper_child(innerFor, 3));
- }
-
- return _slang_gen_operation(A, top);
-}
-
-
-
-/**
- * Generate IR for a for-loop. Unrolling will be done when possible.
- */
-static slang_ir_node *
-_slang_gen_for(slang_assemble_ctx * A, slang_operation *oper)
-{
- GLboolean unroll;
-
- if (!A->EmitContReturn) {
- /* We don't want to emit CONT instructions. If this for-loop has
- * a continue, translate it away.
- */
- if (_slang_loop_contains_continue(slang_oper_child(oper, 3))) {
- return _slang_gen_for_without_continue(A, oper);
- }
- }
-
- unroll = _slang_can_unroll_for_loop(A, oper);
- if (unroll) {
- slang_ir_node *code = _slang_unroll_for_loop(A, oper);
- if (code)
- return code;
- }
-
- assert(oper->type == SLANG_OPER_FOR);
-
- /* conventional for-loop code generation */
- {
- /*
- * init code (child[0])
- * LOOP:
- * BREAK if !expr (child[1])
- * body code (child[3])
- * tail code:
- * incr code (child[2]) // XXX continue here
- */
- slang_ir_node *loop, *cond, *breakIf, *body, *init, *incr;
- init = _slang_gen_operation(A, &oper->children[0]);
- loop = new_loop(NULL);
-
- /* save loop state */
- push_loop(A, oper, loop);
-
- cond = new_cond(new_not(_slang_gen_operation(A, &oper->children[1])));
- breakIf = new_break_if_true(A, cond);
- body = _slang_gen_operation(A, &oper->children[3]);
- incr = _slang_gen_operation(A, &oper->children[2]);
-
- loop->Children[0] = new_seq(breakIf, body);
- loop->Children[1] = incr; /* tail code */
-
- /* restore loop state */
- pop_loop(A);
-
- return new_seq(init, loop);
- }
-}
-
-
-static slang_ir_node *
-_slang_gen_continue(slang_assemble_ctx * A, const slang_operation *oper)
-{
- slang_ir_node *n, *cont, *incr = NULL, *loopNode;
-
- assert(oper->type == SLANG_OPER_CONTINUE);
- loopNode = current_loop_ir(A);
- assert(loopNode);
- assert(loopNode->Opcode == IR_LOOP);
-
- cont = new_node0(IR_CONT);
- if (cont) {
- cont->Parent = loopNode;
- /* insert this node at head of linked list of cont/break instructions */
- cont->List = loopNode->List;
- loopNode->List = cont;
- }
-
- n = new_seq(incr, cont);
- return n;
-}
-
-
-/**
- * Determine if the given operation is of a specific type.
- */
-static GLboolean
-is_operation_type(const slang_operation *oper, slang_operation_type type)
-{
- if (oper->type == type)
- return GL_TRUE;
- else if ((oper->type == SLANG_OPER_BLOCK_NEW_SCOPE ||
- oper->type == SLANG_OPER_BLOCK_NO_NEW_SCOPE) &&
- oper->num_children == 1)
- return is_operation_type(&oper->children[0], type);
- else
- return GL_FALSE;
-}
-
-
-/**
- * Generate IR tree for an if/then/else conditional using high-level
- * IR_IF instruction.
- */
-static slang_ir_node *
-_slang_gen_if(slang_assemble_ctx * A, const slang_operation *oper)
-{
- /*
- * eval expr (child[0])
- * IF expr THEN
- * if-body code
- * ELSE
- * else-body code
- * ENDIF
- */
- const GLboolean haveElseClause = !_slang_is_noop(&oper->children[2]);
- slang_ir_node *ifNode, *cond, *ifBody, *elseBody;
- GLboolean isConst, constTrue;
-
- /* type-check expression */
- if (!_slang_is_boolean(A, &oper->children[0])) {
- slang_info_log_error(A->log, "boolean expression expected for 'if'");
- return NULL;
- }
-
- if (!_slang_is_scalar_or_boolean(A, &oper->children[0])) {
- slang_info_log_error(A->log, "scalar/boolean expression expected for 'if'");
- return NULL;
- }
-
- isConst = _slang_is_constant_cond(&oper->children[0], &constTrue);
- if (isConst) {
- if (constTrue) {
- /* if (true) ... */
- return _slang_gen_operation(A, &oper->children[1]);
- }
- else {
- /* if (false) ... */
- return _slang_gen_operation(A, &oper->children[2]);
- }
- }
-
- cond = _slang_gen_operation(A, &oper->children[0]);
- cond = new_cond(cond);
-
- if (is_operation_type(&oper->children[1], SLANG_OPER_BREAK)
- && !haveElseClause) {
- /* Special case: generate a conditional break */
- ifBody = new_break_if_true(A, cond);
- return ifBody;
- }
- else if (is_operation_type(&oper->children[1], SLANG_OPER_CONTINUE)
- && !haveElseClause
- && current_loop_oper(A)
- && current_loop_oper(A)->type != SLANG_OPER_FOR) {
- /* Special case: generate a conditional continue */
- ifBody = new_cont_if_true(A, cond);
- return ifBody;
- }
- else {
- /* general case */
- ifBody = _slang_gen_operation(A, &oper->children[1]);
- if (haveElseClause)
- elseBody = _slang_gen_operation(A, &oper->children[2]);
- else
- elseBody = NULL;
- ifNode = new_if(cond, ifBody, elseBody);
- return ifNode;
- }
-}
-
-
-
-static slang_ir_node *
-_slang_gen_not(slang_assemble_ctx * A, const slang_operation *oper)
-{
- slang_ir_node *n;
-
- assert(oper->type == SLANG_OPER_NOT);
-
- /* type-check expression */
- if (!_slang_is_scalar_or_boolean(A, &oper->children[0])) {
- slang_info_log_error(A->log,
- "scalar/boolean expression expected for '!'");
- return NULL;
- }
-
- n = _slang_gen_operation(A, &oper->children[0]);
- if (n)
- return new_not(n);
- else
- return NULL;
-}
-
-
-static slang_ir_node *
-_slang_gen_xor(slang_assemble_ctx * A, const slang_operation *oper)
-{
- slang_ir_node *n1, *n2;
-
- assert(oper->type == SLANG_OPER_LOGICALXOR);
-
- if (!_slang_is_scalar_or_boolean(A, &oper->children[0]) ||
- !_slang_is_scalar_or_boolean(A, &oper->children[0])) {
- slang_info_log_error(A->log,
- "scalar/boolean expressions expected for '^^'");
- return NULL;
- }
-
- n1 = _slang_gen_operation(A, &oper->children[0]);
- if (!n1)
- return NULL;
- n2 = _slang_gen_operation(A, &oper->children[1]);
- if (!n2)
- return NULL;
- return new_node2(IR_NOTEQUAL, n1, n2);
-}
-
-
-/**
- * Generate IR node for storage of a temporary of given size.
- */
-static slang_ir_node *
-_slang_gen_temporary(GLint size)
-{
- slang_ir_storage *store;
- slang_ir_node *n = NULL;
-
- store = _slang_new_ir_storage(PROGRAM_TEMPORARY, -2, size);
- if (store) {
- n = new_node0(IR_VAR_DECL);
- if (n) {
- n->Store = store;
- }
- else {
- _slang_free(store);
- }
- }
- return n;
-}
-
-
-/**
- * Generate program constants for an array.
- * Ex: const vec2[3] v = vec2[3](vec2(1,1), vec2(2,2), vec2(3,3));
- * This will allocate and initialize three vector constants, storing
- * the array in constant memory, not temporaries like a non-const array.
- * This can also be used for uniform array initializers.
- * \return GL_TRUE for success, GL_FALSE if failure (semantic error, etc).
- */
-static GLboolean
-make_constant_array(slang_assemble_ctx *A,
- slang_variable *var,
- slang_operation *initializer)
-{
- struct gl_program *prog = A->program;
- const GLenum datatype = _slang_gltype_from_specifier(&var->type.specifier);
- const char *varName = (char *) var->a_name;
- const GLuint numElements = initializer->num_children;
- GLint size;
- GLuint i, j;
- GLfloat *values;
-
- if (!var->store) {
- var->store = _slang_new_ir_storage(PROGRAM_UNDEFINED, -6, -6);
- }
- size = var->store->Size;
-
- assert(var->type.qualifier == SLANG_QUAL_CONST ||
- var->type.qualifier == SLANG_QUAL_UNIFORM);
- assert(initializer->type == SLANG_OPER_CALL);
- assert(initializer->array_constructor);
-
- values = (GLfloat *) malloc(numElements * 4 * sizeof(GLfloat));
-
- /* convert constructor params into ordinary floats */
- for (i = 0; i < numElements; i++) {
- const slang_operation *op = &initializer->children[i];
- if (op->type != SLANG_OPER_LITERAL_FLOAT) {
- /* unsupported type for this optimization */
- free(values);
- return GL_FALSE;
- }
- for (j = 0; j < op->literal_size; j++) {
- values[i * 4 + j] = op->literal[j];
- }
- for ( ; j < 4; j++) {
- values[i * 4 + j] = 0.0f;
- }
- }
-
- /* slightly different paths for constants vs. uniforms */
- if (var->type.qualifier == SLANG_QUAL_UNIFORM) {
- var->store->File = PROGRAM_UNIFORM;
- var->store->Index = _mesa_add_uniform(prog->Parameters, varName,
- size, datatype, values);
- }
- else {
- var->store->File = PROGRAM_CONSTANT;
- var->store->Index = _mesa_add_named_constant(prog->Parameters, varName,
- values, size);
- }
- assert(var->store->Size == size);
-
- free(values);
-
- return GL_TRUE;
-}
-
-
-
-/**
- * Generate IR node for allocating/declaring a variable (either a local or
- * a global).
- * Generally, this involves allocating an slang_ir_storage instance for the
- * variable, choosing a register file (temporary, constant, etc).
- * For ordinary variables we do not yet allocate storage though. We do that
- * when we find the first actual use of the variable to avoid allocating temp
- * regs that will never get used.
- * At this time, uniforms are always allocated space in this function.
- *
- * \param initializer Optional initializer expression for the variable.
- */
-static slang_ir_node *
-_slang_gen_var_decl(slang_assemble_ctx *A, slang_variable *var,
- slang_operation *initializer)
-{
- const char *varName = (const char *) var->a_name;
- const GLenum datatype = _slang_gltype_from_specifier(&var->type.specifier);
- slang_ir_node *varDecl, *n;
- slang_ir_storage *store;
- GLint arrayLen, size, totalSize; /* if array then totalSize > size */
- gl_register_file file;
-
- /*assert(!var->declared);*/
- var->declared = GL_TRUE;
-
- /* determine GPU register file for simple cases */
- if (is_sampler_type(&var->type)) {
- file = PROGRAM_SAMPLER;
- }
- else if (var->type.qualifier == SLANG_QUAL_UNIFORM) {
- file = PROGRAM_UNIFORM;
- }
- else {
- file = PROGRAM_TEMPORARY;
- }
-
- size = _slang_sizeof_type_specifier(&var->type.specifier);
- if (size <= 0) {
- slang_info_log_error(A->log, "invalid declaration for '%s'", varName);
- return NULL;
- }
-
- arrayLen = _slang_array_length(var);
- totalSize = _slang_array_size(size, arrayLen);
-
- /* Allocate IR node for the declaration */
- varDecl = new_node0(IR_VAR_DECL);
- if (!varDecl)
- return NULL;
-
- /* Allocate slang_ir_storage for this variable if needed.
- * Note that we may not actually allocate a constant or temporary register
- * until later.
- */
- if (!var->store) {
- GLint index = -7; /* TBD / unknown */
- var->store = _slang_new_ir_storage(file, index, totalSize);
- if (!var->store)
- return NULL; /* out of memory */
- }
-
- /* set the IR node's Var and Store pointers */
- varDecl->Var = var;
- varDecl->Store = var->store;
-
-
- store = var->store;
-
- /* if there's an initializer, generate IR for the expression */
- if (initializer) {
- slang_ir_node *varRef, *init;
-
- if (var->type.qualifier == SLANG_QUAL_CONST) {
- /* if the variable is const, the initializer must be a const
- * expression as well.
- */
-#if 0
- if (!_slang_is_constant_expr(initializer)) {
- slang_info_log_error(A->log,
- "initializer for %s not constant", varName);
- return NULL;
- }
-#endif
- }
-
- if (var->type.qualifier == SLANG_QUAL_UNIFORM &&
- !A->allow_uniform_initializers) {
- slang_info_log_error(A->log,
- "initializer for uniform %s not allowed",
- varName);
- return NULL;
- }
-
- /* IR for the variable we're initializing */
- varRef = new_var(A, var);
- if (!varRef) {
- slang_info_log_error(A->log, "out of memory");
- return NULL;
- }
-
- /* constant-folding, etc here */
- _slang_simplify(initializer, &A->space, A->atoms);
-
- /* look for simple constant-valued variables and uniforms */
- if (var->type.qualifier == SLANG_QUAL_CONST ||
- var->type.qualifier == SLANG_QUAL_UNIFORM) {
-
- if (initializer->type == SLANG_OPER_CALL &&
- initializer->array_constructor) {
- /* array initializer */
- if (make_constant_array(A, var, initializer))
- return varRef;
- }
- else if (initializer->type == SLANG_OPER_LITERAL_FLOAT ||
- initializer->type == SLANG_OPER_LITERAL_INT) {
- /* simple float/vector initializer */
- if (store->File == PROGRAM_UNIFORM) {
- store->Index = _mesa_add_uniform(A->program->Parameters,
- varName,
- totalSize, datatype,
- initializer->literal);
- store->Swizzle = _slang_var_swizzle(size, 0);
- return varRef;
- }
-#if 0
- else {
- store->File = PROGRAM_CONSTANT;
- store->Index = _mesa_add_named_constant(A->program->Parameters,
- varName,
- initializer->literal,
- totalSize);
- store->Swizzle = _slang_var_swizzle(size, 0);
- return varRef;
- }
-#endif
- }
- }
-
- /* IR for initializer */
- init = _slang_gen_operation(A, initializer);
- if (!init)
- return NULL;
-
- /* XXX remove this when type checking is added above */
- if (init->Store && init->Store->Size != totalSize) {
- slang_info_log_error(A->log, "invalid assignment (wrong types)");
- return NULL;
- }
-
- /* assign RHS to LHS */
- n = new_node2(IR_COPY, varRef, init);
- n = new_seq(varDecl, n);
- }
- else {
- /* no initializer */
- n = varDecl;
- }
-
- if (store->File == PROGRAM_UNIFORM && store->Index < 0) {
- /* always need to allocate storage for uniforms at this point */
- store->Index = _mesa_add_uniform(A->program->Parameters, varName,
- totalSize, datatype, NULL);
- store->Swizzle = _slang_var_swizzle(size, 0);
- }
-
-#if 0
- printf("%s var %p %s store=%p index=%d size=%d\n",
- __FUNCTION__, (void *) var, (char *) varName,
- (void *) store, store->Index, store->Size);
-#endif
-
- return n;
-}
-
-
-/**
- * Generate code for a selection expression: b ? x : y
- * XXX In some cases we could implement a selection expression
- * with an LRP instruction (use the boolean as the interpolant).
- * Otherwise, we use an IF/ELSE/ENDIF construct.
- */
-static slang_ir_node *
-_slang_gen_select(slang_assemble_ctx *A, slang_operation *oper)
-{
- slang_ir_node *cond, *ifNode, *trueExpr, *falseExpr, *trueNode, *falseNode;
- slang_ir_node *tmpDecl, *tmpVar, *tree;
- slang_typeinfo type0, type1, type2;
- int size, isBool, isEqual;
-
- assert(oper->type == SLANG_OPER_SELECT);
- assert(oper->num_children == 3);
-
- /* type of children[0] must be boolean */
- slang_typeinfo_construct(&type0);
- typeof_operation(A, &oper->children[0], &type0);
- isBool = (type0.spec.type == SLANG_SPEC_BOOL);
- slang_typeinfo_destruct(&type0);
- if (!isBool) {
- slang_info_log_error(A->log, "selector type is not boolean");
- return NULL;
- }
-
- slang_typeinfo_construct(&type1);
- slang_typeinfo_construct(&type2);
- typeof_operation(A, &oper->children[1], &type1);
- typeof_operation(A, &oper->children[2], &type2);
- isEqual = slang_type_specifier_equal(&type1.spec, &type2.spec);
- slang_typeinfo_destruct(&type1);
- slang_typeinfo_destruct(&type2);
- if (!isEqual) {
- slang_info_log_error(A->log, "incompatible types for ?: operator");
- return NULL;
- }
-
- /* size of x or y's type */
- size = _slang_sizeof_type_specifier(&type1.spec);
- assert(size > 0);
-
- /* temporary var */
- tmpDecl = _slang_gen_temporary(size);
-
- /* the condition (child 0) */
- cond = _slang_gen_operation(A, &oper->children[0]);
- cond = new_cond(cond);
-
- /* if-true body (child 1) */
- tmpVar = new_node0(IR_VAR);
- tmpVar->Store = tmpDecl->Store;
- trueExpr = _slang_gen_operation(A, &oper->children[1]);
- trueNode = new_node2(IR_COPY, tmpVar, trueExpr);
-
- /* if-false body (child 2) */
- tmpVar = new_node0(IR_VAR);
- tmpVar->Store = tmpDecl->Store;
- falseExpr = _slang_gen_operation(A, &oper->children[2]);
- falseNode = new_node2(IR_COPY, tmpVar, falseExpr);
-
- ifNode = new_if(cond, trueNode, falseNode);
-
- /* tmp var value */
- tmpVar = new_node0(IR_VAR);
- tmpVar->Store = tmpDecl->Store;
-
- tree = new_seq(ifNode, tmpVar);
- tree = new_seq(tmpDecl, tree);
-
- /*_slang_print_ir_tree(tree, 10);*/
- return tree;
-}
-
-
-/**
- * Generate code for &&.
- */
-static slang_ir_node *
-_slang_gen_logical_and(slang_assemble_ctx *A, slang_operation *oper)
-{
- /* rewrite "a && b" as "a ? b : false" */
- slang_operation *select;
- slang_ir_node *n;
-
- select = slang_operation_new(1);
- select->type = SLANG_OPER_SELECT;
- slang_operation_add_children(select, 3);
-
- slang_operation_copy(slang_oper_child(select, 0), &oper->children[0]);
- slang_operation_copy(slang_oper_child(select, 1), &oper->children[1]);
- slang_operation_literal_bool(slang_oper_child(select, 2), GL_FALSE);
-
- n = _slang_gen_select(A, select);
- return n;
-}
-
-
-/**
- * Generate code for ||.
- */
-static slang_ir_node *
-_slang_gen_logical_or(slang_assemble_ctx *A, slang_operation *oper)
-{
- /* rewrite "a || b" as "a ? true : b" */
- slang_operation *select;
- slang_ir_node *n;
-
- select = slang_operation_new(1);
- select->type = SLANG_OPER_SELECT;
- slang_operation_add_children(select, 3);
-
- slang_operation_copy(slang_oper_child(select, 0), &oper->children[0]);
- slang_operation_literal_bool(slang_oper_child(select, 1), GL_TRUE);
- slang_operation_copy(slang_oper_child(select, 2), &oper->children[1]);
-
- n = _slang_gen_select(A, select);
- return n;
-}
-
-
-/**
- * Generate IR tree for a return statement.
- */
-static slang_ir_node *
-_slang_gen_return(slang_assemble_ctx * A, slang_operation *oper)
-{
- assert(oper->type == SLANG_OPER_RETURN);
- return new_return(A->curFuncEndLabel);
-}
-
-
-#if 0
-/**
- * Determine if the given operation/expression is const-valued.
- */
-static GLboolean
-_slang_is_constant_expr(const slang_operation *oper)
-{
- slang_variable *var;
- GLuint i;
-
- switch (oper->type) {
- case SLANG_OPER_IDENTIFIER:
- var = _slang_variable_locate(oper->locals, oper->a_id, GL_TRUE);
- if (var && var->type.qualifier == SLANG_QUAL_CONST)
- return GL_TRUE;
- return GL_FALSE;
- default:
- for (i = 0; i < oper->num_children; i++) {
- if (!_slang_is_constant_expr(&oper->children[i]))
- return GL_FALSE;
- }
- return GL_TRUE;
- }
-}
-#endif
-
-
-/**
- * Check if an assignment of type t1 to t0 is legal.
- * XXX more cases needed.
- */
-static GLboolean
-_slang_assignment_compatible(slang_assemble_ctx *A,
- slang_operation *op0,
- slang_operation *op1)
-{
- slang_typeinfo t0, t1;
- GLuint sz0, sz1;
-
- if (op0->type == SLANG_OPER_POSTINCREMENT ||
- op0->type == SLANG_OPER_POSTDECREMENT) {
- return GL_FALSE;
- }
-
- slang_typeinfo_construct(&t0);
- typeof_operation(A, op0, &t0);
-
- slang_typeinfo_construct(&t1);
- typeof_operation(A, op1, &t1);
-
- sz0 = _slang_sizeof_type_specifier(&t0.spec);
- sz1 = _slang_sizeof_type_specifier(&t1.spec);
-
-#if 1
- if (sz0 != sz1) {
- /*printf("assignment size mismatch %u vs %u\n", sz0, sz1);*/
- return GL_FALSE;
- }
-#endif
-
- if (t0.spec.type == SLANG_SPEC_STRUCT &&
- t1.spec.type == SLANG_SPEC_STRUCT &&
- t0.spec._struct->a_name != t1.spec._struct->a_name)
- return GL_FALSE;
-
- if (t0.spec.type == SLANG_SPEC_FLOAT &&
- t1.spec.type == SLANG_SPEC_BOOL)
- return GL_FALSE;
-
-#if 0 /* not used just yet - causes problems elsewhere */
- if (t0.spec.type == SLANG_SPEC_INT &&
- t1.spec.type == SLANG_SPEC_FLOAT)
- return GL_FALSE;
-#endif
-
- if (t0.spec.type == SLANG_SPEC_BOOL &&
- t1.spec.type == SLANG_SPEC_FLOAT)
- return GL_FALSE;
-
- if (t0.spec.type == SLANG_SPEC_BOOL &&
- t1.spec.type == SLANG_SPEC_INT)
- return GL_FALSE;
-
- return GL_TRUE;
-}
-
-
-/**
- * Generate IR tree for a local variable declaration.
- * Basically do some error checking and call _slang_gen_var_decl().
- */
-static slang_ir_node *
-_slang_gen_declaration(slang_assemble_ctx *A, slang_operation *oper)
-{
- const char *varName = (char *) oper->a_id;
- slang_variable *var;
- slang_ir_node *varDecl;
- slang_operation *initializer;
-
- assert(oper->type == SLANG_OPER_VARIABLE_DECL);
- assert(oper->num_children <= 1);
-
-
- /* lookup the variable by name */
- var = _slang_variable_locate(oper->locals, oper->a_id, GL_TRUE);
- if (!var)
- return NULL; /* "shouldn't happen" */
-
- if (var->type.qualifier == SLANG_QUAL_ATTRIBUTE ||
- var->type.qualifier == SLANG_QUAL_VARYING ||
- var->type.qualifier == SLANG_QUAL_UNIFORM) {
- /* can't declare attribute/uniform vars inside functions */
- slang_info_log_error(A->log,
- "local variable '%s' cannot be an attribute/uniform/varying",
- varName);
- return NULL;
- }
-
-#if 0
- if (v->declared) {
- slang_info_log_error(A->log, "variable '%s' redeclared", varName);
- return NULL;
- }
-#endif
-
- /* check if the var has an initializer */
- if (oper->num_children > 0) {
- assert(oper->num_children == 1);
- initializer = &oper->children[0];
- }
- else if (var->initializer) {
- initializer = var->initializer;
- }
- else {
- initializer = NULL;
- }
-
- if (initializer) {
- /* check/compare var type and initializer type */
- if (!_slang_assignment_compatible(A, oper, initializer)) {
- slang_info_log_error(A->log, "incompatible types in assignment");
- return NULL;
- }
- }
- else {
- if (var->type.qualifier == SLANG_QUAL_CONST) {
- slang_info_log_error(A->log,
- "const-qualified variable '%s' requires initializer",
- varName);
- return NULL;
- }
- }
-
- /* Generate IR node */
- varDecl = _slang_gen_var_decl(A, var, initializer);
- if (!varDecl)
- return NULL;
-
- return varDecl;
-}
-
-
-/**
- * Generate IR tree for a reference to a variable (such as in an expression).
- * This is different from a variable declaration.
- */
-static slang_ir_node *
-_slang_gen_variable(slang_assemble_ctx * A, slang_operation *oper)
-{
- /* If there's a variable associated with this oper (from inlining)
- * use it. Otherwise, use the oper's var id.
- */
- slang_atom name = oper->var ? oper->var->a_name : oper->a_id;
- slang_variable *var = _slang_variable_locate(oper->locals, name, GL_TRUE);
- slang_ir_node *n;
- if (!var || !var->declared) {
- /* Geometry shaders set gl_VerticesIn at link time
- * so we need to wait with resolving this variable
- * until then */
- if (A->program->Target == MESA_GEOMETRY_PROGRAM &&
- !strcmp((char*)name, "gl_VerticesIn") ){
- A->UnresolvedRefs = GL_TRUE;
- return NULL;
- }
- slang_info_log_error(A->log, "undefined variable '%s'", (char *) name);
- return NULL;
- }
- n = new_var(A, var);
- return n;
-}
-
-
-
-/**
- * Return the number of components actually named by the swizzle.
- * Recall that swizzles may have undefined/don't-care values.
- */
-static GLuint
-swizzle_size(GLuint swizzle)
-{
- GLuint size = 0, i;
- for (i = 0; i < 4; i++) {
- GLuint swz = GET_SWZ(swizzle, i);
- size += (swz <= 3);
- }
- return size;
-}
-
-
-static slang_ir_node *
-_slang_gen_swizzle(slang_ir_node *child, GLuint swizzle)
-{
- slang_ir_node *n = new_node1(IR_SWIZZLE, child);
- assert(child);
- if (n) {
- assert(!n->Store);
- n->Store = _slang_new_ir_storage_relative(0,
- swizzle_size(swizzle),
- child->Store);
- assert(n->Store);
- n->Store->Swizzle = swizzle;
- }
- return n;
-}
-
-
-static GLboolean
-is_store_writable(const slang_assemble_ctx *A, const slang_ir_storage *store)
-{
- while (store->Parent)
- store = store->Parent;
-
- if (!(store->File == PROGRAM_OUTPUT ||
- store->File == PROGRAM_TEMPORARY ||
- (store->File == PROGRAM_VARYING &&
- (A->program->Target == GL_VERTEX_PROGRAM_ARB ||
- A->program->Target == MESA_GEOMETRY_PROGRAM)))) {
- return GL_FALSE;
- }
- else {
- return GL_TRUE;
- }
-}
-
-
-/**
- * Walk up an IR storage path to compute the final swizzle.
- * This is used when we find an expression such as "foo.xz.yx".
- */
-static GLuint
-root_swizzle(const slang_ir_storage *st)
-{
- GLuint swizzle = st->Swizzle;
- while (st->Parent) {
- st = st->Parent;
- swizzle = _slang_swizzle_swizzle(st->Swizzle, swizzle);
- }
- return swizzle;
-}
-
-
-/**
- * Generate IR tree for an assignment (=).
- */
-static slang_ir_node *
-_slang_gen_assignment(slang_assemble_ctx * A, slang_operation *oper)
-{
- slang_operation *pred = NULL;
- slang_ir_node *n = NULL;
-
- if (oper->children[0].type == SLANG_OPER_IDENTIFIER) {
- /* Check that var is writeable */
- const char *varName = (char *) oper->children[0].a_id;
- slang_variable *var
- = _slang_variable_locate(oper->children[0].locals,
- oper->children[0].a_id, GL_TRUE);
- if (!var) {
- slang_info_log_error(A->log, "undefined variable '%s'", varName);
- return NULL;
- }
-
- if (var->type.qualifier == SLANG_QUAL_CONST ||
- var->type.qualifier == SLANG_QUAL_ATTRIBUTE ||
- var->type.qualifier == SLANG_QUAL_UNIFORM ||
- (var->type.qualifier == SLANG_QUAL_VARYING &&
- A->program->Target == GL_FRAGMENT_PROGRAM_ARB)) {
- slang_info_log_error(A->log,
- "illegal assignment to read-only variable '%s'",
- varName);
- return NULL;
- }
-
- /* check if we need to predicate this assignment based on __notRetFlag */
- if ((var->is_global ||
- var->type.qualifier == SLANG_QUAL_OUT ||
- var->type.qualifier == SLANG_QUAL_INOUT) && A->UseReturnFlag) {
- /* create predicate, used below */
- pred = slang_operation_new(1);
- pred->type = SLANG_OPER_IDENTIFIER;
- pred->a_id = slang_atom_pool_atom(A->atoms, "__notRetFlag");
- pred->locals->outer_scope = oper->locals->outer_scope;
- }
- }
-
- if (oper->children[0].type == SLANG_OPER_IDENTIFIER &&
- oper->children[1].type == SLANG_OPER_CALL) {
- /* Special case of: x = f(a, b)
- * Replace with f(a, b, x) (where x == hidden __retVal out param)
- *
- * XXX this could be even more effective if we could accomodate
- * cases such as "v.x = f();" - would help with typical vertex
- * transformation.
- */
- n = _slang_gen_function_call_name(A,
- (const char *) oper->children[1].a_id,
- &oper->children[1], &oper->children[0]);
- }
- else {
- slang_ir_node *lhs, *rhs;
-
- /* lhs and rhs type checking */
- if (!_slang_assignment_compatible(A,
- &oper->children[0],
- &oper->children[1])) {
- slang_info_log_error(A->log, "incompatible types in assignment");
- return NULL;
- }
-
- lhs = _slang_gen_operation(A, &oper->children[0]);
- if (!lhs) {
- return NULL;
- }
-
- if (!lhs->Store) {
- slang_info_log_error(A->log,
- "invalid left hand side for assignment");
- return NULL;
- }
-
- /* check that lhs is writable */
- if (!is_store_writable(A, lhs->Store)) {
- slang_info_log_error(A->log,
- "illegal assignment to read-only l-value");
- return NULL;
- }
-
- rhs = _slang_gen_operation(A, &oper->children[1]);
- if (lhs && rhs) {
- /* convert lhs swizzle into writemask */
- const GLuint swizzle = root_swizzle(lhs->Store);
- GLuint writemask, newSwizzle = 0x0;
- if (!swizzle_to_writemask(A, swizzle, &writemask, &newSwizzle)) {
- /* Non-simple writemask, need to swizzle right hand side in
- * order to put components into the right place.
- */
- rhs = _slang_gen_swizzle(rhs, newSwizzle);
- }
- n = new_node2(IR_COPY, lhs, rhs);
- }
- else {
- return NULL;
- }
- }
-
- if (n && pred) {
- /* predicate the assignment code on __notRetFlag */
- slang_ir_node *top, *cond;
-
- cond = _slang_gen_operation(A, pred);
- top = new_if(cond, n, NULL);
- return top;
- }
- return n;
-}
-
-
-/**
- * Generate IR tree for referencing a field in a struct (or basic vector type)
- */
-static slang_ir_node *
-_slang_gen_struct_field(slang_assemble_ctx * A, slang_operation *oper)
-{
- slang_typeinfo ti;
-
- /* type of struct */
- slang_typeinfo_construct(&ti);
- typeof_operation(A, &oper->children[0], &ti);
-
- if (_slang_type_is_vector(ti.spec.type)) {
- /* the field should be a swizzle */
- const GLuint rows = _slang_type_dim(ti.spec.type);
- slang_swizzle swz;
- slang_ir_node *n;
- GLuint swizzle;
- if (!_slang_is_swizzle((char *) oper->a_id, rows, &swz)) {
- slang_info_log_error(A->log, "Bad swizzle");
- return NULL;
- }
- swizzle = MAKE_SWIZZLE4(swz.swizzle[0],
- swz.swizzle[1],
- swz.swizzle[2],
- swz.swizzle[3]);
-
- n = _slang_gen_operation(A, &oper->children[0]);
- /* create new parent node with swizzle */
- if (n)
- n = _slang_gen_swizzle(n, swizzle);
- return n;
- }
- else if ( ti.spec.type == SLANG_SPEC_FLOAT
- || ti.spec.type == SLANG_SPEC_INT
- || ti.spec.type == SLANG_SPEC_BOOL) {
- const GLuint rows = 1;
- slang_swizzle swz;
- slang_ir_node *n;
- GLuint swizzle;
- if (!_slang_is_swizzle((char *) oper->a_id, rows, &swz)) {
- slang_info_log_error(A->log, "Bad swizzle");
- }
- swizzle = MAKE_SWIZZLE4(swz.swizzle[0],
- swz.swizzle[1],
- swz.swizzle[2],
- swz.swizzle[3]);
- n = _slang_gen_operation(A, &oper->children[0]);
- /* create new parent node with swizzle */
- n = _slang_gen_swizzle(n, swizzle);
- return n;
- }
- else {
- /* the field is a structure member (base.field) */
- /* oper->children[0] is the base */
- /* oper->a_id is the field name */
- slang_ir_node *base, *n;
- slang_typeinfo field_ti;
- GLint fieldSize, fieldOffset = -1;
-
- /* type of field */
- slang_typeinfo_construct(&field_ti);
- typeof_operation(A, oper, &field_ti);
-
- fieldSize = _slang_sizeof_type_specifier(&field_ti.spec);
- if (fieldSize > 0)
- fieldOffset = _slang_field_offset(&ti.spec, oper->a_id);
-
- if (fieldSize == 0 || fieldOffset < 0) {
- const char *structName;
- if (ti.spec._struct)
- structName = (char *) ti.spec._struct->a_name;
- else
- structName = "unknown";
- slang_info_log_error(A->log,
- "\"%s\" is not a member of struct \"%s\"",
- (char *) oper->a_id, structName);
- return NULL;
- }
- assert(fieldSize >= 0);
-
- base = _slang_gen_operation(A, &oper->children[0]);
- if (!base) {
- /* error msg should have already been logged */
- return NULL;
- }
-
- n = new_node1(IR_FIELD, base);
- if (!n)
- return NULL;
-
- n->Field = (char *) oper->a_id;
-
- /* Store the field's offset in storage->Index */
- n->Store = _slang_new_ir_storage(base->Store->File,
- fieldOffset,
- fieldSize);
-
- return n;
- }
-}
-
-
-/**
- * Gen code for array indexing.
- */
-static slang_ir_node *
-_slang_gen_array_element(slang_assemble_ctx * A, slang_operation *oper)
-{
- slang_typeinfo array_ti;
-
- /* get array's type info */
- slang_typeinfo_construct(&array_ti);
- typeof_operation(A, &oper->children[0], &array_ti);
-
- if (_slang_type_is_vector(array_ti.spec.type)) {
- /* indexing a simple vector type: "vec4 v; v[0]=p;" */
- /* translate the index into a swizzle/writemask: "v.x=p" */
- const GLuint max = _slang_type_dim(array_ti.spec.type);
- GLint index;
- slang_ir_node *n;
-
- index = (GLint) oper->children[1].literal[0];
- if (oper->children[1].type != SLANG_OPER_LITERAL_INT ||
- index >= (GLint) max) {
-#if 0
- slang_info_log_error(A->log, "Invalid array index for vector type");
- printf("type = %d\n", oper->children[1].type);
- printf("index = %d, max = %d\n", index, max);
- printf("array = %s\n", (char*)oper->children[0].a_id);
- printf("index = %s\n", (char*)oper->children[1].a_id);
- return NULL;
-#else
- index = 0;
-#endif
- }
-
- n = _slang_gen_operation(A, &oper->children[0]);
- if (n) {
- /* use swizzle to access the element */
- GLuint swizzle = MAKE_SWIZZLE4(SWIZZLE_X + index,
- SWIZZLE_NIL,
- SWIZZLE_NIL,
- SWIZZLE_NIL);
- n = _slang_gen_swizzle(n, swizzle);
- }
- return n;
- }
- else {
- /* conventional array */
- slang_typeinfo elem_ti;
- slang_ir_node *elem, *array, *index;
- GLint elemSize, arrayLen;
-
- /* size of array element */
- slang_typeinfo_construct(&elem_ti);
- typeof_operation(A, oper, &elem_ti);
- elemSize = _slang_sizeof_type_specifier(&elem_ti.spec);
-
- if (_slang_type_is_matrix(array_ti.spec.type))
- arrayLen = _slang_type_dim(array_ti.spec.type);
- else
- arrayLen = array_ti.array_len;
-
- slang_typeinfo_destruct(&array_ti);
- slang_typeinfo_destruct(&elem_ti);
-
- if (elemSize <= 0) {
- /* unknown var or type */
- slang_info_log_error(A->log, "Undefined variable or type");
- return NULL;
- }
-
- array = _slang_gen_operation(A, &oper->children[0]);
- index = _slang_gen_operation(A, &oper->children[1]);
- if (array && index) {
- /* bounds check */
- GLint constIndex = -1;
- if (index->Opcode == IR_FLOAT) {
- constIndex = (int) index->Value[0];
- if (constIndex < 0 || constIndex >= arrayLen) {
- slang_info_log_error(A->log,
- "Array index out of bounds (index=%d size=%d)",
- constIndex, arrayLen);
- _slang_free_ir_tree(array);
- _slang_free_ir_tree(index);
- return NULL;
- }
- }
-
- if (!array->Store) {
- slang_info_log_error(A->log, "Invalid array");
- return NULL;
- }
-
- elem = new_node2(IR_ELEMENT, array, index);
-
- /* The storage info here will be updated during code emit */
- elem->Store = _slang_new_ir_storage(array->Store->File,
- array->Store->Index,
- elemSize);
- elem->Store->Swizzle = _slang_var_swizzle(elemSize, 0);
- return elem;
- }
- else {
- _slang_free_ir_tree(array);
- _slang_free_ir_tree(index);
- return NULL;
- }
- }
-}
-
-
-static slang_ir_node *
-_slang_gen_compare(slang_assemble_ctx *A, slang_operation *oper,
- slang_ir_opcode opcode)
-{
- slang_typeinfo t0, t1;
- slang_ir_node *n;
-
- slang_typeinfo_construct(&t0);
- typeof_operation(A, &oper->children[0], &t0);
-
- slang_typeinfo_construct(&t1);
- typeof_operation(A, &oper->children[0], &t1);
-
- if (t0.spec.type == SLANG_SPEC_ARRAY ||
- t1.spec.type == SLANG_SPEC_ARRAY) {
- slang_info_log_error(A->log, "Illegal array comparison");
- return NULL;
- }
-
- if (oper->type != SLANG_OPER_EQUAL &&
- oper->type != SLANG_OPER_NOTEQUAL) {
- /* <, <=, >, >= can only be used with scalars */
- if ((t0.spec.type != SLANG_SPEC_INT &&
- t0.spec.type != SLANG_SPEC_FLOAT) ||
- (t1.spec.type != SLANG_SPEC_INT &&
- t1.spec.type != SLANG_SPEC_FLOAT)) {
- slang_info_log_error(A->log, "Incompatible type(s) for inequality operator");
- return NULL;
- }
- }
-
- n = new_node2(opcode,
- _slang_gen_operation(A, &oper->children[0]),
- _slang_gen_operation(A, &oper->children[1]));
-
- /* result is a bool (size 1) */
- n->Store = _slang_new_ir_storage(PROGRAM_TEMPORARY, -1, 1);
-
- return n;
-}
-
-
-#if 0
-static void
-print_vars(slang_variable_scope *s)
-{
- int i;
- printf("vars: ");
- for (i = 0; i < s->num_variables; i++) {
- printf("%s %d, \n",
- (char*) s->variables[i]->a_name,
- s->variables[i]->declared);
- }
-
- printf("\n");
-}
-#endif
-
-
-#if 0
-static void
-_slang_undeclare_vars(slang_variable_scope *locals)
-{
- if (locals->num_variables > 0) {
- int i;
- for (i = 0; i < locals->num_variables; i++) {
- slang_variable *v = locals->variables[i];
- printf("undeclare %s at %p\n", (char*) v->a_name, v);
- v->declared = GL_FALSE;
- }
- }
-}
-#endif
-
-
-/**
- * Generate IR tree for a slang_operation (AST node)
- */
-static slang_ir_node *
-_slang_gen_operation(slang_assemble_ctx * A, slang_operation *oper)
-{
- switch (oper->type) {
- case SLANG_OPER_BLOCK_NEW_SCOPE:
- {
- slang_ir_node *n;
-
- _slang_push_var_table(A->vartable);
-
- oper->type = SLANG_OPER_BLOCK_NO_NEW_SCOPE; /* temp change */
- n = _slang_gen_operation(A, oper);
- oper->type = SLANG_OPER_BLOCK_NEW_SCOPE; /* restore */
-
- _slang_pop_var_table(A->vartable);
-
- /*_slang_undeclare_vars(oper->locals);*/
- /*print_vars(oper->locals);*/
-
- if (n)
- n = new_node1(IR_SCOPE, n);
- return n;
- }
- break;
-
- case SLANG_OPER_BLOCK_NO_NEW_SCOPE:
- /* list of operations */
- if (oper->num_children > 0)
- {
- slang_ir_node *n, *tree = NULL;
- GLuint i;
-
- for (i = 0; i < oper->num_children; i++) {
- n = _slang_gen_operation(A, &oper->children[i]);
- if (!n) {
- _slang_free_ir_tree(tree);
- return NULL; /* error must have occured */
- }
- tree = new_seq(tree, n);
- }
-
- return tree;
- }
- else {
- return new_node0(IR_NOP);
- }
-
- case SLANG_OPER_EXPRESSION:
- return _slang_gen_operation(A, &oper->children[0]);
-
- case SLANG_OPER_FOR:
- return _slang_gen_for(A, oper);
- case SLANG_OPER_DO:
- return _slang_gen_do(A, oper);
- case SLANG_OPER_WHILE:
- return _slang_gen_while(A, oper);
- case SLANG_OPER_BREAK:
- if (!current_loop_oper(A)) {
- slang_info_log_error(A->log, "'break' not in loop");
- return NULL;
- }
- return new_break(current_loop_ir(A));
- case SLANG_OPER_CONTINUE:
- if (!current_loop_oper(A)) {
- slang_info_log_error(A->log, "'continue' not in loop");
- return NULL;
- }
- return _slang_gen_continue(A, oper);
- case SLANG_OPER_DISCARD:
- return new_node0(IR_KILL);
-
- case SLANG_OPER_EQUAL:
- return _slang_gen_compare(A, oper, IR_EQUAL);
- case SLANG_OPER_NOTEQUAL:
- return _slang_gen_compare(A, oper, IR_NOTEQUAL);
- case SLANG_OPER_GREATER:
- return _slang_gen_compare(A, oper, IR_SGT);
- case SLANG_OPER_LESS:
- return _slang_gen_compare(A, oper, IR_SLT);
- case SLANG_OPER_GREATEREQUAL:
- return _slang_gen_compare(A, oper, IR_SGE);
- case SLANG_OPER_LESSEQUAL:
- return _slang_gen_compare(A, oper, IR_SLE);
- case SLANG_OPER_ADD:
- {
- slang_ir_node *n;
- assert(oper->num_children == 2);
- n = _slang_gen_function_call_name(A, "+", oper, NULL);
- return n;
- }
- case SLANG_OPER_SUBTRACT:
- {
- slang_ir_node *n;
- assert(oper->num_children == 2);
- n = _slang_gen_function_call_name(A, "-", oper, NULL);
- return n;
- }
- case SLANG_OPER_MULTIPLY:
- {
- slang_ir_node *n;
- assert(oper->num_children == 2);
- n = _slang_gen_function_call_name(A, "*", oper, NULL);
- return n;
- }
- case SLANG_OPER_DIVIDE:
- {
- slang_ir_node *n;
- assert(oper->num_children == 2);
- n = _slang_gen_function_call_name(A, "/", oper, NULL);
- return n;
- }
- case SLANG_OPER_MINUS:
- {
- slang_ir_node *n;
- assert(oper->num_children == 1);
- n = _slang_gen_function_call_name(A, "-", oper, NULL);
- return n;
- }
- case SLANG_OPER_PLUS:
- /* +expr --> do nothing */
- return _slang_gen_operation(A, &oper->children[0]);
- case SLANG_OPER_VARIABLE_DECL:
- return _slang_gen_declaration(A, oper);
- case SLANG_OPER_ASSIGN:
- return _slang_gen_assignment(A, oper);
- case SLANG_OPER_ADDASSIGN:
- {
- slang_ir_node *n;
- assert(oper->num_children == 2);
- n = _slang_gen_function_call_name(A, "+=", oper, NULL);
- return n;
- }
- case SLANG_OPER_SUBASSIGN:
- {
- slang_ir_node *n;
- assert(oper->num_children == 2);
- n = _slang_gen_function_call_name(A, "-=", oper, NULL);
- return n;
- }
- break;
- case SLANG_OPER_MULASSIGN:
- {
- slang_ir_node *n;
- assert(oper->num_children == 2);
- n = _slang_gen_function_call_name(A, "*=", oper, NULL);
- return n;
- }
- case SLANG_OPER_DIVASSIGN:
- {
- slang_ir_node *n;
- assert(oper->num_children == 2);
- n = _slang_gen_function_call_name(A, "/=", oper, NULL);
- return n;
- }
- case SLANG_OPER_LOGICALAND:
- {
- slang_ir_node *n;
- assert(oper->num_children == 2);
- n = _slang_gen_logical_and(A, oper);
- return n;
- }
- case SLANG_OPER_LOGICALOR:
- {
- slang_ir_node *n;
- assert(oper->num_children == 2);
- n = _slang_gen_logical_or(A, oper);
- return n;
- }
- case SLANG_OPER_LOGICALXOR:
- return _slang_gen_xor(A, oper);
- case SLANG_OPER_NOT:
- return _slang_gen_not(A, oper);
- case SLANG_OPER_SELECT: /* b ? x : y */
- {
- slang_ir_node *n;
- assert(oper->num_children == 3);
- n = _slang_gen_select(A, oper);
- return n;
- }
-
- case SLANG_OPER_ASM:
- return _slang_gen_asm(A, oper, NULL);
- case SLANG_OPER_CALL:
- return _slang_gen_function_call_name(A, (const char *) oper->a_id,
- oper, NULL);
- case SLANG_OPER_METHOD:
- return _slang_gen_method_call(A, oper);
- case SLANG_OPER_RETURN:
- return _slang_gen_return(A, oper);
- case SLANG_OPER_RETURN_INLINED:
- return _slang_gen_return(A, oper);
- case SLANG_OPER_LABEL:
- return new_label(oper->label);
- case SLANG_OPER_IDENTIFIER:
- return _slang_gen_variable(A, oper);
- case SLANG_OPER_IF:
- return _slang_gen_if(A, oper);
- case SLANG_OPER_FIELD:
- return _slang_gen_struct_field(A, oper);
- case SLANG_OPER_SUBSCRIPT:
- return _slang_gen_array_element(A, oper);
- case SLANG_OPER_LITERAL_FLOAT:
- /* fall-through */
- case SLANG_OPER_LITERAL_INT:
- /* fall-through */
- case SLANG_OPER_LITERAL_BOOL:
- return new_float_literal(oper->literal, oper->literal_size);
-
- case SLANG_OPER_POSTINCREMENT: /* var++ */
- {
- slang_ir_node *n;
- assert(oper->num_children == 1);
- n = _slang_gen_function_call_name(A, "__postIncr", oper, NULL);
- return n;
- }
- case SLANG_OPER_POSTDECREMENT: /* var-- */
- {
- slang_ir_node *n;
- assert(oper->num_children == 1);
- n = _slang_gen_function_call_name(A, "__postDecr", oper, NULL);
- return n;
- }
- case SLANG_OPER_PREINCREMENT: /* ++var */
- {
- slang_ir_node *n;
- assert(oper->num_children == 1);
- n = _slang_gen_function_call_name(A, "++", oper, NULL);
- return n;
- }
- case SLANG_OPER_PREDECREMENT: /* --var */
- {
- slang_ir_node *n;
- assert(oper->num_children == 1);
- n = _slang_gen_function_call_name(A, "--", oper, NULL);
- return n;
- }
-
- case SLANG_OPER_NON_INLINED_CALL:
- case SLANG_OPER_SEQUENCE:
- {
- slang_ir_node *tree = NULL;
- GLuint i;
- for (i = 0; i < oper->num_children; i++) {
- slang_ir_node *n = _slang_gen_operation(A, &oper->children[i]);
- tree = new_seq(tree, n);
- if (n)
- tree->Store = n->Store;
- }
- if (oper->type == SLANG_OPER_NON_INLINED_CALL) {
- tree = new_function_call(tree, oper->label);
- }
- return tree;
- }
-
- case SLANG_OPER_NONE:
- case SLANG_OPER_VOID:
- /* returning NULL here would generate an error */
- return new_node0(IR_NOP);
-
- default:
- _mesa_problem(NULL, "bad node type %d in _slang_gen_operation",
- oper->type);
- return new_node0(IR_NOP);
- }
-
- return NULL;
-}
-
-
-/**
- * Check if the given type specifier is a rectangular texture sampler.
- */
-static GLboolean
-is_rect_sampler_spec(const slang_type_specifier *spec)
-{
- while (spec->_array) {
- spec = spec->_array;
- }
- return spec->type == SLANG_SPEC_SAMPLER_RECT ||
- spec->type == SLANG_SPEC_SAMPLER_RECT_SHADOW;
-}
-
-
-
-/**
- * Called by compiler when a global variable has been parsed/compiled.
- * Here we examine the variable's type to determine what kind of register
- * storage will be used.
- *
- * A uniform such as "gl_Position" will become the register specification
- * (PROGRAM_OUTPUT, VERT_RESULT_HPOS). Or, uniform "gl_FogFragCoord"
- * will be (PROGRAM_INPUT, FRAG_ATTRIB_FOGC).
- *
- * Samplers are interesting. For "uniform sampler2D tex;" we'll specify
- * (PROGRAM_SAMPLER, index) where index is resolved at link-time to an
- * actual texture unit (as specified by the user calling glUniform1i()).
- */
-GLboolean
-_slang_codegen_global_variable(slang_assemble_ctx *A, slang_variable *var,
- slang_unit_type type)
-{
- GET_CURRENT_CONTEXT(ctx);
- struct gl_program *prog = A->program;
- const char *varName = (char *) var->a_name;
- GLboolean success = GL_TRUE;
- slang_ir_storage *store = NULL;
- int dbg = 0;
- const GLenum datatype = _slang_gltype_from_specifier(&var->type.specifier);
- const GLint size = _slang_sizeof_type_specifier(&var->type.specifier);
- const GLint arrayLen = _slang_array_length(var);
- const GLint totalSize = _slang_array_size(size, arrayLen);
- GLint texIndex = sampler_to_texture_index(var->type.specifier.type);
-
- var->is_global = GL_TRUE;
-
- /* check for sampler2D arrays */
- if (texIndex == -1 && var->type.specifier._array)
- texIndex = sampler_to_texture_index(var->type.specifier._array->type);
-
- if (texIndex != -1) {
- /* This is a texture sampler variable...
- * store->File = PROGRAM_SAMPLER
- * store->Index = sampler number (0..7, typically)
- * store->Size = texture type index (1D, 2D, 3D, cube, etc)
- */
- if (var->initializer) {
- slang_info_log_error(A->log, "illegal assignment to '%s'", varName);
- return GL_FALSE;
- }
-#if FEATURE_es2_glsl /* XXX should use FEATURE_texture_rect */
- /* disallow rect samplers */
- if (ctx->API == API_OPENGLES2 &&
- is_rect_sampler_spec(&var->type.specifier)) {
- slang_info_log_error(A->log, "invalid sampler type for '%s'", varName);
- return GL_FALSE;
- }
-#else
- (void) is_rect_sampler_spec; /* silence warning */
- (void) ctx;
-#endif
- {
- GLint sampNum = _mesa_add_sampler(prog->Parameters, varName, datatype);
- store = _slang_new_ir_storage_sampler(sampNum, texIndex, totalSize);
-
- /* If we have a sampler array, then we need to allocate the
- * additional samplers to ensure we don't allocate them elsewhere.
- * We can't directly use _mesa_add_sampler() as that checks the
- * varName and gets a match, so we call _mesa_add_parameter()
- * directly and use the last sampler number from the call above.
- */
- if (arrayLen > 0) {
- GLint a = arrayLen - 1;
- GLint i;
- for (i = 0; i < a; i++) {
- GLfloat value = (GLfloat)(i + sampNum + 1);
- (void) _mesa_add_parameter(prog->Parameters, PROGRAM_SAMPLER,
- varName, 1, datatype, &value, NULL, 0x0);
- }
- }
- }
- if (dbg) printf("SAMPLER ");
- }
- else if (var->type.qualifier == SLANG_QUAL_UNIFORM) {
- /* Uniform variable */
- const GLuint swizzle = _slang_var_swizzle(totalSize, 0);
-
- if (prog) {
- /* user-defined uniform */
- if (datatype == GL_NONE) {
- if ((var->type.specifier.type == SLANG_SPEC_ARRAY &&
- var->type.specifier._array->type == SLANG_SPEC_STRUCT) ||
- (var->type.specifier.type == SLANG_SPEC_STRUCT)) {
- /* temporary work-around */
- GLenum datatype = GL_FLOAT;
- GLint uniformLoc = _mesa_add_uniform(prog->Parameters, varName,
- totalSize, datatype, NULL);
- store = _slang_new_ir_storage_swz(PROGRAM_UNIFORM, uniformLoc,
- totalSize, swizzle);
-
- if (arrayLen > 0) {
- GLint a = arrayLen - 1;
- GLint i;
- for (i = 0; i < a; i++) {
- GLfloat value = (GLfloat)(i + uniformLoc + 1);
- (void) _mesa_add_parameter(prog->Parameters, PROGRAM_UNIFORM,
- varName, 1, datatype, &value, NULL, 0x0);
- }
- }
-
- /* XXX what we need to do is unroll the struct into its
- * basic types, creating a uniform variable for each.
- * For example:
- * struct foo {
- * vec3 a;
- * vec4 b;
- * };
- * uniform foo f;
- *
- * Should produce uniforms:
- * "f.a" (GL_FLOAT_VEC3)
- * "f.b" (GL_FLOAT_VEC4)
- */
-
- if (var->initializer) {
- slang_info_log_error(A->log,
- "unsupported initializer for uniform '%s'", varName);
- return GL_FALSE;
- }
- }
- else {
- slang_info_log_error(A->log,
- "invalid datatype for uniform variable %s",
- varName);
- return GL_FALSE;
- }
- }
- else {
- /* non-struct uniform */
- if (!_slang_gen_var_decl(A, var, var->initializer))
- return GL_FALSE;
- store = var->store;
- }
- }
- else {
- /* pre-defined uniform, like gl_ModelviewMatrix */
- /* We know it's a uniform, but don't allocate storage unless
- * it's really used.
- */
- store = _slang_new_ir_storage_swz(PROGRAM_STATE_VAR, -1,
- totalSize, swizzle);
- }
- if (dbg) printf("UNIFORM (sz %d) ", totalSize);
- }
- else if (var->type.qualifier == SLANG_QUAL_VARYING) {
- /* varyings must be float, vec or mat */
- if (!_slang_type_is_float_vec_mat(var->type.specifier.type) &&
- var->type.specifier.type != SLANG_SPEC_ARRAY) {
- slang_info_log_error(A->log,
- "varying '%s' must be float/vector/matrix",
- varName);
- return GL_FALSE;
- }
-
- if (var->initializer) {
- slang_info_log_error(A->log, "illegal initializer for varying '%s'",
- varName);
- return GL_FALSE;
- }
-
- if (prog) {
- /* user-defined varying */
- GLbitfield flags;
- GLint varyingLoc;
- GLuint swizzle;
-
- flags = 0x0;
- if (var->type.centroid == SLANG_CENTROID)
- flags |= PROG_PARAM_BIT_CENTROID;
- if (var->type.variant == SLANG_INVARIANT)
- flags |= PROG_PARAM_BIT_INVARIANT;
-
- varyingLoc = _mesa_add_varying(prog->Varying, varName,
- totalSize, GL_NONE, flags);
- swizzle = _slang_var_swizzle(size, 0);
- store = _slang_new_ir_storage_swz(PROGRAM_VARYING, varyingLoc,
- totalSize, swizzle);
- }
- else {
- /* pre-defined varying, like gl_Color or gl_TexCoord */
- if (type == SLANG_UNIT_FRAGMENT_BUILTIN) {
- /* fragment program input */
- GLuint swizzle;
- GLint index = _slang_input_index(varName, GL_FRAGMENT_PROGRAM_ARB,
- &swizzle, NULL);
- assert(index >= 0);
- assert(index < FRAG_ATTRIB_MAX);
- store = _slang_new_ir_storage_swz(PROGRAM_INPUT, index,
- size, swizzle);
- } else if (type == SLANG_UNIT_VERTEX_BUILTIN) {
- /* vertex program output */
- GLint index = _slang_output_index(varName, GL_VERTEX_PROGRAM_ARB);
- GLuint swizzle = _slang_var_swizzle(size, 0);
- assert(index >= 0);
- assert(index < VERT_RESULT_MAX);
- assert(type == SLANG_UNIT_VERTEX_BUILTIN);
- store = _slang_new_ir_storage_swz(PROGRAM_OUTPUT, index,
- size, swizzle);
- } else {
- /* geometry program input */
- GLboolean is_array = GL_FALSE;
- GLuint swizzle;
- GLint index = _slang_input_index(varName, MESA_GEOMETRY_PROGRAM,
- &swizzle, &is_array);
- if (index < 0) {
- /* geometry program output */
- index = _slang_output_index(varName, MESA_GEOMETRY_PROGRAM);
- swizzle = _slang_var_swizzle(size, 0);
-
- assert(index >= 0);
- assert(index < GEOM_RESULT_MAX);
-
- store = _slang_new_ir_storage_swz(PROGRAM_OUTPUT, index,
- size, swizzle);
- } else {
- assert(index >= 0);
- /* assert(index < GEOM_ATTRIB_MAX); */
- if (is_array)
- store = _slang_new_ir_storage_2d(PROGRAM_INPUT, 0, index,
- size, swizzle);
- else
- store = _slang_new_ir_storage_swz(PROGRAM_INPUT, index,
- size, swizzle);
- }
- }
- if (dbg) printf("V/F ");
- }
- if (dbg) printf("VARYING ");
- }
- else if (var->type.qualifier == SLANG_QUAL_ATTRIBUTE) {
- GLuint swizzle;
- GLint index;
- /* attributes must be float, vec or mat */
- if (!_slang_type_is_float_vec_mat(var->type.specifier.type)) {
- slang_info_log_error(A->log,
- "attribute '%s' must be float/vector/matrix",
- varName);
- return GL_FALSE;
- }
-
- if (prog) {
- /* user-defined vertex attribute */
- const GLint attr = -1; /* unknown */
- swizzle = _slang_var_swizzle(size, 0);
- index = _mesa_add_attribute(prog->Attributes, varName,
- size, datatype, attr);
- assert(index >= 0);
- index = VERT_ATTRIB_GENERIC0 + index;
- }
- else {
- /* pre-defined vertex attrib */
- index = _slang_input_index(varName, GL_VERTEX_PROGRAM_ARB, &swizzle, NULL);
- assert(index >= 0);
- }
- store = _slang_new_ir_storage_swz(PROGRAM_INPUT, index, size, swizzle);
- if (dbg) printf("ATTRIB ");
- }
- else if (var->type.qualifier == SLANG_QUAL_FIXEDINPUT) {
- GLuint swizzle = SWIZZLE_XYZW; /* silence compiler warning */
- if (type == SLANG_UNIT_FRAGMENT_BUILTIN) {
- GLint index = _slang_input_index(varName, GL_FRAGMENT_PROGRAM_ARB,
- &swizzle, NULL);
- store = _slang_new_ir_storage_swz(PROGRAM_INPUT, index, size, swizzle);
- } else if (type == SLANG_UNIT_GEOMETRY_BUILTIN) {
- GLboolean is_array;
- GLint index = _slang_input_index(varName, MESA_GEOMETRY_PROGRAM,
- &swizzle, &is_array);
- if (is_array)
- store = _slang_new_ir_storage_2d(PROGRAM_INPUT, 0, index, size, swizzle);
- else
- store = _slang_new_ir_storage_swz(PROGRAM_INPUT, index, size, swizzle);
- }
- if (dbg) printf("INPUT ");
- }
- else if (var->type.qualifier == SLANG_QUAL_FIXEDOUTPUT) {
- if (type == SLANG_UNIT_VERTEX_BUILTIN) {
- GLint index = _slang_output_index(varName, GL_VERTEX_PROGRAM_ARB);
- store = _slang_new_ir_storage(PROGRAM_OUTPUT, index, size);
- } else if (type == SLANG_UNIT_FRAGMENT_BUILTIN) {
- GLint index = _slang_output_index(varName, GL_FRAGMENT_PROGRAM_ARB);
- GLint specialSize = 4; /* treat all fragment outputs as float[4] */
- assert(type == SLANG_UNIT_FRAGMENT_BUILTIN);
- store = _slang_new_ir_storage(PROGRAM_OUTPUT, index, specialSize);
- } else {
- GLint index = _slang_output_index(varName, MESA_GEOMETRY_PROGRAM);
- GLint specialSize = 4; /* treat all fragment outputs as float[4] */
- assert(type == SLANG_UNIT_GEOMETRY_BUILTIN);
- store = _slang_new_ir_storage(PROGRAM_OUTPUT, index, specialSize);
- }
- if (dbg) printf("OUTPUT ");
- }
- else if (var->type.qualifier == SLANG_QUAL_CONST && !prog) {
- /* pre-defined global constant, like gl_MaxLights */
- store = _slang_new_ir_storage(PROGRAM_CONSTANT, -1, size);
- if (dbg) printf("CONST ");
- }
- else {
- /* ordinary variable (may be const) */
- slang_ir_node *n;
-
- /* IR node to declare the variable */
- n = _slang_gen_var_decl(A, var, var->initializer);
-
- /* emit GPU instructions */
- success = _slang_emit_code(n, A->vartable, A->program, A->pragmas, GL_FALSE, A->log);
-
- _slang_free_ir_tree(n);
- }
-
- if (dbg) printf("GLOBAL VAR %s idx %d\n", (char*) var->a_name,
- store ? store->Index : -2);
-
- if (store)
- var->store = store; /* save var's storage info */
-
- var->declared = GL_TRUE;
-
- return success;
-}
-
-
-/**
- * Produce an IR tree from a function AST (fun->body).
- * Then call the code emitter to convert the IR tree into gl_program
- * instructions.
- */
-GLboolean
-_slang_codegen_function(slang_assemble_ctx * A, slang_function * fun)
-{
- slang_ir_node *n;
- GLboolean success = GL_TRUE;
-
- if (strcmp((char *) fun->header.a_name, "main") != 0) {
- /* we only really generate code for main, all other functions get
- * inlined or codegen'd upon an actual call.
- */
-#if 0
- /* do some basic error checking though */
- if (fun->header.type.specifier.type != SLANG_SPEC_VOID) {
- /* check that non-void functions actually return something */
- slang_operation *op
- = _slang_find_node_type(fun->body, SLANG_OPER_RETURN);
- if (!op) {
- slang_info_log_error(A->log,
- "function \"%s\" has no return statement",
- (char *) fun->header.a_name);
- printf(
- "function \"%s\" has no return statement\n",
- (char *) fun->header.a_name);
- return GL_FALSE;
- }
- }
-#endif
- return GL_TRUE; /* not an error */
- }
-
-#if 0
- printf("\n*********** codegen_function %s\n", (char *) fun->header.a_name);
- slang_print_function(fun, 1);
-#endif
-
- /* should have been allocated earlier: */
- assert(A->program->Parameters );
- assert(A->program->Varying);
- assert(A->vartable);
-
- A->LoopDepth = 0;
- A->UseReturnFlag = GL_FALSE;
- A->CurFunction = fun;
-
- /* fold constant expressions, etc. */
- _slang_simplify(fun->body, &A->space, A->atoms);
-
-#if 0
- printf("\n*********** simplified %s\n", (char *) fun->header.a_name);
- slang_print_function(fun, 1);
-#endif
-
- /* Create an end-of-function label */
- A->curFuncEndLabel = _slang_label_new("__endOfFunc__main");
-
- /* push new vartable scope */
- _slang_push_var_table(A->vartable);
-
- /* Generate IR tree for the function body code */
- n = _slang_gen_operation(A, fun->body);
- if (n)
- n = new_node1(IR_SCOPE, n);
-
- /* pop vartable, restore previous */
- _slang_pop_var_table(A->vartable);
-
- if (!n) {
- /* XXX record error */
- return GL_FALSE;
- }
-
- /* append an end-of-function-label to IR tree */
- n = new_seq(n, new_label(A->curFuncEndLabel));
-
- /*_slang_label_delete(A->curFuncEndLabel);*/
- A->curFuncEndLabel = NULL;
-
-#if 0
- printf("************* New AST for %s *****\n", (char*)fun->header.a_name);
- slang_print_function(fun, 1);
-#endif
-#if 0
- printf("************* IR for %s *******\n", (char*)fun->header.a_name);
- _slang_print_ir_tree(n, 0);
-#endif
-#if 0
- printf("************* End codegen function ************\n\n");
-#endif
-
- if (A->UnresolvedRefs) {
- /* Can't codegen at this time.
- * At link time we'll concatenate all the vertex shaders and/or all
- * the fragment shaders and try recompiling.
- */
- return GL_TRUE;
- }
-
- /* Emit program instructions */
- success = _slang_emit_code(n, A->vartable, A->program, A->pragmas, GL_TRUE, A->log);
- _slang_free_ir_tree(n);
-
- /* free codegen context */
- /*
- free(A->codegen);
- */
-
- return success;
-}
-
+++ /dev/null
-/*
- * Mesa 3-D graphics library
- * Version: 6.5.3
- *
- * Copyright (C) 2005-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 SLANG_CODEGEN_H
-#define SLANG_CODEGEN_H
-
-
-#include "main/glheader.h"
-#include "slang_compile.h"
-#include "slang_compile_variable.h"
-#include "slang_typeinfo.h"
-#include "slang_utility.h"
-#include "slang_vartable.h"
-
-struct slang_function_;
-
-#define MAX_LOOP_DEPTH 30
-
-
-typedef struct slang_assemble_ctx_
-{
- slang_atom_pool *atoms;
- slang_name_space space;
- struct gl_program *program;
- struct gl_sl_pragmas *pragmas;
- slang_var_table *vartable;
- slang_info_log *log;
- GLboolean allow_uniform_initializers;
-
- /* current loop stack */
- const slang_operation *LoopOperStack[MAX_LOOP_DEPTH];
- struct slang_ir_node_ *LoopIRStack[MAX_LOOP_DEPTH];
- GLuint LoopDepth;
-
- /* current function */
- struct slang_function_ *CurFunction;
- struct slang_label_ *curFuncEndLabel;
- GLboolean UseReturnFlag;
-
- GLboolean UnresolvedRefs;
- GLboolean EmitContReturn;
-} slang_assemble_ctx;
-
-
-extern GLuint
-_slang_sizeof_type_specifier(const slang_type_specifier *spec);
-
-extern GLboolean
-_slang_codegen_function(slang_assemble_ctx *A , struct slang_function_ *fun);
-
-extern GLboolean
-_slang_codegen_global_variable(slang_assemble_ctx *A, slang_variable *var,
- slang_unit_type type);
-
-
-#endif /* SLANG_CODEGEN_H */
+++ /dev/null
-/*
- * Mesa 3-D graphics library
- *
- * Copyright (C) 2005-2006 Brian Paul All Rights Reserved.
- * Copyright (C) 2008 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 slang_compile.c
- * slang front-end compiler
- * \author Michal Krol
- */
-
-#include "main/imports.h"
-#include "main/context.h"
-#include "program/program.h"
-#include "program/programopt.h"
-#include "program/prog_optimize.h"
-#include "program/prog_print.h"
-#include "program/prog_parameter.h"
-#include "../../glsl/pp/sl_pp_public.h"
-#include "../../glsl/pp/sl_pp_purify.h"
-#include "../../glsl/cl/sl_cl_parse.h"
-#include "slang_codegen.h"
-#include "slang_compile.h"
-#include "slang_storage.h"
-#include "slang_log.h"
-#include "slang_mem.h"
-#include "slang_vartable.h"
-#include "slang_simplify.h"
-
-/*
- * This is a straightforward implementation of the slang front-end
- * compiler. Lots of error-checking functionality is missing but
- * every well-formed shader source should compile successfully and
- * execute as expected. However, some semantically ill-formed shaders
- * may be accepted resulting in undefined behaviour.
- */
-
-
-/** re-defined below, should be the same though */
-#define TYPE_SPECIFIER_COUNT 36
-
-
-/**
- * Check if the given identifier is legal.
- */
-static GLboolean
-legal_identifier(slang_atom name)
-{
- /* "gl_" is a reserved prefix */
- if (strncmp((char *) name, "gl_", 3) == 0) {
- return GL_FALSE;
- }
- return GL_TRUE;
-}
-
-
-/*
- * slang_code_unit
- */
-
-GLvoid
-_slang_code_unit_ctr(slang_code_unit * self,
- struct slang_code_object_ * object)
-{
- _slang_variable_scope_ctr(&self->vars);
- _slang_function_scope_ctr(&self->funs);
- _slang_struct_scope_ctr(&self->structs);
- self->object = object;
-}
-
-GLvoid
-_slang_code_unit_dtr(slang_code_unit * self)
-{
- slang_variable_scope_destruct(&self->vars);
- slang_function_scope_destruct(&self->funs);
- slang_struct_scope_destruct(&self->structs);
-}
-
-/*
- * slang_code_object
- */
-
-GLvoid
-_slang_code_object_ctr(slang_code_object * self)
-{
- GLuint i;
-
- for (i = 0; i < SLANG_BUILTIN_TOTAL; i++)
- _slang_code_unit_ctr(&self->builtin[i], self);
- _slang_code_unit_ctr(&self->unit, self);
- slang_atom_pool_construct(&self->atompool);
-}
-
-GLvoid
-_slang_code_object_dtr(slang_code_object * self)
-{
- GLuint i;
-
- for (i = 0; i < SLANG_BUILTIN_TOTAL; i++)
- _slang_code_unit_dtr(&self->builtin[i]);
- _slang_code_unit_dtr(&self->unit);
- slang_atom_pool_destruct(&self->atompool);
-}
-
-
-/* slang_parse_ctx */
-
-typedef struct slang_parse_ctx_
-{
- const unsigned char *I;
- slang_info_log *L;
- int parsing_builtin;
- GLboolean global_scope; /**< Is object being declared a global? */
- slang_atom_pool *atoms;
- slang_unit_type type; /**< Vertex vs. Fragment */
- GLuint version; /**< user-specified (or default) #version */
-} slang_parse_ctx;
-
-/* slang_output_ctx */
-
-typedef struct slang_output_ctx_
-{
- slang_variable_scope *vars;
- slang_function_scope *funs;
- slang_struct_scope *structs;
- struct gl_program *program;
- struct gl_sl_pragmas *pragmas;
- slang_var_table *vartable;
- GLuint default_precision[TYPE_SPECIFIER_COUNT];
- GLboolean allow_precision;
- GLboolean allow_invariant;
- GLboolean allow_centroid;
- GLboolean allow_array_types; /* float[] syntax */
-} slang_output_ctx;
-
-/* _slang_compile() */
-
-
-/* Debugging aid, print file/line where parsing error is detected */
-#define RETURN0 \
- do { \
- if (0) \
- printf("slang error at %s:%d\n", __FILE__, __LINE__); \
- return 0; \
- } while (0)
-
-
-static void
-parse_identifier_str(slang_parse_ctx * C, char **id)
-{
- *id = (char *) C->I;
- C->I += strlen(*id) + 1;
-}
-
-static slang_atom
-parse_identifier(slang_parse_ctx * C)
-{
- const char *id;
-
- id = (const char *) C->I;
- C->I += strlen(id) + 1;
- return slang_atom_pool_atom(C->atoms, id);
-}
-
-static int
-is_hex_digit(char c)
-{
- return (c >= '0' && c <= '9') || (c >= 'a' && c <= 'f') || (c >= 'A' && c <= 'F');
-}
-
-static int
-parse_general_number(slang_parse_ctx *ctx, float *number)
-{
- char *flt = NULL;
-
- if (*ctx->I == '0') {
- int value = 0;
- const unsigned char *pi;
-
- if (ctx->I[1] == 'x' || ctx->I[1] == 'X') {
- ctx->I += 2;
- if (!is_hex_digit(*ctx->I)) {
- return 0;
- }
- do {
- int digit;
-
- if (*ctx->I >= '0' && *ctx->I <= '9') {
- digit = (int)(*ctx->I - '0');
- } else if (*ctx->I >= 'a' && *ctx->I <= 'f') {
- digit = (int)(*ctx->I - 'a') + 10;
- } else {
- digit = (int)(*ctx->I - 'A') + 10;
- }
- value = value * 0x10 + digit;
- ctx->I++;
- } while (is_hex_digit(*ctx->I));
- if (*ctx->I != '\0') {
- return 0;
- }
- ctx->I++;
- *number = (float)value;
- return 1;
- }
-
- pi = ctx->I;
- pi++;
- while (*pi >= '0' && *pi <= '7') {
- int digit;
-
- digit = (int)(*pi - '0');
- value = value * 010 + digit;
- pi++;
- }
- if (*pi == '\0') {
- pi++;
- ctx->I = pi;
- *number = (float)value;
- return 1;
- }
- }
-
- parse_identifier_str(ctx, &flt);
- flt = _mesa_strdup(flt);
- if (!flt) {
- return 0;
- }
- if (flt[strlen(flt) - 1] == 'f' || flt[strlen(flt) - 1] == 'F') {
- flt[strlen(flt) - 1] = '\0';
- }
- *number = _mesa_strtof(flt, (char **)NULL);
- free(flt);
-
- return 1;
-}
-
-static int
-parse_number(slang_parse_ctx * C, int *number)
-{
- const int radix = (int) (*C->I++);
-
- if (radix == 1) {
- float f = 0.0f;
-
- parse_general_number(C, &f);
- *number = (int)f;
- } else {
- *number = 0;
- while (*C->I != '\0') {
- int digit;
- if (*C->I >= '0' && *C->I <= '9')
- digit = (int) (*C->I - '0');
- else if (*C->I >= 'A' && *C->I <= 'Z')
- digit = (int) (*C->I - 'A') + 10;
- else
- digit = (int) (*C->I - 'a') + 10;
- *number = *number * radix + digit;
- C->I++;
- }
- C->I++;
- }
- if (*number > 65535)
- slang_info_log_warning(C->L, "%d: literal integer overflow.", *number);
- return 1;
-}
-
-static int
-parse_float(slang_parse_ctx * C, float *number)
-{
- if (*C->I == 1) {
- C->I++;
- parse_general_number(C, number);
- } else {
- char *integral = NULL;
- char *fractional = NULL;
- char *exponent = NULL;
- char *whole = NULL;
-
- parse_identifier_str(C, &integral);
- parse_identifier_str(C, &fractional);
- parse_identifier_str(C, &exponent);
-
- whole = (char *) _slang_alloc((strlen(integral) +
- strlen(fractional) +
- strlen(exponent) + 3) * sizeof(char));
- if (whole == NULL) {
- slang_info_log_memory(C->L);
- RETURN0;
- }
-
- slang_string_copy(whole, integral);
- slang_string_concat(whole, ".");
- slang_string_concat(whole, fractional);
- slang_string_concat(whole, "E");
- slang_string_concat(whole, exponent);
-
- *number = _mesa_strtof(whole, (char **) NULL);
-
- _slang_free(whole);
- }
-
- return 1;
-}
-
-/* revision number - increment after each change affecting emitted output */
-#define REVISION 5
-
-static int
-check_revision(slang_parse_ctx * C)
-{
- if (*C->I != REVISION) {
- slang_info_log_error(C->L, "Internal compiler error.");
- RETURN0;
- }
- C->I++;
- return 1;
-}
-
-static int parse_statement(slang_parse_ctx *, slang_output_ctx *,
- slang_operation *);
-static int parse_expression(slang_parse_ctx *, slang_output_ctx *,
- slang_operation *);
-static int parse_type_specifier(slang_parse_ctx *, slang_output_ctx *,
- slang_type_specifier *);
-static int
-parse_type_array_size(slang_parse_ctx *C,
- slang_output_ctx *O,
- GLint *array_len);
-
-static GLboolean
-parse_array_len(slang_parse_ctx * C, slang_output_ctx * O, GLuint * len)
-{
- slang_operation array_size;
- slang_name_space space;
- GLboolean result;
-
- if (!slang_operation_construct(&array_size))
- return GL_FALSE;
- if (!parse_expression(C, O, &array_size)) {
- slang_operation_destruct(&array_size);
- return GL_FALSE;
- }
-
- space.funcs = O->funs;
- space.structs = O->structs;
- space.vars = O->vars;
-
- /* evaluate compile-time expression which is array size */
- _slang_simplify(&array_size, &space, C->atoms);
-
- if (array_size.type == SLANG_OPER_LITERAL_INT) {
- result = GL_TRUE;
- *len = (GLint) array_size.literal[0];
- } else if (array_size.type == SLANG_OPER_IDENTIFIER) {
- slang_variable *var = _slang_variable_locate(array_size.locals, array_size.a_id, GL_TRUE);
- if (!var) {
- slang_info_log_error(C->L, "undefined variable '%s'",
- (char *) array_size.a_id);
- result = GL_FALSE;
- } else if (var->type.qualifier == SLANG_QUAL_CONST &&
- var->type.specifier.type == SLANG_SPEC_INT) {
- if (var->initializer &&
- var->initializer->type == SLANG_OPER_LITERAL_INT) {
- *len = (GLint) var->initializer->literal[0];
- result = GL_TRUE;
- } else {
- slang_info_log_error(C->L, "unable to parse array size declaration");
- result = GL_FALSE;
- }
- } else {
- slang_info_log_error(C->L, "unable to parse array size declaration");
- result = GL_FALSE;
- }
- } else {
- result = GL_FALSE;
- }
-
- slang_operation_destruct(&array_size);
- return result;
-}
-
-static GLboolean
-calculate_var_size(slang_parse_ctx * C, slang_output_ctx * O,
- slang_variable * var)
-{
- slang_storage_aggregate agg;
-
- if (!slang_storage_aggregate_construct(&agg))
- return GL_FALSE;
- if (!_slang_aggregate_variable(&agg, &var->type.specifier, var->array_len,
- O->funs, O->structs, O->vars, C->atoms)) {
- slang_storage_aggregate_destruct(&agg);
- return GL_FALSE;
- }
- var->size = _slang_sizeof_aggregate(&agg);
- slang_storage_aggregate_destruct(&agg);
- return GL_TRUE;
-}
-
-static void
-promote_type_to_array(slang_parse_ctx *C,
- slang_fully_specified_type *type,
- GLint array_len)
-{
- slang_type_specifier *baseType =
- slang_type_specifier_new(type->specifier.type, NULL, NULL);
-
- type->specifier.type = SLANG_SPEC_ARRAY;
- type->specifier._array = baseType;
- type->array_len = array_len;
-}
-
-
-static GLboolean
-convert_to_array(slang_parse_ctx * C, slang_variable * var,
- const slang_type_specifier * sp)
-{
- /* sized array - mark it as array, copy the specifier to the array element
- * and parse the expression */
- var->type.specifier.type = SLANG_SPEC_ARRAY;
- var->type.specifier._array = (slang_type_specifier *)
- _slang_alloc(sizeof(slang_type_specifier));
- if (var->type.specifier._array == NULL) {
- slang_info_log_memory(C->L);
- return GL_FALSE;
- }
- slang_type_specifier_ctr(var->type.specifier._array);
- return slang_type_specifier_copy(var->type.specifier._array, sp);
-}
-
-/* structure field */
-#define FIELD_NONE 0
-#define FIELD_NEXT 1
-#define FIELD_ARRAY 2
-
-static GLboolean
-parse_struct_field_var(slang_parse_ctx * C, slang_output_ctx * O,
- slang_variable * var, slang_atom a_name,
- const slang_type_specifier * sp,
- GLuint array_len)
-{
- var->a_name = a_name;
- if (var->a_name == SLANG_ATOM_NULL)
- return GL_FALSE;
-
- switch (*C->I++) {
- case FIELD_NONE:
- if (array_len != -1) {
- if (!convert_to_array(C, var, sp))
- return GL_FALSE;
- var->array_len = array_len;
- }
- else {
- if (!slang_type_specifier_copy(&var->type.specifier, sp))
- return GL_FALSE;
- }
- break;
- case FIELD_ARRAY:
- if (array_len != -1)
- return GL_FALSE;
- if (!convert_to_array(C, var, sp))
- return GL_FALSE;
- if (!parse_array_len(C, O, &var->array_len))
- return GL_FALSE;
- break;
- default:
- return GL_FALSE;
- }
-
- return calculate_var_size(C, O, var);
-}
-
-static int
-parse_struct_field(slang_parse_ctx * C, slang_output_ctx * O,
- slang_struct * st, slang_type_specifier * sp)
-{
- slang_output_ctx o = *O;
- GLint array_len;
-
- o.structs = st->structs;
- if (!parse_type_specifier(C, &o, sp))
- RETURN0;
- if (!parse_type_array_size(C, &o, &array_len))
- RETURN0;
-
- do {
- slang_atom a_name;
- slang_variable *var = slang_variable_scope_grow(st->fields);
- if (!var) {
- slang_info_log_memory(C->L);
- RETURN0;
- }
- a_name = parse_identifier(C);
- if (_slang_variable_locate(st->fields, a_name, GL_FALSE)) {
- slang_info_log_error(C->L, "duplicate field '%s'", (char *) a_name);
- RETURN0;
- }
-
- if (!parse_struct_field_var(C, &o, var, a_name, sp, array_len))
- RETURN0;
- }
- while (*C->I++ != FIELD_NONE);
-
- return 1;
-}
-
-static int
-parse_struct(slang_parse_ctx * C, slang_output_ctx * O, slang_struct ** st)
-{
- slang_atom a_name;
- const char *name;
-
- /* parse struct name (if any) and make sure it is unique in current scope */
- a_name = parse_identifier(C);
- if (a_name == SLANG_ATOM_NULL)
- RETURN0;
-
- name = slang_atom_pool_id(C->atoms, a_name);
- if (name[0] != '\0'
- && slang_struct_scope_find(O->structs, a_name, 0) != NULL) {
- slang_info_log_error(C->L, "%s: duplicate type name.", name);
- RETURN0;
- }
-
- /* set-up a new struct */
- *st = (slang_struct *) _slang_alloc(sizeof(slang_struct));
- if (*st == NULL) {
- slang_info_log_memory(C->L);
- RETURN0;
- }
- if (!slang_struct_construct(*st)) {
- _slang_free(*st);
- *st = NULL;
- slang_info_log_memory(C->L);
- RETURN0;
- }
- (**st).a_name = a_name;
- (**st).structs->outer_scope = O->structs;
-
- /* parse individual struct fields */
- do {
- slang_type_specifier sp;
-
- slang_type_specifier_ctr(&sp);
- if (!parse_struct_field(C, O, *st, &sp)) {
- slang_type_specifier_dtr(&sp);
- RETURN0;
- }
- slang_type_specifier_dtr(&sp);
- }
- while (*C->I++ != FIELD_NONE);
-
- /* if named struct, copy it to current scope */
- if (name[0] != '\0') {
- slang_struct *s;
-
- O->structs->structs =
- (slang_struct *) _slang_realloc(O->structs->structs,
- O->structs->num_structs
- * sizeof(slang_struct),
- (O->structs->num_structs + 1)
- * sizeof(slang_struct));
- if (O->structs->structs == NULL) {
- slang_info_log_memory(C->L);
- RETURN0;
- }
- s = &O->structs->structs[O->structs->num_structs];
- if (!slang_struct_construct(s))
- RETURN0;
- O->structs->num_structs++;
- if (!slang_struct_copy(s, *st))
- RETURN0;
- }
-
- return 1;
-}
-
-
-/* invariant qualifer */
-#define TYPE_VARIANT 90
-#define TYPE_INVARIANT 91
-
-static int
-parse_type_variant(slang_parse_ctx * C, slang_type_variant *variant)
-{
- GLuint invariant = *C->I++;
- switch (invariant) {
- case TYPE_VARIANT:
- *variant = SLANG_VARIANT;
- return 1;
- case TYPE_INVARIANT:
- *variant = SLANG_INVARIANT;
- return 1;
- default:
- RETURN0;
- }
-}
-
-
-/* centroid qualifer */
-#define TYPE_CENTER 95
-#define TYPE_CENTROID 96
-
-static int
-parse_type_centroid(slang_parse_ctx * C, slang_type_centroid *centroid)
-{
- GLuint c = *C->I++;
- switch (c) {
- case TYPE_CENTER:
- *centroid = SLANG_CENTER;
- return 1;
- case TYPE_CENTROID:
- *centroid = SLANG_CENTROID;
- return 1;
- default:
- RETURN0;
- }
-}
-
-
-/* Layout qualifiers */
-#define LAYOUT_QUALIFIER_NONE 0
-#define LAYOUT_QUALIFIER_UPPER_LEFT 1
-#define LAYOUT_QUALIFIER_PIXEL_CENTER_INTEGER 2
-
-static int
-parse_layout_qualifiers(slang_parse_ctx * C, slang_layout_qualifier *layout)
-{
- *layout = 0x0;
-
- /* the layout qualifiers come as a list of LAYOUT_QUALIFER_x tokens,
- * terminated by LAYOUT_QUALIFIER_NONE.
- */
- while (1) {
- GLuint c = *C->I++;
- switch (c) {
- case LAYOUT_QUALIFIER_NONE:
- /* end of list of qualifiers */
- return 1;
- case LAYOUT_QUALIFIER_UPPER_LEFT:
- *layout |= SLANG_LAYOUT_UPPER_LEFT_BIT;
- break;
- case LAYOUT_QUALIFIER_PIXEL_CENTER_INTEGER:
- *layout |= SLANG_LAYOUT_PIXEL_CENTER_INTEGER_BIT;
- break;
- default:
- assert(0 && "Bad layout qualifier");
- }
- }
-}
-
-
-/* type qualifier */
-#define TYPE_QUALIFIER_NONE 0
-#define TYPE_QUALIFIER_CONST 1
-#define TYPE_QUALIFIER_ATTRIBUTE 2
-#define TYPE_QUALIFIER_VARYING 3
-#define TYPE_QUALIFIER_UNIFORM 4
-#define TYPE_QUALIFIER_FIXEDOUTPUT 5
-#define TYPE_QUALIFIER_FIXEDINPUT 6
-
-static int
-parse_type_qualifier(slang_parse_ctx * C, slang_type_qualifier * qual)
-{
- GLuint qualifier = *C->I++;
- switch (qualifier) {
- case TYPE_QUALIFIER_NONE:
- *qual = SLANG_QUAL_NONE;
- break;
- case TYPE_QUALIFIER_CONST:
- *qual = SLANG_QUAL_CONST;
- break;
- case TYPE_QUALIFIER_ATTRIBUTE:
- *qual = SLANG_QUAL_ATTRIBUTE;
- break;
- case TYPE_QUALIFIER_VARYING:
- *qual = SLANG_QUAL_VARYING;
- break;
- case TYPE_QUALIFIER_UNIFORM:
- *qual = SLANG_QUAL_UNIFORM;
- break;
- case TYPE_QUALIFIER_FIXEDOUTPUT:
- *qual = SLANG_QUAL_FIXEDOUTPUT;
- break;
- case TYPE_QUALIFIER_FIXEDINPUT:
- *qual = SLANG_QUAL_FIXEDINPUT;
- break;
- default:
- RETURN0;
- }
- return 1;
-}
-
-/* type specifier */
-#define TYPE_SPECIFIER_VOID 0
-#define TYPE_SPECIFIER_BOOL 1
-#define TYPE_SPECIFIER_BVEC2 2
-#define TYPE_SPECIFIER_BVEC3 3
-#define TYPE_SPECIFIER_BVEC4 4
-#define TYPE_SPECIFIER_INT 5
-#define TYPE_SPECIFIER_IVEC2 6
-#define TYPE_SPECIFIER_IVEC3 7
-#define TYPE_SPECIFIER_IVEC4 8
-#define TYPE_SPECIFIER_FLOAT 9
-#define TYPE_SPECIFIER_VEC2 10
-#define TYPE_SPECIFIER_VEC3 11
-#define TYPE_SPECIFIER_VEC4 12
-#define TYPE_SPECIFIER_MAT2 13
-#define TYPE_SPECIFIER_MAT3 14
-#define TYPE_SPECIFIER_MAT4 15
-#define TYPE_SPECIFIER_SAMPLER1D 16
-#define TYPE_SPECIFIER_SAMPLER2D 17
-#define TYPE_SPECIFIER_SAMPLER3D 18
-#define TYPE_SPECIFIER_SAMPLERCUBE 19
-#define TYPE_SPECIFIER_SAMPLER1DSHADOW 20
-#define TYPE_SPECIFIER_SAMPLER2DSHADOW 21
-#define TYPE_SPECIFIER_SAMPLER2DRECT 22
-#define TYPE_SPECIFIER_SAMPLER2DRECTSHADOW 23
-#define TYPE_SPECIFIER_STRUCT 24
-#define TYPE_SPECIFIER_TYPENAME 25
-#define TYPE_SPECIFIER_MAT23 26
-#define TYPE_SPECIFIER_MAT32 27
-#define TYPE_SPECIFIER_MAT24 28
-#define TYPE_SPECIFIER_MAT42 29
-#define TYPE_SPECIFIER_MAT34 30
-#define TYPE_SPECIFIER_MAT43 31
-#define TYPE_SPECIFIER_SAMPLER_1D_ARRAY 32
-#define TYPE_SPECIFIER_SAMPLER_2D_ARRAY 33
-#define TYPE_SPECIFIER_SAMPLER_1D_ARRAY_SHADOW 34
-#define TYPE_SPECIFIER_SAMPLER_2D_ARRAY_SHADOW 35
-#define TYPE_SPECIFIER_COUNT 36
-
-static int
-parse_type_specifier(slang_parse_ctx * C, slang_output_ctx * O,
- slang_type_specifier * spec)
-{
- int type = *C->I++;
- switch (type) {
- case TYPE_SPECIFIER_VOID:
- spec->type = SLANG_SPEC_VOID;
- break;
- case TYPE_SPECIFIER_BOOL:
- spec->type = SLANG_SPEC_BOOL;
- break;
- case TYPE_SPECIFIER_BVEC2:
- spec->type = SLANG_SPEC_BVEC2;
- break;
- case TYPE_SPECIFIER_BVEC3:
- spec->type = SLANG_SPEC_BVEC3;
- break;
- case TYPE_SPECIFIER_BVEC4:
- spec->type = SLANG_SPEC_BVEC4;
- break;
- case TYPE_SPECIFIER_INT:
- spec->type = SLANG_SPEC_INT;
- break;
- case TYPE_SPECIFIER_IVEC2:
- spec->type = SLANG_SPEC_IVEC2;
- break;
- case TYPE_SPECIFIER_IVEC3:
- spec->type = SLANG_SPEC_IVEC3;
- break;
- case TYPE_SPECIFIER_IVEC4:
- spec->type = SLANG_SPEC_IVEC4;
- break;
- case TYPE_SPECIFIER_FLOAT:
- spec->type = SLANG_SPEC_FLOAT;
- break;
- case TYPE_SPECIFIER_VEC2:
- spec->type = SLANG_SPEC_VEC2;
- break;
- case TYPE_SPECIFIER_VEC3:
- spec->type = SLANG_SPEC_VEC3;
- break;
- case TYPE_SPECIFIER_VEC4:
- spec->type = SLANG_SPEC_VEC4;
- break;
- case TYPE_SPECIFIER_MAT2:
- spec->type = SLANG_SPEC_MAT2;
- break;
- case TYPE_SPECIFIER_MAT3:
- spec->type = SLANG_SPEC_MAT3;
- break;
- case TYPE_SPECIFIER_MAT4:
- spec->type = SLANG_SPEC_MAT4;
- break;
- case TYPE_SPECIFIER_MAT23:
- spec->type = SLANG_SPEC_MAT23;
- break;
- case TYPE_SPECIFIER_MAT32:
- spec->type = SLANG_SPEC_MAT32;
- break;
- case TYPE_SPECIFIER_MAT24:
- spec->type = SLANG_SPEC_MAT24;
- break;
- case TYPE_SPECIFIER_MAT42:
- spec->type = SLANG_SPEC_MAT42;
- break;
- case TYPE_SPECIFIER_MAT34:
- spec->type = SLANG_SPEC_MAT34;
- break;
- case TYPE_SPECIFIER_MAT43:
- spec->type = SLANG_SPEC_MAT43;
- break;
- case TYPE_SPECIFIER_SAMPLER1D:
- spec->type = SLANG_SPEC_SAMPLER_1D;
- break;
- case TYPE_SPECIFIER_SAMPLER2D:
- spec->type = SLANG_SPEC_SAMPLER_2D;
- break;
- case TYPE_SPECIFIER_SAMPLER3D:
- spec->type = SLANG_SPEC_SAMPLER_3D;
- break;
- case TYPE_SPECIFIER_SAMPLERCUBE:
- spec->type = SLANG_SPEC_SAMPLER_CUBE;
- break;
- case TYPE_SPECIFIER_SAMPLER2DRECT:
- spec->type = SLANG_SPEC_SAMPLER_RECT;
- break;
- case TYPE_SPECIFIER_SAMPLER1DSHADOW:
- spec->type = SLANG_SPEC_SAMPLER_1D_SHADOW;
- break;
- case TYPE_SPECIFIER_SAMPLER2DSHADOW:
- spec->type = SLANG_SPEC_SAMPLER_2D_SHADOW;
- break;
- case TYPE_SPECIFIER_SAMPLER2DRECTSHADOW:
- spec->type = SLANG_SPEC_SAMPLER_RECT_SHADOW;
- break;
- case TYPE_SPECIFIER_SAMPLER_1D_ARRAY:
- spec->type = SLANG_SPEC_SAMPLER_1D_ARRAY;
- break;
- case TYPE_SPECIFIER_SAMPLER_2D_ARRAY:
- spec->type = SLANG_SPEC_SAMPLER_2D_ARRAY;
- break;
- case TYPE_SPECIFIER_SAMPLER_1D_ARRAY_SHADOW:
- spec->type = SLANG_SPEC_SAMPLER_1D_ARRAY_SHADOW;
- break;
- case TYPE_SPECIFIER_SAMPLER_2D_ARRAY_SHADOW:
- spec->type = SLANG_SPEC_SAMPLER_2D_ARRAY_SHADOW;
- break;
- case TYPE_SPECIFIER_STRUCT:
- spec->type = SLANG_SPEC_STRUCT;
- if (!parse_struct(C, O, &spec->_struct))
- RETURN0;
- break;
- case TYPE_SPECIFIER_TYPENAME:
- spec->type = SLANG_SPEC_STRUCT;
- {
- slang_atom a_name;
- slang_struct *stru;
-
- a_name = parse_identifier(C);
- if (a_name == NULL)
- RETURN0;
-
- stru = slang_struct_scope_find(O->structs, a_name, 1);
- if (stru == NULL) {
- slang_info_log_error(C->L, "undeclared type name '%s'",
- slang_atom_pool_id(C->atoms, a_name));
- RETURN0;
- }
-
- spec->_struct = (slang_struct *) _slang_alloc(sizeof(slang_struct));
- if (spec->_struct == NULL) {
- slang_info_log_memory(C->L);
- RETURN0;
- }
- if (!slang_struct_construct(spec->_struct)) {
- _slang_free(spec->_struct);
- spec->_struct = NULL;
- RETURN0;
- }
- if (!slang_struct_copy(spec->_struct, stru))
- RETURN0;
- }
- break;
- default:
- RETURN0;
- }
- return 1;
-}
-
-#define TYPE_SPECIFIER_NONARRAY 0
-#define TYPE_SPECIFIER_ARRAY 1
-
-static int
-parse_type_array_size(slang_parse_ctx *C,
- slang_output_ctx *O,
- GLint *array_len)
-{
- GLuint size;
-
- switch (*C->I++) {
- case TYPE_SPECIFIER_NONARRAY:
- *array_len = -1; /* -1 = not an array */
- break;
- case TYPE_SPECIFIER_ARRAY:
- if (!parse_array_len(C, O, &size))
- RETURN0;
- *array_len = (GLint) size;
- break;
- default:
- assert(0);
- RETURN0;
- }
- return 1;
-}
-
-#define PRECISION_DEFAULT 0
-#define PRECISION_LOW 1
-#define PRECISION_MEDIUM 2
-#define PRECISION_HIGH 3
-
-static int
-parse_type_precision(slang_parse_ctx *C,
- slang_type_precision *precision)
-{
- GLint prec = *C->I++;
- switch (prec) {
- case PRECISION_DEFAULT:
- *precision = SLANG_PREC_DEFAULT;
- return 1;
- case PRECISION_LOW:
- *precision = SLANG_PREC_LOW;
- return 1;
- case PRECISION_MEDIUM:
- *precision = SLANG_PREC_MEDIUM;
- return 1;
- case PRECISION_HIGH:
- *precision = SLANG_PREC_HIGH;
- return 1;
- default:
- RETURN0;
- }
-}
-
-
-/* parameter qualifier */
-#define PARAM_QUALIFIER_IN 0
-#define PARAM_QUALIFIER_OUT 1
-#define PARAM_QUALIFIER_INOUT 2
-#define PARAM_QUALIFIER_NONE 3
-static int
-parse_varying_qualifier(slang_parse_ctx * C, slang_fully_specified_type *type)
-{
- int param_qual = *C->I++;
-
- if (type->qualifier != SLANG_QUAL_VARYING &&
- param_qual != PARAM_QUALIFIER_NONE) {
- slang_info_log_error(C->L, "Invalid type qualifier.");
- RETURN0;
- }
- switch (param_qual) {
- case PARAM_QUALIFIER_IN:
- case PARAM_QUALIFIER_NONE:
- type->varying_kind = SLANG_VARYING_IN;
- break;
- case PARAM_QUALIFIER_OUT:
- type->varying_kind = SLANG_VARYING_OUT;
- break;
- case PARAM_QUALIFIER_INOUT:
- slang_info_log_error(C->L, "Invalid type qualifier.");
- RETURN0;
- break;
- default:
- RETURN0;
- }
- return 1;
-}
-
-static int
-parse_fully_specified_type(slang_parse_ctx * C, slang_output_ctx * O,
- slang_fully_specified_type * type)
-{
- if (!parse_layout_qualifiers(C, &type->layout))
- RETURN0;
-
- if (!parse_type_variant(C, &type->variant))
- RETURN0;
-
- if (!parse_type_centroid(C, &type->centroid))
- RETURN0;
-
- if (!parse_type_qualifier(C, &type->qualifier))
- RETURN0;
-
- if (!parse_varying_qualifier(C, type))
- RETURN0;
-
- if (!parse_type_precision(C, &type->precision))
- RETURN0;
-
- if (!parse_type_specifier(C, O, &type->specifier))
- RETURN0;
-
- if (!parse_type_array_size(C, O, &type->array_len))
- RETURN0;
-
- if (!O->allow_invariant && type->variant == SLANG_INVARIANT) {
- slang_info_log_error(C->L,
- "'invariant' keyword not allowed (perhaps set #version 120)");
- RETURN0;
- }
-
- if (!O->allow_centroid && type->centroid == SLANG_CENTROID) {
- slang_info_log_error(C->L,
- "'centroid' keyword not allowed (perhaps set #version 120)");
- RETURN0;
- }
- else if (type->centroid == SLANG_CENTROID &&
- type->qualifier != SLANG_QUAL_VARYING) {
- slang_info_log_error(C->L,
- "'centroid' keyword only allowed for varying vars");
- RETURN0;
- }
-
-
- /* need this?
- if (type->qualifier != SLANG_QUAL_VARYING &&
- type->variant == SLANG_INVARIANT) {
- slang_info_log_error(C->L,
- "invariant qualifer only allowed for varying vars");
- RETURN0;
- }
- */
-
- if (O->allow_precision) {
- if (type->precision == SLANG_PREC_DEFAULT) {
- assert(type->specifier.type < TYPE_SPECIFIER_COUNT);
- /* use the default precision for this datatype */
- type->precision = O->default_precision[type->specifier.type];
- }
- }
- else {
- /* only default is allowed */
- if (type->precision != SLANG_PREC_DEFAULT) {
- slang_info_log_error(C->L, "precision qualifiers not allowed");
- RETURN0;
- }
- }
-
- if (!O->allow_array_types && type->array_len >= 0) {
- slang_info_log_error(C->L, "first-class array types not allowed");
- RETURN0;
- }
-
- if (type->array_len >= 0) {
- /* convert type to array type (ex: convert "int" to "array of int" */
- promote_type_to_array(C, type, type->array_len);
- }
-
- return 1;
-}
-
-/* operation */
-#define OP_END 0
-#define OP_BLOCK_BEGIN_NO_NEW_SCOPE 1
-#define OP_BLOCK_BEGIN_NEW_SCOPE 2
-#define OP_DECLARE 3
-#define OP_ASM 4
-#define OP_BREAK 5
-#define OP_CONTINUE 6
-#define OP_DISCARD 7
-#define OP_RETURN 8
-#define OP_EXPRESSION 9
-#define OP_IF 10
-#define OP_WHILE 11
-#define OP_DO 12
-#define OP_FOR 13
-#define OP_PUSH_VOID 14
-#define OP_PUSH_BOOL 15
-#define OP_PUSH_INT 16
-#define OP_PUSH_FLOAT 17
-#define OP_PUSH_IDENTIFIER 18
-#define OP_SEQUENCE 19
-#define OP_ASSIGN 20
-#define OP_ADDASSIGN 21
-#define OP_SUBASSIGN 22
-#define OP_MULASSIGN 23
-#define OP_DIVASSIGN 24
-/*#define OP_MODASSIGN 25*/
-/*#define OP_LSHASSIGN 26*/
-/*#define OP_RSHASSIGN 27*/
-/*#define OP_ORASSIGN 28*/
-/*#define OP_XORASSIGN 29*/
-/*#define OP_ANDASSIGN 30*/
-#define OP_SELECT 31
-#define OP_LOGICALOR 32
-#define OP_LOGICALXOR 33
-#define OP_LOGICALAND 34
-/*#define OP_BITOR 35*/
-/*#define OP_BITXOR 36*/
-/*#define OP_BITAND 37*/
-#define OP_EQUAL 38
-#define OP_NOTEQUAL 39
-#define OP_LESS 40
-#define OP_GREATER 41
-#define OP_LESSEQUAL 42
-#define OP_GREATEREQUAL 43
-/*#define OP_LSHIFT 44*/
-/*#define OP_RSHIFT 45*/
-#define OP_ADD 46
-#define OP_SUBTRACT 47
-#define OP_MULTIPLY 48
-#define OP_DIVIDE 49
-/*#define OP_MODULUS 50*/
-#define OP_PREINCREMENT 51
-#define OP_PREDECREMENT 52
-#define OP_PLUS 53
-#define OP_MINUS 54
-/*#define OP_COMPLEMENT 55*/
-#define OP_NOT 56
-#define OP_SUBSCRIPT 57
-#define OP_CALL 58
-#define OP_FIELD 59
-#define OP_POSTINCREMENT 60
-#define OP_POSTDECREMENT 61
-#define OP_PRECISION 62
-#define OP_METHOD 63
-
-
-/**
- * When parsing a compound production, this function is used to parse the
- * children.
- * For example, a while-loop compound will have two children, the
- * while condition expression and the loop body. So, this function will
- * be called twice to parse those two sub-expressions.
- * \param C the parsing context
- * \param O the output context
- * \param oper the operation we're parsing
- * \param statement indicates whether parsing a statement, or expression
- * \return 1 if success, 0 if error
- */
-static int
-parse_child_operation(slang_parse_ctx * C, slang_output_ctx * O,
- slang_operation * oper, GLboolean statement)
-{
- slang_operation *ch;
-
- /* grow child array */
- ch = slang_operation_grow(&oper->num_children, &oper->children);
- if (statement)
- return parse_statement(C, O, ch);
- return parse_expression(C, O, ch);
-}
-
-static int parse_declaration(slang_parse_ctx * C, slang_output_ctx * O);
-
-static int
-parse_statement(slang_parse_ctx * C, slang_output_ctx * O,
- slang_operation * oper)
-{
- int op;
-
- oper->locals->outer_scope = O->vars;
-
- op = *C->I++;
- switch (op) {
- case OP_BLOCK_BEGIN_NO_NEW_SCOPE:
- /* parse child statements, do not create new variable scope */
- oper->type = SLANG_OPER_BLOCK_NO_NEW_SCOPE;
- while (*C->I != OP_END)
- if (!parse_child_operation(C, O, oper, GL_TRUE))
- RETURN0;
- C->I++;
- break;
- case OP_BLOCK_BEGIN_NEW_SCOPE:
- /* parse child statements, create new variable scope */
- {
- slang_output_ctx o = *O;
-
- oper->type = SLANG_OPER_BLOCK_NEW_SCOPE;
- o.vars = oper->locals;
- while (*C->I != OP_END)
- if (!parse_child_operation(C, &o, oper, GL_TRUE))
- RETURN0;
- C->I++;
- }
- break;
- case OP_DECLARE:
- /* local variable declaration, individual declarators are stored as
- * children identifiers
- */
- oper->type = SLANG_OPER_BLOCK_NO_NEW_SCOPE;
- {
- const unsigned int first_var = O->vars->num_variables;
-
- /* parse the declaration, note that there can be zero or more
- * than one declarators
- */
- if (!parse_declaration(C, O))
- RETURN0;
- if (first_var < O->vars->num_variables) {
- const unsigned int num_vars = O->vars->num_variables - first_var;
- unsigned int i;
- assert(oper->num_children == 0);
- oper->num_children = num_vars;
- oper->children = slang_operation_new(num_vars);
- if (oper->children == NULL) {
- slang_info_log_memory(C->L);
- RETURN0;
- }
- for (i = first_var; i < O->vars->num_variables; i++) {
- slang_operation *o = &oper->children[i - first_var];
- slang_variable *var = O->vars->variables[i];
- o->type = SLANG_OPER_VARIABLE_DECL;
- o->locals->outer_scope = O->vars;
- o->a_id = var->a_name;
-
- /* new/someday...
- calculate_var_size(C, O, var);
- */
-
- if (!legal_identifier(o->a_id)) {
- slang_info_log_error(C->L, "illegal variable name '%s'",
- (char *) o->a_id);
- RETURN0;
- }
- }
- }
- }
- break;
- case OP_ASM:
- /* the __asm statement, parse the mnemonic and all its arguments
- * as expressions
- */
- oper->type = SLANG_OPER_ASM;
- oper->a_id = parse_identifier(C);
- if (oper->a_id == SLANG_ATOM_NULL)
- RETURN0;
- while (*C->I != OP_END) {
- if (!parse_child_operation(C, O, oper, GL_FALSE))
- RETURN0;
- }
- C->I++;
- break;
- case OP_BREAK:
- oper->type = SLANG_OPER_BREAK;
- break;
- case OP_CONTINUE:
- oper->type = SLANG_OPER_CONTINUE;
- break;
- case OP_DISCARD:
- oper->type = SLANG_OPER_DISCARD;
- break;
- case OP_RETURN:
- oper->type = SLANG_OPER_RETURN;
- if (!parse_child_operation(C, O, oper, GL_FALSE))
- RETURN0;
- break;
- case OP_EXPRESSION:
- oper->type = SLANG_OPER_EXPRESSION;
- if (!parse_child_operation(C, O, oper, GL_FALSE))
- RETURN0;
- break;
- case OP_IF:
- oper->type = SLANG_OPER_IF;
- if (!parse_child_operation(C, O, oper, GL_FALSE))
- RETURN0;
- if (!parse_child_operation(C, O, oper, GL_TRUE))
- RETURN0;
- if (!parse_child_operation(C, O, oper, GL_TRUE))
- RETURN0;
- break;
- case OP_WHILE:
- {
- slang_output_ctx o = *O;
-
- oper->type = SLANG_OPER_WHILE;
- o.vars = oper->locals;
- if (!parse_child_operation(C, &o, oper, GL_TRUE))
- RETURN0;
- if (!parse_child_operation(C, &o, oper, GL_TRUE))
- RETURN0;
- }
- break;
- case OP_DO:
- oper->type = SLANG_OPER_DO;
- if (!parse_child_operation(C, O, oper, GL_TRUE))
- RETURN0;
- if (!parse_child_operation(C, O, oper, GL_FALSE))
- RETURN0;
- break;
- case OP_FOR:
- {
- slang_output_ctx o = *O;
-
- oper->type = SLANG_OPER_FOR;
- o.vars = oper->locals;
- if (!parse_child_operation(C, &o, oper, GL_TRUE))
- RETURN0;
- if (!parse_child_operation(C, &o, oper, GL_TRUE))
- RETURN0;
- if (!parse_child_operation(C, &o, oper, GL_FALSE))
- RETURN0;
- if (!parse_child_operation(C, &o, oper, GL_TRUE))
- RETURN0;
- }
- break;
- case OP_PRECISION:
- {
- /* set default precision for a type in this scope */
- /* ignored at this time */
- int prec_qual = *C->I++;
- int datatype = *C->I++;
- (void) prec_qual;
- (void) datatype;
- }
- break;
- default:
- /*printf("Unexpected operation %d\n", op);*/
- RETURN0;
- }
- return 1;
-}
-
-static int
-handle_nary_expression(slang_parse_ctx * C, slang_operation * op,
- slang_operation ** ops, unsigned int *total_ops,
- unsigned int n)
-{
- unsigned int i;
-
- op->children = slang_operation_new(n);
- if (op->children == NULL) {
- slang_info_log_memory(C->L);
- RETURN0;
- }
- op->num_children = n;
-
- for (i = 0; i < n; i++) {
- slang_operation_destruct(&op->children[i]);
- op->children[i] = (*ops)[*total_ops - (n + 1 - i)];
- }
-
- (*ops)[*total_ops - (n + 1)] = (*ops)[*total_ops - 1];
- *total_ops -= n;
-
- *ops = (slang_operation *)
- _slang_realloc(*ops,
- (*total_ops + n) * sizeof(slang_operation),
- *total_ops * sizeof(slang_operation));
- if (*ops == NULL) {
- slang_info_log_memory(C->L);
- RETURN0;
- }
- return 1;
-}
-
-static int
-is_constructor_name(const char *name, slang_atom a_name,
- slang_struct_scope * structs)
-{
- if (slang_type_specifier_type_from_string(name) != SLANG_SPEC_VOID)
- return 1;
- return slang_struct_scope_find(structs, a_name, 1) != NULL;
-}
-
-#define FUNCTION_CALL_NONARRAY 0
-#define FUNCTION_CALL_ARRAY 1
-
-static int
-parse_expression(slang_parse_ctx * C, slang_output_ctx * O,
- slang_operation * oper)
-{
- slang_operation *ops = NULL;
- unsigned int num_ops = 0;
- int number;
-
- while (*C->I != OP_END) {
- slang_operation *op;
- const unsigned int op_code = *C->I++;
-
- /* allocate default operation, becomes a no-op if not used */
- ops = (slang_operation *)
- _slang_realloc(ops,
- num_ops * sizeof(slang_operation),
- (num_ops + 1) * sizeof(slang_operation));
- if (ops == NULL) {
- slang_info_log_memory(C->L);
- RETURN0;
- }
- op = &ops[num_ops];
- if (!slang_operation_construct(op)) {
- slang_info_log_memory(C->L);
- RETURN0;
- }
- num_ops++;
- op->locals->outer_scope = O->vars;
-
- switch (op_code) {
- case OP_PUSH_VOID:
- op->type = SLANG_OPER_VOID;
- break;
- case OP_PUSH_BOOL:
- op->type = SLANG_OPER_LITERAL_BOOL;
- if (!parse_number(C, &number))
- RETURN0;
- op->literal[0] =
- op->literal[1] =
- op->literal[2] =
- op->literal[3] = (GLfloat) number;
- op->literal_size = 1;
- break;
- case OP_PUSH_INT:
- op->type = SLANG_OPER_LITERAL_INT;
- if (!parse_number(C, &number))
- RETURN0;
- op->literal[0] =
- op->literal[1] =
- op->literal[2] =
- op->literal[3] = (GLfloat) number;
- op->literal_size = 1;
- break;
- case OP_PUSH_FLOAT:
- op->type = SLANG_OPER_LITERAL_FLOAT;
- if (!parse_float(C, &op->literal[0]))
- RETURN0;
- op->literal[1] =
- op->literal[2] =
- op->literal[3] = op->literal[0];
- op->literal_size = 1;
- break;
- case OP_PUSH_IDENTIFIER:
- op->type = SLANG_OPER_IDENTIFIER;
- op->a_id = parse_identifier(C);
- if (op->a_id == SLANG_ATOM_NULL)
- RETURN0;
- break;
- case OP_SEQUENCE:
- op->type = SLANG_OPER_SEQUENCE;
- if (!handle_nary_expression(C, op, &ops, &num_ops, 2))
- RETURN0;
- break;
- case OP_ASSIGN:
- op->type = SLANG_OPER_ASSIGN;
- if (!handle_nary_expression(C, op, &ops, &num_ops, 2))
- RETURN0;
- break;
- case OP_ADDASSIGN:
- op->type = SLANG_OPER_ADDASSIGN;
- if (!handle_nary_expression(C, op, &ops, &num_ops, 2))
- RETURN0;
- break;
- case OP_SUBASSIGN:
- op->type = SLANG_OPER_SUBASSIGN;
- if (!handle_nary_expression(C, op, &ops, &num_ops, 2))
- RETURN0;
- break;
- case OP_MULASSIGN:
- op->type = SLANG_OPER_MULASSIGN;
- if (!handle_nary_expression(C, op, &ops, &num_ops, 2))
- RETURN0;
- break;
- case OP_DIVASSIGN:
- op->type = SLANG_OPER_DIVASSIGN;
- if (!handle_nary_expression(C, op, &ops, &num_ops, 2))
- RETURN0;
- break;
- /*case OP_MODASSIGN: */
- /*case OP_LSHASSIGN: */
- /*case OP_RSHASSIGN: */
- /*case OP_ORASSIGN: */
- /*case OP_XORASSIGN: */
- /*case OP_ANDASSIGN: */
- case OP_SELECT:
- op->type = SLANG_OPER_SELECT;
- if (!handle_nary_expression(C, op, &ops, &num_ops, 3))
- RETURN0;
- break;
- case OP_LOGICALOR:
- op->type = SLANG_OPER_LOGICALOR;
- if (!handle_nary_expression(C, op, &ops, &num_ops, 2))
- RETURN0;
- break;
- case OP_LOGICALXOR:
- op->type = SLANG_OPER_LOGICALXOR;
- if (!handle_nary_expression(C, op, &ops, &num_ops, 2))
- RETURN0;
- break;
- case OP_LOGICALAND:
- op->type = SLANG_OPER_LOGICALAND;
- if (!handle_nary_expression(C, op, &ops, &num_ops, 2))
- RETURN0;
- break;
- /*case OP_BITOR: */
- /*case OP_BITXOR: */
- /*case OP_BITAND: */
- case OP_EQUAL:
- op->type = SLANG_OPER_EQUAL;
- if (!handle_nary_expression(C, op, &ops, &num_ops, 2))
- RETURN0;
- break;
- case OP_NOTEQUAL:
- op->type = SLANG_OPER_NOTEQUAL;
- if (!handle_nary_expression(C, op, &ops, &num_ops, 2))
- RETURN0;
- break;
- case OP_LESS:
- op->type = SLANG_OPER_LESS;
- if (!handle_nary_expression(C, op, &ops, &num_ops, 2))
- RETURN0;
- break;
- case OP_GREATER:
- op->type = SLANG_OPER_GREATER;
- if (!handle_nary_expression(C, op, &ops, &num_ops, 2))
- RETURN0;
- break;
- case OP_LESSEQUAL:
- op->type = SLANG_OPER_LESSEQUAL;
- if (!handle_nary_expression(C, op, &ops, &num_ops, 2))
- RETURN0;
- break;
- case OP_GREATEREQUAL:
- op->type = SLANG_OPER_GREATEREQUAL;
- if (!handle_nary_expression(C, op, &ops, &num_ops, 2))
- RETURN0;
- break;
- /*case OP_LSHIFT: */
- /*case OP_RSHIFT: */
- case OP_ADD:
- op->type = SLANG_OPER_ADD;
- if (!handle_nary_expression(C, op, &ops, &num_ops, 2))
- RETURN0;
- break;
- case OP_SUBTRACT:
- op->type = SLANG_OPER_SUBTRACT;
- if (!handle_nary_expression(C, op, &ops, &num_ops, 2))
- RETURN0;
- break;
- case OP_MULTIPLY:
- op->type = SLANG_OPER_MULTIPLY;
- if (!handle_nary_expression(C, op, &ops, &num_ops, 2))
- RETURN0;
- break;
- case OP_DIVIDE:
- op->type = SLANG_OPER_DIVIDE;
- if (!handle_nary_expression(C, op, &ops, &num_ops, 2))
- RETURN0;
- break;
- /*case OP_MODULUS: */
- case OP_PREINCREMENT:
- op->type = SLANG_OPER_PREINCREMENT;
- if (!handle_nary_expression(C, op, &ops, &num_ops, 1))
- RETURN0;
- break;
- case OP_PREDECREMENT:
- op->type = SLANG_OPER_PREDECREMENT;
- if (!handle_nary_expression(C, op, &ops, &num_ops, 1))
- RETURN0;
- break;
- case OP_PLUS:
- op->type = SLANG_OPER_PLUS;
- if (!handle_nary_expression(C, op, &ops, &num_ops, 1))
- RETURN0;
- break;
- case OP_MINUS:
- op->type = SLANG_OPER_MINUS;
- if (!handle_nary_expression(C, op, &ops, &num_ops, 1))
- RETURN0;
- break;
- case OP_NOT:
- op->type = SLANG_OPER_NOT;
- if (!handle_nary_expression(C, op, &ops, &num_ops, 1))
- RETURN0;
- break;
- /*case OP_COMPLEMENT: */
- case OP_SUBSCRIPT:
- op->type = SLANG_OPER_SUBSCRIPT;
- if (!handle_nary_expression(C, op, &ops, &num_ops, 2))
- RETURN0;
- break;
- case OP_METHOD:
- op->type = SLANG_OPER_METHOD;
- op->a_obj = parse_identifier(C);
- if (op->a_obj == SLANG_ATOM_NULL)
- RETURN0;
-
- op->a_id = parse_identifier(C);
- if (op->a_id == SLANG_ATOM_NULL)
- RETURN0;
-
- assert(*C->I == OP_END);
- C->I++;
-
- while (*C->I != OP_END)
- if (!parse_child_operation(C, O, op, GL_FALSE))
- RETURN0;
- C->I++;
-#if 0
- /* don't lookup the method (not yet anyway) */
- if (!C->parsing_builtin
- && !slang_function_scope_find_by_name(O->funs, op->a_id, 1)) {
- const char *id;
-
- id = slang_atom_pool_id(C->atoms, op->a_id);
- if (!is_constructor_name(id, op->a_id, O->structs)) {
- slang_info_log_error(C->L, "%s: undeclared function name.", id);
- RETURN0;
- }
- }
-#endif
- break;
- case OP_CALL:
- {
- GLboolean array_constructor = GL_FALSE;
- GLint array_constructor_size = 0;
-
- op->type = SLANG_OPER_CALL;
- op->a_id = parse_identifier(C);
- if (op->a_id == SLANG_ATOM_NULL)
- RETURN0;
- switch (*C->I++) {
- case FUNCTION_CALL_NONARRAY:
- /* Nothing to do. */
- break;
- case FUNCTION_CALL_ARRAY:
- /* Calling an array constructor. For example:
- * float[3](1.1, 2.2, 3.3);
- */
- if (!O->allow_array_types) {
- slang_info_log_error(C->L,
- "array constructors not allowed "
- "in this GLSL version");
- RETURN0;
- }
- else {
- /* parse the array constructor size */
- slang_operation array_size;
- array_constructor = GL_TRUE;
- slang_operation_construct(&array_size);
- if (!parse_expression(C, O, &array_size)) {
- slang_operation_destruct(&array_size);
- return GL_FALSE;
- }
- if (array_size.type != SLANG_OPER_LITERAL_INT) {
- slang_info_log_error(C->L,
- "constructor array size is not an integer");
- slang_operation_destruct(&array_size);
- RETURN0;
- }
- array_constructor_size = (int) array_size.literal[0];
- op->array_constructor = GL_TRUE;
- slang_operation_destruct(&array_size);
- }
- break;
- default:
- assert(0);
- RETURN0;
- }
- while (*C->I != OP_END)
- if (!parse_child_operation(C, O, op, GL_FALSE))
- RETURN0;
- C->I++;
-
- if (array_constructor &&
- array_constructor_size != op->num_children) {
- slang_info_log_error(C->L, "number of parameters to array"
- " constructor does not match array size");
- RETURN0;
- }
-
- if (!C->parsing_builtin
- && !slang_function_scope_find_by_name(O->funs, op->a_id, 1)) {
- const char *id;
-
- id = slang_atom_pool_id(C->atoms, op->a_id);
- if (!is_constructor_name(id, op->a_id, O->structs)) {
- slang_info_log_error(C->L, "%s: undeclared function name.", id);
- RETURN0;
- }
- }
- }
- break;
- case OP_FIELD:
- op->type = SLANG_OPER_FIELD;
- op->a_id = parse_identifier(C);
- if (op->a_id == SLANG_ATOM_NULL)
- RETURN0;
- if (!handle_nary_expression(C, op, &ops, &num_ops, 1))
- RETURN0;
- break;
- case OP_POSTINCREMENT:
- op->type = SLANG_OPER_POSTINCREMENT;
- if (!handle_nary_expression(C, op, &ops, &num_ops, 1))
- RETURN0;
- break;
- case OP_POSTDECREMENT:
- op->type = SLANG_OPER_POSTDECREMENT;
- if (!handle_nary_expression(C, op, &ops, &num_ops, 1))
- RETURN0;
- break;
- default:
- RETURN0;
- }
- }
- C->I++;
-
- slang_operation_destruct(oper);
- *oper = *ops; /* struct copy */
- _slang_free(ops);
-
- return 1;
-}
-
-/* function parameter array presence */
-#define PARAMETER_ARRAY_NOT_PRESENT 0
-#define PARAMETER_ARRAY_PRESENT 1
-
-static int
-parse_parameter_declaration(slang_parse_ctx * C, slang_output_ctx * O,
- slang_variable * param)
-{
- int param_qual, precision_qual;
-
- /* parse and validate the parameter's type qualifiers (there can be
- * two at most) because not all combinations are valid
- */
- if (!parse_type_qualifier(C, ¶m->type.qualifier))
- RETURN0;
-
- param_qual = *C->I++;
- switch (param_qual) {
- case PARAM_QUALIFIER_IN:
- if (param->type.qualifier != SLANG_QUAL_CONST
- && param->type.qualifier != SLANG_QUAL_NONE) {
- slang_info_log_error(C->L, "Invalid type qualifier.");
- RETURN0;
- }
- break;
- case PARAM_QUALIFIER_OUT:
- if (param->type.qualifier == SLANG_QUAL_NONE)
- param->type.qualifier = SLANG_QUAL_OUT;
- else {
- slang_info_log_error(C->L, "Invalid type qualifier.");
- RETURN0;
- }
- break;
- case PARAM_QUALIFIER_INOUT:
- if (param->type.qualifier == SLANG_QUAL_NONE)
- param->type.qualifier = SLANG_QUAL_INOUT;
- else {
- slang_info_log_error(C->L, "Invalid type qualifier.");
- RETURN0;
- }
- break;
- case PARAM_QUALIFIER_NONE:
- /* like IN but doesn't throw error */
- break;
- default:
- RETURN0;
- }
-
- /* parse precision qualifier (lowp, mediump, highp */
- precision_qual = *C->I++;
- /* ignored at this time */
- (void) precision_qual;
-
- /* parse parameter's type specifier and name */
- if (!parse_type_specifier(C, O, ¶m->type.specifier))
- RETURN0;
- if (!parse_type_array_size(C, O, ¶m->type.array_len))
- RETURN0;
- param->a_name = parse_identifier(C);
- if (param->a_name == SLANG_ATOM_NULL)
- RETURN0;
-
- /* first-class array
- */
- if (param->type.array_len >= 0) {
- slang_type_specifier p;
-
- slang_type_specifier_ctr(&p);
- if (!slang_type_specifier_copy(&p, ¶m->type.specifier)) {
- slang_type_specifier_dtr(&p);
- RETURN0;
- }
- if (!convert_to_array(C, param, &p)) {
- slang_type_specifier_dtr(&p);
- RETURN0;
- }
- slang_type_specifier_dtr(&p);
- param->array_len = param->type.array_len;
- }
-
- /* if the parameter is an array, parse its size (the size must be
- * explicitly defined
- */
- if (*C->I++ == PARAMETER_ARRAY_PRESENT) {
- slang_type_specifier p;
-
- if (param->type.array_len >= 0) {
- slang_info_log_error(C->L, "multi-dimensional arrays not allowed");
- RETURN0;
- }
- slang_type_specifier_ctr(&p);
- if (!slang_type_specifier_copy(&p, ¶m->type.specifier)) {
- slang_type_specifier_dtr(&p);
- RETURN0;
- }
- if (!convert_to_array(C, param, &p)) {
- slang_type_specifier_dtr(&p);
- RETURN0;
- }
- slang_type_specifier_dtr(&p);
- if (!parse_array_len(C, O, ¶m->array_len))
- RETURN0;
- }
-
-#if 0
- /* calculate the parameter size */
- if (!calculate_var_size(C, O, param))
- RETURN0;
-#endif
- /* TODO: allocate the local address here? */
- return 1;
-}
-
-/* function type */
-#define FUNCTION_ORDINARY 0
-#define FUNCTION_CONSTRUCTOR 1
-#define FUNCTION_OPERATOR 2
-
-/* function parameter */
-#define PARAMETER_NONE 0
-#define PARAMETER_NEXT 1
-
-/* operator type */
-#define OPERATOR_ADDASSIGN 1
-#define OPERATOR_SUBASSIGN 2
-#define OPERATOR_MULASSIGN 3
-#define OPERATOR_DIVASSIGN 4
-/*#define OPERATOR_MODASSIGN 5*/
-/*#define OPERATOR_LSHASSIGN 6*/
-/*#define OPERATOR_RSHASSIGN 7*/
-/*#define OPERATOR_ANDASSIGN 8*/
-/*#define OPERATOR_XORASSIGN 9*/
-/*#define OPERATOR_ORASSIGN 10*/
-#define OPERATOR_LOGICALXOR 11
-/*#define OPERATOR_BITOR 12*/
-/*#define OPERATOR_BITXOR 13*/
-/*#define OPERATOR_BITAND 14*/
-#define OPERATOR_LESS 15
-#define OPERATOR_GREATER 16
-#define OPERATOR_LESSEQUAL 17
-#define OPERATOR_GREATEREQUAL 18
-/*#define OPERATOR_LSHIFT 19*/
-/*#define OPERATOR_RSHIFT 20*/
-#define OPERATOR_MULTIPLY 21
-#define OPERATOR_DIVIDE 22
-/*#define OPERATOR_MODULUS 23*/
-#define OPERATOR_INCREMENT 24
-#define OPERATOR_DECREMENT 25
-#define OPERATOR_PLUS 26
-#define OPERATOR_MINUS 27
-/*#define OPERATOR_COMPLEMENT 28*/
-#define OPERATOR_NOT 29
-
-static const struct
-{
- unsigned int o_code;
- const char *o_name;
-} operator_names[] = {
- {OPERATOR_INCREMENT, "++"},
- {OPERATOR_ADDASSIGN, "+="},
- {OPERATOR_PLUS, "+"},
- {OPERATOR_DECREMENT, "--"},
- {OPERATOR_SUBASSIGN, "-="},
- {OPERATOR_MINUS, "-"},
- {OPERATOR_NOT, "!"},
- {OPERATOR_MULASSIGN, "*="},
- {OPERATOR_MULTIPLY, "*"},
- {OPERATOR_DIVASSIGN, "/="},
- {OPERATOR_DIVIDE, "/"},
- {OPERATOR_LESSEQUAL, "<="},
- /*{ OPERATOR_LSHASSIGN, "<<=" }, */
- /*{ OPERATOR_LSHIFT, "<<" }, */
- {OPERATOR_LESS, "<"},
- {OPERATOR_GREATEREQUAL, ">="},
- /*{ OPERATOR_RSHASSIGN, ">>=" }, */
- /*{ OPERATOR_RSHIFT, ">>" }, */
- {OPERATOR_GREATER, ">"},
- /*{ OPERATOR_MODASSIGN, "%=" }, */
- /*{ OPERATOR_MODULUS, "%" }, */
- /*{ OPERATOR_ANDASSIGN, "&=" }, */
- /*{ OPERATOR_BITAND, "&" }, */
- /*{ OPERATOR_ORASSIGN, "|=" }, */
- /*{ OPERATOR_BITOR, "|" }, */
- /*{ OPERATOR_COMPLEMENT, "~" }, */
- /*{ OPERATOR_XORASSIGN, "^=" }, */
- {OPERATOR_LOGICALXOR, "^^"},
- /*{ OPERATOR_BITXOR, "^" } */
-};
-
-static slang_atom
-parse_operator_name(slang_parse_ctx * C)
-{
- unsigned int i;
-
- for (i = 0; i < sizeof(operator_names) / sizeof(*operator_names); i++) {
- if (operator_names[i].o_code == (unsigned int) (*C->I)) {
- slang_atom atom =
- slang_atom_pool_atom(C->atoms, operator_names[i].o_name);
- if (atom == SLANG_ATOM_NULL) {
- slang_info_log_memory(C->L);
- RETURN0;
- }
- C->I++;
- return atom;
- }
- }
- RETURN0;
-}
-
-
-static int
-parse_function_prototype(slang_parse_ctx * C, slang_output_ctx * O,
- slang_function * func)
-{
- GLuint functype;
- /* parse function type and name */
- if (!parse_fully_specified_type(C, O, &func->header.type))
- RETURN0;
-
- functype = *C->I++;
- switch (functype) {
- case FUNCTION_ORDINARY:
- func->kind = SLANG_FUNC_ORDINARY;
- func->header.a_name = parse_identifier(C);
- if (func->header.a_name == SLANG_ATOM_NULL)
- RETURN0;
- break;
- case FUNCTION_CONSTRUCTOR:
- func->kind = SLANG_FUNC_CONSTRUCTOR;
- if (func->header.type.specifier.type == SLANG_SPEC_STRUCT)
- RETURN0;
- func->header.a_name =
- slang_atom_pool_atom(C->atoms,
- slang_type_specifier_type_to_string
- (func->header.type.specifier.type));
- if (func->header.a_name == SLANG_ATOM_NULL) {
- slang_info_log_memory(C->L);
- RETURN0;
- }
- break;
- case FUNCTION_OPERATOR:
- func->kind = SLANG_FUNC_OPERATOR;
- func->header.a_name = parse_operator_name(C);
- if (func->header.a_name == SLANG_ATOM_NULL)
- RETURN0;
- break;
- default:
- RETURN0;
- }
-
- if (!legal_identifier(func->header.a_name)) {
- slang_info_log_error(C->L, "illegal function name '%s'",
- (char *) func->header.a_name);
- RETURN0;
- }
-
- /* parse function parameters */
- while (*C->I++ == PARAMETER_NEXT) {
- slang_variable *p = slang_variable_scope_grow(func->parameters);
- if (!p) {
- slang_info_log_memory(C->L);
- RETURN0;
- }
- if (!parse_parameter_declaration(C, O, p))
- RETURN0;
- }
-
- /* if the function returns a value, append a hidden __retVal 'out'
- * parameter that corresponds to the return value.
- */
- if (_slang_function_has_return_value(func)) {
- slang_variable *p = slang_variable_scope_grow(func->parameters);
- slang_atom a_retVal = slang_atom_pool_atom(C->atoms, "__retVal");
- assert(a_retVal);
- p->a_name = a_retVal;
- p->type = func->header.type;
- p->type.qualifier = SLANG_QUAL_OUT;
- }
-
- /* function formal parameters and local variables share the same
- * scope, so save the information about param count in a seperate
- * place also link the scope to the global variable scope so when a
- * given identifier is not found here, the search process continues
- * in the global space
- */
- func->param_count = func->parameters->num_variables;
- func->parameters->outer_scope = O->vars;
-
- return 1;
-}
-
-static int
-parse_function_definition(slang_parse_ctx * C, slang_output_ctx * O,
- slang_function * func)
-{
- slang_output_ctx o = *O;
-
- if (!parse_function_prototype(C, O, func))
- RETURN0;
-
- /* create function's body operation */
- func->body = (slang_operation *) _slang_alloc(sizeof(slang_operation));
- if (func->body == NULL) {
- slang_info_log_memory(C->L);
- RETURN0;
- }
- if (!slang_operation_construct(func->body)) {
- _slang_free(func->body);
- func->body = NULL;
- slang_info_log_memory(C->L);
- RETURN0;
- }
-
- /* to parse the body the parse context is modified in order to
- * capture parsed variables into function's local variable scope
- */
- C->global_scope = GL_FALSE;
- o.vars = func->parameters;
- if (!parse_statement(C, &o, func->body))
- RETURN0;
-
- C->global_scope = GL_TRUE;
- return 1;
-}
-
-static GLboolean
-initialize_global(slang_assemble_ctx * A, slang_variable * var)
-{
- slang_operation op_id, op_assign;
- GLboolean result;
-
- /* construct the left side of assignment */
- if (!slang_operation_construct(&op_id))
- return GL_FALSE;
- op_id.type = SLANG_OPER_IDENTIFIER;
- op_id.a_id = var->a_name;
-
- /* put the variable into operation's scope */
- op_id.locals->variables =
- (slang_variable **) _slang_alloc(sizeof(slang_variable *));
- if (op_id.locals->variables == NULL) {
- slang_operation_destruct(&op_id);
- return GL_FALSE;
- }
- op_id.locals->num_variables = 1;
- op_id.locals->variables[0] = var;
-
- /* construct the assignment expression */
- if (!slang_operation_construct(&op_assign)) {
- op_id.locals->num_variables = 0;
- slang_operation_destruct(&op_id);
- return GL_FALSE;
- }
- op_assign.type = SLANG_OPER_ASSIGN;
- op_assign.children =
- (slang_operation *) _slang_alloc(2 * sizeof(slang_operation));
- if (op_assign.children == NULL) {
- slang_operation_destruct(&op_assign);
- op_id.locals->num_variables = 0;
- slang_operation_destruct(&op_id);
- return GL_FALSE;
- }
- op_assign.num_children = 2;
- op_assign.children[0] = op_id;
- op_assign.children[1] = *var->initializer;
-
- result = 1;
-
- /* carefully destroy the operations */
- op_assign.num_children = 0;
- _slang_free(op_assign.children);
- op_assign.children = NULL;
- slang_operation_destruct(&op_assign);
- op_id.locals->num_variables = 0;
- slang_operation_destruct(&op_id);
-
- if (!result)
- return GL_FALSE;
-
- return GL_TRUE;
-}
-
-/* init declarator list */
-#define DECLARATOR_NONE 0
-#define DECLARATOR_NEXT 1
-
-/* variable declaration */
-#define VARIABLE_NONE 0
-#define VARIABLE_IDENTIFIER 1
-#define VARIABLE_INITIALIZER 2
-#define VARIABLE_ARRAY_EXPLICIT 3
-#define VARIABLE_ARRAY_UNKNOWN 4
-
-
-/**
- * Check if it's OK to re-declare a variable with the given new type.
- * This happens when applying layout qualifiers to gl_FragCoord or
- * (re)setting an array size.
- * If redeclaration is OK, return a pointer to the incoming variable
- * updated with new type info. Else return NULL;
- */
-static slang_variable *
-redeclare_variable(slang_variable *var,
- const slang_fully_specified_type *type)
-{
- if (slang_fully_specified_types_compatible(&var->type, type)) {
- /* replace orig var layout with new layout */
- var->type.layout = type->layout;
-
- /* XXX there may be other type updates in the future here */
-
- return var;
- }
- else
- return NULL;
-}
-
-
-/**
- * Parse the initializer for a variable declaration.
- */
-static int
-parse_init_declarator(slang_parse_ctx * C, slang_output_ctx * O,
- const slang_fully_specified_type * type)
-{
- GET_CURRENT_CONTEXT(ctx); /* a hack */
- slang_variable *var = NULL, *prevDecl;
- slang_atom a_name;
-
- /* empty init declatator (without name, e.g. "float ;") */
- if (*C->I++ == VARIABLE_NONE)
- return 1;
-
- a_name = parse_identifier(C);
-
- /* check if name is already in this scope */
- prevDecl = _slang_variable_locate(O->vars, a_name, C->global_scope);
- if (prevDecl) {
- /* A var with this name has already been declared.
- * Check if redeclaring the var with a different type/layout is legal.
- */
- if (C->global_scope) {
- var = redeclare_variable(prevDecl, type);
- }
- if (!var) {
- slang_info_log_error(C->L,
- "declaration of '%s' conflicts with previous declaration",
- (char *) a_name);
- RETURN0;
- }
- }
-
- if (!var) {
- /* make room for a new variable and initialize it */
- var = slang_variable_scope_grow(O->vars);
- if (!var) {
- slang_info_log_memory(C->L);
- RETURN0;
- }
-
- /* copy the declarator type qualifier/etc info, parse the identifier */
- var->type.qualifier = type->qualifier;
- var->type.centroid = type->centroid;
- var->type.precision = type->precision;
- var->type.specifier = type->specifier;/*new*/
- var->type.variant = type->variant;
- var->type.layout = type->layout;
- var->type.array_len = type->array_len;
- var->type.varying_kind = type->varying_kind;
- var->a_name = a_name;
- if (var->a_name == SLANG_ATOM_NULL)
- RETURN0;
- }
-
- switch (*C->I++) {
- case VARIABLE_NONE:
- /* simple variable declarator - just copy the specifier */
- if (!slang_type_specifier_copy(&var->type.specifier, &type->specifier))
- RETURN0;
- break;
- case VARIABLE_INITIALIZER:
- /* initialized variable - copy the specifier and parse the expression */
- if (0 && type->array_len >= 0) {
- /* The type was something like "float[4]" */
- convert_to_array(C, var, &type->specifier);
- var->array_len = type->array_len;
- }
- else {
- if (!slang_type_specifier_copy(&var->type.specifier, &type->specifier))
- RETURN0;
- }
- var->initializer =
- (slang_operation *) _slang_alloc(sizeof(slang_operation));
- if (var->initializer == NULL) {
- slang_info_log_memory(C->L);
- RETURN0;
- }
- if (!slang_operation_construct(var->initializer)) {
- _slang_free(var->initializer);
- var->initializer = NULL;
- slang_info_log_memory(C->L);
- RETURN0;
- }
- if (!parse_expression(C, O, var->initializer))
- RETURN0;
- break;
- case VARIABLE_ARRAY_UNKNOWN:
- /* unsized array - mark it as array and copy the specifier to
- * the array element
- */
- if (type->array_len >= 0) {
- slang_info_log_error(C->L, "multi-dimensional arrays not allowed");
- RETURN0;
- }
- if (!convert_to_array(C, var, &type->specifier))
- return GL_FALSE;
- break;
- case VARIABLE_ARRAY_EXPLICIT:
- if (type->array_len >= 0) {
- /* the user is trying to do something like: float[2] x[3]; */
- slang_info_log_error(C->L, "multi-dimensional arrays not allowed");
- RETURN0;
- }
- if (!convert_to_array(C, var, &type->specifier))
- return GL_FALSE;
- if (!parse_array_len(C, O, &var->array_len))
- return GL_FALSE;
- break;
- default:
- RETURN0;
- }
-
- /* allocate global address space for a variable with a known size */
- if (C->global_scope
- && !(var->type.specifier.type == SLANG_SPEC_ARRAY
- && var->array_len == 0)) {
- if (!calculate_var_size(C, O, var))
- return GL_FALSE;
- }
-
- /* emit code for global var decl */
- if (C->global_scope) {
- slang_assemble_ctx A;
- memset(&A, 0, sizeof(slang_assemble_ctx));
- A.allow_uniform_initializers = C->version > 110;
- A.atoms = C->atoms;
- A.space.funcs = O->funs;
- A.space.structs = O->structs;
- A.space.vars = O->vars;
- A.program = O->program;
- A.pragmas = O->pragmas;
- A.vartable = O->vartable;
- A.log = C->L;
- A.curFuncEndLabel = NULL;
- A.EmitContReturn = ctx->Shader.EmitContReturn;
- if (!_slang_codegen_global_variable(&A, var, C->type))
- RETURN0;
- }
-
- /* initialize global variable */
- if (C->global_scope) {
- if (var->initializer != NULL) {
- slang_assemble_ctx A;
- memset(&A, 0, sizeof(slang_assemble_ctx));
- A.allow_uniform_initializers = C->version > 110;
- A.atoms = C->atoms;
- A.space.funcs = O->funs;
- A.space.structs = O->structs;
- A.space.vars = O->vars;
- if (!initialize_global(&A, var))
- RETURN0;
- }
- }
-
- if (var->type.qualifier == SLANG_QUAL_FIXEDINPUT &&
- var->a_name == slang_atom_pool_atom(C->atoms, "gl_FragCoord")) {
- /* set the program's PixelCenterInteger, OriginUpperLeft fields */
- struct gl_fragment_program *fragProg =
- (struct gl_fragment_program *) O->program;
-
- if (var->type.layout & SLANG_LAYOUT_UPPER_LEFT_BIT) {
- fragProg->OriginUpperLeft = GL_TRUE;
- }
- if (var->type.layout & SLANG_LAYOUT_PIXEL_CENTER_INTEGER_BIT) {
- fragProg->PixelCenterInteger = GL_TRUE;
- }
- }
-
- return 1;
-}
-
-/**
- * Parse a list of variable declarations. Each variable may have an
- * initializer.
- */
-static int
-parse_init_declarator_list(slang_parse_ctx * C, slang_output_ctx * O)
-{
- slang_fully_specified_type type;
-
- /* parse the fully specified type, common to all declarators */
- if (!slang_fully_specified_type_construct(&type))
- RETURN0;
- if (!parse_fully_specified_type(C, O, &type)) {
- slang_fully_specified_type_destruct(&type);
- RETURN0;
- }
-
- /* parse declarators, pass-in the parsed type */
- do {
- if (!parse_init_declarator(C, O, &type)) {
- slang_fully_specified_type_destruct(&type);
- RETURN0;
- }
- }
- while (*C->I++ == DECLARATOR_NEXT);
-
- slang_fully_specified_type_destruct(&type);
- return 1;
-}
-
-
-/**
- * Parse a function definition or declaration.
- * \param C parsing context
- * \param O output context
- * \param definition if non-zero expect a definition, else a declaration
- * \param parsed_func_ret returns the parsed function
- * \return GL_TRUE if success, GL_FALSE if failure
- */
-static GLboolean
-parse_function(slang_parse_ctx * C, slang_output_ctx * O, int definition,
- slang_function ** parsed_func_ret)
-{
- slang_function parsed_func, *found_func;
-
- /* parse function definition/declaration */
- if (!slang_function_construct(&parsed_func))
- return GL_FALSE;
- if (definition) {
- if (!parse_function_definition(C, O, &parsed_func)) {
- slang_function_destruct(&parsed_func);
- return GL_FALSE;
- }
- }
- else {
- if (!parse_function_prototype(C, O, &parsed_func)) {
- slang_function_destruct(&parsed_func);
- return GL_FALSE;
- }
- }
-
- /* find a function with a prototype matching the parsed one - only
- * the current scope is being searched to allow built-in function
- * overriding
- */
- found_func = slang_function_scope_find(O->funs, &parsed_func, 0);
- if (found_func == NULL) {
- /* New function, add it to the function list */
- O->funs->functions =
- (slang_function *) _slang_realloc(O->funs->functions,
- O->funs->num_functions
- * sizeof(slang_function),
- (O->funs->num_functions + 1)
- * sizeof(slang_function));
- if (O->funs->functions == NULL) {
- /* Make sure that there are no functions marked, as the
- * allocation is currently NULL, in order to avoid
- * a potental segfault as we clean up later.
- */
- O->funs->num_functions = 0;
-
- slang_info_log_memory(C->L);
- slang_function_destruct(&parsed_func);
- return GL_FALSE;
- }
- O->funs->functions[O->funs->num_functions] = parsed_func;
- O->funs->num_functions++;
-
- /* return the newly parsed function */
- *parsed_func_ret = &O->funs->functions[O->funs->num_functions - 1];
- }
- else {
- /* previously defined or declared */
- /* TODO: check function return type qualifiers and specifiers */
- if (definition) {
- if (found_func->body != NULL) {
- slang_info_log_error(C->L, "%s: function already has a body.",
- slang_atom_pool_id(C->atoms,
- parsed_func.header.
- a_name));
- slang_function_destruct(&parsed_func);
- return GL_FALSE;
- }
-
- /* destroy the existing function declaration and replace it
- * with the new one
- */
- slang_function_destruct(found_func);
- *found_func = parsed_func;
- }
- else {
- /* another declaration of the same function prototype - ignore it */
- slang_function_destruct(&parsed_func);
- }
-
- /* return the found function */
- *parsed_func_ret = found_func;
- }
-
- return GL_TRUE;
-}
-
-/* declaration */
-#define DECLARATION_FUNCTION_PROTOTYPE 1
-#define DECLARATION_INIT_DECLARATOR_LIST 2
-
-static int
-parse_declaration(slang_parse_ctx * C, slang_output_ctx * O)
-{
- switch (*C->I++) {
- case DECLARATION_INIT_DECLARATOR_LIST:
- if (!parse_init_declarator_list(C, O))
- RETURN0;
- break;
- case DECLARATION_FUNCTION_PROTOTYPE:
- {
- slang_function *dummy_func;
-
- if (!parse_function(C, O, 0, &dummy_func))
- RETURN0;
- }
- break;
- default:
- RETURN0;
- }
- return 1;
-}
-
-static int
-parse_default_precision(slang_parse_ctx * C, slang_output_ctx * O)
-{
- int precision, type;
-
- if (!O->allow_precision) {
- slang_info_log_error(C->L, "syntax error at \"precision\"");
- RETURN0;
- }
-
- precision = *C->I++;
- switch (precision) {
- case PRECISION_LOW:
- case PRECISION_MEDIUM:
- case PRECISION_HIGH:
- /* OK */
- break;
- default:
- _mesa_problem(NULL, "unexpected precision %d at %s:%d\n",
- precision, __FILE__, __LINE__);
- RETURN0;
- }
-
- type = *C->I++;
- switch (type) {
- case TYPE_SPECIFIER_FLOAT:
- case TYPE_SPECIFIER_INT:
- case TYPE_SPECIFIER_SAMPLER1D:
- case TYPE_SPECIFIER_SAMPLER2D:
- case TYPE_SPECIFIER_SAMPLER3D:
- case TYPE_SPECIFIER_SAMPLERCUBE:
- case TYPE_SPECIFIER_SAMPLER1DSHADOW:
- case TYPE_SPECIFIER_SAMPLER2DSHADOW:
- case TYPE_SPECIFIER_SAMPLER2DRECT:
- case TYPE_SPECIFIER_SAMPLER2DRECTSHADOW:
- case TYPE_SPECIFIER_SAMPLER_1D_ARRAY:
- case TYPE_SPECIFIER_SAMPLER_2D_ARRAY:
- case TYPE_SPECIFIER_SAMPLER_1D_ARRAY_SHADOW:
- case TYPE_SPECIFIER_SAMPLER_2D_ARRAY_SHADOW:
- /* OK */
- break;
- default:
- _mesa_problem(NULL, "unexpected type %d at %s:%d\n",
- type, __FILE__, __LINE__);
- RETURN0;
- }
-
- assert(type < TYPE_SPECIFIER_COUNT);
- O->default_precision[type] = precision;
-
- return 1;
-}
-
-
-/**
- * Initialize the default precision for all types.
- * XXX this info isn't used yet.
- */
-static void
-init_default_precision(slang_output_ctx *O, slang_unit_type type)
-{
- GET_CURRENT_CONTEXT(ctx);
- GLuint i;
- for (i = 0; i < TYPE_SPECIFIER_COUNT; i++) {
-#if FEATURE_es2_glsl
- if (ctx->API == API_OPENGLES2)
- O->default_precision[i] = PRECISION_LOW;
- else
- O->default_precision[i] = PRECISION_HIGH;
-#else
- (void) ctx;
- O->default_precision[i] = PRECISION_HIGH;
-#endif
- }
-
- if (type == SLANG_UNIT_VERTEX_SHADER || type == SLANG_UNIT_GEOMETRY_SHADER) {
- O->default_precision[TYPE_SPECIFIER_FLOAT] = PRECISION_HIGH;
- O->default_precision[TYPE_SPECIFIER_INT] = PRECISION_HIGH;
- }
- else {
- O->default_precision[TYPE_SPECIFIER_INT] = PRECISION_MEDIUM;
- }
-}
-
-
-static int
-parse_invariant(slang_parse_ctx * C, slang_output_ctx * O)
-{
- if (O->allow_invariant) {
- slang_atom *a = parse_identifier(C);
- /* XXX not doing anything with this var yet */
- /*printf("ID: %s\n", (char*) a);*/
- return a ? 1 : 0;
- }
- else {
- slang_info_log_error(C->L, "syntax error at \"invariant\"");
- RETURN0;
- }
-}
-
-
-/* external declaration or default precision specifier */
-#define EXTERNAL_NULL 0
-#define EXTERNAL_FUNCTION_DEFINITION 1
-#define EXTERNAL_DECLARATION 2
-#define DEFAULT_PRECISION 3
-#define INVARIANT_STMT 4
-
-
-static GLboolean
-parse_code_unit(slang_parse_ctx * C, slang_code_unit * unit,
- struct gl_shader *shader)
-{
- GET_CURRENT_CONTEXT(ctx);
- slang_output_ctx o;
- GLboolean success;
- GLuint maxRegs;
- slang_function *mainFunc = NULL;
-
- if (unit->type == SLANG_UNIT_FRAGMENT_BUILTIN ||
- unit->type == SLANG_UNIT_FRAGMENT_SHADER) {
- maxRegs = ctx->Const.FragmentProgram.MaxTemps;
- }
- else if (unit->type == SLANG_UNIT_VERTEX_BUILTIN ||
- unit->type == SLANG_UNIT_VERTEX_SHADER) {
- maxRegs = ctx->Const.VertexProgram.MaxTemps;
- } else {
- assert(unit->type == SLANG_UNIT_GEOMETRY_BUILTIN ||
- unit->type == SLANG_UNIT_GEOMETRY_SHADER);
- maxRegs = ctx->Const.GeometryProgram.MaxTemps;
- }
-
- /* setup output context */
- o.funs = &unit->funs;
- o.structs = &unit->structs;
- o.vars = &unit->vars;
- o.program = shader ? shader->Program : NULL;
- o.pragmas = shader ? &shader->Pragmas : NULL;
- o.vartable = _slang_new_var_table(maxRegs);
- _slang_push_var_table(o.vartable);
-
- /* allow 'invariant' keyword? */
-#if FEATURE_es2_glsl
- o.allow_invariant =
- (ctx->API == API_OPENGLES2 || C->version >= 120) ? GL_TRUE : GL_FALSE;
-#else
- o.allow_invariant = (C->version >= 120) ? GL_TRUE : GL_FALSE;
-#endif
-
- /* allow 'centroid' keyword? */
- o.allow_centroid = (C->version >= 120) ? GL_TRUE : GL_FALSE;
-
- /* allow 'lowp/mediump/highp' keywords? */
-#if FEATURE_es2_glsl
- o.allow_precision =
- (ctx->API == API_OPENGLES2 || C->version >= 120) ? GL_TRUE : GL_FALSE;
-#else
- o.allow_precision = (C->version >= 120) ? GL_TRUE : GL_FALSE;
-#endif
- init_default_precision(&o, unit->type);
-
- /* allow 'float[]' keyword? */
- o.allow_array_types = (C->version >= 120) ? GL_TRUE : GL_FALSE;
-
- /* parse individual functions and declarations */
- while (*C->I != EXTERNAL_NULL) {
- switch (*C->I++) {
- case EXTERNAL_FUNCTION_DEFINITION:
- {
- slang_function *func;
- success = parse_function(C, &o, 1, &func);
- if (success && strcmp((char *) func->header.a_name, "main") == 0) {
- /* found main() */
- mainFunc = func;
- }
- }
- break;
- case EXTERNAL_DECLARATION:
- success = parse_declaration(C, &o);
- break;
- case DEFAULT_PRECISION:
- success = parse_default_precision(C, &o);
- break;
- case INVARIANT_STMT:
- success = parse_invariant(C, &o);
- break;
- default:
- success = GL_FALSE;
- }
-
- if (!success) {
- /* xxx free codegen */
- _slang_pop_var_table(o.vartable);
- return GL_FALSE;
- }
- }
- C->I++;
-
- if (mainFunc) {
- /* assemble (generate code) for main() */
- slang_assemble_ctx A;
- memset(&A, 0, sizeof(slang_assemble_ctx));
- A.atoms = C->atoms;
- A.space.funcs = o.funs;
- A.space.structs = o.structs;
- A.space.vars = o.vars;
- A.program = o.program;
- A.pragmas = &shader->Pragmas;
- A.vartable = o.vartable;
- A.EmitContReturn = ctx->Shader.EmitContReturn;
- A.log = C->L;
- A.allow_uniform_initializers = C->version > 110;
-
- /* main() takes no parameters */
- if (mainFunc->param_count > 0) {
- slang_info_log_error(A.log, "main() takes no arguments");
- return GL_FALSE;
- }
-
- _slang_codegen_function(&A, mainFunc);
-
- shader->Main = GL_TRUE; /* this shader defines main() */
-
- shader->UnresolvedRefs = A.UnresolvedRefs;
- }
-
- _slang_pop_var_table(o.vartable);
- _slang_delete_var_table(o.vartable);
-
- return GL_TRUE;
-}
-
-static GLboolean
-compile_binary(const unsigned char * prod, slang_code_unit * unit,
- GLuint version,
- slang_unit_type type, slang_info_log * infolog,
- slang_code_unit * builtin, slang_code_unit * downlink,
- struct gl_shader *shader)
-{
- slang_parse_ctx C;
-
- unit->type = type;
-
- /* setup parse context */
- C.I = prod;
- C.L = infolog;
- C.parsing_builtin = (builtin == NULL);
- C.global_scope = GL_TRUE;
- C.atoms = &unit->object->atompool;
- C.type = type;
- C.version = version;
-
- if (!check_revision(&C))
- return GL_FALSE;
-
- if (downlink != NULL) {
- unit->vars.outer_scope = &downlink->vars;
- unit->funs.outer_scope = &downlink->funs;
- unit->structs.outer_scope = &downlink->structs;
- }
-
- /* parse translation unit */
- return parse_code_unit(&C, unit, shader);
-}
-
-static GLboolean
-compile_with_grammar(const char *source,
- slang_code_unit *unit,
- slang_unit_type type,
- slang_info_log *infolog,
- slang_code_unit *builtin,
- struct gl_shader *shader,
- struct gl_sl_pragmas *pragmas,
- unsigned int shader_type,
- unsigned int parsing_builtin)
-{
- GET_CURRENT_CONTEXT(ctx);
- struct sl_pp_purify_options options;
- struct sl_pp_context *context;
- unsigned char *prod;
- GLuint size;
- unsigned int version;
- unsigned int maxVersion;
- int result;
- char errmsg[200] = "";
-
- assert(shader_type == 1 || shader_type == 2);
-
- memset(&options, 0, sizeof(options));
-
- context = sl_pp_context_create(source, &options);
- if (!context) {
- slang_info_log_error(infolog, "out of memory");
- return GL_FALSE;
- }
-
- if (sl_pp_version(context, &version)) {
- slang_info_log_error(infolog, "%s", sl_pp_context_error_message(context));
- sl_pp_context_destroy(context);
- return GL_FALSE;
- }
-
- if (sl_pp_context_add_extension(context, "GL_ARB_draw_buffers") ||
- sl_pp_context_add_extension(context, "GL_ARB_texture_rectangle")) {
- slang_info_log_error(infolog, "%s", sl_pp_context_error_message(context));
- sl_pp_context_destroy(context);
- return GL_FALSE;
- }
-
- if (type == SLANG_UNIT_FRAGMENT_SHADER) {
- sl_pp_context_add_extension(context, "GL_ARB_fragment_coord_conventions");
- }
-
-
-#if FEATURE_es2_glsl
- if (ctx->API == API_OPENGLES2) {
- if (sl_pp_context_add_predefined(context, "GL_ES", "1") ||
- sl_pp_context_add_predefined(context, "GL_FRAGMENT_PRECISION_HIGH", "1")) {
- slang_info_log_error(infolog, "%s", sl_pp_context_error_message(context));
- sl_pp_context_destroy(context);
- return GL_FALSE;
- }
- }
-#else
- (void) ctx;
-#endif
-
-#if FEATURE_ARB_shading_language_120
- maxVersion = 120;
-#elif FEATURE_es2_glsl
- maxVersion = 100;
-#else
- maxVersion = 110;
-#endif
-
- if (version > maxVersion ||
- (version != 100 && version != 110 && version != 120)) {
- slang_info_log_error(infolog,
- "language version %.2f is not supported.",
- version * 0.01);
- sl_pp_context_destroy(context);
- return GL_FALSE;
- }
-
- /* Finally check the syntax and generate its binary representation. */
- result = sl_cl_compile(context,
- shader_type,
- parsing_builtin,
- &prod,
- &size,
- errmsg,
- sizeof(errmsg));
-
- sl_pp_context_destroy(context);
-
- if (result) {
- /*GLint pos;*/
-
- slang_info_log_error(infolog, errmsg);
- /* syntax error (possibly in library code) */
-#if 0
- {
- int line, col;
- char *s;
- s = (char *) _mesa_find_line_column((const GLubyte *) source,
- (const GLubyte *) source + pos,
- &line, &col);
- printf("Error on line %d, col %d: %s\n", line, col, s);
- }
-#endif
- return GL_FALSE;
- }
-
- /* Syntax is okay - translate it to internal representation. */
- if (!compile_binary(prod, unit, version, type, infolog, builtin,
- &builtin[SLANG_BUILTIN_TOTAL - 1],
- shader)) {
- free(prod);
- return GL_FALSE;
- }
- free(prod);
- return GL_TRUE;
-}
-
-static const unsigned char slang_core_gc[] = {
-#include "library/slang_core_gc.h"
-};
-
-static const unsigned char slang_120_core_gc[] = {
-#include "library/slang_120_core_gc.h"
-};
-
-static const unsigned char slang_120_fragment_gc[] = {
-#include "library/slang_builtin_120_fragment_gc.h"
-};
-
-static const unsigned char slang_common_builtin_gc[] = {
-#include "library/slang_common_builtin_gc.h"
-};
-
-static const unsigned char slang_fragment_builtin_gc[] = {
-#include "library/slang_fragment_builtin_gc.h"
-};
-
-static const unsigned char slang_vertex_builtin_gc[] = {
-#include "library/slang_vertex_builtin_gc.h"
-};
-
-static const unsigned char slang_geometry_builtin_gc[] = {
-#include "library/slang_geometry_builtin_gc.h"
-};
-
-static GLboolean
-compile_object(const char *source,
- slang_code_object *object,
- slang_unit_type type,
- slang_info_log *infolog,
- struct gl_shader *shader,
- struct gl_sl_pragmas *pragmas)
-{
- slang_code_unit *builtins = NULL;
- GLuint base_version = 110;
- unsigned int shader_type;
- unsigned int parsing_builtin;
-
- /* set shader type - the syntax is slightly different for different shaders */
- if (type == SLANG_UNIT_FRAGMENT_SHADER || type == SLANG_UNIT_FRAGMENT_BUILTIN) {
- shader_type = 1;
- } else {
- shader_type = 2;
- }
-
- /* enable language extensions */
- parsing_builtin = 1;
-
- /* if parsing user-specified shader, load built-in library */
- if (type == SLANG_UNIT_FRAGMENT_SHADER || type == SLANG_UNIT_VERTEX_SHADER ||
- type == SLANG_UNIT_GEOMETRY_SHADER) {
- /* compile core functionality first */
- if (!compile_binary(slang_core_gc,
- &object->builtin[SLANG_BUILTIN_CORE],
- base_version,
- SLANG_UNIT_FRAGMENT_BUILTIN, infolog,
- NULL, NULL, NULL))
- return GL_FALSE;
-
-#if FEATURE_ARB_shading_language_120
- if (!compile_binary(slang_120_core_gc,
- &object->builtin[SLANG_BUILTIN_120_CORE],
- 120,
- SLANG_UNIT_FRAGMENT_BUILTIN, infolog,
- NULL, &object->builtin[SLANG_BUILTIN_CORE], NULL))
- return GL_FALSE;
-#endif
-
- /* compile common functions and variables, link to core */
- if (!compile_binary(slang_common_builtin_gc,
- &object->builtin[SLANG_BUILTIN_COMMON],
-#if FEATURE_ARB_shading_language_120
- 120,
-#else
- base_version,
-#endif
- SLANG_UNIT_FRAGMENT_BUILTIN, infolog, NULL,
-#if FEATURE_ARB_shading_language_120
- &object->builtin[SLANG_BUILTIN_120_CORE],
-#else
- &object->builtin[SLANG_BUILTIN_CORE],
-#endif
- NULL))
- return GL_FALSE;
-
- /* compile target-specific functions and variables, link to common */
- if (type == SLANG_UNIT_FRAGMENT_SHADER) {
- if (!compile_binary(slang_fragment_builtin_gc,
- &object->builtin[SLANG_BUILTIN_TARGET],
- base_version,
- SLANG_UNIT_FRAGMENT_BUILTIN, infolog, NULL,
- &object->builtin[SLANG_BUILTIN_COMMON], NULL))
- return GL_FALSE;
-#if FEATURE_ARB_shading_language_120
- if (!compile_binary(slang_120_fragment_gc,
- &object->builtin[SLANG_BUILTIN_TARGET],
- 120,
- SLANG_UNIT_FRAGMENT_BUILTIN, infolog, NULL,
- &object->builtin[SLANG_BUILTIN_COMMON], NULL))
- return GL_FALSE;
-#endif
- }
- else if (type == SLANG_UNIT_VERTEX_SHADER) {
- if (!compile_binary(slang_vertex_builtin_gc,
- &object->builtin[SLANG_BUILTIN_TARGET],
- base_version,
- SLANG_UNIT_VERTEX_BUILTIN, infolog, NULL,
- &object->builtin[SLANG_BUILTIN_COMMON], NULL))
- return GL_FALSE;
- }
-#if FEATURE_ARB_geometry_shader4
- else if (type == SLANG_UNIT_GEOMETRY_SHADER) {
- if (!compile_binary(slang_geometry_builtin_gc,
- &object->builtin[SLANG_BUILTIN_TARGET],
- base_version,
- SLANG_UNIT_GEOMETRY_BUILTIN, infolog, NULL,
- &object->builtin[SLANG_BUILTIN_COMMON], NULL))
- return GL_FALSE;
- }
-#endif
-
- /* disable language extensions */
- parsing_builtin = 0;
-
- builtins = object->builtin;
- }
-
- /* compile the actual shader - pass-in built-in library for external shader */
- return compile_with_grammar(source,
- &object->unit,
- type,
- infolog,
- builtins,
- shader,
- pragmas,
- shader_type,
- parsing_builtin);
-}
-
-
-GLboolean
-_slang_compile(GLcontext *ctx, struct gl_shader *shader)
-{
- GLboolean success;
- slang_info_log info_log;
- slang_code_object obj;
- slang_unit_type type;
- GLenum progTarget;
-
- if (shader->Type == GL_VERTEX_SHADER) {
- type = SLANG_UNIT_VERTEX_SHADER;
- }
- else if (shader->Type == GL_FRAGMENT_SHADER) {
- type = SLANG_UNIT_FRAGMENT_SHADER;
- } else {
- assert(shader->Type == GL_GEOMETRY_SHADER_ARB);
- type = SLANG_UNIT_GEOMETRY_SHADER;
- }
-
- if (!shader->Source)
- return GL_FALSE;
-
- ctx->Shader.MemPool = _slang_new_mempool(1024*1024);
-
- shader->Main = GL_FALSE;
-
- /* free the shader's old instructions, etc */
- _mesa_reference_program(ctx, &shader->Program, NULL);
-
- /* allocate new GPU program, parameter lists, etc. */
- if (shader->Type == GL_VERTEX_SHADER)
- progTarget = GL_VERTEX_PROGRAM_ARB;
- else if (shader->Type == GL_FRAGMENT_SHADER)
- progTarget = GL_FRAGMENT_PROGRAM_ARB;
- else
- progTarget = MESA_GEOMETRY_PROGRAM;
- shader->Program = ctx->Driver.NewProgram(ctx, progTarget, 1);
- shader->Program->Parameters = _mesa_new_parameter_list();
- shader->Program->Varying = _mesa_new_parameter_list();
- shader->Program->Attributes = _mesa_new_parameter_list();
-
- slang_info_log_construct(&info_log);
- _slang_code_object_ctr(&obj);
-
- success = compile_object(shader->Source,
- &obj,
- type,
- &info_log,
- shader,
- &shader->Pragmas);
-
- /* free shader's prev info log */
- if (shader->InfoLog) {
- free(shader->InfoLog);
- shader->InfoLog = NULL;
- }
-
- if (info_log.text) {
- /* copy info-log string to shader object */
- shader->InfoLog = _mesa_strdup(info_log.text);
- }
-
- if (info_log.error_flag) {
- success = GL_FALSE;
- }
-
- slang_info_log_destruct(&info_log);
- _slang_code_object_dtr(&obj);
-
- _slang_delete_mempool((slang_mempool *) ctx->Shader.MemPool);
- ctx->Shader.MemPool = NULL;
-
- /* remove any reads of output registers */
-#if 0
- printf("Pre-remove output reads:\n");
- _mesa_print_program(shader->Program);
-#endif
- _mesa_remove_output_reads(shader->Program, PROGRAM_OUTPUT);
- if (shader->Type == GL_VERTEX_SHADER) {
- /* and remove writes to varying vars in vertex programs */
- _mesa_remove_output_reads(shader->Program, PROGRAM_VARYING);
- }
-#if 0
- printf("Post-remove output reads:\n");
- _mesa_print_program(shader->Program);
-#endif
-
- shader->CompileStatus = success;
-
- if (success) {
- if (shader->Pragmas.Optimize &&
- (ctx->Shader.Flags & GLSL_NO_OPT) == 0) {
- _mesa_optimize_program(ctx, shader->Program);
- }
- if ((ctx->Shader.Flags & GLSL_NOP_VERT) &&
- shader->Program->Target == GL_VERTEX_PROGRAM_ARB) {
- _mesa_nop_vertex_program(ctx,
- (struct gl_vertex_program *) shader->Program);
- }
- if ((ctx->Shader.Flags & GLSL_NOP_FRAG) &&
- shader->Program->Target == GL_FRAGMENT_PROGRAM_ARB) {
- _mesa_nop_fragment_program(ctx,
- (struct gl_fragment_program *) shader->Program);
- }
- }
-
- if (ctx->Shader.Flags & GLSL_LOG) {
- _mesa_write_shader_to_file(shader);
- }
-
- return success;
-}
-
+++ /dev/null
-/*
- * Mesa 3-D graphics library
- * Version: 6.5
- *
- * Copyright (C) 2005-2006 Brian Paul All Rights Reserved.
- *
- * Permission is hereby granted, free of charge, to any person obtaining a
- * copy of this software and associated documentation files (the "Software"),
- * to deal in the Software without restriction, including without limitation
- * the rights to use, copy, modify, merge, publish, distribute, sublicense,
- * and/or sell copies of the Software, and to permit persons to whom the
- * Software is furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included
- * in all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
- * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
- * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
- * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
- * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
- */
-
-#if !defined SLANG_COMPILE_H
-#define SLANG_COMPILE_H
-
-#include "main/glheader.h"
-#include "main/mtypes.h"
-#include "slang_compile_function.h"
-#include "slang_compile_struct.h"
-#include "slang_compile_variable.h"
-#include "slang_utility.h"
-
-struct slang_code_object_;
-
-#if defined __cplusplus
-extern "C" {
-#endif
-
-typedef struct slang_name_space_
-{
- struct slang_function_scope_ *funcs;
- struct slang_struct_scope_ *structs;
- struct slang_variable_scope_ *vars;
-} slang_name_space;
-
-typedef enum slang_unit_type_
-{
- SLANG_UNIT_FRAGMENT_SHADER,
- SLANG_UNIT_VERTEX_SHADER,
- SLANG_UNIT_GEOMETRY_SHADER,
- SLANG_UNIT_FRAGMENT_BUILTIN,
- SLANG_UNIT_VERTEX_BUILTIN,
- SLANG_UNIT_GEOMETRY_BUILTIN
-} slang_unit_type;
-
-
-typedef struct slang_code_unit_
-{
- slang_variable_scope vars;
- slang_function_scope funs;
- slang_struct_scope structs;
- slang_unit_type type;
- struct slang_code_object_ *object;
-} slang_code_unit;
-
-
-extern GLvoid
-_slang_code_unit_ctr (slang_code_unit *, struct slang_code_object_ *);
-
-extern GLvoid
-_slang_code_unit_dtr (slang_code_unit *);
-
-#define SLANG_BUILTIN_CORE 0
-#define SLANG_BUILTIN_120_CORE 1
-#define SLANG_BUILTIN_COMMON 2
-#define SLANG_BUILTIN_TARGET 3
-
-#define SLANG_BUILTIN_TOTAL 4
-
-typedef struct slang_code_object_
-{
- slang_code_unit builtin[SLANG_BUILTIN_TOTAL];
- slang_code_unit unit;
- slang_atom_pool atompool;
-} slang_code_object;
-
-extern GLvoid
-_slang_code_object_ctr (slang_code_object *);
-
-extern GLvoid
-_slang_code_object_dtr (slang_code_object *);
-
-extern GLboolean
-_slang_compile (GLcontext *ctx, struct gl_shader *shader);
-
-#ifdef __cplusplus
-}
-#endif
-
-#endif
-
+++ /dev/null
-/*
- * Mesa 3-D graphics library
- * Version: 6.5
- *
- * Copyright (C) 2005-2006 Brian Paul All Rights Reserved.
- *
- * Permission is hereby granted, free of charge, to any person obtaining a
- * copy of this software and associated documentation files (the "Software"),
- * to deal in the Software without restriction, including without limitation
- * the rights to use, copy, modify, merge, publish, distribute, sublicense,
- * and/or sell copies of the Software, and to permit persons to whom the
- * Software is furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included
- * in all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
- * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
- * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
- * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
- * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
- */
-
-/**
- * \file slang_compile_function.c
- * slang front-end compiler
- * \author Michal Krol
- */
-
-#include "main/imports.h"
-#include "slang_compile.h"
-#include "slang_mem.h"
-
-
-int
-slang_function_construct(slang_function * func)
-{
- func->kind = SLANG_FUNC_ORDINARY;
- if (!slang_variable_construct(&func->header))
- return 0;
-
- func->parameters = (slang_variable_scope *)
- _slang_alloc(sizeof(slang_variable_scope));
- if (func->parameters == NULL) {
- slang_variable_destruct(&func->header);
- return 0;
- }
-
- _slang_variable_scope_ctr(func->parameters);
- func->param_count = 0;
- func->body = NULL;
- return 1;
-}
-
-void
-slang_function_destruct(slang_function * func)
-{
- slang_variable_destruct(&func->header);
- slang_variable_scope_destruct(func->parameters);
- _slang_free(func->parameters);
- if (func->body != NULL) {
- slang_operation_destruct(func->body);
- _slang_free(func->body);
- }
-}
-
-
-slang_function *
-slang_function_new(slang_function_kind kind)
-{
- slang_function *fun = (slang_function *)
- _slang_alloc(sizeof(slang_function));
- if (fun) {
- slang_function_construct(fun);
- fun->kind = kind;
- }
- return fun;
-}
-
-
-/*
- * slang_function_scope
- */
-
-GLvoid
-_slang_function_scope_ctr(slang_function_scope * self)
-{
- self->functions = NULL;
- self->num_functions = 0;
- self->outer_scope = NULL;
-}
-
-void
-slang_function_scope_destruct(slang_function_scope * scope)
-{
- unsigned int i;
-
- for (i = 0; i < scope->num_functions; i++)
- slang_function_destruct(scope->functions + i);
- _slang_free(scope->functions);
-}
-
-
-/**
- * Does this function have a non-void return value?
- */
-GLboolean
-_slang_function_has_return_value(const slang_function *fun)
-{
- return fun->header.type.specifier.type != SLANG_SPEC_VOID;
-}
-
-
-/**
- * Search a list of functions for a particular function by name.
- * \param funcs the list of functions to search
- * \param a_name the name to search for
- * \param all_scopes if non-zero, search containing scopes too.
- * \return pointer to found function, or NULL.
- */
-int
-slang_function_scope_find_by_name(slang_function_scope * funcs,
- slang_atom a_name, int all_scopes)
-{
- unsigned int i;
-
- for (i = 0; i < funcs->num_functions; i++)
- if (a_name == funcs->functions[i].header.a_name)
- return 1;
- if (all_scopes && funcs->outer_scope != NULL)
- return slang_function_scope_find_by_name(funcs->outer_scope, a_name, 1);
- return 0;
-}
-
-
-/**
- * Search a list of functions for a particular function (for implementing
- * function calls. Matching is done by first comparing the function's name,
- * then the function's parameter list.
- *
- * \param funcs the list of functions to search
- * \param fun the function to search for
- * \param all_scopes if non-zero, search containing scopes too.
- * \return pointer to found function, or NULL.
- */
-slang_function *
-slang_function_scope_find(slang_function_scope * funcs, slang_function * fun,
- int all_scopes)
-{
- unsigned int i;
-
- for (i = 0; i < funcs->num_functions; i++) {
- slang_function *f = &funcs->functions[i];
- const GLuint haveRetValue = 0;
-#if 0
- = (f->header.type.specifier.type != SLANG_SPEC_VOID);
-#endif
- unsigned int j;
-
- /*
- printf("Compare name %s to %s (ret %u, %d, %d)\n",
- (char *) fun->header.a_name, (char *) f->header.a_name,
- haveRetValue,
- fun->param_count, f->param_count);
- */
-
- if (fun->header.a_name != f->header.a_name)
- continue;
- if (fun->param_count != f->param_count)
- continue;
- for (j = haveRetValue; j < fun->param_count; j++) {
- if (!slang_type_specifier_equal
- (&fun->parameters->variables[j]->type.specifier,
- &f->parameters->variables[j]->type.specifier))
- break;
- }
- if (j == fun->param_count) {
- /*
- printf("Found match\n");
- */
- return f;
- }
- }
- /*
- printf("Not found\n");
- */
- if (all_scopes && funcs->outer_scope != NULL)
- return slang_function_scope_find(funcs->outer_scope, fun, 1);
- return NULL;
-}
-
-
-/**
- * Lookup a function according to name and parameter count/types.
- */
-slang_function *
-_slang_function_locate(const slang_function_scope * funcs, slang_atom a_name,
- slang_operation * args, GLuint num_args,
- const slang_name_space * space, slang_atom_pool * atoms,
- slang_info_log *log, GLboolean *error)
-{
- slang_typeinfo arg_ti[100];
- GLuint i;
-
- *error = GL_FALSE;
-
- /* determine type of each argument */
- assert(num_args < 100);
- for (i = 0; i < num_args; i++) {
- if (!slang_typeinfo_construct(&arg_ti[i]))
- return NULL;
- if (!_slang_typeof_operation(&args[i], space, &arg_ti[i], atoms, log)) {
- return NULL;
- }
- }
-
- /* loop over function scopes */
- while (funcs) {
-
- /* look for function with matching name and argument/param types */
- for (i = 0; i < funcs->num_functions; i++) {
- slang_function *f = &funcs->functions[i];
- const GLuint haveRetValue = _slang_function_has_return_value(f);
- GLuint j;
-
- if (a_name != f->header.a_name)
- continue;
- if (f->param_count - haveRetValue != num_args)
- continue;
-
- /* compare parameter / argument types */
- for (j = 0; j < num_args; j++) {
- if (!slang_type_specifier_compatible(&arg_ti[j].spec,
- &f->parameters->variables[j]->type.specifier)) {
- /* param/arg types don't match */
- break;
- }
-
- /* "out" and "inout" formal parameter requires the actual
- * argument to be an l-value.
- */
- if (!arg_ti[j].can_be_referenced &&
- (f->parameters->variables[j]->type.qualifier == SLANG_QUAL_OUT ||
- f->parameters->variables[j]->type.qualifier == SLANG_QUAL_INOUT)) {
- /* param is not an lvalue! */
- *error = GL_TRUE;
- return NULL;
- }
- }
-
- if (j == num_args) {
- /* name and args match! */
- return f;
- }
- }
-
- funcs = funcs->outer_scope;
- }
-
- return NULL;
-}
+++ /dev/null
-/*
- * Mesa 3-D graphics library
- * Version: 6.5.2
- *
- * Copyright (C) 2005-2006 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 SLANG_COMPILE_FUNCTION_H
-#define SLANG_COMPILE_FUNCTION_H
-
-#include "main/glheader.h"
-#include "slang_compile_operation.h"
-#include "slang_compile_variable.h"
-#include "slang_log.h"
-#include "slang_utility.h"
-
-struct slang_name_space_;
-struct slang_operation_;
-
-/**
- * Types of functions.
- */
-typedef enum slang_function_kind_
-{
- SLANG_FUNC_ORDINARY,
- SLANG_FUNC_CONSTRUCTOR,
- SLANG_FUNC_OPERATOR
-} slang_function_kind;
-
-
-/**
- * Description of a compiled shader function.
- */
-typedef struct slang_function_
-{
- slang_function_kind kind;
- slang_variable header; /**< The function's name and return type */
- slang_variable_scope *parameters; /**< formal parameters AND local vars */
- unsigned int param_count; /**< number of formal params (no locals) */
- slang_operation *body; /**< The instruction tree */
-} slang_function;
-
-extern int slang_function_construct(slang_function *);
-extern void slang_function_destruct(slang_function *);
-extern slang_function *slang_function_new(slang_function_kind kind);
-
-extern GLboolean
-_slang_function_has_return_value(const slang_function *fun);
-
-
-/**
- * Basically, a list of compiled functions.
- */
-typedef struct slang_function_scope_
-{
- slang_function *functions;
- GLuint num_functions;
- struct slang_function_scope_ *outer_scope;
-} slang_function_scope;
-
-
-extern GLvoid
-_slang_function_scope_ctr(slang_function_scope *);
-
-extern void
-slang_function_scope_destruct(slang_function_scope *);
-
-extern int
-slang_function_scope_find_by_name(slang_function_scope *, slang_atom, int);
-
-extern slang_function *
-slang_function_scope_find(slang_function_scope *, slang_function *, int);
-
-extern struct slang_function_ *
-_slang_function_locate(const struct slang_function_scope_ *funcs,
- slang_atom name, struct slang_operation_ *params,
- GLuint num_params,
- const struct slang_name_space_ *space,
- slang_atom_pool *atoms, slang_info_log *log,
- GLboolean *error);
-
-
-#endif /* SLANG_COMPILE_FUNCTION_H */
+++ /dev/null
-/*
- * Mesa 3-D graphics library
- * Version: 6.5.2
- *
- * Copyright (C) 2005-2006 Brian Paul All Rights Reserved.
- *
- * Permission is hereby granted, free of charge, to any person obtaining a
- * copy of this software and associated documentation files (the "Software"),
- * to deal in the Software without restriction, including without limitation
- * the rights to use, copy, modify, merge, publish, distribute, sublicense,
- * and/or sell copies of the Software, and to permit persons to whom the
- * Software is furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included
- * in all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
- * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
- * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
- * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
- * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
- */
-
-/**
- * \file slang_compile_operation.c
- * slang front-end compiler
- * \author Michal Krol
- */
-
-#include "main/imports.h"
-#include "slang_compile.h"
-#include "slang_mem.h"
-
-
-/**
- * Init a slang_operation object
- */
-GLboolean
-slang_operation_construct(slang_operation * oper)
-{
- oper->type = SLANG_OPER_NONE;
- oper->children = NULL;
- oper->num_children = 0;
- oper->literal[0] = 0.0;
- oper->literal_size = 1;
- oper->array_constructor = GL_FALSE;
- oper->a_id = SLANG_ATOM_NULL;
- oper->a_obj = SLANG_ATOM_NULL;
- oper->locals = _slang_variable_scope_new(NULL);
- if (oper->locals == NULL)
- return GL_FALSE;
- _slang_variable_scope_ctr(oper->locals);
- oper->fun = NULL;
- oper->var = NULL;
- oper->label = NULL;
- return GL_TRUE;
-}
-
-void
-slang_operation_destruct(slang_operation * oper)
-{
- GLuint i;
-
- for (i = 0; i < oper->num_children; i++)
- slang_operation_destruct(oper->children + i);
- _slang_free(oper->children);
- slang_variable_scope_destruct(oper->locals);
- _slang_free(oper->locals);
- oper->children = NULL;
- oper->num_children = 0;
- oper->locals = NULL;
-}
-
-
-/**
- * Recursively traverse 'oper', replacing occurances of 'oldScope' with
- * 'newScope' in the oper->locals->outer_scope field.
- */
-void
-slang_replace_scope(slang_operation *oper,
- slang_variable_scope *oldScope,
- slang_variable_scope *newScope)
-{
- GLuint i;
-
- if (oper->locals != newScope &&
- oper->locals->outer_scope == oldScope) {
- /* found. replace old w/ new */
- oper->locals->outer_scope = newScope;
- }
-
- if (oper->type == SLANG_OPER_VARIABLE_DECL) {
- /* search/replace in the initializer */
- slang_variable *var;
- var = _slang_variable_locate(oper->locals, oper->a_id, GL_TRUE);
- if (var && var->initializer) {
- slang_replace_scope(var->initializer, oldScope, newScope);
- }
- }
-
- /* search/replace in children */
- for (i = 0; i < oper->num_children; i++) {
- slang_replace_scope(&oper->children[i], oldScope, newScope);
- }
-}
-
-
-/**
- * Recursively copy a slang_operation node.
- * \param x copy target
- * \param y copy source
- * \return GL_TRUE for success, GL_FALSE if failure
- */
-GLboolean
-slang_operation_copy(slang_operation * x, const slang_operation * y)
-{
- slang_operation z;
- GLuint i;
-
- if (!slang_operation_construct(&z))
- return GL_FALSE;
- z.type = y->type;
- if (y->num_children > 0) {
- z.children = (slang_operation *)
- _slang_alloc(y->num_children * sizeof(slang_operation));
- if (z.children == NULL) {
- slang_operation_destruct(&z);
- return GL_FALSE;
- }
- }
- for (z.num_children = 0; z.num_children < y->num_children;
- z.num_children++) {
- if (!slang_operation_construct(&z.children[z.num_children])) {
- slang_operation_destruct(&z);
- return GL_FALSE;
- }
- }
- for (i = 0; i < z.num_children; i++) {
- if (!slang_operation_copy(&z.children[i], &y->children[i])) {
- slang_operation_destruct(&z);
- return GL_FALSE;
- }
- }
- z.literal[0] = y->literal[0];
- z.literal[1] = y->literal[1];
- z.literal[2] = y->literal[2];
- z.literal[3] = y->literal[3];
- z.literal_size = y->literal_size;
- assert(y->literal_size >= 1);
- assert(y->literal_size <= 4);
- z.a_id = y->a_id;
- if (y->locals) {
- if (!slang_variable_scope_copy(z.locals, y->locals)) {
- slang_operation_destruct(&z);
- return GL_FALSE;
- }
- }
-
- /* update scoping for children */
- for (i = 0; i < y->num_children; i++) {
- if (y->children[i].locals &&
- y->children[i].locals->outer_scope == y->locals) {
- z.children[i].locals->outer_scope = z.locals;
- }
- }
-
-#if 0
- z.var = y->var;
- z.fun = y->fun;
-#endif
- slang_operation_destruct(x);
- *x = z;
-
- /* If this operation declares a new scope, we need to make sure
- * all children point to it, not the original operation's scope!
- */
- if (x->type == SLANG_OPER_BLOCK_NEW_SCOPE ||
- x->type == SLANG_OPER_WHILE ||
- x->type == SLANG_OPER_FOR) {
- slang_replace_scope(x, y->locals, x->locals);
- }
-
- return GL_TRUE;
-}
-
-
-slang_operation *
-slang_operation_new(GLuint count)
-{
- slang_operation *ops
- = (slang_operation *) _slang_alloc(count * sizeof(slang_operation));
- assert(count > 0);
- if (ops) {
- GLuint i;
- for (i = 0; i < count; i++)
- slang_operation_construct(ops + i);
- }
- return ops;
-}
-
-
-/**
- * Delete operation and all children
- */
-void
-slang_operation_delete(slang_operation *oper)
-{
- slang_operation_destruct(oper);
- _slang_free(oper);
-}
-
-
-void
-slang_operation_free_children(slang_operation *oper)
-{
- GLuint i;
- for (i = 0; i < slang_oper_num_children(oper); i++) {
- slang_operation *child = slang_oper_child(oper, i);
- slang_operation_destruct(child);
- }
- _slang_free(oper->children);
- oper->children = NULL;
- oper->num_children = 0;
-}
-
-
-slang_operation *
-slang_operation_grow(GLuint *numChildren, slang_operation **children)
-{
- slang_operation *ops;
-
- ops = (slang_operation *)
- _slang_realloc(*children,
- *numChildren * sizeof(slang_operation),
- (*numChildren + 1) * sizeof(slang_operation));
- if (ops) {
- slang_operation *newOp = ops + *numChildren;
- if (!slang_operation_construct(newOp)) {
- _slang_free(ops);
- *children = NULL;
- return NULL;
- }
- *children = ops;
- (*numChildren)++;
- return newOp;
- }
- return NULL;
-}
-
-/**
- * Insert a new slang_operation into an array.
- * \param numElements pointer to current array size (in/out)
- * \param array address of the array (in/out)
- * \param pos position to insert new element
- * \return pointer to the new operation/element
- */
-slang_operation *
-slang_operation_insert(GLuint *numElements, slang_operation **array,
- GLuint pos)
-{
- slang_operation *ops;
-
- assert(pos <= *numElements);
-
- ops = (slang_operation *)
- _slang_alloc((*numElements + 1) * sizeof(slang_operation));
- if (ops) {
- slang_operation *newOp;
- newOp = ops + pos;
- if (pos > 0)
- memcpy(ops, *array, pos * sizeof(slang_operation));
- if (pos < *numElements)
- memcpy(newOp + 1, (*array) + pos,
- (*numElements - pos) * sizeof(slang_operation));
-
- if (!slang_operation_construct(newOp)) {
- _slang_free(ops);
- *numElements = 0;
- *array = NULL;
- return NULL;
- }
- if (*array)
- _slang_free(*array);
- *array = ops;
- (*numElements)++;
- return newOp;
- }
- return NULL;
-}
-
-
-/**
- * Add/insert new child into given node at given position.
- * \return pointer to the new child node
- */
-slang_operation *
-slang_operation_insert_child(slang_operation *oper, GLuint pos)
-{
- slang_operation *newOp;
-
- newOp = slang_operation_insert(&oper->num_children,
- &oper->children,
- pos);
- if (newOp) {
- newOp->locals->outer_scope = oper->locals;
- }
-
- return newOp;
-}
-
-
-void
-_slang_operation_swap(slang_operation *oper0, slang_operation *oper1)
-{
- slang_operation tmp = *oper0;
- *oper0 = *oper1;
- *oper1 = tmp;
-}
-
-
-void
-slang_operation_add_children(slang_operation *oper, GLuint num_children)
-{
- GLuint i;
- assert(oper->num_children == 0);
- assert(oper->children == NULL);
- oper->num_children = num_children;
- oper->children = slang_operation_new(num_children);
- for (i = 0; i < num_children; i++) {
- oper->children[i].locals = _slang_variable_scope_new(oper->locals);
- }
-}
-
+++ /dev/null
-/*
- * Mesa 3-D graphics library
- * Version: 6.5.2
- *
- * Copyright (C) 2005-2006 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 SLANG_COMPILE_OPERATION_H
-#define SLANG_COMPILE_OPERATION_H
-
-
-#include "main/compiler.h"
-#include "main/glheader.h"
-#include "slang_compile_variable.h"
-#include "slang_utility.h"
-
-/**
- * Types of slang operations.
- * These are the types of the AST (abstract syntax tree) nodes.
- * [foo] indicates a sub-tree or reference to another type of node
- */
-typedef enum slang_operation_type_
-{
- SLANG_OPER_NONE,
- SLANG_OPER_BLOCK_NO_NEW_SCOPE, /* "{" sequence "}" */
- SLANG_OPER_BLOCK_NEW_SCOPE, /* "{" sequence "}" */
- SLANG_OPER_VARIABLE_DECL, /* [type] [var] or [var] = [expr] */
- SLANG_OPER_ASM,
- SLANG_OPER_BREAK, /* "break" statement */
- SLANG_OPER_CONTINUE, /* "continue" statement */
- SLANG_OPER_DISCARD, /* "discard" (kill fragment) statement */
- SLANG_OPER_RETURN, /* "return" [expr] */
- SLANG_OPER_RETURN_INLINED, /* "return" [expr] from inlined function */
- SLANG_OPER_LABEL, /* a jump target */
- SLANG_OPER_EXPRESSION, /* [expr] */
- SLANG_OPER_IF, /* "if" [0] then [1] else [2] */
- SLANG_OPER_WHILE, /* "while" [cond] [body] */
- SLANG_OPER_DO, /* "do" [body] "while" [cond] */
- SLANG_OPER_FOR, /* "for" [init] [while] [incr] [body] */
- SLANG_OPER_VOID, /* nop */
- SLANG_OPER_LITERAL_BOOL, /* "true" or "false" */
- SLANG_OPER_LITERAL_INT, /* integer literal */
- SLANG_OPER_LITERAL_FLOAT, /* float literal */
- SLANG_OPER_IDENTIFIER, /* var name, func name, etc */
- SLANG_OPER_SEQUENCE, /* [expr] "," [expr] "," etc */
- SLANG_OPER_ASSIGN, /* [var] "=" [expr] */
- SLANG_OPER_ADDASSIGN, /* [var] "+=" [expr] */
- SLANG_OPER_SUBASSIGN, /* [var] "-=" [expr] */
- SLANG_OPER_MULASSIGN, /* [var] "*=" [expr] */
- SLANG_OPER_DIVASSIGN, /* [var] "/=" [expr] */
- /*SLANG_OPER_MODASSIGN, */
- /*SLANG_OPER_LSHASSIGN, */
- /*SLANG_OPER_RSHASSIGN, */
- /*SLANG_OPER_ORASSIGN, */
- /*SLANG_OPER_XORASSIGN, */
- /*SLANG_OPER_ANDASSIGN, */
- SLANG_OPER_SELECT, /* [expr] "?" [expr] ":" [expr] */
- SLANG_OPER_LOGICALOR, /* [expr] "||" [expr] */
- SLANG_OPER_LOGICALXOR, /* [expr] "^^" [expr] */
- SLANG_OPER_LOGICALAND, /* [expr] "&&" [expr] */
- /*SLANG_OPER_BITOR, */
- /*SLANG_OPER_BITXOR, */
- /*SLANG_OPER_BITAND, */
- SLANG_OPER_EQUAL, /* [expr] "==" [expr] */
- SLANG_OPER_NOTEQUAL, /* [expr] "!=" [expr] */
- SLANG_OPER_LESS, /* [expr] "<" [expr] */
- SLANG_OPER_GREATER, /* [expr] ">" [expr] */
- SLANG_OPER_LESSEQUAL, /* [expr] "<=" [expr] */
- SLANG_OPER_GREATEREQUAL, /* [expr] ">=" [expr] */
- /*SLANG_OPER_LSHIFT, */
- /*SLANG_OPER_RSHIFT, */
- SLANG_OPER_ADD, /* [expr] "+" [expr] */
- SLANG_OPER_SUBTRACT, /* [expr] "-" [expr] */
- SLANG_OPER_MULTIPLY, /* [expr] "*" [expr] */
- SLANG_OPER_DIVIDE, /* [expr] "/" [expr] */
- /*SLANG_OPER_MODULUS, */
- SLANG_OPER_PREINCREMENT, /* "++" [var] */
- SLANG_OPER_PREDECREMENT, /* "--" [var] */
- SLANG_OPER_PLUS, /* "-" [expr] */
- SLANG_OPER_MINUS, /* "+" [expr] */
- /*SLANG_OPER_COMPLEMENT, */
- SLANG_OPER_NOT, /* "!" [expr] */
- SLANG_OPER_SUBSCRIPT, /* [expr] "[" [expr] "]" */
- SLANG_OPER_CALL, /* [func name] [param] [param] [...] */
- SLANG_OPER_NON_INLINED_CALL, /* a real function call */
- SLANG_OPER_METHOD, /* method call, such as v.length() */
- SLANG_OPER_FIELD, /* i.e.: ".next" or ".xzy" or ".xxx" etc */
- SLANG_OPER_POSTINCREMENT, /* [var] "++" */
- SLANG_OPER_POSTDECREMENT /* [var] "--" */
-} slang_operation_type;
-
-
-/**
- * A slang_operation is basically a compiled instruction (such as assignment,
- * a while-loop, a conditional, a multiply, a function call, etc).
- * The AST (abstract syntax tree) is built from these nodes.
- * NOTE: This structure could have been implemented as a union of simpler
- * structs which would correspond to the operation types above.
- */
-typedef struct slang_operation_
-{
- slang_operation_type type;
- struct slang_operation_ *children;
- GLuint num_children;
- GLfloat literal[4]; /**< Used for float, int and bool values */
- GLuint literal_size; /**< 1, 2, 3, or 4 */
- slang_atom a_id; /**< type: asm, identifier, call, field */
- slang_atom a_obj; /**< object in a method call */
- slang_variable_scope *locals; /**< local vars for scope */
- struct slang_function_ *fun; /**< If type == SLANG_OPER_CALL */
- struct slang_variable_ *var; /**< If type == slang_oper_identier */
- struct slang_label_ *label; /**< If type == SLANG_OPER_LABEL */
- /** If type==SLANG_OPER_CALL and we're calling an array constructor,
- * for which there's no real function, we need to have a flag to
- * indicate such. num_children indicates number of elements.
- */
- GLboolean array_constructor;
-} slang_operation;
-
-
-extern GLboolean
-slang_operation_construct(slang_operation *);
-
-extern void
-slang_operation_destruct(slang_operation *);
-
-extern void
-slang_replace_scope(slang_operation *oper,
- slang_variable_scope *oldScope,
- slang_variable_scope *newScope);
-
-extern GLboolean
-slang_operation_copy(slang_operation *, const slang_operation *);
-
-extern slang_operation *
-slang_operation_new(GLuint count);
-
-extern void
-slang_operation_delete(slang_operation *oper);
-
-extern void
-slang_operation_free_children(slang_operation *oper);
-
-extern slang_operation *
-slang_operation_grow(GLuint *numChildren, slang_operation **children);
-
-extern slang_operation *
-slang_operation_insert(GLuint *numChildren, slang_operation **children,
- GLuint pos);
-
-extern slang_operation *
-slang_operation_insert_child(slang_operation *oper, GLuint pos);
-
-extern void
-_slang_operation_swap(slang_operation *oper0, slang_operation *oper1);
-
-
-extern void
-slang_operation_add_children(slang_operation *oper, GLuint num_children);
-
-
-/** Return number of children of given node */
-static INLINE GLuint
-slang_oper_num_children(const slang_operation *oper)
-{
- return oper->num_children;
-}
-
-/** Return child of given operation node */
-static INLINE slang_operation *
-slang_oper_child(slang_operation *oper, GLuint child)
-{
- assert(child < oper->num_children);
- return &oper->children[child];
-}
-
-
-/** Return child of given operation node, const version */
-static INLINE const slang_operation *
-slang_oper_child_const(const slang_operation *oper, GLuint child)
-{
- assert(child < oper->num_children);
- return &oper->children[child];
-}
-
-
-/** Init oper to a boolean literal. */
-static INLINE void
-slang_operation_literal_bool(slang_operation *oper, GLboolean value)
-{
- oper->type = SLANG_OPER_LITERAL_BOOL;
- oper->literal[0] =
- oper->literal[1] =
- oper->literal[2] =
- oper->literal[3] = (float) value;
- oper->literal_size = 1;
-}
-
-
-/** Init oper to an int literal. */
-static INLINE void
-slang_operation_literal_int(slang_operation *oper, GLint value)
-{
- oper->type = SLANG_OPER_LITERAL_INT;
- oper->literal[0] =
- oper->literal[1] =
- oper->literal[2] =
- oper->literal[3] = (float) value;
- oper->literal_size = 1;
-}
-
-
-#endif /* SLANG_COMPILE_OPERATION_H */
+++ /dev/null
-/*
- * Mesa 3-D graphics library
- * Version: 6.5.3
- *
- * Copyright (C) 2005-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.
- */
-
-/**
- * \file slang_compile_struct.c
- * slang front-end compiler
- * \author Michal Krol
- */
-
-#include "main/imports.h"
-#include "slang_mem.h"
-#include "slang_compile.h"
-
-
-GLvoid
-_slang_struct_scope_ctr(slang_struct_scope * self)
-{
- self->structs = NULL;
- self->num_structs = 0;
- self->outer_scope = NULL;
-}
-
-void
-slang_struct_scope_destruct(slang_struct_scope * scope)
-{
- GLuint i;
-
- for (i = 0; i < scope->num_structs; i++)
- slang_struct_destruct(scope->structs + i);
- _slang_free(scope->structs);
- /* do not free scope->outer_scope */
-}
-
-int
-slang_struct_scope_copy(slang_struct_scope * x, const slang_struct_scope * y)
-{
- slang_struct_scope z;
- GLuint i;
-
- _slang_struct_scope_ctr(&z);
- z.structs = (slang_struct *)
- _slang_alloc(y->num_structs * sizeof(slang_struct));
- if (z.structs == NULL) {
- slang_struct_scope_destruct(&z);
- return 0;
- }
- for (z.num_structs = 0; z.num_structs < y->num_structs; z.num_structs++)
- if (!slang_struct_construct(&z.structs[z.num_structs])) {
- slang_struct_scope_destruct(&z);
- return 0;
- }
- for (i = 0; i < z.num_structs; i++)
- if (!slang_struct_copy(&z.structs[i], &y->structs[i])) {
- slang_struct_scope_destruct(&z);
- return 0;
- }
- z.outer_scope = y->outer_scope;
- slang_struct_scope_destruct(x);
- *x = z;
- return 1;
-}
-
-slang_struct *
-slang_struct_scope_find(slang_struct_scope * stru, slang_atom a_name,
- int all_scopes)
-{
- GLuint i;
-
- for (i = 0; i < stru->num_structs; i++)
- if (a_name == stru->structs[i].a_name)
- return &stru->structs[i];
- if (all_scopes && stru->outer_scope != NULL)
- return slang_struct_scope_find(stru->outer_scope, a_name, 1);
- return NULL;
-}
-
-/* slang_struct */
-
-int
-slang_struct_construct(slang_struct * stru)
-{
- stru->a_name = SLANG_ATOM_NULL;
- stru->fields = (slang_variable_scope *)
- _slang_alloc(sizeof(slang_variable_scope));
- if (stru->fields == NULL)
- return 0;
- _slang_variable_scope_ctr(stru->fields);
-
- stru->structs =
- (slang_struct_scope *) _slang_alloc(sizeof(slang_struct_scope));
- if (stru->structs == NULL) {
- slang_variable_scope_destruct(stru->fields);
- _slang_free(stru->fields);
- return 0;
- }
- _slang_struct_scope_ctr(stru->structs);
- stru->constructor = NULL;
- return 1;
-}
-
-void
-slang_struct_destruct(slang_struct * stru)
-{
- slang_variable_scope_destruct(stru->fields);
- _slang_free(stru->fields);
- slang_struct_scope_destruct(stru->structs);
- _slang_free(stru->structs);
-}
-
-int
-slang_struct_copy(slang_struct * x, const slang_struct * y)
-{
- slang_struct z;
-
- if (!slang_struct_construct(&z))
- return 0;
- z.a_name = y->a_name;
- if (!slang_variable_scope_copy(z.fields, y->fields)) {
- slang_struct_destruct(&z);
- return 0;
- }
- if (!slang_struct_scope_copy(z.structs, y->structs)) {
- slang_struct_destruct(&z);
- return 0;
- }
- slang_struct_destruct(x);
- *x = z;
- return 1;
-}
-
-int
-slang_struct_equal(const slang_struct * x, const slang_struct * y)
-{
- GLuint i;
-
- if (x->fields->num_variables != y->fields->num_variables)
- return 0;
-
- for (i = 0; i < x->fields->num_variables; i++) {
- const slang_variable *varx = x->fields->variables[i];
- const slang_variable *vary = y->fields->variables[i];
-
- if (varx->a_name != vary->a_name)
- return 0;
- if (!slang_type_specifier_equal(&varx->type.specifier,
- &vary->type.specifier))
- return 0;
- if (varx->type.specifier.type == SLANG_SPEC_ARRAY)
- if (varx->array_len != vary->array_len)
- return GL_FALSE;
- }
- return 1;
-}
+++ /dev/null
-/*
- * Mesa 3-D graphics library
- * Version: 6.5
- *
- * Copyright (C) 2005-2006 Brian Paul All Rights Reserved.
- *
- * Permission is hereby granted, free of charge, to any person obtaining a
- * copy of this software and associated documentation files (the "Software"),
- * to deal in the Software without restriction, including without limitation
- * the rights to use, copy, modify, merge, publish, distribute, sublicense,
- * and/or sell copies of the Software, and to permit persons to whom the
- * Software is furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included
- * in all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
- * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
- * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
- * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
- * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
- */
-
-#if !defined SLANG_COMPILE_STRUCT_H
-#define SLANG_COMPILE_STRUCT_H
-
-#if defined __cplusplus
-extern "C" {
-#endif
-
-#include "main/glheader.h"
-#include "slang_utility.h"
-
-struct slang_function_;
-
-typedef struct slang_struct_scope_
-{
- struct slang_struct_ *structs;
- GLuint num_structs;
- struct slang_struct_scope_ *outer_scope;
-} slang_struct_scope;
-
-extern GLvoid
-_slang_struct_scope_ctr (slang_struct_scope *);
-
-void slang_struct_scope_destruct (slang_struct_scope *);
-int slang_struct_scope_copy (slang_struct_scope *, const slang_struct_scope *);
-struct slang_struct_ *slang_struct_scope_find (slang_struct_scope *, slang_atom, int);
-
-typedef struct slang_struct_
-{
- slang_atom a_name;
- struct slang_variable_scope_ *fields;
- slang_struct_scope *structs;
- struct slang_function_ *constructor;
-} slang_struct;
-
-int slang_struct_construct (slang_struct *);
-void slang_struct_destruct (slang_struct *);
-int slang_struct_copy (slang_struct *, const slang_struct *);
-int slang_struct_equal (const slang_struct *, const slang_struct *);
-
-#ifdef __cplusplus
-}
-#endif
-
-#endif
-
+++ /dev/null
-/*
- * Mesa 3-D graphics library
- * Version: 6.5.3
- *
- * Copyright (C) 2005-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.
- */
-
-/**
- * \file slang_compile_variable.c
- * slang front-end compiler
- * \author Michal Krol
- */
-
-#include "main/imports.h"
-#include "slang_compile.h"
-#include "slang_mem.h"
-
-
-static slang_variable *
-slang_variable_new(void)
-{
- slang_variable *v = (slang_variable *) _slang_alloc(sizeof(slang_variable));
- if (v) {
- if (!slang_variable_construct(v)) {
- _slang_free(v);
- v = NULL;
- }
- }
- return v;
-}
-
-
-static void
-slang_variable_delete(slang_variable * var)
-{
- slang_variable_destruct(var);
- _slang_free(var);
-}
-
-
-/*
- * slang_variable_scope
- */
-
-slang_variable_scope *
-_slang_variable_scope_new(slang_variable_scope *parent)
-{
- slang_variable_scope *s;
- s = (slang_variable_scope *) _slang_alloc(sizeof(slang_variable_scope));
- if (s)
- s->outer_scope = parent;
- return s;
-}
-
-
-GLvoid
-_slang_variable_scope_ctr(slang_variable_scope * self)
-{
- self->variables = NULL;
- self->num_variables = 0;
- self->outer_scope = NULL;
-}
-
-void
-slang_variable_scope_destruct(slang_variable_scope * scope)
-{
- unsigned int i;
-
- if (!scope)
- return;
- for (i = 0; i < scope->num_variables; i++) {
- if (scope->variables[i])
- slang_variable_delete(scope->variables[i]);
- }
- _slang_free(scope->variables);
- /* do not free scope->outer_scope */
-}
-
-int
-slang_variable_scope_copy(slang_variable_scope * x,
- const slang_variable_scope * y)
-{
- slang_variable_scope z;
- unsigned int i;
-
- _slang_variable_scope_ctr(&z);
- z.variables = (slang_variable **)
- _slang_alloc(y->num_variables * sizeof(slang_variable *));
- if (z.variables == NULL) {
- slang_variable_scope_destruct(&z);
- return 0;
- }
- for (z.num_variables = 0; z.num_variables < y->num_variables;
- z.num_variables++) {
- z.variables[z.num_variables] = slang_variable_new();
- if (!z.variables[z.num_variables]) {
- slang_variable_scope_destruct(&z);
- return 0;
- }
- }
- for (i = 0; i < z.num_variables; i++) {
- if (!slang_variable_copy(z.variables[i], y->variables[i])) {
- slang_variable_scope_destruct(&z);
- return 0;
- }
- }
- z.outer_scope = y->outer_scope;
- slang_variable_scope_destruct(x);
- *x = z;
- return 1;
-}
-
-
-/**
- * Grow the variable list by one.
- * \return pointer to space for the new variable (will be initialized)
- */
-slang_variable *
-slang_variable_scope_grow(slang_variable_scope *scope)
-{
- const int n = scope->num_variables;
- scope->variables = (slang_variable **)
- _slang_realloc(scope->variables,
- n * sizeof(slang_variable *),
- (n + 1) * sizeof(slang_variable *));
- if (!scope->variables)
- return NULL;
-
- scope->num_variables++;
-
- scope->variables[n] = slang_variable_new();
- if (!scope->variables[n])
- return NULL;
-
- return scope->variables[n];
-}
-
-
-
-/* slang_variable */
-
-int
-slang_variable_construct(slang_variable * var)
-{
- if (!slang_fully_specified_type_construct(&var->type))
- return 0;
- var->a_name = SLANG_ATOM_NULL;
- var->array_len = 0;
- var->initializer = NULL;
- var->size = 0;
- var->isTemp = GL_FALSE;
- var->store = NULL;
- var->declared = 0;
- return 1;
-}
-
-
-void
-slang_variable_destruct(slang_variable * var)
-{
- slang_fully_specified_type_destruct(&var->type);
- if (var->initializer != NULL) {
- slang_operation_destruct(var->initializer);
- _slang_free(var->initializer);
- }
-#if 0
- if (var->aux) {
- free(var->aux);
- }
-#endif
-}
-
-
-int
-slang_variable_copy(slang_variable * x, const slang_variable * y)
-{
- slang_variable z;
-
- if (!slang_variable_construct(&z))
- return 0;
- if (!slang_fully_specified_type_copy(&z.type, &y->type)) {
- slang_variable_destruct(&z);
- return 0;
- }
- z.a_name = y->a_name;
- z.array_len = y->array_len;
- if (y->initializer != NULL) {
- z.initializer
- = (slang_operation *) _slang_alloc(sizeof(slang_operation));
- if (z.initializer == NULL) {
- slang_variable_destruct(&z);
- return 0;
- }
- if (!slang_operation_construct(z.initializer)) {
- _slang_free(z.initializer);
- slang_variable_destruct(&z);
- return 0;
- }
- if (!slang_operation_copy(z.initializer, y->initializer)) {
- slang_variable_destruct(&z);
- return 0;
- }
- }
- z.size = y->size;
- slang_variable_destruct(x);
- *x = z;
- return 1;
-}
-
-
-/**
- * Search for named variable in given scope.
- * \param all if true, search parent scopes too.
- */
-slang_variable *
-_slang_variable_locate(const slang_variable_scope * scope,
- const slang_atom a_name, GLboolean all)
-{
- while (scope) {
- GLuint i;
- for (i = 0; i < scope->num_variables; i++)
- if (a_name == scope->variables[i]->a_name)
- return scope->variables[i];
- if (all)
- scope = scope->outer_scope;
- else
- scope = NULL;
- }
- return NULL;
-}
+++ /dev/null
-/*
- * Mesa 3-D graphics library
- * Version: 6.5.2
- *
- * Copyright (C) 2005-2006 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 SLANG_COMPILE_VARIABLE_H
-#define SLANG_COMPILE_VARIABLE_H
-
-
-#include "main/glheader.h"
-#include "slang_typeinfo.h"
-#include "slang_utility.h"
-
-
-/**
- * A shading language program variable.
- */
-typedef struct slang_variable_
-{
- slang_fully_specified_type type; /**< Variable's data type */
- slang_atom a_name; /**< The variable's name (char *) */
- GLuint array_len; /**< only if type == SLANG_SPEC_ARRAy */
- struct slang_operation_ *initializer; /**< Optional initializer code */
- GLuint size; /**< Variable's size in bytes */
- GLboolean is_global;
- GLboolean isTemp; /**< a named temporary (__resultTmp) */
- GLboolean declared; /**< has the var been declared? */
- struct slang_ir_storage_ *store; /**< Storage for this var */
-} slang_variable;
-
-
-/**
- * Basically a list of variables, with a pointer to the parent scope.
- */
-typedef struct slang_variable_scope_
-{
- slang_variable **variables; /**< Array [num_variables] of ptrs to vars */
- GLuint num_variables;
- struct slang_variable_scope_ *outer_scope;
-} slang_variable_scope;
-
-
-extern slang_variable_scope *
-_slang_variable_scope_new(slang_variable_scope *parent);
-
-extern GLvoid
-_slang_variable_scope_ctr(slang_variable_scope *);
-
-extern void
-slang_variable_scope_destruct(slang_variable_scope *);
-
-extern int
-slang_variable_scope_copy(slang_variable_scope *,
- const slang_variable_scope *);
-
-extern slang_variable *
-slang_variable_scope_grow(slang_variable_scope *);
-
-extern int
-slang_variable_construct(slang_variable *);
-
-extern void
-slang_variable_destruct(slang_variable *);
-
-extern int
-slang_variable_copy(slang_variable *, const slang_variable *);
-
-extern slang_variable *
-_slang_variable_locate(const slang_variable_scope *, const slang_atom a_name,
- GLboolean all);
-
-
-#endif /* SLANG_COMPILE_VARIABLE_H */
+++ /dev/null
-/*
- * Mesa 3-D graphics library
- *
- * Copyright (C) 2005-2008 Brian Paul All Rights Reserved.
- * Copyright (C) 2008 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 slang_emit.c
- * Emit program instructions (PI code) from IR trees.
- * \author Brian Paul
- */
-
-/***
- *** NOTES
- ***
- *** To emit GPU instructions, we basically just do an in-order traversal
- *** of the IR tree.
- ***/
-
-
-#include "main/imports.h"
-#include "main/context.h"
-#include "program/program.h"
-#include "program/prog_instruction.h"
-#include "program/prog_parameter.h"
-#include "program/prog_print.h"
-#include "slang_builtin.h"
-#include "slang_emit.h"
-#include "slang_mem.h"
-
-
-#define PEEPHOLE_OPTIMIZATIONS 1
-#define ANNOTATE 0
-
-
-typedef struct
-{
- slang_info_log *log;
- slang_var_table *vt;
- struct gl_program *prog;
- struct gl_program **Subroutines;
- GLuint NumSubroutines;
-
- GLuint MaxInstructions; /**< size of prog->Instructions[] buffer */
-
- GLboolean UnresolvedFunctions;
-
- /* code-gen options */
- GLboolean EmitHighLevelInstructions;
- GLboolean EmitCondCodes;
- GLboolean EmitComments;
- GLboolean EmitBeginEndSub; /* XXX TEMPORARY */
-} slang_emit_info;
-
-
-
-static struct gl_program *
-new_subroutine(slang_emit_info *emitInfo, GLuint *id)
-{
- GET_CURRENT_CONTEXT(ctx);
- const GLuint n = emitInfo->NumSubroutines;
-
- emitInfo->Subroutines = (struct gl_program **)
- _mesa_realloc(emitInfo->Subroutines,
- n * sizeof(struct gl_program *),
- (n + 1) * sizeof(struct gl_program *));
- emitInfo->Subroutines[n] = ctx->Driver.NewProgram(ctx, emitInfo->prog->Target, 0);
- emitInfo->Subroutines[n]->Parameters = emitInfo->prog->Parameters;
- emitInfo->NumSubroutines++;
- *id = n;
- return emitInfo->Subroutines[n];
-}
-
-
-/**
- * Convert a writemask to a swizzle. Used for testing cond codes because
- * we only want to test the cond code component(s) that was set by the
- * previous instruction.
- */
-static GLuint
-writemask_to_swizzle(GLuint writemask)
-{
- if (writemask == WRITEMASK_X)
- return SWIZZLE_XXXX;
- if (writemask == WRITEMASK_Y)
- return SWIZZLE_YYYY;
- if (writemask == WRITEMASK_Z)
- return SWIZZLE_ZZZZ;
- if (writemask == WRITEMASK_W)
- return SWIZZLE_WWWW;
- return SWIZZLE_XYZW; /* shouldn't be hit */
-}
-
-
-/**
- * Convert a swizzle mask to a writemask.
- * Note that the slang_ir_storage->Swizzle field can represent either a
- * swizzle mask or a writemask, depending on how it's used. For example,
- * when we parse "direction.yz" alone, we don't know whether .yz is a
- * writemask or a swizzle. In this case, we encode ".yz" in store->Swizzle
- * as a swizzle mask (.yz?? actually). Later, if direction.yz is used as
- * an R-value, we use store->Swizzle as-is. Otherwise, if direction.yz is
- * used as an L-value, we convert it to a writemask.
- */
-static GLuint
-swizzle_to_writemask(GLuint swizzle)
-{
- GLuint i, writemask = 0x0;
- for (i = 0; i < 4; i++) {
- GLuint swz = GET_SWZ(swizzle, i);
- if (swz <= SWIZZLE_W) {
- writemask |= (1 << swz);
- }
- }
- return writemask;
-}
-
-
-/**
- * Swizzle a swizzle (function composition).
- * That is, return swz2(swz1), or said another way: swz1.szw2
- * Example: swizzle_swizzle(".zwxx", ".xxyw") yields ".zzwx"
- */
-GLuint
-_slang_swizzle_swizzle(GLuint swz1, GLuint swz2)
-{
- GLuint i, swz, s[4];
- for (i = 0; i < 4; i++) {
- GLuint c = GET_SWZ(swz2, i);
- if (c <= SWIZZLE_W)
- s[i] = GET_SWZ(swz1, c);
- else
- s[i] = c;
- }
- swz = MAKE_SWIZZLE4(s[0], s[1], s[2], s[3]);
- return swz;
-}
-
-
-/**
- * Return the default swizzle mask for accessing a variable of the
- * given size (in floats). If size = 1, comp is used to identify
- * which component [0..3] of the register holds the variable.
- */
-GLuint
-_slang_var_swizzle(GLint size, GLint comp)
-{
- switch (size) {
- case 1:
- return MAKE_SWIZZLE4(comp, SWIZZLE_NIL, SWIZZLE_NIL, SWIZZLE_NIL);
- case 2:
- return MAKE_SWIZZLE4(SWIZZLE_X, SWIZZLE_Y, SWIZZLE_NIL, SWIZZLE_NIL);
- case 3:
- return MAKE_SWIZZLE4(SWIZZLE_X, SWIZZLE_Y, SWIZZLE_Z, SWIZZLE_NIL);
- default:
- return SWIZZLE_XYZW;
- }
-}
-
-
-
-/**
- * Allocate storage for the given node (if it hasn't already been allocated).
- *
- * Typically this is temporary storage for an intermediate result (such as
- * for a multiply or add, etc).
- *
- * If n->Store does not exist it will be created and will be of the size
- * specified by defaultSize.
- */
-static GLboolean
-alloc_node_storage(slang_emit_info *emitInfo, slang_ir_node *n,
- GLint defaultSize)
-{
- assert(!n->Var);
- if (!n->Store) {
- assert(defaultSize > 0);
- n->Store = _slang_new_ir_storage(PROGRAM_TEMPORARY, -1, defaultSize);
- if (!n->Store) {
- return GL_FALSE;
- }
- }
-
- /* now allocate actual register(s). I.e. set n->Store->Index >= 0 */
- if (n->Store->Index < 0) {
- if (!_slang_alloc_temp(emitInfo->vt, n->Store)) {
- slang_info_log_error(emitInfo->log,
- "Ran out of registers, too many temporaries");
- _slang_free(n->Store);
- n->Store = NULL;
- return GL_FALSE;
- }
- }
- return GL_TRUE;
-}
-
-
-/**
- * Free temporary storage, if n->Store is, in fact, temp storage.
- * Otherwise, no-op.
- */
-static void
-free_node_storage(slang_var_table *vt, slang_ir_node *n)
-{
- if (n->Store->File == PROGRAM_TEMPORARY &&
- n->Store->Index >= 0 &&
- n->Opcode != IR_SWIZZLE) {
- if (_slang_is_temp(vt, n->Store)) {
- _slang_free_temp(vt, n->Store);
- n->Store->Index = -1;
- n->Store = NULL; /* XXX this may not be needed */
- }
- }
-}
-
-
-/**
- * Helper function to allocate a short-term temporary.
- * Free it with _slang_free_temp().
- */
-static GLboolean
-alloc_local_temp(slang_emit_info *emitInfo, slang_ir_storage *temp, GLint size)
-{
- assert(size >= 1);
- assert(size <= 4);
- memset(temp, 0, sizeof(*temp));
- temp->Size = size;
- temp->File = PROGRAM_TEMPORARY;
- temp->Index = -1;
- return _slang_alloc_temp(emitInfo->vt, temp);
-}
-
-
-/**
- * Remove any SWIZZLE_NIL terms from given swizzle mask.
- * For a swizzle like .z??? generate .zzzz (replicate single component).
- * Else, for .wx?? generate .wxzw (insert default component for the position).
- */
-static GLuint
-fix_swizzle(GLuint swizzle)
-{
- GLuint c0 = GET_SWZ(swizzle, 0),
- c1 = GET_SWZ(swizzle, 1),
- c2 = GET_SWZ(swizzle, 2),
- c3 = GET_SWZ(swizzle, 3);
- if (c1 == SWIZZLE_NIL && c2 == SWIZZLE_NIL && c3 == SWIZZLE_NIL) {
- /* smear first component across all positions */
- c1 = c2 = c3 = c0;
- }
- else {
- /* insert default swizzle components */
- if (c0 == SWIZZLE_NIL)
- c0 = SWIZZLE_X;
- if (c1 == SWIZZLE_NIL)
- c1 = SWIZZLE_Y;
- if (c2 == SWIZZLE_NIL)
- c2 = SWIZZLE_Z;
- if (c3 == SWIZZLE_NIL)
- c3 = SWIZZLE_W;
- }
- return MAKE_SWIZZLE4(c0, c1, c2, c3);
-}
-
-
-
-/**
- * Convert IR storage to an instruction dst register.
- */
-static void
-storage_to_dst_reg(struct prog_dst_register *dst, const slang_ir_storage *st)
-{
- const GLboolean relAddr = st->RelAddr;
- const GLint size = st->Size;
- GLint index = st->Index;
- GLuint swizzle = st->Swizzle;
-
- assert(index >= 0);
- /* if this is storage relative to some parent storage, walk up the tree */
- while (st->Parent) {
- st = st->Parent;
- assert(st->Index >= 0);
- index += st->Index;
- swizzle = _slang_swizzle_swizzle(st->Swizzle, swizzle);
- }
-
- assert(st->File != PROGRAM_UNDEFINED);
- dst->File = st->File;
-
- assert(index >= 0);
- dst->Index = index;
-
- assert(size >= 1);
- assert(size <= 4);
-
- if (swizzle != SWIZZLE_XYZW) {
- dst->WriteMask = swizzle_to_writemask(swizzle);
- }
- else {
- switch (size) {
- case 1:
- dst->WriteMask = WRITEMASK_X << GET_SWZ(st->Swizzle, 0);
- break;
- case 2:
- dst->WriteMask = WRITEMASK_XY;
- break;
- case 3:
- dst->WriteMask = WRITEMASK_XYZ;
- break;
- case 4:
- dst->WriteMask = WRITEMASK_XYZW;
- break;
- default:
- ; /* error would have been caught above */
- }
- }
-
- dst->RelAddr = relAddr;
-}
-
-
-/**
- * Convert IR storage to an instruction src register.
- */
-static void
-storage_to_src_reg(struct prog_src_register *src, const slang_ir_storage *st)
-{
- const GLboolean relAddr = st->RelAddr;
- GLint index = st->Index;
- GLuint swizzle = st->Swizzle;
-
- /* if this is storage relative to some parent storage, walk up the tree */
- assert(index >= 0);
- while (st->Parent) {
- st = st->Parent;
- if (st->Index < 0) {
- /* an error should have been reported already */
- return;
- }
- assert(st->Index >= 0);
- index += st->Index;
- swizzle = _slang_swizzle_swizzle(fix_swizzle(st->Swizzle), swizzle);
- }
-
- assert(st->File >= 0);
-#if 1 /* XXX temporary */
- if (st->File == PROGRAM_UNDEFINED) {
- slang_ir_storage *st0 = (slang_ir_storage *) st;
- st0->File = PROGRAM_TEMPORARY;
- }
-#endif
- assert(st->File < PROGRAM_FILE_MAX);
- src->File = st->File;
-
- assert(index >= 0);
- src->Index = index;
-
- swizzle = fix_swizzle(swizzle);
- assert(GET_SWZ(swizzle, 0) <= SWIZZLE_W);
- assert(GET_SWZ(swizzle, 1) <= SWIZZLE_W);
- assert(GET_SWZ(swizzle, 2) <= SWIZZLE_W);
- assert(GET_SWZ(swizzle, 3) <= SWIZZLE_W);
- src->Swizzle = swizzle;
-
- src->HasIndex2 = st->Is2D;
- src->Index2 = st->Index2;
-
- src->RelAddr = relAddr;
-}
-
-
-/*
- * Setup storage pointing to a scalar constant/literal.
- */
-static void
-constant_to_storage(slang_emit_info *emitInfo,
- GLfloat val,
- slang_ir_storage *store)
-{
- GLuint swizzle;
- GLint reg;
- GLfloat value[4];
-
- value[0] = val;
- reg = _mesa_add_unnamed_constant(emitInfo->prog->Parameters,
- value, 1, &swizzle);
-
- memset(store, 0, sizeof(*store));
- store->File = PROGRAM_CONSTANT;
- store->Index = reg;
- store->Swizzle = swizzle;
-}
-
-
-/**
- * Add new instruction at end of given program.
- * \param prog the program to append instruction onto
- * \param opcode opcode for the new instruction
- * \return pointer to the new instruction
- */
-static struct prog_instruction *
-new_instruction(slang_emit_info *emitInfo, gl_inst_opcode opcode)
-{
- struct gl_program *prog = emitInfo->prog;
- struct prog_instruction *inst;
-
-#if 0
- /* print prev inst */
- if (prog->NumInstructions > 0) {
- _mesa_print_instruction(prog->Instructions + prog->NumInstructions - 1);
- }
-#endif
- assert(prog->NumInstructions <= emitInfo->MaxInstructions);
-
- if (prog->NumInstructions == emitInfo->MaxInstructions) {
- /* grow the instruction buffer */
- emitInfo->MaxInstructions += 20;
- prog->Instructions =
- _mesa_realloc_instructions(prog->Instructions,
- prog->NumInstructions,
- emitInfo->MaxInstructions);
- if (!prog->Instructions) {
- return NULL;
- }
- }
-
- inst = prog->Instructions + prog->NumInstructions;
- prog->NumInstructions++;
- _mesa_init_instructions(inst, 1);
- inst->Opcode = opcode;
- inst->BranchTarget = -1; /* invalid */
- /*
- printf("New inst %d: %p %s\n", prog->NumInstructions-1,(void*)inst,
- _mesa_opcode_string(inst->Opcode));
- */
- return inst;
-}
-
-
-static struct prog_instruction *
-emit_arl_load(slang_emit_info *emitInfo,
- gl_register_file file, GLint index, GLuint swizzle)
-{
- struct prog_instruction *inst = new_instruction(emitInfo, OPCODE_ARL);
- if (inst) {
- inst->SrcReg[0].File = file;
- inst->SrcReg[0].Index = index;
- inst->SrcReg[0].Swizzle = fix_swizzle(swizzle);
- inst->DstReg.File = PROGRAM_ADDRESS;
- inst->DstReg.Index = 0;
- inst->DstReg.WriteMask = WRITEMASK_X;
- }
- return inst;
-}
-
-
-/**
- * Emit a new instruction with given opcode, operands.
- * At this point the instruction may have multiple indirect register
- * loads/stores. We convert those into ARL loads and address-relative
- * operands. See comments inside.
- * At some point in the future we could directly emit indirectly addressed
- * registers in Mesa GPU instructions.
- */
-static struct prog_instruction *
-emit_instruction(slang_emit_info *emitInfo,
- gl_inst_opcode opcode,
- const slang_ir_storage *dst,
- const slang_ir_storage *src0,
- const slang_ir_storage *src1,
- const slang_ir_storage *src2)
-{
- struct prog_instruction *inst;
- GLuint numIndirect = 0;
- const slang_ir_storage *src[3];
- slang_ir_storage newSrc[3], newDst;
- GLuint i;
- GLboolean isTemp[3];
-
- isTemp[0] = isTemp[1] = isTemp[2] = GL_FALSE;
-
- src[0] = src0;
- src[1] = src1;
- src[2] = src2;
-
- /* count up how many operands are indirect loads */
- for (i = 0; i < 3; i++) {
- if (src[i] && src[i]->IsIndirect)
- numIndirect++;
- }
- if (dst && dst->IsIndirect)
- numIndirect++;
-
- /* Take special steps for indirect register loads.
- * If we had multiple address registers this would be simpler.
- * For example, this GLSL code:
- * x[i] = y[j] + z[k];
- * would translate into something like:
- * ARL ADDR.x, i;
- * ARL ADDR.y, j;
- * ARL ADDR.z, k;
- * ADD TEMP[ADDR.x+5], TEMP[ADDR.y+9], TEMP[ADDR.z+4];
- * But since we currently only have one address register we have to do this:
- * ARL ADDR.x, i;
- * MOV t1, TEMP[ADDR.x+9];
- * ARL ADDR.x, j;
- * MOV t2, TEMP[ADDR.x+4];
- * ARL ADDR.x, k;
- * ADD TEMP[ADDR.x+5], t1, t2;
- * The code here figures this out...
- */
- if (numIndirect > 0) {
- for (i = 0; i < 3; i++) {
- if (src[i] && src[i]->IsIndirect) {
- /* load the ARL register with the indirect register */
- emit_arl_load(emitInfo,
- src[i]->IndirectFile,
- src[i]->IndirectIndex,
- src[i]->IndirectSwizzle);
-
- if (numIndirect > 1) {
- /* Need to load src[i] into a temporary register */
- slang_ir_storage srcRelAddr;
- alloc_local_temp(emitInfo, &newSrc[i], src[i]->Size);
- isTemp[i] = GL_TRUE;
-
- /* set RelAddr flag on src register */
- srcRelAddr = *src[i];
- srcRelAddr.RelAddr = GL_TRUE;
- srcRelAddr.IsIndirect = GL_FALSE; /* not really needed */
-
- /* MOV newSrc, srcRelAddr; */
- inst = emit_instruction(emitInfo,
- OPCODE_MOV,
- &newSrc[i],
- &srcRelAddr,
- NULL,
- NULL);
- if (!inst) {
- return NULL;
- }
-
- src[i] = &newSrc[i];
- }
- else {
- /* just rewrite the src[i] storage to be ARL-relative */
- newSrc[i] = *src[i];
- newSrc[i].RelAddr = GL_TRUE;
- newSrc[i].IsIndirect = GL_FALSE; /* not really needed */
- src[i] = &newSrc[i];
- }
- }
- }
- }
-
- /* Take special steps for indirect dest register write */
- if (dst && dst->IsIndirect) {
- /* load the ARL register with the indirect register */
- emit_arl_load(emitInfo,
- dst->IndirectFile,
- dst->IndirectIndex,
- dst->IndirectSwizzle);
- newDst = *dst;
- newDst.RelAddr = GL_TRUE;
- newDst.IsIndirect = GL_FALSE;
- dst = &newDst;
- }
-
- /* OK, emit the instruction and its dst, src regs */
- inst = new_instruction(emitInfo, opcode);
- if (!inst)
- return NULL;
-
- if (dst)
- storage_to_dst_reg(&inst->DstReg, dst);
-
- for (i = 0; i < 3; i++) {
- if (src[i])
- storage_to_src_reg(&inst->SrcReg[i], src[i]);
- }
-
- /* Free any temp registers that we allocated above */
- for (i = 0; i < 3; i++) {
- if (isTemp[i])
- _slang_free_temp(emitInfo->vt, &newSrc[i]);
- }
-
- return inst;
-}
-
-
-
-/**
- * Put a comment on the given instruction.
- */
-static void
-inst_comment(struct prog_instruction *inst, const char *comment)
-{
- if (inst)
- inst->Comment = _mesa_strdup(comment);
-}
-
-
-
-/**
- * Return pointer to last instruction in program.
- */
-static struct prog_instruction *
-prev_instruction(slang_emit_info *emitInfo)
-{
- struct gl_program *prog = emitInfo->prog;
- if (prog->NumInstructions == 0)
- return NULL;
- else
- return prog->Instructions + prog->NumInstructions - 1;
-}
-
-
-static struct prog_instruction *
-emit(slang_emit_info *emitInfo, slang_ir_node *n);
-
-
-/**
- * Return an annotation string for given node's storage.
- */
-static char *
-storage_annotation(const slang_ir_node *n, const struct gl_program *prog)
-{
-#if ANNOTATE
- const slang_ir_storage *st = n->Store;
- static char s[100] = "";
-
- if (!st)
- return _mesa_strdup("");
-
- switch (st->File) {
- case PROGRAM_CONSTANT:
- if (st->Index >= 0) {
- const GLfloat *val = prog->Parameters->ParameterValues[st->Index];
- if (st->Swizzle == SWIZZLE_NOOP)
- _mesa_snprintf(s, sizeof(s), "{%g, %g, %g, %g}", val[0], val[1], val[2], val[3]);
- else {
- _mesa_snprintf(s, sizeof(s), "%g", val[GET_SWZ(st->Swizzle, 0)]);
- }
- }
- break;
- case PROGRAM_TEMPORARY:
- if (n->Var)
- _mesa_snprintf(s, sizeof(s), "%s", (char *) n->Var->a_name);
- else
- _mesa_snprintf(s, sizeof(s), "t[%d]", st->Index);
- break;
- case PROGRAM_STATE_VAR:
- case PROGRAM_UNIFORM:
- _mesa_snprintf(s, sizeof(s), "%s", prog->Parameters->Parameters[st->Index].Name);
- break;
- case PROGRAM_VARYING:
- _mesa_snprintf(s, sizeof(s), "%s", prog->Varying->Parameters[st->Index].Name);
- break;
- case PROGRAM_INPUT:
- _mesa_snprintf(s, sizeof(s), "input[%d]", st->Index);
- break;
- case PROGRAM_OUTPUT:
- _mesa_snprintf(s, sizeof(s), "output[%d]", st->Index);
- break;
- default:
- s[0] = 0;
- }
- return _mesa_strdup(s);
-#else
- return NULL;
-#endif
-}
-
-
-/**
- * Return an annotation string for an instruction.
- */
-static char *
-instruction_annotation(gl_inst_opcode opcode, char *dstAnnot,
- char *srcAnnot0, char *srcAnnot1, char *srcAnnot2)
-{
-#if ANNOTATE
- const char *operator;
- char *s;
- int len = 50;
-
- if (dstAnnot)
- len += strlen(dstAnnot);
- else
- dstAnnot = _mesa_strdup("");
-
- if (srcAnnot0)
- len += strlen(srcAnnot0);
- else
- srcAnnot0 = _mesa_strdup("");
-
- if (srcAnnot1)
- len += strlen(srcAnnot1);
- else
- srcAnnot1 = _mesa_strdup("");
-
- if (srcAnnot2)
- len += strlen(srcAnnot2);
- else
- srcAnnot2 = _mesa_strdup("");
-
- switch (opcode) {
- case OPCODE_ADD:
- operator = "+";
- break;
- case OPCODE_SUB:
- operator = "-";
- break;
- case OPCODE_MUL:
- operator = "*";
- break;
- case OPCODE_DP2:
- operator = "DP2";
- break;
- case OPCODE_DP3:
- operator = "DP3";
- break;
- case OPCODE_DP4:
- operator = "DP4";
- break;
- case OPCODE_XPD:
- operator = "XPD";
- break;
- case OPCODE_RSQ:
- operator = "RSQ";
- break;
- case OPCODE_SGT:
- operator = ">";
- break;
- default:
- operator = ",";
- }
-
- s = (char *) malloc(len);
- _mesa_snprintf(s, len, "%s = %s %s %s %s", dstAnnot,
- srcAnnot0, operator, srcAnnot1, srcAnnot2);
-
- free(dstAnnot);
- free(srcAnnot0);
- free(srcAnnot1);
- free(srcAnnot2);
-
- return s;
-#else
- return NULL;
-#endif
-}
-
-
-/**
- * Emit an instruction that's just a comment.
- */
-static struct prog_instruction *
-emit_comment(slang_emit_info *emitInfo, const char *comment)
-{
- struct prog_instruction *inst = new_instruction(emitInfo, OPCODE_NOP);
- if (inst) {
- inst_comment(inst, comment);
- }
- return inst;
-}
-
-
-/**
- * Generate code for a simple arithmetic instruction.
- * Either 1, 2 or 3 operands.
- */
-static struct prog_instruction *
-emit_arith(slang_emit_info *emitInfo, slang_ir_node *n)
-{
- const slang_ir_info *info = _slang_ir_info(n->Opcode);
- struct prog_instruction *inst;
- GLuint i;
-
- assert(info);
- assert(info->InstOpcode != OPCODE_NOP);
-
-#if PEEPHOLE_OPTIMIZATIONS
- /* Look for MAD opportunity */
- if (info->NumParams == 2 &&
- n->Opcode == IR_ADD && n->Children[0]->Opcode == IR_MUL) {
- /* found pattern IR_ADD(IR_MUL(A, B), C) */
- emit(emitInfo, n->Children[0]->Children[0]); /* A */
- emit(emitInfo, n->Children[0]->Children[1]); /* B */
- emit(emitInfo, n->Children[1]); /* C */
- if (!alloc_node_storage(emitInfo, n, -1)) { /* dest */
- return NULL;
- }
-
- inst = emit_instruction(emitInfo,
- OPCODE_MAD,
- n->Store,
- n->Children[0]->Children[0]->Store,
- n->Children[0]->Children[1]->Store,
- n->Children[1]->Store);
-
- free_node_storage(emitInfo->vt, n->Children[0]->Children[0]);
- free_node_storage(emitInfo->vt, n->Children[0]->Children[1]);
- free_node_storage(emitInfo->vt, n->Children[1]);
- return inst;
- }
-
- if (info->NumParams == 2 &&
- n->Opcode == IR_ADD && n->Children[1]->Opcode == IR_MUL) {
- /* found pattern IR_ADD(A, IR_MUL(B, C)) */
- emit(emitInfo, n->Children[0]); /* A */
- emit(emitInfo, n->Children[1]->Children[0]); /* B */
- emit(emitInfo, n->Children[1]->Children[1]); /* C */
- if (!alloc_node_storage(emitInfo, n, -1)) { /* dest */
- return NULL;
- }
-
- inst = emit_instruction(emitInfo,
- OPCODE_MAD,
- n->Store,
- n->Children[1]->Children[0]->Store,
- n->Children[1]->Children[1]->Store,
- n->Children[0]->Store);
-
- free_node_storage(emitInfo->vt, n->Children[1]->Children[0]);
- free_node_storage(emitInfo->vt, n->Children[1]->Children[1]);
- free_node_storage(emitInfo->vt, n->Children[0]);
- return inst;
- }
-#endif
-
- /* gen code for children, may involve temp allocation */
- for (i = 0; i < info->NumParams; i++) {
- emit(emitInfo, n->Children[i]);
- if (!n->Children[i] || !n->Children[i]->Store) {
- /* error recovery */
- return NULL;
- }
- }
-
- /* result storage */
- if (!alloc_node_storage(emitInfo, n, -1)) {
- return NULL;
- }
-
- inst = emit_instruction(emitInfo,
- info->InstOpcode,
- n->Store, /* dest */
- (info->NumParams > 0 ? n->Children[0]->Store : NULL),
- (info->NumParams > 1 ? n->Children[1]->Store : NULL),
- (info->NumParams > 2 ? n->Children[2]->Store : NULL)
- );
-
- /* free temps */
- for (i = 0; i < info->NumParams; i++)
- free_node_storage(emitInfo->vt, n->Children[i]);
-
- return inst;
-}
-
-
-/**
- * Emit code for == and != operators. These could normally be handled
- * by emit_arith() except we need to be able to handle structure comparisons.
- */
-static struct prog_instruction *
-emit_compare(slang_emit_info *emitInfo, slang_ir_node *n)
-{
- struct prog_instruction *inst = NULL;
- GLint size;
-
- assert(n->Opcode == IR_EQUAL || n->Opcode == IR_NOTEQUAL);
-
- /* gen code for children */
- emit(emitInfo, n->Children[0]);
- emit(emitInfo, n->Children[1]);
-
- if (n->Children[0]->Store->Size != n->Children[1]->Store->Size) {
- /* XXX this error should have been caught in slang_codegen.c */
- slang_info_log_error(emitInfo->log, "invalid operands to == or !=");
- n->Store = NULL;
- return NULL;
- }
-
- /* final result is 1 bool */
- if (!alloc_node_storage(emitInfo, n, 1))
- return NULL;
-
- size = n->Children[0]->Store->Size;
-
- if (size == 1) {
- gl_inst_opcode opcode = n->Opcode == IR_EQUAL ? OPCODE_SEQ : OPCODE_SNE;
- inst = emit_instruction(emitInfo,
- opcode,
- n->Store, /* dest */
- n->Children[0]->Store,
- n->Children[1]->Store,
- NULL);
- }
- else if (size <= 4) {
- /* compare two vectors.
- * Unfortunately, there's no instruction to compare vectors and
- * return a scalar result. Do it with some compare and dot product
- * instructions...
- */
- GLuint swizzle;
- gl_inst_opcode dotOp;
- slang_ir_storage tempStore;
-
- if (!alloc_local_temp(emitInfo, &tempStore, 4)) {
- n->Store = NULL;
- return NULL;
- /* out of temps */
- }
-
- if (size == 4) {
- dotOp = OPCODE_DP4;
- swizzle = SWIZZLE_XYZW;
- }
- else if (size == 3) {
- dotOp = OPCODE_DP3;
- swizzle = SWIZZLE_XYZW;
- }
- else {
- assert(size == 2);
- dotOp = OPCODE_DP3; /* XXX use OPCODE_DP2 eventually */
- swizzle = MAKE_SWIZZLE4(SWIZZLE_X, SWIZZLE_Y, SWIZZLE_Y, SWIZZLE_Y);
- }
-
- /* Compute inequality (temp = (A != B)) */
- inst = emit_instruction(emitInfo,
- OPCODE_SNE,
- &tempStore,
- n->Children[0]->Store,
- n->Children[1]->Store,
- NULL);
- if (!inst) {
- return NULL;
- }
- inst_comment(inst, "Compare values");
-
- /* Compute val = DOT(temp, temp) (reduction) */
- inst = emit_instruction(emitInfo,
- dotOp,
- n->Store,
- &tempStore,
- &tempStore,
- NULL);
- if (!inst) {
- return NULL;
- }
- inst->SrcReg[0].Swizzle = inst->SrcReg[1].Swizzle = swizzle; /*override*/
- inst_comment(inst, "Reduce vec to bool");
-
- _slang_free_temp(emitInfo->vt, &tempStore); /* free temp */
-
- if (n->Opcode == IR_EQUAL) {
- /* compute val = !val.x with SEQ val, val, 0; */
- slang_ir_storage zero;
- constant_to_storage(emitInfo, 0.0, &zero);
- inst = emit_instruction(emitInfo,
- OPCODE_SEQ,
- n->Store, /* dest */
- n->Store,
- &zero,
- NULL);
- if (!inst) {
- return NULL;
- }
- inst_comment(inst, "Invert true/false");
- }
- }
- else {
- /* size > 4, struct or array compare.
- * XXX this won't work reliably for structs with padding!!
- */
- GLint i, num = (n->Children[0]->Store->Size + 3) / 4;
- slang_ir_storage accTemp, sneTemp;
-
- if (!alloc_local_temp(emitInfo, &accTemp, 4))
- return NULL;
-
- if (!alloc_local_temp(emitInfo, &sneTemp, 4))
- return NULL;
-
- for (i = 0; i < num; i++) {
- slang_ir_storage srcStore0 = *n->Children[0]->Store;
- slang_ir_storage srcStore1 = *n->Children[1]->Store;
- srcStore0.Index += i;
- srcStore1.Index += i;
-
- if (i == 0) {
- /* SNE accTemp, left[i], right[i] */
- inst = emit_instruction(emitInfo, OPCODE_SNE,
- &accTemp, /* dest */
- &srcStore0,
- &srcStore1,
- NULL);
- if (!inst) {
- return NULL;
- }
- inst_comment(inst, "Begin struct/array comparison");
- }
- else {
- /* SNE sneTemp, left[i], right[i] */
- inst = emit_instruction(emitInfo, OPCODE_SNE,
- &sneTemp, /* dest */
- &srcStore0,
- &srcStore1,
- NULL);
- if (!inst) {
- return NULL;
- }
- /* ADD accTemp, accTemp, sneTemp; # like logical-OR */
- inst = emit_instruction(emitInfo, OPCODE_ADD,
- &accTemp, /* dest */
- &accTemp,
- &sneTemp,
- NULL);
- if (!inst) {
- return NULL;
- }
- }
- }
-
- /* compute accTemp.x || accTemp.y || accTemp.z || accTemp.w with DOT4 */
- inst = emit_instruction(emitInfo, OPCODE_DP4,
- n->Store,
- &accTemp,
- &accTemp,
- NULL);
- if (!inst) {
- return NULL;
- }
- inst_comment(inst, "End struct/array comparison");
-
- if (n->Opcode == IR_EQUAL) {
- /* compute tmp.x = !tmp.x via tmp.x = (tmp.x == 0) */
- slang_ir_storage zero;
- constant_to_storage(emitInfo, 0.0, &zero);
- inst = emit_instruction(emitInfo, OPCODE_SEQ,
- n->Store, /* dest */
- n->Store,
- &zero,
- NULL);
- if (!inst) {
- return NULL;
- }
- inst_comment(inst, "Invert true/false");
- }
-
- _slang_free_temp(emitInfo->vt, &accTemp);
- _slang_free_temp(emitInfo->vt, &sneTemp);
- }
-
- /* free temps */
- free_node_storage(emitInfo->vt, n->Children[0]);
- free_node_storage(emitInfo->vt, n->Children[1]);
-
- return inst;
-}
-
-
-
-/**
- * Generate code for an IR_CLAMP instruction.
- */
-static struct prog_instruction *
-emit_clamp(slang_emit_info *emitInfo, slang_ir_node *n)
-{
- struct prog_instruction *inst;
- slang_ir_node tmpNode;
-
- assert(n->Opcode == IR_CLAMP);
- /* ch[0] = value
- * ch[1] = min limit
- * ch[2] = max limit
- */
-
- inst = emit(emitInfo, n->Children[0]);
-
- /* If lower limit == 0.0 and upper limit == 1.0,
- * set prev instruction's SaturateMode field to SATURATE_ZERO_ONE.
- * Else,
- * emit OPCODE_MIN, OPCODE_MAX sequence.
- */
-#if 0
- /* XXX this isn't quite finished yet */
- if (n->Children[1]->Opcode == IR_FLOAT &&
- n->Children[1]->Value[0] == 0.0 &&
- n->Children[1]->Value[1] == 0.0 &&
- n->Children[1]->Value[2] == 0.0 &&
- n->Children[1]->Value[3] == 0.0 &&
- n->Children[2]->Opcode == IR_FLOAT &&
- n->Children[2]->Value[0] == 1.0 &&
- n->Children[2]->Value[1] == 1.0 &&
- n->Children[2]->Value[2] == 1.0 &&
- n->Children[2]->Value[3] == 1.0) {
- if (!inst) {
- inst = prev_instruction(prog);
- }
- if (inst && inst->Opcode != OPCODE_NOP) {
- /* and prev instruction's DstReg matches n->Children[0]->Store */
- inst->SaturateMode = SATURATE_ZERO_ONE;
- n->Store = n->Children[0]->Store;
- return inst;
- }
- }
-#else
- (void) inst;
-#endif
-
- if (!alloc_node_storage(emitInfo, n, n->Children[0]->Store->Size))
- return NULL;
-
- emit(emitInfo, n->Children[1]);
- emit(emitInfo, n->Children[2]);
-
- /* Some GPUs don't allow reading from output registers. So if the
- * dest for this clamp() is an output reg, we can't use that reg for
- * the intermediate result. Use a temp register instead.
- */
- memset(&tmpNode, 0, sizeof(tmpNode));
- if (!alloc_node_storage(emitInfo, &tmpNode, n->Store->Size)) {
- return NULL;
- }
-
- /* tmp = max(ch[0], ch[1]) */
- inst = emit_instruction(emitInfo, OPCODE_MAX,
- tmpNode.Store, /* dest */
- n->Children[0]->Store,
- n->Children[1]->Store,
- NULL);
- if (!inst) {
- return NULL;
- }
-
- /* n->dest = min(tmp, ch[2]) */
- inst = emit_instruction(emitInfo, OPCODE_MIN,
- n->Store, /* dest */
- tmpNode.Store,
- n->Children[2]->Store,
- NULL);
-
- free_node_storage(emitInfo->vt, &tmpNode);
-
- return inst;
-}
-
-
-static struct prog_instruction *
-emit_negation(slang_emit_info *emitInfo, slang_ir_node *n)
-{
- /* Implement as MOV dst, -src; */
- /* XXX we could look at the previous instruction and in some circumstances
- * modify it to accomplish the negation.
- */
- struct prog_instruction *inst;
-
- emit(emitInfo, n->Children[0]);
-
- if (!alloc_node_storage(emitInfo, n, n->Children[0]->Store->Size))
- return NULL;
-
- inst = emit_instruction(emitInfo,
- OPCODE_MOV,
- n->Store, /* dest */
- n->Children[0]->Store,
- NULL,
- NULL);
- if (inst) {
- inst->SrcReg[0].Negate = NEGATE_XYZW;
- }
- return inst;
-}
-
-
-static struct prog_instruction *
-emit_label(slang_emit_info *emitInfo, const slang_ir_node *n)
-{
- assert(n->Label);
-#if 0
- /* XXX this fails in loop tail code - investigate someday */
- assert(_slang_label_get_location(n->Label) < 0);
- _slang_label_set_location(n->Label, emitInfo->prog->NumInstructions,
- emitInfo->prog);
-#else
- if (_slang_label_get_location(n->Label) < 0)
- _slang_label_set_location(n->Label, emitInfo->prog->NumInstructions,
- emitInfo->prog);
-#endif
- return NULL;
-}
-
-
-/**
- * Emit code for a function call.
- * Note that for each time a function is called, we emit the function's
- * body code again because the set of available registers may be different.
- */
-static struct prog_instruction *
-emit_fcall(slang_emit_info *emitInfo, slang_ir_node *n)
-{
- struct gl_program *progSave;
- struct prog_instruction *inst;
- GLuint subroutineId;
- GLuint maxInstSave;
-
- assert(n->Opcode == IR_CALL);
- assert(n->Label);
-
- /* save/push cur program */
- maxInstSave = emitInfo->MaxInstructions;
- progSave = emitInfo->prog;
-
- emitInfo->prog = new_subroutine(emitInfo, &subroutineId);
- emitInfo->MaxInstructions = emitInfo->prog->NumInstructions;
-
- _slang_label_set_location(n->Label, emitInfo->prog->NumInstructions,
- emitInfo->prog);
-
- if (emitInfo->EmitBeginEndSub) {
- /* BGNSUB isn't a real instruction.
- * We require a label (i.e. "foobar:") though, if we're going to
- * print the program in the NV format. The BNGSUB instruction is
- * really just a NOP to attach the label to.
- */
- inst = new_instruction(emitInfo, OPCODE_BGNSUB);
- if (!inst) {
- return NULL;
- }
- inst_comment(inst, n->Label->Name);
- }
-
- /* body of function: */
- emit(emitInfo, n->Children[0]);
- n->Store = n->Children[0]->Store;
-
- /* add RET instruction now, if needed */
- inst = prev_instruction(emitInfo);
- if (inst && inst->Opcode != OPCODE_RET) {
- inst = new_instruction(emitInfo, OPCODE_RET);
- if (!inst) {
- return NULL;
- }
- }
-
- if (emitInfo->EmitBeginEndSub) {
- inst = new_instruction(emitInfo, OPCODE_ENDSUB);
- if (!inst) {
- return NULL;
- }
- inst_comment(inst, n->Label->Name);
- }
-
- /* pop/restore cur program */
- emitInfo->prog = progSave;
- emitInfo->MaxInstructions = maxInstSave;
-
- /* emit the function call */
- inst = new_instruction(emitInfo, OPCODE_CAL);
- if (!inst) {
- return NULL;
- }
- /* The branch target is just the subroutine number (changed later) */
- inst->BranchTarget = subroutineId;
- inst_comment(inst, n->Label->Name);
- assert(inst->BranchTarget >= 0);
-
- return inst;
-}
-
-
-/**
- * Emit code for a 'return' statement.
- */
-static struct prog_instruction *
-emit_return(slang_emit_info *emitInfo, slang_ir_node *n)
-{
- struct prog_instruction *inst;
- assert(n);
- assert(n->Opcode == IR_RETURN);
- assert(n->Label);
- inst = new_instruction(emitInfo, OPCODE_RET);
- if (inst) {
- inst->DstReg.CondMask = COND_TR; /* always return */
- }
- return inst;
-}
-
-
-static struct prog_instruction *
-emit_kill(slang_emit_info *emitInfo)
-{
- struct gl_fragment_program *fp;
- struct prog_instruction *inst;
- /* NV-KILL - discard fragment depending on condition code.
- * Note that ARB-KILL depends on sign of vector operand.
- */
- inst = new_instruction(emitInfo, OPCODE_KIL_NV);
- if (!inst) {
- return NULL;
- }
- inst->DstReg.CondMask = COND_TR; /* always kill */
-
- assert(emitInfo->prog->Target == GL_FRAGMENT_PROGRAM_ARB);
- fp = (struct gl_fragment_program *) emitInfo->prog;
- fp->UsesKill = GL_TRUE;
-
- return inst;
-}
-
-
-static struct prog_instruction *
-emit_tex(slang_emit_info *emitInfo, slang_ir_node *n)
-{
- struct prog_instruction *inst;
- gl_inst_opcode opcode;
- GLboolean shadow = GL_FALSE;
-
- switch (n->Opcode) {
- case IR_TEX:
- opcode = OPCODE_TEX;
- break;
- case IR_TEX_SH:
- opcode = OPCODE_TEX;
- shadow = GL_TRUE;
- break;
- case IR_TEXB:
- opcode = OPCODE_TXB;
- break;
- case IR_TEXB_SH:
- opcode = OPCODE_TXB;
- shadow = GL_TRUE;
- break;
- case IR_TEXP:
- opcode = OPCODE_TXP;
- break;
- case IR_TEXP_SH:
- opcode = OPCODE_TXP;
- shadow = GL_TRUE;
- break;
- default:
- _mesa_problem(NULL, "Bad IR TEX code");
- return NULL;
- }
-
- if (n->Children[0]->Opcode == IR_ELEMENT) {
- /* array is the sampler (a uniform which'll indicate the texture unit) */
- assert(n->Children[0]->Children[0]->Store);
- assert(n->Children[0]->Children[0]->Store->File == PROGRAM_SAMPLER);
-
- emit(emitInfo, n->Children[0]);
-
- n->Children[0]->Var = n->Children[0]->Children[0]->Var;
- } else {
- /* this is the sampler (a uniform which'll indicate the texture unit) */
- assert(n->Children[0]->Store);
- assert(n->Children[0]->Store->File == PROGRAM_SAMPLER);
- }
-
- /* emit code for the texcoord operand */
- (void) emit(emitInfo, n->Children[1]);
-
- /* alloc storage for result of texture fetch */
- if (!alloc_node_storage(emitInfo, n, 4))
- return NULL;
-
- /* emit TEX instruction; Child[1] is the texcoord */
- inst = emit_instruction(emitInfo,
- opcode,
- n->Store,
- n->Children[1]->Store,
- NULL,
- NULL);
- if (!inst) {
- return NULL;
- }
-
- inst->TexShadow = shadow;
-
- /* Store->Index is the uniform/sampler index */
- assert(n->Children[0]->Store->Index >= 0);
- inst->TexSrcUnit = n->Children[0]->Store->Index;
- inst->TexSrcTarget = n->Children[0]->Store->TexTarget;
-
- /* mark the sampler as being used */
- _mesa_use_uniform(emitInfo->prog->Parameters,
- (char *) n->Children[0]->Var->a_name);
-
- return inst;
-}
-
-
-/**
- * Assignment/copy
- */
-static struct prog_instruction *
-emit_copy(slang_emit_info *emitInfo, slang_ir_node *n)
-{
- struct prog_instruction *inst;
-
- assert(n->Opcode == IR_COPY);
-
- /* lhs */
- emit(emitInfo, n->Children[0]);
- if (!n->Children[0]->Store || n->Children[0]->Store->Index < 0) {
- /* an error should have been already recorded */
- return NULL;
- }
-
- /* rhs */
- assert(n->Children[1]);
- inst = emit(emitInfo, n->Children[1]);
-
- if (!n->Children[1]->Store || n->Children[1]->Store->Index < 0) {
- if (!emitInfo->log->text && !emitInfo->UnresolvedFunctions) {
- /* XXX this error should have been caught in slang_codegen.c */
- slang_info_log_error(emitInfo->log, "invalid assignment");
- }
- return NULL;
- }
-
- assert(n->Children[1]->Store->Index >= 0);
-
- /*assert(n->Children[0]->Store->Size == n->Children[1]->Store->Size);*/
-
- n->Store = n->Children[0]->Store;
-
- if (n->Store->File == PROGRAM_SAMPLER) {
- /* no code generated for sampler assignments,
- * just copy the sampler index/target at compile time.
- */
- n->Store->Index = n->Children[1]->Store->Index;
- n->Store->TexTarget = n->Children[1]->Store->TexTarget;
- return NULL;
- }
-
-#if PEEPHOLE_OPTIMIZATIONS
- if (inst &&
- (n->Children[1]->Opcode != IR_SWIZZLE) &&
- _slang_is_temp(emitInfo->vt, n->Children[1]->Store) &&
- (inst->DstReg.File == n->Children[1]->Store->File) &&
- (inst->DstReg.Index == n->Children[1]->Store->Index) &&
- !n->Children[0]->Store->IsIndirect &&
- n->Children[0]->Store->Size <= 4) {
- /* Peephole optimization:
- * The Right-Hand-Side has its results in a temporary place.
- * Modify the RHS (and the prev instruction) to store its results
- * in the destination specified by n->Children[0].
- * Then, this MOVE is a no-op.
- * Ex:
- * MUL tmp, x, y;
- * MOV a, tmp;
- * becomes:
- * MUL a, x, y;
- */
-
- /* fixup the previous instruction (which stored the RHS result) */
- assert(n->Children[0]->Store->Index >= 0);
- storage_to_dst_reg(&inst->DstReg, n->Children[0]->Store);
- return inst;
- }
- else
-#endif
- {
- if (n->Children[0]->Store->Size > 4) {
- /* move matrix/struct etc (block of registers) */
- slang_ir_storage dstStore = *n->Children[0]->Store;
- slang_ir_storage srcStore = *n->Children[1]->Store;
- GLint size = srcStore.Size;
- ASSERT(n->Children[1]->Store->Swizzle == SWIZZLE_NOOP);
- dstStore.Size = 4;
- srcStore.Size = 4;
- while (size >= 4) {
- inst = emit_instruction(emitInfo, OPCODE_MOV,
- &dstStore,
- &srcStore,
- NULL,
- NULL);
- if (!inst) {
- return NULL;
- }
- inst_comment(inst, "IR_COPY block");
- srcStore.Index++;
- dstStore.Index++;
- size -= 4;
- }
- }
- else {
- /* single register move */
- char *srcAnnot, *dstAnnot;
- assert(n->Children[0]->Store->Index >= 0);
- inst = emit_instruction(emitInfo, OPCODE_MOV,
- n->Children[0]->Store, /* dest */
- n->Children[1]->Store,
- NULL,
- NULL);
- if (!inst) {
- return NULL;
- }
- dstAnnot = storage_annotation(n->Children[0], emitInfo->prog);
- srcAnnot = storage_annotation(n->Children[1], emitInfo->prog);
- inst->Comment = instruction_annotation(inst->Opcode, dstAnnot,
- srcAnnot, NULL, NULL);
- }
- free_node_storage(emitInfo->vt, n->Children[1]);
- return inst;
- }
-}
-
-
-/**
- * An IR_COND node wraps a boolean expression which is used by an
- * IF or WHILE test. This is where we'll set condition codes, if needed.
- */
-static struct prog_instruction *
-emit_cond(slang_emit_info *emitInfo, slang_ir_node *n)
-{
- struct prog_instruction *inst;
-
- assert(n->Opcode == IR_COND);
-
- if (!n->Children[0])
- return NULL;
-
- /* emit code for the expression */
- inst = emit(emitInfo, n->Children[0]);
-
- if (!n->Children[0]->Store) {
- /* error recovery */
- return NULL;
- }
-
- assert(n->Children[0]->Store);
- /*assert(n->Children[0]->Store->Size == 1);*/
-
- if (emitInfo->EmitCondCodes) {
- if (inst &&
- n->Children[0]->Store &&
- inst->DstReg.File == n->Children[0]->Store->File &&
- inst->DstReg.Index == n->Children[0]->Store->Index) {
- /* The previous instruction wrote to the register who's value
- * we're testing. Just fix that instruction so that the
- * condition codes are computed.
- */
- inst->CondUpdate = GL_TRUE;
- n->Store = n->Children[0]->Store;
- return inst;
- }
- else {
- /* This'll happen for things like "if (i) ..." where no code
- * is normally generated for the expression "i".
- * Generate a move instruction just to set condition codes.
- */
- if (!alloc_node_storage(emitInfo, n, 1))
- return NULL;
- inst = emit_instruction(emitInfo, OPCODE_MOV,
- n->Store, /* dest */
- n->Children[0]->Store,
- NULL,
- NULL);
- if (!inst) {
- return NULL;
- }
- inst->CondUpdate = GL_TRUE;
- inst_comment(inst, "COND expr");
- _slang_free_temp(emitInfo->vt, n->Store);
- return inst;
- }
- }
- else {
- /* No-op: the boolean result of the expression is in a regular reg */
- n->Store = n->Children[0]->Store;
- return inst;
- }
-}
-
-
-/**
- * Logical-NOT
- */
-static struct prog_instruction *
-emit_not(slang_emit_info *emitInfo, slang_ir_node *n)
-{
- static const struct {
- gl_inst_opcode op, opNot;
- } operators[] = {
- { OPCODE_SLT, OPCODE_SGE },
- { OPCODE_SLE, OPCODE_SGT },
- { OPCODE_SGT, OPCODE_SLE },
- { OPCODE_SGE, OPCODE_SLT },
- { OPCODE_SEQ, OPCODE_SNE },
- { OPCODE_SNE, OPCODE_SEQ },
- { 0, 0 }
- };
- struct prog_instruction *inst;
- slang_ir_storage zero;
- GLuint i;
-
- /* child expr */
- inst = emit(emitInfo, n->Children[0]);
-
-#if PEEPHOLE_OPTIMIZATIONS
- if (inst) {
- /* if the prev instruction was a comparison instruction, invert it */
- for (i = 0; operators[i].op; i++) {
- if (inst->Opcode == operators[i].op) {
- inst->Opcode = operators[i].opNot;
- n->Store = n->Children[0]->Store;
- return inst;
- }
- }
- }
-#endif
-
- /* else, invert using SEQ (v = v == 0) */
- if (!alloc_node_storage(emitInfo, n, n->Children[0]->Store->Size))
- return NULL;
-
- constant_to_storage(emitInfo, 0.0, &zero);
- inst = emit_instruction(emitInfo,
- OPCODE_SEQ,
- n->Store,
- n->Children[0]->Store,
- &zero,
- NULL);
- if (!inst) {
- return NULL;
- }
- inst_comment(inst, "NOT");
-
- free_node_storage(emitInfo->vt, n->Children[0]);
-
- return inst;
-}
-
-
-static struct prog_instruction *
-emit_if(slang_emit_info *emitInfo, slang_ir_node *n)
-{
- struct gl_program *prog = emitInfo->prog;
- GLuint ifInstLoc, elseInstLoc = 0;
- GLuint condWritemask = 0;
-
- /* emit condition expression code */
- {
- struct prog_instruction *inst;
- inst = emit(emitInfo, n->Children[0]);
- if (emitInfo->EmitCondCodes) {
- if (!inst) {
- /* error recovery */
- return NULL;
- }
- condWritemask = inst->DstReg.WriteMask;
- }
- }
-
- if (!n->Children[0]->Store)
- return NULL;
-
-#if 0
- assert(n->Children[0]->Store->Size == 1); /* a bool! */
-#endif
-
- ifInstLoc = prog->NumInstructions;
- if (emitInfo->EmitHighLevelInstructions) {
- if (emitInfo->EmitCondCodes) {
- /* IF condcode THEN ... */
- struct prog_instruction *ifInst = new_instruction(emitInfo, OPCODE_IF);
- if (!ifInst) {
- return NULL;
- }
- ifInst->DstReg.CondMask = COND_NE; /* if cond is non-zero */
- /* only test the cond code (1 of 4) that was updated by the
- * previous instruction.
- */
- ifInst->DstReg.CondSwizzle = writemask_to_swizzle(condWritemask);
- }
- else {
- struct prog_instruction *inst;
-
- /* IF src[0] THEN ... */
- inst = emit_instruction(emitInfo, OPCODE_IF,
- NULL, /* dst */
- n->Children[0]->Store, /* op0 */
- NULL,
- NULL);
- if (!inst) {
- return NULL;
- }
- }
- }
- else {
- /* conditional jump to else, or endif */
- struct prog_instruction *ifInst = new_instruction(emitInfo, OPCODE_BRA);
- if (!ifInst) {
- return NULL;
- }
- ifInst->DstReg.CondMask = COND_EQ; /* BRA if cond is zero */
- inst_comment(ifInst, "if zero");
- ifInst->DstReg.CondSwizzle = writemask_to_swizzle(condWritemask);
- }
-
- /* if body */
- emit(emitInfo, n->Children[1]);
-
- if (n->Children[2]) {
- /* have else body */
- elseInstLoc = prog->NumInstructions;
- if (emitInfo->EmitHighLevelInstructions) {
- struct prog_instruction *inst = new_instruction(emitInfo, OPCODE_ELSE);
- if (!inst) {
- return NULL;
- }
- prog->Instructions[ifInstLoc].BranchTarget = prog->NumInstructions - 1;
- }
- else {
- /* jump to endif instruction */
- struct prog_instruction *inst = new_instruction(emitInfo, OPCODE_BRA);
- if (!inst) {
- return NULL;
- }
- inst_comment(inst, "else");
- inst->DstReg.CondMask = COND_TR; /* always branch */
- prog->Instructions[ifInstLoc].BranchTarget = prog->NumInstructions;
- }
- emit(emitInfo, n->Children[2]);
- }
- else {
- /* no else body */
- prog->Instructions[ifInstLoc].BranchTarget = prog->NumInstructions;
- }
-
- if (emitInfo->EmitHighLevelInstructions) {
- struct prog_instruction *inst = new_instruction(emitInfo, OPCODE_ENDIF);
- if (!inst) {
- return NULL;
- }
- }
-
- if (elseInstLoc) {
- /* point ELSE instruction BranchTarget at ENDIF */
- if (emitInfo->EmitHighLevelInstructions) {
- prog->Instructions[elseInstLoc].BranchTarget = prog->NumInstructions - 1;
- }
- else {
- prog->Instructions[elseInstLoc].BranchTarget = prog->NumInstructions;
- }
- }
- return NULL;
-}
-
-
-static struct prog_instruction *
-emit_loop(slang_emit_info *emitInfo, slang_ir_node *n)
-{
- struct gl_program *prog = emitInfo->prog;
- struct prog_instruction *endInst;
- GLuint beginInstLoc, tailInstLoc, endInstLoc;
- slang_ir_node *ir;
-
- /* emit OPCODE_BGNLOOP */
- beginInstLoc = prog->NumInstructions;
- if (emitInfo->EmitHighLevelInstructions) {
- struct prog_instruction *inst = new_instruction(emitInfo, OPCODE_BGNLOOP);
- if (!inst) {
- return NULL;
- }
- }
-
- /* body */
- emit(emitInfo, n->Children[0]);
-
- /* tail */
- tailInstLoc = prog->NumInstructions;
- if (n->Children[1]) {
- if (emitInfo->EmitComments)
- emit_comment(emitInfo, "Loop tail code:");
- emit(emitInfo, n->Children[1]);
- }
-
- endInstLoc = prog->NumInstructions;
- if (emitInfo->EmitHighLevelInstructions) {
- /* emit OPCODE_ENDLOOP */
- endInst = new_instruction(emitInfo, OPCODE_ENDLOOP);
- if (!endInst) {
- return NULL;
- }
- }
- else {
- /* emit unconditional BRA-nch */
- endInst = new_instruction(emitInfo, OPCODE_BRA);
- if (!endInst) {
- return NULL;
- }
- endInst->DstReg.CondMask = COND_TR; /* always true */
- }
- /* ENDLOOP's BranchTarget points to the BGNLOOP inst */
- endInst->BranchTarget = beginInstLoc;
-
- if (emitInfo->EmitHighLevelInstructions) {
- /* BGNLOOP's BranchTarget points to the ENDLOOP inst */
- prog->Instructions[beginInstLoc].BranchTarget = prog->NumInstructions -1;
- }
-
- /* Done emitting loop code. Now walk over the loop's linked list of
- * BREAK and CONT nodes, filling in their BranchTarget fields (which
- * will point to the corresponding ENDLOOP instruction.
- */
- for (ir = n->List; ir; ir = ir->List) {
- struct prog_instruction *inst = prog->Instructions + ir->InstLocation;
- assert(inst->BranchTarget < 0);
- if (ir->Opcode == IR_BREAK ||
- ir->Opcode == IR_BREAK_IF_TRUE) {
- assert(inst->Opcode == OPCODE_BRK ||
- inst->Opcode == OPCODE_BRA);
- /* go to instruction at end of loop */
- if (emitInfo->EmitHighLevelInstructions) {
- inst->BranchTarget = endInstLoc;
- }
- else {
- inst->BranchTarget = endInstLoc + 1;
- }
- }
- else {
- assert(ir->Opcode == IR_CONT ||
- ir->Opcode == IR_CONT_IF_TRUE);
- assert(inst->Opcode == OPCODE_CONT ||
- inst->Opcode == OPCODE_BRA);
- /* go to instruction at tail of loop */
- inst->BranchTarget = endInstLoc;
- }
- }
- return NULL;
-}
-
-
-/**
- * Unconditional "continue" or "break" statement.
- * Either OPCODE_CONT, OPCODE_BRK or OPCODE_BRA will be emitted.
- */
-static struct prog_instruction *
-emit_cont_break(slang_emit_info *emitInfo, slang_ir_node *n)
-{
- gl_inst_opcode opcode;
- struct prog_instruction *inst;
-
- if (n->Opcode == IR_CONT) {
- /* we need to execute the loop's tail code before doing CONT */
- assert(n->Parent);
- assert(n->Parent->Opcode == IR_LOOP);
- if (n->Parent->Children[1]) {
- /* emit tail code */
- if (emitInfo->EmitComments) {
- emit_comment(emitInfo, "continue - tail code:");
- }
- emit(emitInfo, n->Parent->Children[1]);
- }
- }
-
- /* opcode selection */
- if (emitInfo->EmitHighLevelInstructions) {
- opcode = (n->Opcode == IR_CONT) ? OPCODE_CONT : OPCODE_BRK;
- }
- else {
- opcode = OPCODE_BRA;
- }
- n->InstLocation = emitInfo->prog->NumInstructions;
- inst = new_instruction(emitInfo, opcode);
- if (inst) {
- inst->DstReg.CondMask = COND_TR; /* always true */
- }
- return inst;
-}
-
-
-/**
- * Conditional "continue" or "break" statement.
- * Either OPCODE_CONT, OPCODE_BRK or OPCODE_BRA will be emitted.
- */
-static struct prog_instruction *
-emit_cont_break_if_true(slang_emit_info *emitInfo, slang_ir_node *n)
-{
- struct prog_instruction *inst;
-
- assert(n->Opcode == IR_CONT_IF_TRUE ||
- n->Opcode == IR_BREAK_IF_TRUE);
-
- /* evaluate condition expr, setting cond codes */
- inst = emit(emitInfo, n->Children[0]);
- if (emitInfo->EmitCondCodes) {
- assert(inst);
- inst->CondUpdate = GL_TRUE;
- }
-
- n->InstLocation = emitInfo->prog->NumInstructions;
-
- /* opcode selection */
- if (emitInfo->EmitHighLevelInstructions) {
- const gl_inst_opcode opcode
- = (n->Opcode == IR_CONT_IF_TRUE) ? OPCODE_CONT : OPCODE_BRK;
- if (emitInfo->EmitCondCodes) {
- /* Get the writemask from the previous instruction which set
- * the condcodes. Use that writemask as the CondSwizzle.
- */
- const GLuint condWritemask = inst->DstReg.WriteMask;
- inst = new_instruction(emitInfo, opcode);
- if (inst) {
- inst->DstReg.CondMask = COND_NE;
- inst->DstReg.CondSwizzle = writemask_to_swizzle(condWritemask);
- }
- return inst;
- }
- else {
- /* IF reg
- * BRK/CONT;
- * ENDIF
- */
- GLint ifInstLoc;
- ifInstLoc = emitInfo->prog->NumInstructions;
- inst = emit_instruction(emitInfo, OPCODE_IF,
- NULL, /* dest */
- n->Children[0]->Store,
- NULL,
- NULL);
- if (!inst) {
- return NULL;
- }
- n->InstLocation = emitInfo->prog->NumInstructions;
-
- inst = new_instruction(emitInfo, opcode);
- if (!inst) {
- return NULL;
- }
- inst = new_instruction(emitInfo, OPCODE_ENDIF);
- if (!inst) {
- return NULL;
- }
-
- emitInfo->prog->Instructions[ifInstLoc].BranchTarget
- = emitInfo->prog->NumInstructions - 1;
- return inst;
- }
- }
- else {
- const GLuint condWritemask = inst->DstReg.WriteMask;
- assert(emitInfo->EmitCondCodes);
- inst = new_instruction(emitInfo, OPCODE_BRA);
- if (inst) {
- inst->DstReg.CondMask = COND_NE;
- inst->DstReg.CondSwizzle = writemask_to_swizzle(condWritemask);
- }
- return inst;
- }
-}
-
-
-/**
- * Return the size of a swizzle mask given that some swizzle components
- * may be NIL/undefined. For example:
- * swizzle_size(".zzxx") = 4
- * swizzle_size(".xy??") = 2
- * swizzle_size(".w???") = 1
- */
-static GLuint
-swizzle_size(GLuint swizzle)
-{
- GLuint i;
- for (i = 0; i < 4; i++) {
- if (GET_SWZ(swizzle, i) == SWIZZLE_NIL)
- return i;
- }
- return 4;
-}
-
-
-static struct prog_instruction *
-emit_swizzle(slang_emit_info *emitInfo, slang_ir_node *n)
-{
- struct prog_instruction *inst;
-
- inst = emit(emitInfo, n->Children[0]);
-
- if (!n->Store->Parent) {
- /* this covers a case such as "(b ? p : q).x" */
- n->Store->Parent = n->Children[0]->Store;
- assert(n->Store->Parent);
- }
-
- {
- const GLuint swizzle = n->Store->Swizzle;
- /* new storage is parent storage with updated Swizzle + Size fields */
- _slang_copy_ir_storage(n->Store, n->Store->Parent);
- /* Apply this node's swizzle to parent's storage */
- n->Store->Swizzle = _slang_swizzle_swizzle(n->Store->Swizzle, swizzle);
- /* Update size */
- n->Store->Size = swizzle_size(n->Store->Swizzle);
- }
-
- assert(!n->Store->Parent);
- assert(n->Store->Index >= 0);
-
- return inst;
-}
-
-
-/**
- * Dereference array element: element == array[index]
- * This basically involves emitting code for computing the array index
- * and updating the node/element's storage info.
- */
-static struct prog_instruction *
-emit_array_element(slang_emit_info *emitInfo, slang_ir_node *n)
-{
- slang_ir_storage *arrayStore, *indexStore;
- const int elemSize = n->Store->Size; /* number of floats */
- const GLint elemSizeVec = (elemSize + 3) / 4; /* number of vec4 */
- struct prog_instruction *inst;
-
- assert(n->Opcode == IR_ELEMENT);
- assert(elemSize > 0);
-
- /* special case for built-in state variables, like light state */
- {
- slang_ir_storage *root = n->Store;
- assert(!root->Parent);
- while (root->Parent)
- root = root->Parent;
-
- if (root->File == PROGRAM_STATE_VAR) {
- GLboolean direct;
- GLint index =
- _slang_alloc_statevar(n, emitInfo->prog->Parameters, &direct);
- if (index < 0) {
- /* error */
- return NULL;
- }
- if (direct) {
- n->Store->Index = index;
- return NULL; /* all done */
- }
- }
- }
-
- /* do codegen for array itself */
- emit(emitInfo, n->Children[0]);
- arrayStore = n->Children[0]->Store;
-
- /* The initial array element storage is the array's storage,
- * then modified below.
- */
- _slang_copy_ir_storage(n->Store, arrayStore);
-
-
- if (n->Children[1]->Opcode == IR_FLOAT) {
- /* Constant array index */
- const GLint element = (GLint) n->Children[1]->Value[0];
-
- /* this element's storage is the array's storage, plus constant offset */
- n->Store->Index += elemSizeVec * element;
- }
- else {
- /* Variable array index */
-
- /* do codegen for array index expression */
- emit(emitInfo, n->Children[1]);
- indexStore = n->Children[1]->Store;
-
- if (indexStore->IsIndirect) {
- /* need to put the array index into a temporary since we can't
- * directly support a[b[i]] constructs.
- */
-
-
- /*indexStore = tempstore();*/
- }
-
-
- if (elemSize > 4) {
- /* need to multiply array index by array element size */
- struct prog_instruction *inst;
- slang_ir_storage *indexTemp;
- slang_ir_storage elemSizeStore;
-
- /* allocate 1 float indexTemp */
- indexTemp = _slang_new_ir_storage(PROGRAM_TEMPORARY, -1, 1);
- _slang_alloc_temp(emitInfo->vt, indexTemp);
-
- /* allocate a constant containing the element size */
- constant_to_storage(emitInfo, (float) elemSizeVec, &elemSizeStore);
-
- /* multiply array index by element size */
- inst = emit_instruction(emitInfo,
- OPCODE_MUL,
- indexTemp, /* dest */
- indexStore, /* the index */
- &elemSizeStore,
- NULL);
- if (!inst) {
- return NULL;
- }
-
- indexStore = indexTemp;
- }
-
- if (arrayStore->IsIndirect) {
- /* ex: in a[i][j], a[i] (the arrayStore) is indirect */
- /* Need to add indexStore to arrayStore->Indirect store */
- slang_ir_storage indirectArray;
- slang_ir_storage *indexTemp;
-
- _slang_init_ir_storage(&indirectArray,
- arrayStore->IndirectFile,
- arrayStore->IndirectIndex,
- 1,
- arrayStore->IndirectSwizzle);
-
- /* allocate 1 float indexTemp */
- indexTemp = _slang_new_ir_storage(PROGRAM_TEMPORARY, -1, 1);
- _slang_alloc_temp(emitInfo->vt, indexTemp);
-
- inst = emit_instruction(emitInfo,
- OPCODE_ADD,
- indexTemp, /* dest */
- indexStore, /* the index */
- &indirectArray, /* indirect array base */
- NULL);
- if (!inst) {
- return NULL;
- }
-
- indexStore = indexTemp;
- }
-
- /* update the array element storage info */
- n->Store->IsIndirect = GL_TRUE;
- n->Store->IndirectFile = indexStore->File;
- n->Store->IndirectIndex = indexStore->Index;
- n->Store->IndirectSwizzle = indexStore->Swizzle;
- }
-
- n->Store->Size = elemSize;
- n->Store->Swizzle = _slang_var_swizzle(elemSize, 0);
-
- return NULL; /* no instruction */
-}
-
-
-/**
- * Resolve storage for accessing a structure field.
- */
-static struct prog_instruction *
-emit_struct_field(slang_emit_info *emitInfo, slang_ir_node *n)
-{
- slang_ir_storage *root = n->Store;
- GLint fieldOffset, fieldSize;
-
- assert(n->Opcode == IR_FIELD);
-
- assert(!root->Parent);
- while (root->Parent)
- root = root->Parent;
-
- /* If this is the field of a state var, allocate constant/uniform
- * storage for it now if we haven't already.
- * Note that we allocate storage (uniform/constant slots) for state
- * variables here rather than at declaration time so we only allocate
- * space for the ones that we actually use!
- */
- if (root->File == PROGRAM_STATE_VAR) {
- GLboolean direct;
- GLint index = _slang_alloc_statevar(n, emitInfo->prog->Parameters, &direct);
- if (index < 0) {
- slang_info_log_error(emitInfo->log, "Error parsing state variable");
- return NULL;
- }
- if (direct) {
- root->Index = index;
- return NULL; /* all done */
- }
- }
-
- /* do codegen for struct */
- emit(emitInfo, n->Children[0]);
- assert(n->Children[0]->Store->Index >= 0);
-
-
- fieldOffset = n->Store->Index;
- fieldSize = n->Store->Size;
-
- _slang_copy_ir_storage(n->Store, n->Children[0]->Store);
-
- n->Store->Index = n->Children[0]->Store->Index + fieldOffset / 4;
- n->Store->Size = fieldSize;
-
- switch (fieldSize) {
- case 1:
- {
- GLint swz = fieldOffset % 4;
- n->Store->Swizzle = MAKE_SWIZZLE4(swz, swz, swz, swz);
- }
- break;
- case 2:
- n->Store->Swizzle = MAKE_SWIZZLE4(SWIZZLE_X, SWIZZLE_Y,
- SWIZZLE_NIL, SWIZZLE_NIL);
- break;
- case 3:
- n->Store->Swizzle = MAKE_SWIZZLE4(SWIZZLE_X, SWIZZLE_Y,
- SWIZZLE_Z, SWIZZLE_NIL);
- break;
- default:
- n->Store->Swizzle = SWIZZLE_XYZW;
- }
-
- assert(n->Store->Index >= 0);
-
- return NULL; /* no instruction */
-}
-
-
-/**
- * Emit code for a variable declaration.
- * This usually doesn't result in any code generation, but just
- * memory allocation.
- */
-static struct prog_instruction *
-emit_var_decl(slang_emit_info *emitInfo, slang_ir_node *n)
-{
- assert(n->Store);
- assert(n->Store->File != PROGRAM_UNDEFINED);
- assert(n->Store->Size > 0);
- /*assert(n->Store->Index < 0);*/
-
- if (!n->Var || n->Var->isTemp) {
- /* a nameless/temporary variable, will be freed after first use */
- /*NEW*/
- if (n->Store->Index < 0 && !_slang_alloc_temp(emitInfo->vt, n->Store)) {
- slang_info_log_error(emitInfo->log,
- "Ran out of registers, too many temporaries");
- return NULL;
- }
- }
- else {
- /* a regular variable */
- _slang_add_variable(emitInfo->vt, n->Var);
- if (!_slang_alloc_var(emitInfo->vt, n->Store)) {
- slang_info_log_error(emitInfo->log,
- "Ran out of registers, too many variables");
- return NULL;
- }
- /*
- printf("IR_VAR_DECL %s %d store %p\n",
- (char*) n->Var->a_name, n->Store->Index, (void*) n->Store);
- */
- assert(n->Var->store == n->Store);
- }
- if (emitInfo->EmitComments) {
- /* emit NOP with comment describing the variable's storage location */
- char s[1000];
- _mesa_snprintf(s, sizeof(s), "TEMP[%d]%s = variable %s (size %d)",
- n->Store->Index,
- _mesa_swizzle_string(n->Store->Swizzle, 0, GL_FALSE),
- (n->Var ? (char *) n->Var->a_name : "anonymous"),
- n->Store->Size);
- emit_comment(emitInfo, s);
- }
- return NULL;
-}
-
-
-/**
- * Emit code for a reference to a variable.
- * Actually, no code is generated but we may do some memory allocation.
- * In particular, state vars (uniforms) are allocated on an as-needed basis.
- */
-static struct prog_instruction *
-emit_var_ref(slang_emit_info *emitInfo, slang_ir_node *n)
-{
- assert(n->Store);
- assert(n->Store->File != PROGRAM_UNDEFINED);
-
- if (n->Store->File == PROGRAM_STATE_VAR && n->Store->Index < 0) {
- GLboolean direct;
- GLint index = _slang_alloc_statevar(n, emitInfo->prog->Parameters, &direct);
- if (index < 0) {
- /* error */
- char s[100];
- /* XXX isn't this really an out of memory/resources error? */
- _mesa_snprintf(s, sizeof(s), "Undefined variable '%s'",
- (char *) n->Var->a_name);
- slang_info_log_error(emitInfo->log, s);
- return NULL;
- }
-
- n->Store->Index = index;
- }
- else if (n->Store->File == PROGRAM_UNIFORM ||
- n->Store->File == PROGRAM_SAMPLER) {
- /* mark var as used */
- _mesa_use_uniform(emitInfo->prog->Parameters, (char *) n->Var->a_name);
- }
- else if (n->Store->File == PROGRAM_INPUT) {
- assert(n->Store->Index >= 0);
- /* geometry shaders have the input index in the second
- * index */
- if (emitInfo->prog->Target == MESA_GEOMETRY_PROGRAM &&
- n->Store->Is2D) {
- emitInfo->prog->InputsRead |= (1 << n->Store->Index2);
- } else
- emitInfo->prog->InputsRead |= (1 << n->Store->Index);
- }
-
- if (n->Store->Index < 0) {
- /* probably ran out of registers */
- return NULL;
- }
- assert(n->Store->Size > 0);
-
- return NULL;
-}
-
-
-static struct prog_instruction *
-emit(slang_emit_info *emitInfo, slang_ir_node *n)
-{
- struct prog_instruction *inst;
- if (!n)
- return NULL;
-
- if (emitInfo->log->error_flag) {
- return NULL;
- }
-
- if (n->Comment) {
- inst = new_instruction(emitInfo, OPCODE_NOP);
- if (inst) {
- inst->Comment = _mesa_strdup(n->Comment);
- }
- inst = NULL;
- }
-
- switch (n->Opcode) {
- case IR_SEQ:
- /* sequence of two sub-trees */
- assert(n->Children[0]);
- assert(n->Children[1]);
- emit(emitInfo, n->Children[0]);
- if (emitInfo->log->error_flag)
- return NULL;
- inst = emit(emitInfo, n->Children[1]);
-#if 0
- assert(!n->Store);
-#endif
- if (n->Children[1]->Store)
- n->Store = n->Children[1]->Store;
- else
- n->Store = n->Children[0]->Store;
- return inst;
-
- case IR_SCOPE:
- /* new variable scope */
- _slang_push_var_table(emitInfo->vt);
- inst = emit(emitInfo, n->Children[0]);
- _slang_pop_var_table(emitInfo->vt);
- n->Store = n->Children[0]->Store;
- return inst;
-
- case IR_VAR_DECL:
- /* Variable declaration - allocate a register for it */
- inst = emit_var_decl(emitInfo, n);
- return inst;
-
- case IR_VAR:
- /* Reference to a variable
- * Storage should have already been resolved/allocated.
- */
- return emit_var_ref(emitInfo, n);
-
- case IR_ELEMENT:
- return emit_array_element(emitInfo, n);
- case IR_FIELD:
- return emit_struct_field(emitInfo, n);
- case IR_SWIZZLE:
- return emit_swizzle(emitInfo, n);
-
- /* Simple arithmetic */
- /* unary */
- case IR_MOVE:
- case IR_RSQ:
- case IR_RCP:
- case IR_FLOOR:
- case IR_FRAC:
- case IR_F_TO_I:
- case IR_I_TO_F:
- case IR_ABS:
- case IR_SIN:
- case IR_COS:
- case IR_DDX:
- case IR_DDY:
- case IR_EXP:
- case IR_EXP2:
- case IR_LOG2:
- case IR_NOISE1:
- case IR_NOISE2:
- case IR_NOISE3:
- case IR_NOISE4:
- case IR_NRM4:
- case IR_NRM3:
- /* binary */
- case IR_ADD:
- case IR_SUB:
- case IR_MUL:
- case IR_DOT4:
- case IR_DOT3:
- case IR_DOT2:
- case IR_CROSS:
- case IR_MIN:
- case IR_MAX:
- case IR_SEQUAL:
- case IR_SNEQUAL:
- case IR_SGE:
- case IR_SGT:
- case IR_SLE:
- case IR_SLT:
- case IR_POW:
- /* trinary operators */
- case IR_LRP:
- case IR_CMP:
- return emit_arith(emitInfo, n);
-
- case IR_EQUAL:
- case IR_NOTEQUAL:
- return emit_compare(emitInfo, n);
-
- case IR_CLAMP:
- return emit_clamp(emitInfo, n);
- case IR_TEX:
- case IR_TEXB:
- case IR_TEXP:
- case IR_TEX_SH:
- case IR_TEXB_SH:
- case IR_TEXP_SH:
- return emit_tex(emitInfo, n);
- case IR_NEG:
- return emit_negation(emitInfo, n);
- case IR_FLOAT:
- /* find storage location for this float constant */
- n->Store->Index = _mesa_add_unnamed_constant(emitInfo->prog->Parameters,
- n->Value,
- n->Store->Size,
- &n->Store->Swizzle);
- if (n->Store->Index < 0) {
- slang_info_log_error(emitInfo->log, "Ran out of space for constants");
- return NULL;
- }
- return NULL;
-
- case IR_COPY:
- return emit_copy(emitInfo, n);
-
- case IR_COND:
- return emit_cond(emitInfo, n);
-
- case IR_NOT:
- return emit_not(emitInfo, n);
-
- case IR_LABEL:
- return emit_label(emitInfo, n);
-
- case IR_KILL:
- return emit_kill(emitInfo);
-
- case IR_CALL:
- /* new variable scope for subroutines/function calls */
- _slang_push_var_table(emitInfo->vt);
- inst = emit_fcall(emitInfo, n);
- _slang_pop_var_table(emitInfo->vt);
- return inst;
-
- case IR_IF:
- return emit_if(emitInfo, n);
-
- case IR_LOOP:
- return emit_loop(emitInfo, n);
- case IR_BREAK_IF_TRUE:
- case IR_CONT_IF_TRUE:
- return emit_cont_break_if_true(emitInfo, n);
- case IR_BREAK:
- /* fall-through */
- case IR_CONT:
- return emit_cont_break(emitInfo, n);
-
- case IR_BEGIN_SUB:
- return new_instruction(emitInfo, OPCODE_BGNSUB);
- case IR_END_SUB:
- return new_instruction(emitInfo, OPCODE_ENDSUB);
- case IR_RETURN:
- return emit_return(emitInfo, n);
-
- case IR_NOP:
- return NULL;
-
- case IR_EMIT_VERTEX:
- return new_instruction(emitInfo, OPCODE_EMIT_VERTEX);
- case IR_END_PRIMITIVE:
- return new_instruction(emitInfo, OPCODE_END_PRIMITIVE);
-
- default:
- _mesa_problem(NULL, "Unexpected IR opcode in emit()\n");
- }
- return NULL;
-}
-
-
-/**
- * After code generation, any subroutines will be in separate program
- * objects. This function appends all the subroutines onto the main
- * program and resolves the linking of all the branch/call instructions.
- * XXX this logic should really be part of the linking process...
- */
-static void
-_slang_resolve_subroutines(slang_emit_info *emitInfo)
-{
- GET_CURRENT_CONTEXT(ctx);
- struct gl_program *mainP = emitInfo->prog;
- GLuint *subroutineLoc, i, total;
-
- subroutineLoc
- = (GLuint *) malloc(emitInfo->NumSubroutines * sizeof(GLuint));
-
- /* total number of instructions */
- total = mainP->NumInstructions;
- for (i = 0; i < emitInfo->NumSubroutines; i++) {
- subroutineLoc[i] = total;
- total += emitInfo->Subroutines[i]->NumInstructions;
- }
-
- /* adjust BranchTargets within the functions */
- for (i = 0; i < emitInfo->NumSubroutines; i++) {
- struct gl_program *sub = emitInfo->Subroutines[i];
- GLuint j;
- for (j = 0; j < sub->NumInstructions; j++) {
- struct prog_instruction *inst = sub->Instructions + j;
- if (inst->Opcode != OPCODE_CAL && inst->BranchTarget >= 0) {
- inst->BranchTarget += subroutineLoc[i];
- }
- }
- }
-
- /* append subroutines' instructions after main's instructions */
- mainP->Instructions = _mesa_realloc_instructions(mainP->Instructions,
- mainP->NumInstructions,
- total);
- mainP->NumInstructions = total;
- for (i = 0; i < emitInfo->NumSubroutines; i++) {
- struct gl_program *sub = emitInfo->Subroutines[i];
- _mesa_copy_instructions(mainP->Instructions + subroutineLoc[i],
- sub->Instructions,
- sub->NumInstructions);
- /* delete subroutine code */
- sub->Parameters = NULL; /* prevent double-free */
- _mesa_reference_program(ctx, &emitInfo->Subroutines[i], NULL);
- }
-
- /* free subroutine list */
- if (emitInfo->Subroutines) {
- free(emitInfo->Subroutines);
- emitInfo->Subroutines = NULL;
- }
- emitInfo->NumSubroutines = 0;
-
- /* Examine CAL instructions.
- * At this point, the BranchTarget field of the CAL instruction is
- * the number/id of the subroutine to call (an index into the
- * emitInfo->Subroutines list).
- * Translate that into an actual instruction location now.
- */
- for (i = 0; i < mainP->NumInstructions; i++) {
- struct prog_instruction *inst = mainP->Instructions + i;
- if (inst->Opcode == OPCODE_CAL) {
- const GLuint f = inst->BranchTarget;
- inst->BranchTarget = subroutineLoc[f];
- }
- }
-
- free(subroutineLoc);
-}
-
-
-
-/**
- * Convert the IR tree into GPU instructions.
- * \param n root of IR tree
- * \param vt variable table
- * \param prog program to put GPU instructions into
- * \param pragmas controls codegen options
- * \param withEnd if true, emit END opcode at end
- * \param log log for emitting errors/warnings/info
- */
-GLboolean
-_slang_emit_code(slang_ir_node *n, slang_var_table *vt,
- struct gl_program *prog,
- const struct gl_sl_pragmas *pragmas,
- GLboolean withEnd,
- slang_info_log *log)
-{
- GET_CURRENT_CONTEXT(ctx);
- GLboolean success;
- slang_emit_info emitInfo;
- GLuint maxUniforms;
-
- emitInfo.log = log;
- emitInfo.vt = vt;
- emitInfo.prog = prog;
- emitInfo.Subroutines = NULL;
- emitInfo.NumSubroutines = 0;
- emitInfo.MaxInstructions = prog->NumInstructions;
-
- emitInfo.EmitHighLevelInstructions = ctx->Shader.EmitHighLevelInstructions;
- emitInfo.EmitCondCodes = ctx->Shader.EmitCondCodes;
- emitInfo.EmitComments = ctx->Shader.EmitComments || pragmas->Debug;
- emitInfo.EmitBeginEndSub = GL_TRUE;
-
- if (!emitInfo.EmitCondCodes) {
- emitInfo.EmitHighLevelInstructions = GL_TRUE;
- }
-
- /* Check uniform/constant limits */
- if (prog->Target == GL_FRAGMENT_PROGRAM_ARB) {
- maxUniforms = ctx->Const.FragmentProgram.MaxUniformComponents / 4;
- }
- else if (prog->Target == GL_VERTEX_PROGRAM_ARB) {
- maxUniforms = ctx->Const.VertexProgram.MaxUniformComponents / 4;
- } else {
- assert(prog->Target == MESA_GEOMETRY_PROGRAM);
- maxUniforms = ctx->Const.GeometryProgram.MaxUniformComponents / 4;
- }
- if (prog->Parameters->NumParameters > maxUniforms) {
- slang_info_log_error(log, "Constant/uniform register limit exceeded "
- "(max=%u vec4)", maxUniforms);
-
- return GL_FALSE;
- }
-
- (void) emit(&emitInfo, n);
-
- /* finish up by adding the END opcode to program */
- if (withEnd) {
- struct prog_instruction *inst;
- inst = new_instruction(&emitInfo, OPCODE_END);
- if (!inst) {
- return GL_FALSE;
- }
- }
-
- _slang_resolve_subroutines(&emitInfo);
-
- success = GL_TRUE;
-
-#if 0
- printf("*********** End emit code (%u inst):\n", prog->NumInstructions);
- _mesa_print_program(prog);
- _mesa_print_program_parameters(ctx,prog);
-#endif
-
- return success;
-}
+++ /dev/null
-/*
- * Mesa 3-D graphics library
- * Version: 7.1
- *
- * Copyright (C) 2005-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.
- */
-
-#ifndef SLANG_EMIT_H
-#define SLANG_EMIT_H
-
-#include "main/glheader.h"
-#include "slang_ir.h"
-#include "slang_vartable.h"
-
-
-extern GLuint
-_slang_swizzle_swizzle(GLuint swz1, GLuint swz2);
-
-
-extern GLuint
-_slang_var_swizzle(GLint size, GLint comp);
-
-
-extern GLboolean
-_slang_emit_code(slang_ir_node *n, slang_var_table *vartable,
- struct gl_program *prog,
- const struct gl_sl_pragmas *pragmas,
- GLboolean withEnd,
- slang_info_log *log);
-
-
-#endif /* SLANG_EMIT_H */
+++ /dev/null
-/*
- * Mesa 3-D graphics library
- *
- * Copyright (C) 2005-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.
- */
-
-
-#include "main/imports.h"
-#include "main/context.h"
-#include "slang_ir.h"
-#include "slang_mem.h"
-#include "program/prog_instruction.h"
-#include "program/prog_print.h"
-
-
-static const slang_ir_info IrInfo[] = {
- /* binary ops */
- { IR_ADD, "IR_ADD", OPCODE_ADD, 4, 2 },
- { IR_SUB, "IR_SUB", OPCODE_SUB, 4, 2 },
- { IR_MUL, "IR_MUL", OPCODE_MUL, 4, 2 },
- { IR_DIV, "IR_DIV", OPCODE_NOP, 0, 2 }, /* XXX broke */
- { IR_DOT4, "IR_DOT4", OPCODE_DP4, 1, 2 },
- { IR_DOT3, "IR_DOT3", OPCODE_DP3, 1, 2 },
- { IR_DOT2, "IR_DOT2", OPCODE_DP2, 1, 2 },
- { IR_NRM4, "IR_NRM4", OPCODE_NRM4, 1, 1 },
- { IR_NRM3, "IR_NRM3", OPCODE_NRM3, 1, 1 },
- { IR_CROSS, "IR_CROSS", OPCODE_XPD, 3, 2 },
- { IR_LRP, "IR_LRP", OPCODE_LRP, 4, 3 },
- { IR_MIN, "IR_MIN", OPCODE_MIN, 4, 2 },
- { IR_MAX, "IR_MAX", OPCODE_MAX, 4, 2 },
- { IR_CLAMP, "IR_CLAMP", OPCODE_NOP, 4, 3 }, /* special case: emit_clamp() */
- { IR_SEQUAL, "IR_SEQUAL", OPCODE_SEQ, 4, 2 },
- { IR_SNEQUAL, "IR_SNEQUAL", OPCODE_SNE, 4, 2 },
- { IR_SGE, "IR_SGE", OPCODE_SGE, 4, 2 },
- { IR_SGT, "IR_SGT", OPCODE_SGT, 4, 2 },
- { IR_SLE, "IR_SLE", OPCODE_SLE, 4, 2 },
- { IR_SLT, "IR_SLT", OPCODE_SLT, 4, 2 },
- { IR_POW, "IR_POW", OPCODE_POW, 1, 2 },
- { IR_EQUAL, "IR_EQUAL", OPCODE_NOP, 1, 2 },
- { IR_NOTEQUAL, "IR_NOTEQUAL", OPCODE_NOP, 1, 2 },
-
- /* unary ops */
- { IR_MOVE, "IR_MOVE", OPCODE_MOV, 4, 1 },
- { IR_I_TO_F, "IR_I_TO_F", OPCODE_MOV, 4, 1 }, /* int[4] to float[4] */
- { IR_F_TO_I, "IR_F_TO_I", OPCODE_TRUNC, 4, 1 },
- { IR_EXP, "IR_EXP", OPCODE_EXP, 1, 1 },
- { IR_EXP2, "IR_EXP2", OPCODE_EX2, 1, 1 },
- { IR_LOG2, "IR_LOG2", OPCODE_LG2, 1, 1 },
- { IR_RSQ, "IR_RSQ", OPCODE_RSQ, 1, 1 },
- { IR_RCP, "IR_RCP", OPCODE_RCP, 1, 1 },
- { IR_FLOOR, "IR_FLOOR", OPCODE_FLR, 4, 1 },
- { IR_FRAC, "IR_FRAC", OPCODE_FRC, 4, 1 },
- { IR_ABS, "IR_ABS", OPCODE_ABS, 4, 1 },
- { IR_NEG, "IR_NEG", OPCODE_NOP, 4, 1 }, /* special case: emit_negation() */
- { IR_DDX, "IR_DDX", OPCODE_DDX, 4, 1 },
- { IR_DDY, "IR_DDY", OPCODE_DDY, 4, 1 },
- { IR_SIN, "IR_SIN", OPCODE_SIN, 1, 1 },
- { IR_COS, "IR_COS", OPCODE_COS, 1, 1 },
- { IR_NOISE1, "IR_NOISE1", OPCODE_NOISE1, 1, 1 },
- { IR_NOISE2, "IR_NOISE2", OPCODE_NOISE2, 1, 1 },
- { IR_NOISE3, "IR_NOISE3", OPCODE_NOISE3, 1, 1 },
- { IR_NOISE4, "IR_NOISE4", OPCODE_NOISE4, 1, 1 },
-
- /* other */
- { IR_CMP, "IR_CMP", OPCODE_CMP, 4, 3 }, /* compare/select */
- { IR_SEQ, "IR_SEQ", OPCODE_NOP, 0, 0 },
- { IR_SCOPE, "IR_SCOPE", OPCODE_NOP, 0, 0 },
- { IR_LABEL, "IR_LABEL", OPCODE_NOP, 0, 0 },
- { IR_IF, "IR_IF", OPCODE_NOP, 0, 0 },
- { IR_KILL, "IR_KILL", OPCODE_NOP, 0, 0 },
- { IR_COND, "IR_COND", OPCODE_NOP, 0, 0 },
- { IR_CALL, "IR_CALL", OPCODE_NOP, 0, 0 },
- { IR_COPY, "IR_COPY", OPCODE_NOP, 0, 1 },
- { IR_NOT, "IR_NOT", OPCODE_NOP, 1, 1 },
- { IR_VAR, "IR_VAR", OPCODE_NOP, 0, 0 },
- { IR_VAR_DECL, "IR_VAR_DECL", OPCODE_NOP, 0, 0 },
- { IR_TEX, "IR_TEX", OPCODE_TEX, 4, 1 },
- { IR_TEXB, "IR_TEXB", OPCODE_TXB, 4, 1 },
- { IR_TEXP, "IR_TEXP", OPCODE_TXP, 4, 1 },
- { IR_TEX_SH, "IR_TEX_SH", OPCODE_TEX, 4, 1 },
- { IR_TEXB_SH, "IR_TEXB_SH", OPCODE_TXB, 4, 1 },
- { IR_TEXP_SH, "IR_TEXP_SH", OPCODE_TXP, 4, 1 },
- { IR_FLOAT, "IR_FLOAT", OPCODE_NOP, 0, 0 }, /* float literal */
- { IR_FIELD, "IR_FIELD", OPCODE_NOP, 0, 0 },
- { IR_ELEMENT, "IR_ELEMENT", OPCODE_NOP, 0, 0 },
- { IR_SWIZZLE, "IR_SWIZZLE", OPCODE_NOP, 0, 0 },
- { IR_NOP, "IR_NOP", OPCODE_NOP, 0, 0 },
- { IR_EMIT_VERTEX, "IR_EMIT_VERTEX", OPCODE_EMIT_VERTEX, 0, 0 },
- { IR_END_PRIMITIVE, "IR_END_PRIMITIVE", OPCODE_END_PRIMITIVE, 0, 0 },
- { 0, NULL, 0, 0, 0 }
-};
-
-
-const slang_ir_info *
-_slang_ir_info(slang_ir_opcode opcode)
-{
- GLuint i;
- for (i = 0; IrInfo[i].IrName; i++) {
- if (IrInfo[i].IrOpcode == opcode) {
- return IrInfo + i;
- }
- }
- return NULL;
-}
-
-
-void
-_slang_init_ir_storage(slang_ir_storage *st,
- gl_register_file file, GLint index, GLint size,
- GLuint swizzle)
-{
- st->File = file;
- st->Index = index;
- st->Size = size;
- st->Swizzle = swizzle;
- st->Parent = NULL;
- st->IsIndirect = GL_FALSE;
- st->Is2D = GL_FALSE;
- st->Index2 = 0;
-}
-
-
-/**
- * Return a new slang_ir_storage object.
- */
-slang_ir_storage *
-_slang_new_ir_storage(gl_register_file file, GLint index, GLint size)
-{
- slang_ir_storage *st;
- st = (slang_ir_storage *) _slang_alloc(sizeof(slang_ir_storage));
- if (st) {
- st->File = file;
- st->Index = index;
- st->Size = size;
- st->Swizzle = SWIZZLE_NOOP;
- st->Parent = NULL;
- st->IsIndirect = GL_FALSE;
- st->Is2D = GL_FALSE;
- st->Index2 = 0;
- }
- return st;
-}
-
-
-/**
- * Return a new slang_ir_storage object.
- */
-slang_ir_storage *
-_slang_new_ir_storage_swz(gl_register_file file, GLint index, GLint size,
- GLuint swizzle)
-{
- slang_ir_storage *st;
- st = (slang_ir_storage *) _slang_alloc(sizeof(slang_ir_storage));
- if (st) {
- st->File = file;
- st->Index = index;
- st->Size = size;
- st->Swizzle = swizzle;
- st->Parent = NULL;
- st->IsIndirect = GL_FALSE;
- st->Is2D = GL_FALSE;
- st->Index2 = 0;
- }
- return st;
-}
-
-/**
- * Return a new slang_ir_storage object.
- */
-slang_ir_storage *
-_slang_new_ir_storage_2d(gl_register_file file,
- GLint index, GLint index2,
- GLint size, GLuint swizzle)
-{
- slang_ir_storage *st;
- st = (slang_ir_storage *) _slang_alloc(sizeof(slang_ir_storage));
- if (st) {
- st->File = file;
- st->Index = index;
- st->Size = size;
- st->Swizzle = swizzle;
- st->Parent = NULL;
- st->IsIndirect = GL_FALSE;
- st->Is2D = GL_TRUE;
- st->Index2 = index2;
- }
- return st;
-}
-
-
-
-/**
- * Return a new slang_ir_storage object.
- */
-slang_ir_storage *
-_slang_new_ir_storage_relative(GLint index, GLint size,
- slang_ir_storage *parent)
-{
- slang_ir_storage *st;
- st = (slang_ir_storage *) _slang_alloc(sizeof(slang_ir_storage));
- if (st) {
- st->File = PROGRAM_UNDEFINED;
- st->Index = index;
- st->Size = size;
- st->Swizzle = SWIZZLE_NOOP;
- st->Parent = parent;
- st->IsIndirect = GL_FALSE;
- st->Is2D = GL_FALSE;
- st->Index2 = 0;
- }
- return st;
-}
-
-
-slang_ir_storage *
-_slang_new_ir_storage_indirect(gl_register_file file,
- GLint index,
- GLint size,
- gl_register_file indirectFile,
- GLint indirectIndex,
- GLuint indirectSwizzle)
-{
- slang_ir_storage *st;
- st = (slang_ir_storage *) _slang_alloc(sizeof(slang_ir_storage));
- if (st) {
- st->File = file;
- st->Index = index;
- st->Size = size;
- st->Swizzle = SWIZZLE_NOOP;
- st->IsIndirect = GL_TRUE;
- st->IndirectFile = indirectFile;
- st->IndirectIndex = indirectIndex;
- st->IndirectSwizzle = indirectSwizzle;
- st->Is2D = GL_FALSE;
- st->Index2 = 0;
- }
- return st;
-}
-
-
-/**
- * Allocate IR storage for a texture sampler.
- * \param sampNum the sampler number/index
- * \param texTarget one of TEXTURE_x_INDEX values
- * \param size number of samplers (in case of sampler array)
- */
-slang_ir_storage *
-_slang_new_ir_storage_sampler(GLint sampNum, GLuint texTarget, GLint size)
-{
- slang_ir_storage *st;
- assert(texTarget < NUM_TEXTURE_TARGETS);
- st = _slang_new_ir_storage(PROGRAM_SAMPLER, sampNum, size);
- if (st) {
- st->TexTarget = texTarget;
- }
- return st;
-}
-
-
-
-/* XXX temporary function */
-void
-_slang_copy_ir_storage(slang_ir_storage *dst, const slang_ir_storage *src)
-{
- *dst = *src;
- dst->Parent = NULL;
-}
-
-
-
-static const char *
-_slang_ir_name(slang_ir_opcode opcode)
-{
- return _slang_ir_info(opcode)->IrName;
-}
-
-
-
-#if 0 /* no longer needed with mempool */
-/**
- * Since many IR nodes might point to the same IR storage info, we need
- * to be careful when deleting things.
- * Before deleting an IR tree, traverse it and do refcounting on the
- * IR storage nodes. Use the refcount info during delete to free things
- * properly.
- */
-static void
-_slang_refcount_storage(slang_ir_node *n)
-{
- GLuint i;
- if (!n)
- return;
- if (n->Store)
- n->Store->RefCount++;
- for (i = 0; i < 3; i++)
- _slang_refcount_storage(n->Children[i]);
-}
-#endif
-
-
-static void
-_slang_free_ir(slang_ir_node *n)
-{
- GLuint i;
- if (!n)
- return;
-
-#if 0
- if (n->Store) {
- n->Store->RefCount--;
- if (n->Store->RefCount == 0) {
- _slang_free(n->Store);
- n->Store = NULL;
- }
- }
-#endif
-
- for (i = 0; i < 3; i++)
- _slang_free_ir(n->Children[i]);
- /* Do not free n->List since it's a child elsewhere */
- _slang_free(n);
-}
-
-
-/**
- * Recursively free an IR tree.
- */
-void
-_slang_free_ir_tree(slang_ir_node *n)
-{
-#if 0
- _slang_refcount_storage(n);
-#endif
- _slang_free_ir(n);
-}
-
-
-static const char *
-storage_string(const slang_ir_storage *st)
-{
- static const char *files[] = {
- "TEMP",
- "LOCAL_PARAM",
- "ENV_PARAM",
- "STATE",
- "INPUT",
- "OUTPUT",
- "NAMED_PARAM",
- "CONSTANT",
- "UNIFORM",
- "VARYING",
- "WRITE_ONLY",
- "ADDRESS",
- "SAMPLER",
- "UNDEFINED"
- };
- static char s[100];
- assert(Elements(files) == PROGRAM_FILE_MAX);
-#if 0
- if (st->Size == 1)
- _mesa_snprintf(s, "%s[%d]", files[st->File], st->Index);
- else
- _mesa_snprintf(s, "%s[%d..%d]", files[st->File], st->Index,
- st->Index + st->Size - 1);
-#endif
- assert(st->File < (GLint) (sizeof(files) / sizeof(files[0])));
- _mesa_snprintf(s, sizeof(s), "%s[%d]", files[st->File], st->Index);
- return s;
-}
-
-
-static void
-spaces(int n)
-{
- while (n-- > 0) {
- printf(" ");
- }
-}
-
-
-void
-_slang_print_ir_tree(const slang_ir_node *n, int indent)
-{
-#define IND 0
-
- if (!n)
- return;
-#if !IND
- if (n->Opcode != IR_SEQ)
-#else
- printf("%3d:", indent);
-#endif
- spaces(indent);
-
- switch (n->Opcode) {
- case IR_SEQ:
-#if IND
- printf("SEQ at %p\n", (void*) n);
-#endif
- assert(n->Children[0]);
- assert(n->Children[1]);
- _slang_print_ir_tree(n->Children[0], indent + IND);
- _slang_print_ir_tree(n->Children[1], indent + IND);
- break;
- case IR_SCOPE:
- printf("NEW SCOPE\n");
- assert(!n->Children[1]);
- _slang_print_ir_tree(n->Children[0], indent + 3);
- break;
- case IR_COPY:
- printf("COPY\n");
- _slang_print_ir_tree(n->Children[0], indent+3);
- _slang_print_ir_tree(n->Children[1], indent+3);
- break;
- case IR_LABEL:
- printf("LABEL: %s\n", n->Label->Name);
- break;
- case IR_COND:
- printf("COND\n");
- _slang_print_ir_tree(n->Children[0], indent + 3);
- break;
-
- case IR_IF:
- printf("IF \n");
- _slang_print_ir_tree(n->Children[0], indent+3);
- spaces(indent);
- printf("THEN\n");
- _slang_print_ir_tree(n->Children[1], indent+3);
- if (n->Children[2]) {
- spaces(indent);
- printf("ELSE\n");
- _slang_print_ir_tree(n->Children[2], indent+3);
- }
- spaces(indent);
- printf("ENDIF\n");
- break;
-
- case IR_BEGIN_SUB:
- printf("BEGIN_SUB\n");
- break;
- case IR_END_SUB:
- printf("END_SUB\n");
- break;
- case IR_RETURN:
- printf("RETURN\n");
- break;
- case IR_CALL:
- printf("CALL %s\n", n->Label->Name);
- break;
-
- case IR_LOOP:
- printf("LOOP\n");
- _slang_print_ir_tree(n->Children[0], indent+3);
- if (n->Children[1]) {
- spaces(indent);
- printf("TAIL:\n");
- _slang_print_ir_tree(n->Children[1], indent+3);
- }
- spaces(indent);
- printf("ENDLOOP\n");
- break;
- case IR_CONT:
- printf("CONT\n");
- break;
- case IR_BREAK:
- printf("BREAK\n");
- break;
- case IR_BREAK_IF_TRUE:
- printf("BREAK_IF_TRUE\n");
- _slang_print_ir_tree(n->Children[0], indent+3);
- break;
- case IR_CONT_IF_TRUE:
- printf("CONT_IF_TRUE\n");
- _slang_print_ir_tree(n->Children[0], indent+3);
- break;
-
- case IR_VAR:
- printf("VAR %s%s at %s store %p\n",
- (n->Var ? (char *) n->Var->a_name : "TEMP"),
- _mesa_swizzle_string(n->Store->Swizzle, 0, 0),
- storage_string(n->Store), (void*) n->Store);
- break;
- case IR_VAR_DECL:
- printf("VAR_DECL %s (%p) at %s store %p\n",
- (n->Var ? (char *) n->Var->a_name : "TEMP"),
- (void*) n->Var, storage_string(n->Store),
- (void*) n->Store);
- break;
- case IR_FIELD:
- printf("FIELD %s of\n", n->Field);
- _slang_print_ir_tree(n->Children[0], indent+3);
- break;
- case IR_FLOAT:
- printf("FLOAT %g %g %g %g\n",
- n->Value[0], n->Value[1], n->Value[2], n->Value[3]);
- break;
- case IR_I_TO_F:
- printf("INT_TO_FLOAT\n");
- _slang_print_ir_tree(n->Children[0], indent+3);
- break;
- case IR_F_TO_I:
- printf("FLOAT_TO_INT\n");
- _slang_print_ir_tree(n->Children[0], indent+3);
- break;
- case IR_SWIZZLE:
- printf("SWIZZLE %s of (store %p) \n",
- _mesa_swizzle_string(n->Store->Swizzle, 0, 0), (void*) n->Store);
- _slang_print_ir_tree(n->Children[0], indent + 3);
- break;
- default:
- printf("%s (%p, %p) (store %p)\n", _slang_ir_name(n->Opcode),
- (void*) n->Children[0], (void*) n->Children[1], (void*) n->Store);
- _slang_print_ir_tree(n->Children[0], indent+3);
- _slang_print_ir_tree(n->Children[1], indent+3);
- }
-}
+++ /dev/null
-/*
- * Mesa 3-D graphics library
- *
- * Copyright (C) 2005-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 slang_ir.h
- * Mesa GLSL Intermediate Representation tree types and constants.
- * \author Brian Paul
- */
-
-
-#ifndef SLANG_IR_H
-#define SLANG_IR_H
-
-
-#include "main/glheader.h"
-#include "main/mtypes.h"
-#include "program/prog_instruction.h"
-#include "slang_compile_variable.h"
-#include "slang_label.h"
-
-
-/**
- * Intermediate Representation opcodes
- */
-typedef enum
-{
- IR_NOP = 0,
- IR_SEQ, /* sequence (eval left, then right) */
- IR_SCOPE, /* new variable scope (one child) */
-
- IR_LABEL, /* target of a jump or cjump */
-
- IR_COND, /* conditional expression/predicate */
-
- IR_IF, /* high-level IF/then/else */
- /* Children[0] = conditional expression */
- /* Children[1] = if-true part */
- /* Children[2] = if-else part, or NULL */
-
- IR_BEGIN_SUB, /* begin subroutine */
- IR_END_SUB, /* end subroutine */
- IR_RETURN, /* return from subroutine */
- IR_CALL, /* call subroutine */
-
- IR_LOOP, /* high-level loop-begin / loop-end */
- /* Children[0] = loop body */
- /* Children[1] = loop tail code, or NULL */
-
- IR_CONT, /* continue loop */
- /* n->Parent = ptr to parent IR_LOOP Node */
- IR_BREAK, /* break loop */
-
- IR_BREAK_IF_TRUE, /**< Children[0] = the condition expression */
- IR_CONT_IF_TRUE,
-
- IR_COPY, /**< assignment/copy */
- IR_MOVE, /**< assembly MOV instruction */
-
- /* vector ops: */
- IR_ADD, /**< assembly ADD instruction */
- IR_SUB,
- IR_MUL,
- IR_DIV,
- IR_DOT4,
- IR_DOT3,
- IR_DOT2,
- IR_NRM4,
- IR_NRM3,
- IR_CROSS, /* vec3 cross product */
- IR_LRP,
- IR_CLAMP,
- IR_MIN,
- IR_MAX,
- IR_CMP, /* = (op0 < 0) ? op1 : op2 */
- IR_SEQUAL, /* Set if args are equal (vector) */
- IR_SNEQUAL, /* Set if args are not equal (vector) */
- IR_SGE, /* Set if greater or equal (vector) */
- IR_SGT, /* Set if greater than (vector) */
- IR_SLE, /* Set if less or equal (vector) */
- IR_SLT, /* Set if less than (vector) */
- IR_POW, /* x^y */
- IR_EXP, /* e^x */
- IR_EXP2, /* 2^x */
- IR_LOG2, /* log base 2 */
- IR_RSQ, /* 1/sqrt() */
- IR_RCP, /* reciprocol */
- IR_FLOOR,
- IR_FRAC,
- IR_ABS, /* absolute value */
- IR_NEG, /* negate */
- IR_DDX, /* derivative w.r.t. X */
- IR_DDY, /* derivative w.r.t. Y */
- IR_SIN, /* sine */
- IR_COS, /* cosine */
- IR_NOISE1, /* noise(x) */
- IR_NOISE2, /* noise(x, y) */
- IR_NOISE3, /* noise(x, y, z) */
- IR_NOISE4, /* noise(x, y, z, w) */
-
- IR_EQUAL, /* boolean equality */
- IR_NOTEQUAL,/* boolean inequality */
- IR_NOT, /* boolean not */
-
- IR_VAR, /* variable reference */
- IR_VAR_DECL,/* var declaration */
-
- IR_ELEMENT, /* array element */
- IR_FIELD, /* struct field */
- IR_SWIZZLE, /* swizzled storage access */
-
- IR_TEX, /* texture lookup */
- IR_TEXB, /* texture lookup with LOD bias */
- IR_TEXP, /* texture lookup with projection */
-
- IR_TEX_SH, /* texture lookup, shadow compare */
- IR_TEXB_SH, /* texture lookup with LOD bias, shadow compare */
- IR_TEXP_SH, /* texture lookup with projection, shadow compare */
-
- IR_FLOAT,
- IR_I_TO_F, /* int[4] to float[4] conversion */
- IR_F_TO_I, /* float[4] to int[4] conversion */
-
- IR_KILL, /* fragment kill/discard */
-
- IR_EMIT_VERTEX, /* geometry shader: emit vertex */
- IR_END_PRIMITIVE /* geometry shader: end primitive */
-} slang_ir_opcode;
-
-
-/**
- * Describes where data/variables are stored in the various register files.
- *
- * In the simple case, the File, Index and Size fields indicate where
- * a variable is stored. For example, a vec3 variable may be stored
- * as (File=PROGRAM_TEMPORARY, Index=6, Size=3). Or, File[Index].
- * Or, a program input like color may be stored as
- * (File=PROGRAM_INPUT,Index=3,Size=4);
- *
- * For single-float values, the Swizzle field indicates which component
- * of the vector contains the float.
- *
- * If IsIndirect is set, the storage is accessed through an indirect
- * register lookup. The value in question will be located at:
- * File[Index + IndirectFile[IndirectIndex]]
- *
- * This is primary used for indexing arrays. For example, consider this
- * GLSL code:
- * uniform int i;
- * float a[10];
- * float x = a[i];
- *
- * here, storage for a[i] would be described by (File=PROGRAM_TEMPORAY,
- * Index=aPos, IndirectFile=PROGRAM_UNIFORM, IndirectIndex=iPos), which
- * would mean TEMP[aPos + UNIFORM[iPos]]
- */
-struct slang_ir_storage_
-{
- gl_register_file File; /**< PROGRAM_TEMPORARY, PROGRAM_INPUT, etc */
- GLint Index; /**< -1 means unallocated */
- GLint Size; /**< number of floats or ints */
- GLuint Swizzle; /**< Swizzle AND writemask info */
- GLint RefCount; /**< Used during IR tree delete */
-
- GLboolean RelAddr; /* we'll remove this eventually */
-
- GLboolean IsIndirect;
- gl_register_file IndirectFile;
- GLint IndirectIndex;
- GLuint IndirectSwizzle;
- GLuint TexTarget; /**< If File==PROGRAM_SAMPLER, one of TEXTURE_x_INDEX */
-
- /* Is the register two-dimensional and
- * if so what's the second index */
- GLboolean Is2D;
- GLint Index2;
-
- /** If Parent is non-null, Index is relative to parent.
- * The other fields are ignored.
- */
- struct slang_ir_storage_ *Parent;
-};
-
-typedef struct slang_ir_storage_ slang_ir_storage;
-
-
-/**
- * Intermediate Representation (IR) tree node
- * Basically a binary tree, but IR_LRP and IR_CLAMP have three children.
- */
-typedef struct slang_ir_node_
-{
- slang_ir_opcode Opcode;
- struct slang_ir_node_ *Children[3];
- slang_ir_storage *Store; /**< location of result of this operation */
- GLint InstLocation; /**< Location of instruction emitted for this node */
-
- /** special fields depending on Opcode: */
- const char *Field; /**< If Opcode == IR_FIELD */
- GLfloat Value[4]; /**< If Opcode == IR_FLOAT */
- slang_variable *Var; /**< If Opcode == IR_VAR or IR_VAR_DECL */
- struct slang_ir_node_ *List; /**< For various linked lists */
- struct slang_ir_node_ *Parent; /**< Pointer to logical parent (ie. loop) */
- slang_label *Label; /**< Used for branches */
- const char *Comment; /**< If Opcode == IR_COMMENT */
-} slang_ir_node;
-
-
-
-/**
- * Assembly and IR info
- */
-typedef struct
-{
- slang_ir_opcode IrOpcode;
- const char *IrName;
- gl_inst_opcode InstOpcode;
- GLuint ResultSize, NumParams;
-} slang_ir_info;
-
-
-
-extern const slang_ir_info *
-_slang_ir_info(slang_ir_opcode opcode);
-
-
-extern void
-_slang_init_ir_storage(slang_ir_storage *st,
- gl_register_file file, GLint index, GLint size,
- GLuint swizzle);
-
-extern slang_ir_storage *
-_slang_new_ir_storage(gl_register_file file, GLint index, GLint size);
-
-
-extern slang_ir_storage *
-_slang_new_ir_storage_swz(gl_register_file file, GLint index, GLint size,
- GLuint swizzle);
-
-extern slang_ir_storage *
-_slang_new_ir_storage_2d(gl_register_file file, GLint index, GLint index2d,
- GLint size, GLuint swizzle);
-
-extern slang_ir_storage *
-_slang_new_ir_storage_relative(GLint index, GLint size,
- slang_ir_storage *parent);
-
-
-extern slang_ir_storage *
-_slang_new_ir_storage_indirect(gl_register_file file,
- GLint index,
- GLint size,
- gl_register_file indirectFile,
- GLint indirectIndex,
- GLuint indirectSwizzle);
-
-extern slang_ir_storage *
-_slang_new_ir_storage_sampler(GLint sampNum, GLuint texTarget, GLint size);
-
-
-extern void
-_slang_copy_ir_storage(slang_ir_storage *dst, const slang_ir_storage *src);
-
-
-extern void
-_slang_free_ir_tree(slang_ir_node *n);
-
-
-extern void
-_slang_print_ir_tree(const slang_ir_node *n, int indent);
-
-
-#endif /* SLANG_IR_H */
+++ /dev/null
-
-
-/**
- * Functions for managing instruction labels.
- * Basically, this is used to manage the problem of forward branches where
- * we have a branch instruciton but don't know the target address yet.
- */
-
-
-#include "main/imports.h"
-#include "main/mtypes.h"
-#include "program/prog_instruction.h"
-#include "slang_label.h"
-#include "slang_mem.h"
-
-
-
-slang_label *
-_slang_label_new(const char *name)
-{
- slang_label *l = (slang_label *) _slang_alloc(sizeof(slang_label));
- if (l) {
- l->Name = _slang_strdup(name);
- l->Location = -1;
- }
- return l;
-}
-
-/**
- * As above, but suffix the name with a unique number.
- */
-slang_label *
-_slang_label_new_unique(const char *name)
-{
- static int id = 1;
- slang_label *l = (slang_label *) _slang_alloc(sizeof(slang_label));
- if (l) {
- l->Name = (char *) _slang_alloc(strlen(name) + 10);
- if (!l->Name) {
- free(l);
- return NULL;
- }
- _mesa_snprintf(l->Name, strlen(name) + 10, "%s_%d", name, id);
- id++;
- l->Location = -1;
- }
- return l;
-}
-
-void
-_slang_label_delete(slang_label *l)
-{
- if (l->Name) {
- _slang_free(l->Name);
- l->Name = NULL;
- }
- if (l->References) {
- _slang_free(l->References);
- l->References = NULL;
- }
- _slang_free(l);
-}
-
-
-void
-_slang_label_add_reference(slang_label *l, GLuint inst)
-{
- const GLuint oldSize = l->NumReferences * sizeof(GLuint);
- assert(l->Location < 0);
- l->References = _slang_realloc(l->References,
- oldSize, oldSize + sizeof(GLuint));
- if (l->References) {
- l->References[l->NumReferences] = inst;
- l->NumReferences++;
- }
-}
-
-
-GLint
-_slang_label_get_location(const slang_label *l)
-{
- return l->Location;
-}
-
-
-void
-_slang_label_set_location(slang_label *l, GLint location,
- struct gl_program *prog)
-{
- GLuint i;
-
- assert(l->Location < 0);
- assert(location >= 0);
-
- l->Location = location;
-
- /* for the instructions that were waiting to learn the label's location: */
- for (i = 0; i < l->NumReferences; i++) {
- const GLuint j = l->References[i];
- prog->Instructions[j].BranchTarget = location;
- }
-
- if (l->References) {
- _slang_free(l->References);
- l->References = NULL;
- }
-}
+++ /dev/null
-#ifndef SLANG_LABEL_H
-#define SLANG_LABEL_H 1
-
-#include "main/glheader.h"
-
-struct gl_program;
-
-struct slang_label_
-{
- char *Name;
- GLint Location;
- /**
- * List of instruction references (numbered starting at zero) which need
- * their BranchTarget field filled in with the location eventually
- * assigned to the label.
- */
- GLuint NumReferences;
- GLuint *References; /** Array [NumReferences] */
-};
-
-typedef struct slang_label_ slang_label;
-
-
-extern slang_label *
-_slang_label_new(const char *name);
-
-extern slang_label *
-_slang_label_new_unique(const char *name);
-
-extern void
-_slang_label_delete(slang_label *l);
-
-extern void
-_slang_label_add_reference(slang_label *l, GLuint inst);
-
-extern GLint
-_slang_label_get_location(const slang_label *l);
-
-extern void
-_slang_label_set_location(slang_label *l, GLint location,
- struct gl_program *prog);
-
-
-#endif /* SLANG_LABEL_H */
+++ /dev/null
-/*
- * Mesa 3-D graphics library
- * Version: 7.3
- *
- * Copyright (C) 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 slang_link.c
- * GLSL linker
- * \author Brian Paul
- */
-
-#include "main/imports.h"
-#include "main/context.h"
-#include "main/macros.h"
-#include "main/shaderapi.h"
-#include "main/shaderobj.h"
-#include "main/uniforms.h"
-#include "program/program.h"
-#include "program/prog_instruction.h"
-#include "program/prog_parameter.h"
-#include "program/prog_print.h"
-#include "program/prog_statevars.h"
-#include "program/prog_uniform.h"
-#include "slang_builtin.h"
-#include "slang_compile.h"
-#include "slang_link.h"
-
-
-/** cast wrapper */
-static struct gl_vertex_program *
-vertex_program(struct gl_program *prog)
-{
- assert(prog->Target == GL_VERTEX_PROGRAM_ARB);
- return (struct gl_vertex_program *) prog;
-}
-
-
-/** cast wrapper */
-static struct gl_fragment_program *
-fragment_program(struct gl_program *prog)
-{
- assert(prog->Target == GL_FRAGMENT_PROGRAM_ARB);
- return (struct gl_fragment_program *) prog;
-}
-
-static struct gl_geometry_program *
-geometry_program(struct gl_program *prog)
-{
- assert(prog->Target == MESA_GEOMETRY_PROGRAM);
- return (struct gl_geometry_program *)prog;
-}
-
-/**
- * Record a linking error.
- */
-static void
-link_error(struct gl_shader_program *shProg, const char *msg)
-{
- if (shProg->InfoLog) {
- free(shProg->InfoLog);
- }
- shProg->InfoLog = _mesa_strdup(msg);
- shProg->LinkStatus = GL_FALSE;
-}
-
-
-
-/**
- * Check if the given bit is either set or clear in both bitfields.
- */
-static GLboolean
-bits_agree(GLbitfield flags1, GLbitfield flags2, GLbitfield bit)
-{
- return (flags1 & bit) == (flags2 & bit);
-}
-
-
-/**
- * Examine the outputs/varyings written by the vertex shader and
- * append the names of those outputs onto the Varyings list.
- * This will only capture the pre-defined/built-in varyings like
- * gl_Position, not user-defined varyings.
- */
-static void
-update_varying_var_list(GLcontext *ctx, struct gl_shader_program *shProg)
-{
- if (shProg->VertexProgram) {
- GLbitfield64 written = shProg->VertexProgram->Base.OutputsWritten;
- GLuint i;
- for (i = 0; written && i < VERT_RESULT_MAX; i++) {
- if (written & BITFIELD64_BIT(i)) {
- const char *name = _slang_vertex_output_name(i);
- if (name)
- _mesa_add_varying(shProg->Varying, name, 1, GL_FLOAT_VEC4, 0x0);
- written &= ~BITFIELD64_BIT(i);
- }
- }
- }
- if (shProg->GeometryProgram) {
- GLbitfield64 written = shProg->GeometryProgram->Base.OutputsWritten;
- GLuint i;
- for (i = 0; written && i < GEOM_RESULT_MAX; i++) {
- if (written & BITFIELD64_BIT(i)) {
- const char *name = _slang_geometry_output_name(i);
- if (name)
- _mesa_add_varying(shProg->Varying, name, 1, GL_FLOAT_VEC4, 0x0);
- written &= ~BITFIELD64_BIT(i);
- }
- }
- }
-}
-
-
-/**
- * Do link error checking related to transform feedback.
- */
-static GLboolean
-link_transform_feedback(GLcontext *ctx, struct gl_shader_program *shProg)
-{
- GLbitfield varyingMask;
- GLuint totalComps, maxComps, i;
-
- if (shProg->TransformFeedback.NumVarying == 0) {
- /* nothing to do */
- return GL_TRUE;
- }
-
- /* Check that there's a vertex shader */
- if (shProg->TransformFeedback.NumVarying > 0 &&
- !shProg->VertexProgram) {
- link_error(shProg, "Transform feedback without vertex shader");
- return GL_FALSE;
- }
-
- /* Check that all named variables exist, and that none are duplicated.
- * Also, build a count of the number of varying components to feedback.
- */
- totalComps = 0;
- varyingMask = 0x0;
- for (i = 0; i < shProg->TransformFeedback.NumVarying; i++) {
- const GLchar *name = shProg->TransformFeedback.VaryingNames[i];
- GLint v = _mesa_lookup_parameter_index(shProg->Varying, -1, name);
- struct gl_program_parameter *p;
-
- if (v < 0) {
- char msg[100];
- _mesa_snprintf(msg, sizeof(msg),
- "vertex shader does not emit %s", name);
- link_error(shProg, msg);
- return GL_FALSE;
- }
-
- assert(v < MAX_VARYING);
-
- /* already seen this varying name? */
- if (varyingMask & (1 << v)) {
- char msg[100];
- _mesa_snprintf(msg, sizeof(msg),
- "duplicated transform feedback varying name: %s",
- name);
- link_error(shProg, msg);
- return GL_FALSE;
- }
-
- varyingMask |= (1 << v);
-
- p = &shProg->Varying->Parameters[v];
-
- totalComps += _mesa_sizeof_glsl_type(p->DataType);
- }
-
- if (shProg->TransformFeedback.BufferMode == GL_INTERLEAVED_ATTRIBS)
- maxComps = ctx->Const.MaxTransformFeedbackInterleavedComponents;
- else
- maxComps = ctx->Const.MaxTransformFeedbackSeparateComponents;
-
- /* check max varying components against the limit */
- if (totalComps > maxComps) {
- char msg[100];
- _mesa_snprintf(msg, sizeof(msg),
- "Too many feedback components: %u, max is %u",
- totalComps, maxComps);
- link_error(shProg, msg);
- return GL_FALSE;
- }
-
- return GL_TRUE;
-}
-
-
-/**
- * Linking varying vars involves rearranging varying vars so that the
- * vertex program's output varyings matches the order of the fragment
- * program's input varyings.
- * We'll then rewrite instructions to replace PROGRAM_VARYING with either
- * PROGRAM_INPUT or PROGRAM_OUTPUT depending on whether it's a vertex or
- * fragment shader.
- * This is also where we set program Input/OutputFlags to indicate
- * which inputs are centroid-sampled, invariant, etc.
- */
-static GLboolean
-link_varying_vars(GLcontext *ctx,
- struct gl_shader_program *shProg, struct gl_program *prog)
-{
- GLuint *map, i, firstSrcVarying, firstDstVarying, newSrcFile, newDstFile;
- GLbitfield *inOutFlags = NULL;
-
- map = (GLuint *) malloc(prog->Varying->NumParameters * sizeof(GLuint));
- if (!map)
- return GL_FALSE;
-
- /* Varying variables are treated like other vertex program outputs
- * (and like other fragment program inputs). The position of the
- * first varying differs for vertex/fragment programs...
- * Also, replace File=PROGRAM_VARYING with File=PROGRAM_INPUT/OUTPUT.
- */
- if (prog->Target == GL_VERTEX_PROGRAM_ARB) {
- firstSrcVarying = firstDstVarying = VERT_RESULT_VAR0;
- newSrcFile = newDstFile = PROGRAM_OUTPUT;
- inOutFlags = prog->OutputFlags;
- }
- else if (prog->Target == MESA_GEOMETRY_PROGRAM) {
- firstSrcVarying = GEOM_ATTRIB_VAR0;
- newSrcFile = PROGRAM_INPUT;
- firstDstVarying = GEOM_RESULT_VAR0;
- newDstFile = PROGRAM_OUTPUT;
- }
- else {
- assert(prog->Target == GL_FRAGMENT_PROGRAM_ARB);
- firstSrcVarying = firstDstVarying = FRAG_ATTRIB_VAR0;
- newSrcFile = newDstFile = PROGRAM_INPUT;
- inOutFlags = prog->InputFlags;
- }
-
- for (i = 0; i < prog->Varying->NumParameters; i++) {
- /* see if this varying is in the linked varying list */
- const struct gl_program_parameter *var = prog->Varying->Parameters + i;
- GLint j = _mesa_lookup_parameter_index(shProg->Varying, -1, var->Name);
- if (j >= 0) {
- /* varying is already in list, do some error checking */
- const struct gl_program_parameter *v =
- &shProg->Varying->Parameters[j];
- if (var->Size != v->Size) {
- link_error(shProg, "mismatched varying variable types");
- free(map);
- return GL_FALSE;
- }
- if (!bits_agree(var->Flags, v->Flags, PROG_PARAM_BIT_CENTROID)) {
- char msg[100];
- _mesa_snprintf(msg, sizeof(msg),
- "centroid modifier mismatch for '%s'", var->Name);
- link_error(shProg, msg);
- free(map);
- return GL_FALSE;
- }
- if (!bits_agree(var->Flags, v->Flags, PROG_PARAM_BIT_INVARIANT)) {
- char msg[100];
- _mesa_snprintf(msg, sizeof(msg),
- "invariant modifier mismatch for '%s'", var->Name);
- link_error(shProg, msg);
- free(map);
- return GL_FALSE;
- }
- }
- else {
- /* not already in linked list */
- j = _mesa_add_varying(shProg->Varying, var->Name, var->Size,
- var->DataType, var->Flags);
- }
-
- if (shProg->Varying->NumParameters > ctx->Const.MaxVarying) {
- link_error(shProg, "Too many varying variables");
- free(map);
- return GL_FALSE;
- }
-
- /* Map varying[i] to varying[j].
- * Note: the loop here takes care of arrays or large (sz>4) vars.
- */
- {
- GLint sz = var->Size;
- while (sz > 0) {
- inOutFlags[firstDstVarying + j] = var->Flags;
- /*printf("Link varying from %d to %d\n", i, j);*/
- map[i++] = j++;
- sz -= 4;
- }
- i--; /* go back one */
- }
- }
-
-
- /* OK, now scan the program/shader instructions looking for varying vars,
- * replacing the old index with the new index.
- */
- for (i = 0; i < prog->NumInstructions; i++) {
- struct prog_instruction *inst = prog->Instructions + i;
- GLuint j;
-
- if (inst->DstReg.File == PROGRAM_VARYING) {
- inst->DstReg.File = newDstFile;
- inst->DstReg.Index = map[ inst->DstReg.Index ] + firstDstVarying;
- }
-
- for (j = 0; j < 3; j++) {
- if (inst->SrcReg[j].File == PROGRAM_VARYING) {
- inst->SrcReg[j].File = newSrcFile;
- inst->SrcReg[j].Index = map[ inst->SrcReg[j].Index ] + firstSrcVarying;
- }
- }
- }
-
- free(map);
-
- /* these will get recomputed before linking is completed */
- prog->InputsRead = 0x0;
- prog->OutputsWritten = 0x0;
-
- return GL_TRUE;
-}
-
-
-/**
- * Build the shProg->Uniforms list.
- * This is basically a list/index of all uniforms found in either/both of
- * the vertex and fragment shaders.
- *
- * About uniforms:
- * Each uniform has two indexes, one that points into the vertex
- * program's parameter array and another that points into the fragment
- * program's parameter array. When the user changes a uniform's value
- * we have to change the value in the vertex and/or fragment program's
- * parameter array.
- *
- * This function will be called twice to set up the two uniform->parameter
- * mappings.
- *
- * If a uniform is only present in the vertex program OR fragment program
- * then the fragment/vertex parameter index, respectively, will be -1.
- */
-static GLboolean
-link_uniform_vars(GLcontext *ctx,
- struct gl_shader_program *shProg,
- struct gl_program *prog,
- GLuint *numSamplers)
-{
- GLuint samplerMap[200]; /* max number of samplers declared, not used */
- GLuint i;
-
- for (i = 0; i < prog->Parameters->NumParameters; i++) {
- const struct gl_program_parameter *p = prog->Parameters->Parameters + i;
-
- /*
- * XXX FIX NEEDED HERE
- * We should also be adding a uniform if p->Type == PROGRAM_STATE_VAR.
- * For example, modelview matrix, light pos, etc.
- * Also, we need to update the state-var name-generator code to
- * generate GLSL-style names, like "gl_LightSource[0].position".
- * Furthermore, we'll need to fix the state-var's size/datatype info.
- */
-
- if ((p->Type == PROGRAM_UNIFORM || p->Type == PROGRAM_SAMPLER)
- && p->Used) {
- /* add this uniform, indexing into the target's Parameters list */
- struct gl_uniform *uniform =
- _mesa_append_uniform(shProg->Uniforms, p->Name, prog->Target, i);
- if (uniform)
- uniform->Initialized = p->Initialized;
- }
-
- /* The samplerMap[] table we build here is used to remap/re-index
- * sampler references by TEX instructions.
- */
- if (p->Type == PROGRAM_SAMPLER && p->Used) {
- /* Allocate a new sampler index */
- GLuint oldSampNum = (GLuint) prog->Parameters->ParameterValues[i][0];
- GLuint newSampNum = *numSamplers;
- if (newSampNum >= ctx->Const.MaxTextureImageUnits) {
- char s[100];
- _mesa_snprintf(s, sizeof(s),
- "Too many texture samplers (%u, max is %u)",
- newSampNum, ctx->Const.MaxTextureImageUnits);
- link_error(shProg, s);
- return GL_FALSE;
- }
- /* save old->new mapping in the table */
- if (oldSampNum < Elements(samplerMap))
- samplerMap[oldSampNum] = newSampNum;
- /* update parameter's sampler index */
- prog->Parameters->ParameterValues[i][0] = (GLfloat) newSampNum;
- (*numSamplers)++;
- }
- }
-
- /* OK, now scan the program/shader instructions looking for texture
- * instructions using sampler vars. Replace old sampler indexes with
- * new ones.
- */
- prog->SamplersUsed = 0x0;
- for (i = 0; i < prog->NumInstructions; i++) {
- struct prog_instruction *inst = prog->Instructions + i;
- if (_mesa_is_tex_instruction(inst->Opcode)) {
- /* here, inst->TexSrcUnit is really the sampler unit */
- const GLint oldSampNum = inst->TexSrcUnit;
-
-#if 0
- printf("====== remap sampler from %d to %d\n",
- inst->TexSrcUnit, samplerMap[ inst->TexSrcUnit ]);
-#endif
-
- if (oldSampNum < Elements(samplerMap)) {
- const GLuint newSampNum = samplerMap[oldSampNum];
- inst->TexSrcUnit = newSampNum;
- prog->SamplerTargets[newSampNum] = inst->TexSrcTarget;
- prog->SamplersUsed |= (1 << newSampNum);
- if (inst->TexShadow) {
- prog->ShadowSamplers |= (1 << newSampNum);
- }
- }
- }
- }
-
- return GL_TRUE;
-}
-
-
-/**
- * Resolve binding of generic vertex attributes.
- * For example, if the vertex shader declared "attribute vec4 foobar" we'll
- * allocate a generic vertex attribute for "foobar" and plug that value into
- * the vertex program instructions.
- * But if the user called glBindAttributeLocation(), those bindings will
- * have priority.
- */
-static GLboolean
-_slang_resolve_attributes(struct gl_shader_program *shProg,
- const struct gl_program *origProg,
- struct gl_program *linkedProg)
-{
- GLint attribMap[MAX_VERTEX_GENERIC_ATTRIBS];
- GLuint i, j;
- GLbitfield usedAttributes; /* generics only, not legacy attributes */
- GLbitfield inputsRead = 0x0;
-
- assert(origProg != linkedProg);
- assert(origProg->Target == GL_VERTEX_PROGRAM_ARB);
- assert(linkedProg->Target == GL_VERTEX_PROGRAM_ARB);
-
- if (!shProg->Attributes)
- shProg->Attributes = _mesa_new_parameter_list();
-
- if (linkedProg->Attributes) {
- _mesa_free_parameter_list(linkedProg->Attributes);
- }
- linkedProg->Attributes = _mesa_new_parameter_list();
-
-
- /* Build a bitmask indicating which attribute indexes have been
- * explicitly bound by the user with glBindAttributeLocation().
- */
- usedAttributes = 0x0;
- for (i = 0; i < shProg->Attributes->NumParameters; i++) {
- GLint attr = shProg->Attributes->Parameters[i].StateIndexes[0];
- usedAttributes |= (1 << attr);
- }
-
- /* If gl_Vertex is used, that actually counts against the limit
- * on generic vertex attributes. This avoids the ambiguity of
- * whether glVertexAttrib4fv(0, v) sets legacy attribute 0 (vert pos)
- * or generic attribute[0]. If gl_Vertex is used, we want the former.
- */
- if (origProg->InputsRead & VERT_BIT_POS) {
- usedAttributes |= 0x1;
- }
-
- /* initialize the generic attribute map entries to -1 */
- for (i = 0; i < MAX_VERTEX_GENERIC_ATTRIBS; i++) {
- attribMap[i] = -1;
- }
-
- /*
- * Scan program for generic attribute references
- */
- for (i = 0; i < linkedProg->NumInstructions; i++) {
- struct prog_instruction *inst = linkedProg->Instructions + i;
- for (j = 0; j < 3; j++) {
- if (inst->SrcReg[j].File == PROGRAM_INPUT) {
- inputsRead |= (1 << inst->SrcReg[j].Index);
- }
-
- if (inst->SrcReg[j].File == PROGRAM_INPUT &&
- inst->SrcReg[j].Index >= VERT_ATTRIB_GENERIC0) {
- /*
- * OK, we've found a generic vertex attribute reference.
- */
- const GLint k = inst->SrcReg[j].Index - VERT_ATTRIB_GENERIC0;
-
- GLint attr = attribMap[k];
-
- if (attr < 0) {
- /* Need to figure out attribute mapping now.
- */
- const char *name = origProg->Attributes->Parameters[k].Name;
- const GLint size = origProg->Attributes->Parameters[k].Size;
- const GLenum type =origProg->Attributes->Parameters[k].DataType;
- GLint index;
-
- /* See if there's a user-defined attribute binding for
- * this name.
- */
- index = _mesa_lookup_parameter_index(shProg->Attributes,
- -1, name);
- if (index >= 0) {
- /* Found a user-defined binding */
- attr = shProg->Attributes->Parameters[index].StateIndexes[0];
- }
- else {
- /* No user-defined binding, choose our own attribute number.
- * Start at 1 since generic attribute 0 always aliases
- * glVertex/position.
- */
- for (attr = 0; attr < MAX_VERTEX_GENERIC_ATTRIBS; attr++) {
- if (((1 << attr) & usedAttributes) == 0)
- break;
- }
- if (attr == MAX_VERTEX_GENERIC_ATTRIBS) {
- link_error(shProg, "Too many vertex attributes");
- return GL_FALSE;
- }
-
- /* mark this attribute as used */
- usedAttributes |= (1 << attr);
- }
-
- attribMap[k] = attr;
-
- /* Save the final name->attrib binding so it can be queried
- * with glGetAttributeLocation().
- */
- _mesa_add_attribute(linkedProg->Attributes, name,
- size, type, attr);
- }
-
- assert(attr >= 0);
-
- /* update the instruction's src reg */
- inst->SrcReg[j].Index = VERT_ATTRIB_GENERIC0 + attr;
- }
- }
- }
-
- /* Handle pre-defined attributes here (gl_Vertex, gl_Normal, etc).
- * When the user queries the active attributes we need to include both
- * the user-defined attributes and the built-in ones.
- */
- for (i = VERT_ATTRIB_POS; i < VERT_ATTRIB_GENERIC0; i++) {
- if (inputsRead & (1 << i)) {
- _mesa_add_attribute(linkedProg->Attributes,
- _slang_vert_attrib_name(i),
- 4, /* size in floats */
- _slang_vert_attrib_type(i),
- -1 /* attrib/input */);
- }
- }
-
- return GL_TRUE;
-}
-
-
-/**
- * Scan program instructions to update the program's NumTemporaries field.
- * Note: this implemenation relies on the code generator allocating
- * temps in increasing order (0, 1, 2, ... ).
- */
-static void
-_slang_count_temporaries(struct gl_program *prog)
-{
- GLuint i, j;
- GLint maxIndex = -1;
-
- for (i = 0; i < prog->NumInstructions; i++) {
- const struct prog_instruction *inst = prog->Instructions + i;
- const GLuint numSrc = _mesa_num_inst_src_regs(inst->Opcode);
- for (j = 0; j < numSrc; j++) {
- if (inst->SrcReg[j].File == PROGRAM_TEMPORARY) {
- if (maxIndex < inst->SrcReg[j].Index)
- maxIndex = inst->SrcReg[j].Index;
- }
- if (inst->DstReg.File == PROGRAM_TEMPORARY) {
- if (maxIndex < (GLint) inst->DstReg.Index)
- maxIndex = inst->DstReg.Index;
- }
- }
- }
-
- prog->NumTemporaries = (GLuint) (maxIndex + 1);
-}
-
-
-/**
- * If an input attribute is indexed with relative addressing we have
- * to compute a gl_program::InputsRead bitmask which reflects the fact
- * that any input may be referenced by array element. Ex: gl_TexCoord[i].
- * This function computes the bitmask of potentially read inputs.
- */
-static GLbitfield
-get_inputs_read_mask(GLenum target, GLuint index, GLboolean relAddr)
-{
- GLbitfield mask;
-
- mask = 1 << index;
-
- if (relAddr) {
- if (target == GL_VERTEX_PROGRAM_ARB) {
- switch (index) {
- case VERT_ATTRIB_TEX0:
- mask = ((1U << (VERT_ATTRIB_TEX7 + 1)) - 1)
- - ((1U << VERT_ATTRIB_TEX0) - 1);
- break;
- case VERT_ATTRIB_GENERIC0:
- /* different code to avoid uint overflow */
- mask = ~0x0U - ((1U << VERT_ATTRIB_GENERIC0) - 1);
- break;
- default:
- ; /* a non-array input attribute */
- }
- }
- else if (target == GL_FRAGMENT_PROGRAM_ARB) {
- switch (index) {
- case FRAG_ATTRIB_TEX0:
- mask = ((1U << (FRAG_ATTRIB_TEX7 + 1)) - 1)
- - ((1U << FRAG_ATTRIB_TEX0) - 1);
- break;
- case FRAG_ATTRIB_VAR0:
- mask = ((1U << (FRAG_ATTRIB_VAR0 + MAX_VARYING)) - 1)
- - ((1U << FRAG_ATTRIB_VAR0) - 1);
- break;
- default:
- ; /* a non-array input attribute */
- }
- }
- else if (target == MESA_GEOMETRY_PROGRAM) {
- switch (index) {
- case GEOM_ATTRIB_VAR0:
- mask = ((1ULL << (GEOM_ATTRIB_VAR0 + MAX_VARYING)) - 1)
- - ((1ULL << GEOM_ATTRIB_VAR0) - 1);
- break;
- default:
- ; /* a non-array input attribute */
- }
- }
- else {
- assert(0 && "bad program target");
- }
- }
- else {
- }
-
- return mask;
-}
-
-
-/**
- * If an output attribute is indexed with relative addressing we have
- * to compute a gl_program::OutputsWritten bitmask which reflects the fact
- * that any output may be referenced by array element. Ex: gl_TexCoord[i].
- * This function computes the bitmask of potentially written outputs.
- */
-static GLbitfield64
-get_outputs_written_mask(GLenum target, GLuint index, GLboolean relAddr)
-{
- GLbitfield64 mask;
-
- mask = BITFIELD64_BIT(index);
-
- if (relAddr) {
- if (target == GL_VERTEX_PROGRAM_ARB) {
- switch (index) {
- case VERT_RESULT_TEX0:
- mask = BITFIELD64_RANGE(VERT_RESULT_TEX0,
- (VERT_RESULT_TEX0
- + MAX_TEXTURE_COORD_UNITS - 1));
- break;
- case VERT_RESULT_VAR0:
- mask = BITFIELD64_RANGE(VERT_RESULT_VAR0,
- (VERT_RESULT_VAR0 + MAX_VARYING - 1));
- break;
- default:
- ; /* a non-array output attribute */
- }
- }
- else if (target == GL_FRAGMENT_PROGRAM_ARB) {
- switch (index) {
- case FRAG_RESULT_DATA0:
- mask = BITFIELD64_RANGE(FRAG_RESULT_DATA0,
- (FRAG_RESULT_DATA0
- + MAX_DRAW_BUFFERS - 1));
- break;
- default:
- ; /* a non-array output attribute */
- }
- }
- else if (target == MESA_GEOMETRY_PROGRAM) {
- switch (index) {
- case GEOM_RESULT_TEX0:
- mask = BITFIELD64_RANGE(GEOM_RESULT_TEX0,
- (GEOM_RESULT_TEX0
- + MAX_TEXTURE_COORD_UNITS - 1));
- break;
- case GEOM_RESULT_VAR0:
- mask = BITFIELD64_RANGE(GEOM_RESULT_VAR0,
- (GEOM_RESULT_VAR0 + MAX_VARYING - 1));
- break;
- default:
- ; /* a non-array output attribute */
- }
- }
- else {
- assert(0 && "bad program target");
- }
- }
-
- return mask;
-}
-
-
-/**
- * Scan program instructions to update the program's InputsRead and
- * OutputsWritten fields.
- */
-static void
-_slang_update_inputs_outputs(struct gl_program *prog)
-{
- GLuint i, j;
- GLuint maxAddrReg = 0;
-
- prog->InputsRead = 0x0;
- prog->OutputsWritten = 0x0;
-
- prog->IndirectRegisterFiles = 0x0;
-
- for (i = 0; i < prog->NumInstructions; i++) {
- const struct prog_instruction *inst = prog->Instructions + i;
- const GLuint numSrc = _mesa_num_inst_src_regs(inst->Opcode);
- for (j = 0; j < numSrc; j++) {
- if (inst->SrcReg[j].File == PROGRAM_INPUT) {
- if (prog->Target == MESA_GEOMETRY_PROGRAM &&
- inst->SrcReg[j].HasIndex2)
- prog->InputsRead |= get_inputs_read_mask(prog->Target,
- inst->SrcReg[j].Index2,
- inst->SrcReg[j].RelAddr2);
- else
- prog->InputsRead |= get_inputs_read_mask(prog->Target,
- inst->SrcReg[j].Index,
- inst->SrcReg[j].RelAddr);
- }
- else if (inst->SrcReg[j].File == PROGRAM_ADDRESS) {
- maxAddrReg = MAX2(maxAddrReg, (GLuint) (inst->SrcReg[j].Index + 1));
- }
-
- if (inst->SrcReg[j].RelAddr)
- prog->IndirectRegisterFiles |= (1 << inst->SrcReg[j].File);
- }
-
- if (inst->DstReg.File == PROGRAM_OUTPUT) {
- prog->OutputsWritten |= get_outputs_written_mask(prog->Target,
- inst->DstReg.Index,
- inst->DstReg.RelAddr);
- }
- else if (inst->DstReg.File == PROGRAM_ADDRESS) {
- maxAddrReg = MAX2(maxAddrReg, inst->DstReg.Index + 1);
- }
- if (inst->DstReg.RelAddr)
- prog->IndirectRegisterFiles |= (1 << inst->DstReg.File);
- }
- prog->NumAddressRegs = maxAddrReg;
-}
-
-
-
-/**
- * Remove extra #version directives from the concatenated source string.
- * Disable the extra ones by converting first two chars to //, a comment.
- * This is a bit of hack to work around a preprocessor bug that only
- * allows one #version directive per source.
- */
-static void
-remove_extra_version_directives(GLchar *source)
-{
- GLuint verCount = 0;
- while (1) {
- char *ver = strstr(source, "#version");
- if (ver) {
- verCount++;
- if (verCount > 1) {
- ver[0] = '/';
- ver[1] = '/';
- }
- source += 8;
- }
- else {
- break;
- }
- }
-}
-
-/* Returns the number of vertices per geometry shader
- * input primitive.
- * XXX: duplicated in Gallium in u_vertices_per_prim
- * method. Once Mesa core will start using Gallium
- * this should be removed
- */
-static int
-vertices_per_prim(int prim)
-{
- switch (prim) {
- case GL_POINTS:
- return 1;
- case GL_LINES:
- return 2;
- case GL_TRIANGLES:
- return 3;
- case GL_LINES_ADJACENCY_ARB:
- return 4;
- case GL_TRIANGLES_ADJACENCY_ARB:
- return 6;
- default:
- ASSERT(!"Bad primitive");
- return 3;
- }
-}
-
-/**
- * Return a new shader whose source code is the concatenation of
- * all the shader sources of the given type.
- */
-static struct gl_shader *
-concat_shaders(struct gl_shader_program *shProg, GLenum shaderType)
-{
- struct gl_shader *newShader;
- const struct gl_shader *firstShader = NULL;
- GLuint *shaderLengths;
- GLchar *source;
- GLuint totalLen = 0, len = 0;
- GLuint i;
-
- shaderLengths = (GLuint *)malloc(shProg->NumShaders * sizeof(GLuint));
- if (!shaderLengths) {
- return NULL;
- }
-
- /* compute total size of new shader source code */
- for (i = 0; i < shProg->NumShaders; i++) {
- const struct gl_shader *shader = shProg->Shaders[i];
- if (shader->Type == shaderType) {
- shaderLengths[i] = strlen(shader->Source);
- totalLen += shaderLengths[i];
- if (!firstShader)
- firstShader = shader;
- }
- }
-
- if (totalLen == 0) {
- free(shaderLengths);
- return NULL;
- }
-
- /* Geometry shader will inject definition of
- * const int gl_VerticesIn */
- if (shaderType == GL_GEOMETRY_SHADER_ARB) {
- totalLen += 32;
- }
-
- source = (GLchar *) malloc(totalLen + 1);
- if (!source) {
- free(shaderLengths);
- return NULL;
- }
-
- /* concatenate shaders */
- for (i = 0; i < shProg->NumShaders; i++) {
- const struct gl_shader *shader = shProg->Shaders[i];
- if (shader->Type == shaderType) {
- memcpy(source + len, shader->Source, shaderLengths[i]);
- len += shaderLengths[i];
- }
- }
- /* if it's geometry shader we need to inject definition
- * of "const int gl_VerticesIn = X;" where X is the number
- * of vertices per input primitive
- */
- if (shaderType == GL_GEOMETRY_SHADER_ARB) {
- GLchar gs_pre[32];
- GLuint num_verts = vertices_per_prim(shProg->Geom.InputType);
- _mesa_snprintf(gs_pre, 31,
- "const int gl_VerticesIn = %d;\n", num_verts);
- memcpy(source + len, gs_pre, strlen(gs_pre));
- len += strlen(gs_pre);
- }
- source[len] = '\0';
- /*
- printf("---NEW CONCATENATED SHADER---:\n%s\n------------\n", source);
- */
-
- free(shaderLengths);
-
- remove_extra_version_directives(source);
-
- newShader = CALLOC_STRUCT(gl_shader);
- if (!newShader) {
- free(source);
- return NULL;
- }
-
- newShader->Type = shaderType;
- newShader->Source = source;
- newShader->Pragmas = firstShader->Pragmas;
-
- return newShader;
-}
-
-/**
- * Search the shader program's list of shaders to find the one that
- * defines main().
- * This will involve shader concatenation and recompilation if needed.
- */
-static struct gl_shader *
-get_main_shader(GLcontext *ctx,
- struct gl_shader_program *shProg, GLenum type)
-{
- struct gl_shader *shader = NULL;
- GLuint i;
-
- /*
- * Look for a shader that defines main() and has no unresolved references.
- */
- for (i = 0; i < shProg->NumShaders; i++) {
- shader = shProg->Shaders[i];
- if (shader->Type == type &&
- shader->Main &&
- !shader->UnresolvedRefs) {
- /* All set! */
- return shader;
- }
- }
-
- /*
- * There must have been unresolved references during the original
- * compilation. Try concatenating all the shaders of the given type
- * and recompile that.
- */
- shader = concat_shaders(shProg, type);
-
- if (shader) {
- _slang_compile(ctx, shader);
-
- /* Finally, check if recompiling failed */
- if (!shader->CompileStatus ||
- !shader->Main ||
- shader->UnresolvedRefs) {
- link_error(shProg, "Unresolved symbols");
- ctx->Driver.DeleteShader(ctx, shader);
- return NULL;
- }
- }
-
- return shader;
-}
-
-
-/**
- * Shader linker. Currently:
- *
- * 1. The last attached vertex shader and fragment shader are linked.
- * 2. Varying vars in the two shaders are combined so their locations
- * agree between the vertex and fragment stages. They're treated as
- * vertex program output attribs and as fragment program input attribs.
- * 3. The vertex and fragment programs are cloned and modified to update
- * src/dst register references so they use the new, linked varying
- * storage locations.
- */
-void
-_slang_link(GLcontext *ctx,
- GLhandleARB programObj,
- struct gl_shader_program *shProg)
-{
- const struct gl_vertex_program *vertProg = NULL;
- const struct gl_fragment_program *fragProg = NULL;
- const struct gl_geometry_program *geomProg = NULL;
- GLboolean vertNotify = GL_TRUE, fragNotify = GL_TRUE, geomNotify = GL_TRUE;
- GLuint numSamplers = 0;
- GLuint i;
-
- _mesa_clear_shader_program_data(ctx, shProg);
-
- /* Initialize LinkStatus to "success". Will be cleared if error. */
- shProg->LinkStatus = GL_TRUE;
-
- /* check that all programs compiled successfully */
- for (i = 0; i < shProg->NumShaders; i++) {
- if (!shProg->Shaders[i]->CompileStatus) {
- link_error(shProg, "linking with uncompiled shader\n");
- return;
- }
- }
-
- shProg->Uniforms = _mesa_new_uniform_list();
- shProg->Varying = _mesa_new_parameter_list();
-
- /*
- * Find the vertex and fragment shaders which define main()
- */
- {
- struct gl_shader *vertShader, *fragShader, *geomShader;
- vertShader = get_main_shader(ctx, shProg, GL_VERTEX_SHADER);
- geomShader = get_main_shader(ctx, shProg, GL_GEOMETRY_SHADER_ARB);
- fragShader = get_main_shader(ctx, shProg, GL_FRAGMENT_SHADER);
-
- if (vertShader)
- vertProg = vertex_program(vertShader->Program);
- if (geomShader)
- geomProg = geometry_program(geomShader->Program);
- if (fragShader)
- fragProg = fragment_program(fragShader->Program);
- if (!shProg->LinkStatus)
- return;
- }
-
-#if FEATURE_es2_glsl
- /* must have both a vertex and fragment program for ES2 */
- if (ctx->API == API_OPENGLES2) {
- if (!vertProg) {
- link_error(shProg, "missing vertex shader\n");
- return;
- }
- if (!fragProg) {
- link_error(shProg, "missing fragment shader\n");
- return;
- }
- }
-#endif
-
- /*
- * Make copies of the vertex/fragment programs now since we'll be
- * changing src/dst registers after merging the uniforms and varying vars.
- */
- _mesa_reference_vertprog(ctx, &shProg->VertexProgram, NULL);
- if (vertProg) {
- struct gl_vertex_program *linked_vprog =
- _mesa_clone_vertex_program(ctx, vertProg);
- shProg->VertexProgram = linked_vprog; /* refcount OK */
- /* vertex program ID not significant; just set Id for debugging purposes */
- shProg->VertexProgram->Base.Id = shProg->Name;
- ASSERT(shProg->VertexProgram->Base.RefCount == 1);
- }
- _mesa_reference_geomprog(ctx, &shProg->GeometryProgram, NULL);
- if (geomProg) {
- struct gl_geometry_program *linked_gprog =
- _mesa_clone_geometry_program(ctx, geomProg);
- shProg->GeometryProgram = linked_gprog; /* refcount OK */
- shProg->GeometryProgram->Base.Id = shProg->Name;
- ASSERT(shProg->GeometryProgram->Base.RefCount == 1);
- }
- _mesa_reference_fragprog(ctx, &shProg->FragmentProgram, NULL);
- if (fragProg) {
- struct gl_fragment_program *linked_fprog =
- _mesa_clone_fragment_program(ctx, fragProg);
- shProg->FragmentProgram = linked_fprog; /* refcount OK */
- /* vertex program ID not significant; just set Id for debugging purposes */
- shProg->FragmentProgram->Base.Id = shProg->Name;
- ASSERT(shProg->FragmentProgram->Base.RefCount == 1);
- }
-
- /* link varying vars */
- if (shProg->VertexProgram) {
- if (!link_varying_vars(ctx, shProg, &shProg->VertexProgram->Base))
- return;
- }
- if (shProg->GeometryProgram) {
- if (!link_varying_vars(ctx, shProg, &shProg->GeometryProgram->Base))
- return;
- }
- if (shProg->FragmentProgram) {
- if (!link_varying_vars(ctx, shProg, &shProg->FragmentProgram->Base))
- return;
- }
-
- /* link uniform vars */
- if (shProg->VertexProgram) {
- if (!link_uniform_vars(ctx, shProg, &shProg->VertexProgram->Base,
- &numSamplers)) {
- return;
- }
- }
- if (shProg->GeometryProgram) {
- if (!link_uniform_vars(ctx, shProg, &shProg->GeometryProgram->Base,
- &numSamplers)) {
- return;
- }
- }
- if (shProg->FragmentProgram) {
- if (!link_uniform_vars(ctx, shProg, &shProg->FragmentProgram->Base,
- &numSamplers)) {
- return;
- }
- }
-
- /*_mesa_print_uniforms(shProg->Uniforms);*/
-
- if (shProg->VertexProgram) {
- if (!_slang_resolve_attributes(shProg, &vertProg->Base,
- &shProg->VertexProgram->Base)) {
- return;
- }
- }
-
- if (shProg->VertexProgram) {
- _slang_update_inputs_outputs(&shProg->VertexProgram->Base);
- _slang_count_temporaries(&shProg->VertexProgram->Base);
- if (!(shProg->VertexProgram->Base.OutputsWritten
- & BITFIELD64_BIT(VERT_RESULT_HPOS))) {
- /* the vertex program did not compute a vertex position */
- link_error(shProg,
- "gl_Position was not written by vertex shader\n");
- return;
- }
- }
- if (shProg->GeometryProgram) {
- if (!shProg->VertexProgram) {
- link_error(shProg,
- "Geometry shader without a vertex shader is illegal!\n");
- return;
- }
- if (shProg->Geom.VerticesOut == 0) {
- link_error(shProg,
- "GEOMETRY_VERTICES_OUT is zero\n");
- return;
- }
-
- _slang_count_temporaries(&shProg->GeometryProgram->Base);
- _slang_update_inputs_outputs(&shProg->GeometryProgram->Base);
- }
- if (shProg->FragmentProgram) {
- _slang_count_temporaries(&shProg->FragmentProgram->Base);
- _slang_update_inputs_outputs(&shProg->FragmentProgram->Base);
- }
-
- /* Check that all the varying vars needed by the fragment shader are
- * actually produced by the vertex shader.
- */
- if (shProg->FragmentProgram) {
- const GLbitfield varyingRead
- = shProg->FragmentProgram->Base.InputsRead >> FRAG_ATTRIB_VAR0;
- const GLbitfield64 varyingWritten = shProg->VertexProgram ?
- shProg->VertexProgram->Base.OutputsWritten >> VERT_RESULT_VAR0 : 0x0;
- if ((varyingRead & varyingWritten) != varyingRead) {
- link_error(shProg,
- "Fragment program using varying vars not written by vertex shader\n");
- return;
- }
- }
-
- /* check that gl_FragColor and gl_FragData are not both written to */
- if (shProg->FragmentProgram) {
- const GLbitfield64 outputsWritten =
- shProg->FragmentProgram->Base.OutputsWritten;
- if ((outputsWritten & BITFIELD64_BIT(FRAG_RESULT_COLOR)) &&
- (outputsWritten >= BITFIELD64_BIT(FRAG_RESULT_DATA0))) {
- link_error(shProg, "Fragment program cannot write both gl_FragColor"
- " and gl_FragData[].\n");
- return;
- }
- }
-
- update_varying_var_list(ctx, shProg);
-
- /* checks related to transform feedback */
- if (!link_transform_feedback(ctx, shProg)) {
- return;
- }
-
- if (fragProg && shProg->FragmentProgram) {
- /* Compute initial program's TexturesUsed info */
- _mesa_update_shader_textures_used(&shProg->FragmentProgram->Base);
-
- /* notify driver that a new fragment program has been compiled/linked */
- vertNotify = ctx->Driver.ProgramStringNotify(ctx, GL_FRAGMENT_PROGRAM_ARB,
- &shProg->FragmentProgram->Base);
- if (ctx->Shader.Flags & GLSL_DUMP) {
- fprintf(stderr, "Mesa pre-link fragment program:\n");
- _mesa_print_program(&fragProg->Base);
- _mesa_print_program_parameters(ctx, &fragProg->Base);
-
- fprintf(stderr, "Mesa post-link fragment program:\n");
- _mesa_print_program(&shProg->FragmentProgram->Base);
- _mesa_print_program_parameters(ctx, &shProg->FragmentProgram->Base);
- }
- }
-
- if (geomProg && shProg->GeometryProgram) {
- /* Compute initial program's TexturesUsed info */
- _mesa_update_shader_textures_used(&shProg->GeometryProgram->Base);
-
- /* Copy some per-shader-program fields to per-shader object */
- shProg->GeometryProgram->VerticesOut = shProg->Geom.VerticesOut;
- shProg->GeometryProgram->InputType = shProg->Geom.InputType;
- shProg->GeometryProgram->OutputType = shProg->Geom.OutputType;
-
- /* notify driver that a new fragment program has been compiled/linked */
- geomNotify = ctx->Driver.ProgramStringNotify(ctx, MESA_GEOMETRY_PROGRAM,
- &shProg->GeometryProgram->Base);
- if (ctx->Shader.Flags & GLSL_DUMP) {
- fprintf(stderr, "Mesa pre-link geometry program:\n");
- _mesa_print_program(&geomProg->Base);
- _mesa_print_program_parameters(ctx, &geomProg->Base);
-
- fprintf(stderr, "Mesa post-link geometry program:\n");
- _mesa_print_program(&shProg->GeometryProgram->Base);
- _mesa_print_program_parameters(ctx, &shProg->GeometryProgram->Base);
- }
- }
-
- if (vertProg && shProg->VertexProgram) {
- /* Compute initial program's TexturesUsed info */
- _mesa_update_shader_textures_used(&shProg->VertexProgram->Base);
-
- /* notify driver that a new vertex program has been compiled/linked */
- fragNotify = ctx->Driver.ProgramStringNotify(ctx, GL_VERTEX_PROGRAM_ARB,
- &shProg->VertexProgram->Base);
- if (ctx->Shader.Flags & GLSL_DUMP) {
- fprintf(stderr, "Mesa pre-link vertex program:\n");
- _mesa_print_program(&vertProg->Base);
- _mesa_print_program_parameters(ctx, &vertProg->Base);
-
- fprintf(stderr, "Mesa post-link vertex program:\n");
- _mesa_print_program(&shProg->VertexProgram->Base);
- _mesa_print_program_parameters(ctx, &shProg->VertexProgram->Base);
- }
- }
-
- /* Debug: */
- if (0) {
- if (shProg->VertexProgram)
- _mesa_postprocess_program(ctx, &shProg->VertexProgram->Base);
- if (shProg->FragmentProgram)
- _mesa_postprocess_program(ctx, &shProg->FragmentProgram->Base);
- }
-
- if (ctx->Shader.Flags & GLSL_DUMP) {
- fprintf(stderr, "Varying vars:\n");
- _mesa_print_parameter_list(shProg->Varying);
- if (shProg->InfoLog) {
- fprintf(stderr, "Info Log: %s\n", shProg->InfoLog);
- }
- }
-
- if (!vertNotify || !fragNotify || !geomNotify) {
- /* driver rejected one/both of the vertex/fragment programs */
- if (!shProg->InfoLog) {
- link_error(shProg,
- "Vertex, geometry and/or fragment program rejected by driver\n");
- }
- }
- else {
- shProg->LinkStatus = (shProg->VertexProgram || shProg->FragmentProgram);
- }
-}
-
+++ /dev/null
-/*
- * Mesa 3-D graphics library
- * Version: 7.2
- *
- * Copyright (C) 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.
- */
-
-#ifndef SLANG_LINK_H
-#define SLANG_LINK_H 1
-
-#include "main/mtypes.h"
-
-
-extern void
-_slang_link(GLcontext *ctx, GLhandleARB h,
- struct gl_shader_program *shProg);
-
-
-#endif
-
+++ /dev/null
-/*
- * Mesa 3-D graphics library
- * Version: 7.3
- *
- * Copyright (C) 2005-2007 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.
- */
-
-#include "main/imports.h"
-#include "slang_log.h"
-#include "slang_utility.h"
-
-
-
-static char *out_of_memory = "Error: Out of memory.\n";
-
-void
-slang_info_log_construct(slang_info_log * log)
-{
- log->text = NULL;
- log->dont_free_text = GL_FALSE;
- log->error_flag = GL_FALSE;
-}
-
-void
-slang_info_log_destruct(slang_info_log * log)
-{
- if (!log->dont_free_text)
- free(log->text);
-}
-
-static int
-slang_info_log_message(slang_info_log * log, const char *prefix,
- const char *msg)
-{
- GLuint size;
-
- if (log->dont_free_text)
- return 0;
- size = slang_string_length(msg) + 2;
- if (prefix != NULL)
- size += slang_string_length(prefix) + 2;
- if (log->text != NULL) {
- GLuint old_len = slang_string_length(log->text);
- log->text = (char *)
- _mesa_realloc(log->text, old_len + 1, old_len + size);
- }
- else {
- log->text = (char *) (malloc(size));
- if (log->text != NULL)
- log->text[0] = '\0';
- }
- if (log->text == NULL)
- return 0;
- if (prefix != NULL) {
- slang_string_concat(log->text, prefix);
- slang_string_concat(log->text, ": ");
- }
- slang_string_concat(log->text, msg);
- slang_string_concat(log->text, "\n");
-
- return 1;
-}
-
-int
-slang_info_log_print(slang_info_log * log, const char *msg, ...)
-{
- va_list va;
- char buf[1024];
-
- va_start(va, msg);
- vsprintf(buf, msg, va);
- va_end(va);
- return slang_info_log_message(log, NULL, buf);
-}
-
-int
-slang_info_log_error(slang_info_log * log, const char *msg, ...)
-{
- va_list va;
- char buf[1024];
-
- va_start(va, msg);
- vsprintf(buf, msg, va);
- va_end(va);
- log->error_flag = GL_TRUE;
- if (slang_info_log_message(log, "Error", buf))
- return 1;
- slang_info_log_memory(log);
- return 0;
-}
-
-int
-slang_info_log_warning(slang_info_log * log, const char *msg, ...)
-{
- va_list va;
- char buf[1024];
-
- va_start(va, msg);
- vsprintf(buf, msg, va);
- va_end(va);
- if (slang_info_log_message(log, "Warning", buf))
- return 1;
- slang_info_log_memory(log);
- return 0;
-}
-
-void
-slang_info_log_memory(slang_info_log * log)
-{
- if (!slang_info_log_message(log, "Error", "Out of memory.")) {
- log->dont_free_text = GL_TRUE;
- log->error_flag = GL_TRUE;
- log->text = out_of_memory;
- }
-}
+++ /dev/null
-/*
- * Mesa 3-D graphics library
- * Version: 6.5.3
- *
- * Copyright (C) 2005-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 SLANG_LOG_H
-#define SLANG_LOG_H
-
-
-#include "main/glheader.h"
-
-typedef struct slang_info_log_
-{
- char *text;
- GLboolean dont_free_text;
- GLboolean error_flag;
-} slang_info_log;
-
-
-extern void
-slang_info_log_construct(slang_info_log *);
-
-extern void
-slang_info_log_destruct(slang_info_log *);
-
-extern int
-slang_info_log_print(slang_info_log *, const char *, ...);
-
-extern int
-slang_info_log_error(slang_info_log *, const char *, ...);
-
-extern int
-slang_info_log_warning(slang_info_log *, const char *, ...);
-
-extern void
-slang_info_log_memory(slang_info_log *);
-
-
-#endif /* SLANG_LOG_H */
+++ /dev/null
-/*
- * Mesa 3-D graphics library
- * Version: 6.5.3
- *
- * Copyright (C) 2005-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.
- */
-
-/**
- * \file slang_mem.c
- *
- * Memory manager for GLSL compiler. The general idea is to do all
- * allocations out of a large pool then just free the pool when done
- * compiling to avoid intricate malloc/free tracking and memory leaks.
- *
- * \author Brian Paul
- */
-
-#include "main/context.h"
-#include "main/macros.h"
-#include "slang_mem.h"
-
-
-#define GRANULARITY 8
-#define ROUND_UP(B) ( ((B) + (GRANULARITY - 1)) & ~(GRANULARITY - 1) )
-
-
-/** If 1, use conventional malloc/free. Helpful for debugging */
-#define USE_MALLOC_FREE 0
-
-
-struct slang_mempool_
-{
- GLuint Size, Used, Count, Largest;
- char *Data;
- struct slang_mempool_ *Next;
-};
-
-
-slang_mempool *
-_slang_new_mempool(GLuint initialSize)
-{
- slang_mempool *pool = (slang_mempool *) calloc(1, sizeof(slang_mempool));
- if (pool) {
- pool->Data = (char *) calloc(1, initialSize);
- /*printf("ALLOC MEMPOOL %d at %p\n", initialSize, pool->Data);*/
- if (!pool->Data) {
- free(pool);
- return NULL;
- }
- pool->Size = initialSize;
- pool->Used = 0;
- }
- return pool;
-}
-
-
-void
-_slang_delete_mempool(slang_mempool *pool)
-{
- GLuint total = 0;
- while (pool) {
- slang_mempool *next = pool->Next;
- /*
- printf("DELETE MEMPOOL %u / %u count=%u largest=%u\n",
- pool->Used, pool->Size, pool->Count, pool->Largest);
- */
- total += pool->Used;
- free(pool->Data);
- free(pool);
- pool = next;
- }
- /*printf("TOTAL ALLOCATED: %u\n", total);*/
-}
-
-
-#ifdef DEBUG
-static void
-check_zero(const char *addr, GLuint n)
-{
- GLuint i;
- for (i = 0; i < n; i++) {
- assert(addr[i]==0);
- }
-}
-#endif
-
-
-#ifdef DEBUG
-static GLboolean
-is_valid_address(const slang_mempool *pool, void *addr)
-{
- while (pool) {
- if ((char *) addr >= pool->Data &&
- (char *) addr < pool->Data + pool->Used)
- return GL_TRUE;
-
- pool = pool->Next;
- }
- return GL_FALSE;
-}
-#endif
-
-
-/**
- * Alloc 'bytes' from shader mempool.
- */
-void *
-_slang_alloc(GLuint bytes)
-{
-#if USE_MALLOC_FREE
- return calloc(1, bytes);
-#else
- slang_mempool *pool;
- GET_CURRENT_CONTEXT(ctx);
- pool = (slang_mempool *) ctx->Shader.MemPool;
-
- if (bytes == 0)
- bytes = 1;
-
- while (pool) {
- if (pool->Used + bytes <= pool->Size) {
- /* found room */
- void *addr = (void *) (pool->Data + pool->Used);
-#ifdef DEBUG
- check_zero((char*) addr, bytes);
-#endif
- pool->Used += ROUND_UP(bytes);
- pool->Largest = MAX2(pool->Largest, bytes);
- pool->Count++;
- /*printf("alloc %u Used %u\n", bytes, pool->Used);*/
- return addr;
- }
- else if (pool->Next) {
- /* try next block */
- pool = pool->Next;
- }
- else {
- /* alloc new pool */
- const GLuint sz = MAX2(bytes, pool->Size);
- pool->Next = _slang_new_mempool(sz);
- if (!pool->Next) {
- /* we're _really_ out of memory */
- return NULL;
- }
- else {
- pool = pool->Next;
- pool->Largest = bytes;
- pool->Count++;
- pool->Used = ROUND_UP(bytes);
-#ifdef DEBUG
- check_zero((char*) pool->Data, bytes);
-#endif
- return (void *) pool->Data;
- }
- }
- }
- return NULL;
-#endif
-}
-
-
-void *
-_slang_realloc(void *oldBuffer, GLuint oldSize, GLuint newSize)
-{
-#if USE_MALLOC_FREE
- return _mesa_realloc(oldBuffer, oldSize, newSize);
-#else
- GET_CURRENT_CONTEXT(ctx);
- slang_mempool *pool = (slang_mempool *) ctx->Shader.MemPool;
- (void) pool;
-
- if (newSize < oldSize) {
- return oldBuffer;
- }
- else {
- const GLuint copySize = (oldSize < newSize) ? oldSize : newSize;
- void *newBuffer = _slang_alloc(newSize);
-
- if (oldBuffer)
- ASSERT(is_valid_address(pool, oldBuffer));
-
- if (newBuffer && oldBuffer && copySize > 0)
- memcpy(newBuffer, oldBuffer, copySize);
-
- return newBuffer;
- }
-#endif
-}
-
-
-/**
- * Clone string, storing in current mempool.
- */
-char *
-_slang_strdup(const char *s)
-{
- if (s) {
- size_t l = strlen(s);
- char *s2 = (char *) _slang_alloc(l + 1);
- if (s2)
- strcpy(s2, s);
- return s2;
- }
- else {
- return NULL;
- }
-}
-
-
-/**
- * Don't actually free memory, but mark it (for debugging).
- */
-void
-_slang_free(void *addr)
-{
-#if USE_MALLOC_FREE
- free(addr);
-#else
- if (addr) {
- GET_CURRENT_CONTEXT(ctx);
- slang_mempool *pool = (slang_mempool *) ctx->Shader.MemPool;
- (void) pool;
- ASSERT(is_valid_address(pool, addr));
- }
-#endif
-}
+++ /dev/null
-/*
- * Mesa 3-D graphics library
- * Version: 6.5.3
- *
- * Copyright (C) 2005-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 SLANG_MEM_H
-#define SLANG_MEM_H
-
-
-#include "main/glheader.h"
-
-
-typedef struct slang_mempool_ slang_mempool;
-
-
-extern slang_mempool *
-_slang_new_mempool(GLuint initialSize);
-
-extern void
-_slang_delete_mempool(slang_mempool *pool);
-
-extern void *
-_slang_alloc(GLuint bytes);
-
-extern void *
-_slang_realloc(void *oldBuffer, GLuint oldSize, GLuint newSize);
-
-extern char *
-_slang_strdup(const char *s);
-
-extern void
-_slang_free(void *addr);
-
-
-#endif
+++ /dev/null
-
-/**
- * Dump/print a slang_operation tree
- */
-
-
-#include "main/imports.h"
-#include "slang_compile.h"
-#include "slang_print.h"
-
-
-static void
-spaces(int n)
-{
- while (n--)
- printf(" ");
-}
-
-
-static void
-print_type(const slang_fully_specified_type *t)
-{
- switch (t->qualifier) {
- case SLANG_QUAL_NONE:
- /*printf("");*/
- break;
- case SLANG_QUAL_CONST:
- printf("const ");
- break;
- case SLANG_QUAL_ATTRIBUTE:
- printf("attrib ");
- break;
- case SLANG_QUAL_VARYING:
- printf("varying ");
- break;
- case SLANG_QUAL_UNIFORM:
- printf("uniform ");
- break;
- case SLANG_QUAL_OUT:
- printf("output ");
- break;
- case SLANG_QUAL_INOUT:
- printf("inout ");
- break;
- case SLANG_QUAL_FIXEDOUTPUT:
- printf("fixedoutput");
- break;
- case SLANG_QUAL_FIXEDINPUT:
- printf("fixedinput");
- break;
- default:
- printf("unknown qualifer!");
- }
-
- switch (t->specifier.type) {
- case SLANG_SPEC_VOID:
- printf("void");
- break;
- case SLANG_SPEC_BOOL:
- printf("bool");
- break;
- case SLANG_SPEC_BVEC2:
- printf("bvec2");
- break;
- case SLANG_SPEC_BVEC3:
- printf("bvec3");
- break;
- case SLANG_SPEC_BVEC4:
- printf("bvec4");
- break;
- case SLANG_SPEC_INT:
- printf("int");
- break;
- case SLANG_SPEC_IVEC2:
- printf("ivec2");
- break;
- case SLANG_SPEC_IVEC3:
- printf("ivec3");
- break;
- case SLANG_SPEC_IVEC4:
- printf("ivec4");
- break;
- case SLANG_SPEC_FLOAT:
- printf("float");
- break;
- case SLANG_SPEC_VEC2:
- printf("vec2");
- break;
- case SLANG_SPEC_VEC3:
- printf("vec3");
- break;
- case SLANG_SPEC_VEC4:
- printf("vec4");
- break;
- case SLANG_SPEC_MAT2:
- printf("mat2");
- break;
- case SLANG_SPEC_MAT3:
- printf("mat3");
- break;
- case SLANG_SPEC_MAT4:
- printf("mat4");
- break;
- case SLANG_SPEC_MAT23:
- printf("mat2x3");
- break;
- case SLANG_SPEC_MAT32:
- printf("mat3x2");
- break;
- case SLANG_SPEC_MAT24:
- printf("mat2x4");
- break;
- case SLANG_SPEC_MAT42:
- printf("mat4x2");
- break;
- case SLANG_SPEC_MAT34:
- printf("mat3x4");
- break;
- case SLANG_SPEC_MAT43:
- printf("mat4x3");
- break;
- case SLANG_SPEC_SAMPLER_1D:
- printf("sampler1D");
- break;
- case SLANG_SPEC_SAMPLER_2D:
- printf("sampler2D");
- break;
- case SLANG_SPEC_SAMPLER_3D:
- printf("sampler3D");
- break;
- case SLANG_SPEC_SAMPLER_CUBE:
- printf("samplerCube");
- break;
- case SLANG_SPEC_SAMPLER_1D_SHADOW:
- printf("sampler1DShadow");
- break;
- case SLANG_SPEC_SAMPLER_2D_SHADOW:
- printf("sampler2DShadow");
- break;
- case SLANG_SPEC_STRUCT:
- printf("struct");
- break;
- case SLANG_SPEC_ARRAY:
- printf("array");
- break;
- default:
- printf("unknown type");
- }
- /*printf("\n");*/
-}
-
-
-static void
-print_variable(const slang_variable *v, int indent)
-{
- spaces(indent);
- printf("VAR ");
- print_type(&v->type);
- printf(" %s (at %p)", (char *) v->a_name, (void *) v);
- if (v->initializer) {
- printf(" :=\n");
- slang_print_tree(v->initializer, indent + 3);
- }
- else {
- printf(";\n");
- }
-}
-
-
-static void
-print_binary(const slang_operation *op, const char *oper, int indent)
-{
- assert(op->num_children == 2);
-#if 0
- printf("binary at %p locals=%p outer=%p\n",
- (void *) op,
- (void *) op->locals,
- (void *) op->locals->outer_scope);
-#endif
- slang_print_tree(&op->children[0], indent + 3);
- spaces(indent);
- printf("%s at %p locals=%p outer=%p\n",
- oper, (void *) op, (void *) op->locals,
- (void *) op->locals->outer_scope);
- slang_print_tree(&op->children[1], indent + 3);
-}
-
-
-static void
-print_generic2(const slang_operation *op, const char *oper,
- const char *s, int indent)
-{
- GLuint i;
- if (oper) {
- spaces(indent);
- printf("%s %s at %p locals=%p outer=%p\n",
- oper, s, (void *) op, (void *) op->locals,
- (void *) op->locals->outer_scope);
- }
- for (i = 0; i < op->num_children; i++) {
- spaces(indent);
- printf("//child %u of %u:\n", i, op->num_children);
- slang_print_tree(&op->children[i], indent);
- }
-}
-
-static void
-print_generic(const slang_operation *op, const char *oper, int indent)
-{
- print_generic2(op, oper, "", indent);
-}
-
-
-static const slang_variable_scope *
-find_scope(const slang_variable_scope *s, slang_atom name)
-{
- GLuint i;
- for (i = 0; i < s->num_variables; i++) {
- if (s->variables[i]->a_name == name)
- return s;
- }
- if (s->outer_scope)
- return find_scope(s->outer_scope, name);
- else
- return NULL;
-}
-
-static const slang_variable *
-find_var(const slang_variable_scope *s, slang_atom name)
-{
- GLuint i;
- for (i = 0; i < s->num_variables; i++) {
- if (s->variables[i]->a_name == name)
- return s->variables[i];
- }
- if (s->outer_scope)
- return find_var(s->outer_scope, name);
- else
- return NULL;
-}
-
-
-void
-slang_print_tree(const slang_operation *op, int indent)
-{
- GLuint i;
-
- switch (op->type) {
-
- case SLANG_OPER_NONE:
- spaces(indent);
- printf("SLANG_OPER_NONE\n");
- break;
-
- case SLANG_OPER_BLOCK_NO_NEW_SCOPE:
- spaces(indent);
- printf("{ locals=%p outer=%p\n", (void*)op->locals, (void*)op->locals->outer_scope);
- print_generic(op, NULL, indent+3);
- spaces(indent);
- printf("}\n");
- break;
-
- case SLANG_OPER_BLOCK_NEW_SCOPE:
- case SLANG_OPER_NON_INLINED_CALL:
- spaces(indent);
- printf("{{ // new scope locals=%p outer=%p: ",
- (void *) op->locals,
- (void *) op->locals->outer_scope);
- for (i = 0; i < op->locals->num_variables; i++) {
- printf("%s ", (char *) op->locals->variables[i]->a_name);
- }
- printf("\n");
- print_generic(op, NULL, indent+3);
- spaces(indent);
- printf("}}\n");
- break;
-
- case SLANG_OPER_VARIABLE_DECL:
- assert(op->num_children == 0 || op->num_children == 1);
- {
- slang_variable *v;
- v = _slang_variable_locate(op->locals, op->a_id, GL_TRUE);
- if (v) {
- const slang_variable_scope *scope;
- spaces(indent);
- printf("DECL (locals=%p outer=%p) ", (void*)op->locals, (void*) op->locals->outer_scope);
- print_type(&v->type);
- printf(" %s (%p)", (char *) op->a_id,
- (void *) find_var(op->locals, op->a_id));
-
- scope = find_scope(op->locals, op->a_id);
- printf(" (in scope %p) ", (void *) scope);
- assert(scope);
- if (op->num_children == 1) {
- printf(" :=\n");
- slang_print_tree(&op->children[0], indent + 3);
- }
- else if (v->initializer) {
- printf(" := INITIALIZER\n");
- slang_print_tree(v->initializer, indent + 3);
- }
- else {
- printf(";\n");
- }
- /*
- spaces(indent);
- printf("TYPE: ");
- print_type(&v->type);
- spaces(indent);
- printf("ADDR: %d size: %d\n", v->address, v->size);
- */
- }
- else {
- spaces(indent);
- printf("DECL %s (anonymous variable!!!!)\n", (char *) op->a_id);
- }
- }
- break;
-
- case SLANG_OPER_ASM:
- spaces(indent);
- printf("ASM: %s at %p locals=%p outer=%p\n",
- (char *) op->a_id,
- (void *) op,
- (void *) op->locals,
- (void *) op->locals->outer_scope);
- print_generic(op, "ASM", indent+3);
- break;
-
- case SLANG_OPER_BREAK:
- spaces(indent);
- printf("BREAK\n");
- break;
-
- case SLANG_OPER_CONTINUE:
- spaces(indent);
- printf("CONTINUE\n");
- break;
-
- case SLANG_OPER_DISCARD:
- spaces(indent);
- printf("DISCARD\n");
- break;
-
- case SLANG_OPER_RETURN:
- spaces(indent);
- printf("RETURN\n");
- if (op->num_children > 0)
- slang_print_tree(&op->children[0], indent + 3);
- break;
-
- case SLANG_OPER_RETURN_INLINED:
- spaces(indent);
- printf("RETURN_INLINED\n");
- if (op->num_children > 0)
- slang_print_tree(&op->children[0], indent + 3);
- break;
-
- case SLANG_OPER_LABEL:
- spaces(indent);
- printf("LABEL %s\n", (char *) op->a_id);
- break;
-
- case SLANG_OPER_EXPRESSION:
- spaces(indent);
- printf("EXPR: locals=%p outer=%p\n",
- (void *) op->locals,
- (void *) op->locals->outer_scope);
- /*print_generic(op, "SLANG_OPER_EXPRESSION", indent);*/
- slang_print_tree(&op->children[0], indent + 3);
- break;
-
- case SLANG_OPER_IF:
- spaces(indent);
- printf("IF\n");
- slang_print_tree(&op->children[0], indent + 3);
- spaces(indent);
- printf("THEN\n");
- slang_print_tree(&op->children[1], indent + 3);
- spaces(indent);
- printf("ELSE\n");
- slang_print_tree(&op->children[2], indent + 3);
- spaces(indent);
- printf("ENDIF\n");
- break;
-
- case SLANG_OPER_WHILE:
- assert(op->num_children == 2);
- spaces(indent);
- printf("WHILE LOOP: locals = %p\n", (void *) op->locals);
- indent += 3;
- spaces(indent);
- printf("WHILE cond:\n");
- slang_print_tree(&op->children[0], indent + 3);
- spaces(indent);
- printf("WHILE body:\n");
- slang_print_tree(&op->children[1], indent + 3);
- indent -= 3;
- spaces(indent);
- printf("END WHILE LOOP\n");
- break;
-
- case SLANG_OPER_DO:
- spaces(indent);
- printf("DO LOOP: locals = %p\n", (void *) op->locals);
- indent += 3;
- spaces(indent);
- printf("DO body:\n");
- slang_print_tree(&op->children[0], indent + 3);
- spaces(indent);
- printf("DO cond:\n");
- slang_print_tree(&op->children[1], indent + 3);
- indent -= 3;
- spaces(indent);
- printf("END DO LOOP\n");
- break;
-
- case SLANG_OPER_FOR:
- spaces(indent);
- printf("FOR LOOP: locals = %p\n", (void *) op->locals);
- indent += 3;
- spaces(indent);
- printf("FOR init:\n");
- slang_print_tree(&op->children[0], indent + 3);
- spaces(indent);
- printf("FOR condition:\n");
- slang_print_tree(&op->children[1], indent + 3);
- spaces(indent);
- printf("FOR step:\n");
- slang_print_tree(&op->children[2], indent + 3);
- spaces(indent);
- printf("FOR body:\n");
- slang_print_tree(&op->children[3], indent + 3);
- indent -= 3;
- spaces(indent);
- printf("ENDFOR\n");
- /*
- print_generic(op, "FOR", indent + 3);
- */
- break;
-
- case SLANG_OPER_VOID:
- spaces(indent);
- printf("(oper-void)\n");
- break;
-
- case SLANG_OPER_LITERAL_BOOL:
- spaces(indent);
- printf("LITERAL (");
- for (i = 0; i < op->literal_size; i++)
- printf("%s ", op->literal[0] ? "TRUE" : "FALSE");
- printf(")\n");
-
- break;
-
- case SLANG_OPER_LITERAL_INT:
- spaces(indent);
- printf("LITERAL (");
- for (i = 0; i < op->literal_size; i++)
- printf("%d ", (int) op->literal[i]);
- printf(")\n");
- break;
-
- case SLANG_OPER_LITERAL_FLOAT:
- spaces(indent);
- printf("LITERAL (");
- for (i = 0; i < op->literal_size; i++)
- printf("%f ", op->literal[i]);
- printf(")\n");
- break;
-
- case SLANG_OPER_IDENTIFIER:
- {
- const slang_variable_scope *scope;
- spaces(indent);
- if (op->var && op->var->a_name) {
- scope = find_scope(op->locals, op->var->a_name);
- printf("VAR %s (in scope %p)\n", (char *) op->var->a_name,
- (void *) scope);
- assert(scope);
- }
- else {
- scope = find_scope(op->locals, op->a_id);
- printf("VAR' %s (in scope %p) locals=%p outer=%p\n",
- (char *) op->a_id,
- (void *) scope,
- (void *) op->locals,
- (void *) op->locals->outer_scope);
- /*assert(scope);*/
- }
- }
- break;
-
- case SLANG_OPER_SEQUENCE:
- print_generic(op, "COMMA-SEQ", indent+3);
- break;
-
- case SLANG_OPER_ASSIGN:
- spaces(indent);
- printf("ASSIGNMENT locals=%p outer=%p\n",
- (void *) op->locals,
- (void *) op->locals->outer_scope);
- print_binary(op, ":=", indent);
- break;
-
- case SLANG_OPER_ADDASSIGN:
- spaces(indent);
- printf("ASSIGN\n");
- print_binary(op, "+=", indent);
- break;
-
- case SLANG_OPER_SUBASSIGN:
- spaces(indent);
- printf("ASSIGN\n");
- print_binary(op, "-=", indent);
- break;
-
- case SLANG_OPER_MULASSIGN:
- spaces(indent);
- printf("ASSIGN\n");
- print_binary(op, "*=", indent);
- break;
-
- case SLANG_OPER_DIVASSIGN:
- spaces(indent);
- printf("ASSIGN\n");
- print_binary(op, "/=", indent);
- break;
-
- /*SLANG_OPER_MODASSIGN,*/
- /*SLANG_OPER_LSHASSIGN,*/
- /*SLANG_OPER_RSHASSIGN,*/
- /*SLANG_OPER_ORASSIGN,*/
- /*SLANG_OPER_XORASSIGN,*/
- /*SLANG_OPER_ANDASSIGN,*/
- case SLANG_OPER_SELECT:
- spaces(indent);
- printf("SLANG_OPER_SELECT n=%d\n", op->num_children);
- assert(op->num_children == 3);
- slang_print_tree(&op->children[0], indent+3);
- spaces(indent);
- printf("?\n");
- slang_print_tree(&op->children[1], indent+3);
- spaces(indent);
- printf(":\n");
- slang_print_tree(&op->children[2], indent+3);
- break;
-
- case SLANG_OPER_LOGICALOR:
- print_binary(op, "||", indent);
- break;
-
- case SLANG_OPER_LOGICALXOR:
- print_binary(op, "^^", indent);
- break;
-
- case SLANG_OPER_LOGICALAND:
- print_binary(op, "&&", indent);
- break;
-
- /*SLANG_OPER_BITOR*/
- /*SLANG_OPER_BITXOR*/
- /*SLANG_OPER_BITAND*/
- case SLANG_OPER_EQUAL:
- print_binary(op, "==", indent);
- break;
-
- case SLANG_OPER_NOTEQUAL:
- print_binary(op, "!=", indent);
- break;
-
- case SLANG_OPER_LESS:
- print_binary(op, "<", indent);
- break;
-
- case SLANG_OPER_GREATER:
- print_binary(op, ">", indent);
- break;
-
- case SLANG_OPER_LESSEQUAL:
- print_binary(op, "<=", indent);
- break;
-
- case SLANG_OPER_GREATEREQUAL:
- print_binary(op, ">=", indent);
- break;
-
- /*SLANG_OPER_LSHIFT*/
- /*SLANG_OPER_RSHIFT*/
- case SLANG_OPER_ADD:
- print_binary(op, "+", indent);
- break;
-
- case SLANG_OPER_SUBTRACT:
- print_binary(op, "-", indent);
- break;
-
- case SLANG_OPER_MULTIPLY:
- print_binary(op, "*", indent);
- break;
-
- case SLANG_OPER_DIVIDE:
- print_binary(op, "/", indent);
- break;
-
- /*SLANG_OPER_MODULUS*/
- case SLANG_OPER_PREINCREMENT:
- spaces(indent);
- printf("PRE++\n");
- slang_print_tree(&op->children[0], indent+3);
- break;
-
- case SLANG_OPER_PREDECREMENT:
- spaces(indent);
- printf("PRE--\n");
- slang_print_tree(&op->children[0], indent+3);
- break;
-
- case SLANG_OPER_PLUS:
- spaces(indent);
- printf("SLANG_OPER_PLUS\n");
- break;
-
- case SLANG_OPER_MINUS:
- spaces(indent);
- printf("SLANG_OPER_MINUS\n");
- break;
-
- /*SLANG_OPER_COMPLEMENT*/
- case SLANG_OPER_NOT:
- spaces(indent);
- printf("NOT\n");
- slang_print_tree(&op->children[0], indent+3);
- break;
-
- case SLANG_OPER_SUBSCRIPT:
- spaces(indent);
- printf("SLANG_OPER_SUBSCRIPT locals=%p outer=%p\n",
- (void *) op->locals,
- (void *) op->locals->outer_scope);
- print_generic(op, NULL, indent+3);
- break;
-
- case SLANG_OPER_CALL:
-#if 0
- slang_function *fun
- = _slang_function_locate(A->space.funcs, oper->a_id,
- oper->children,
- oper->num_children, &A->space, A->atoms);
-#endif
- spaces(indent);
- printf("CALL %s(\n", (char *) op->a_id);
- for (i = 0; i < op->num_children; i++) {
- slang_print_tree(&op->children[i], indent+3);
- if (i + 1 < op->num_children) {
- spaces(indent + 3);
- printf(",\n");
- }
- }
- spaces(indent);
- printf(")\n");
- break;
-
- case SLANG_OPER_METHOD:
- spaces(indent);
- printf("METHOD CALL %s.%s\n", (char *) op->a_obj, (char *) op->a_id);
- break;
-
- case SLANG_OPER_FIELD:
- spaces(indent);
- printf("FIELD %s of\n", (char*) op->a_id);
- slang_print_tree(&op->children[0], indent+3);
- break;
-
- case SLANG_OPER_POSTINCREMENT:
- spaces(indent);
- printf("POST++\n");
- slang_print_tree(&op->children[0], indent+3);
- break;
-
- case SLANG_OPER_POSTDECREMENT:
- spaces(indent);
- printf("POST--\n");
- slang_print_tree(&op->children[0], indent+3);
- break;
-
- default:
- printf("unknown op->type %d\n", (int) op->type);
- }
-
-}
-
-
-
-void
-slang_print_function(const slang_function *f, GLboolean body)
-{
- GLuint i;
-
-#if 0
- if (strcmp((char *) f->header.a_name, "main") != 0)
- return;
-#endif
-
- printf("FUNCTION %s ( scope=%p\n",
- (char *) f->header.a_name, (void *) f->parameters);
-
- for (i = 0; i < f->param_count; i++) {
- print_variable(f->parameters->variables[i], 3);
- }
-
- printf(") param scope = %p\n", (void *) f->parameters);
-
- if (body && f->body)
- slang_print_tree(f->body, 0);
-}
-
-
-
-
-
-const char *
-slang_type_qual_string(slang_type_qualifier q)
-{
- switch (q) {
- case SLANG_QUAL_NONE:
- return "none";
- case SLANG_QUAL_CONST:
- return "const";
- case SLANG_QUAL_ATTRIBUTE:
- return "attribute";
- case SLANG_QUAL_VARYING:
- return "varying";
- case SLANG_QUAL_UNIFORM:
- return "uniform";
- case SLANG_QUAL_OUT:
- return "out";
- case SLANG_QUAL_INOUT:
- return "inout";
- case SLANG_QUAL_FIXEDOUTPUT:
- return "fixedoutput";
- case SLANG_QUAL_FIXEDINPUT:
- return "fixedinputk";
- default:
- return "qual?";
- }
-}
-
-
-static const char *
-slang_type_string(slang_type_specifier_type t)
-{
- switch (t) {
- case SLANG_SPEC_VOID:
- return "void";
- case SLANG_SPEC_BOOL:
- return "bool";
- case SLANG_SPEC_BVEC2:
- return "bvec2";
- case SLANG_SPEC_BVEC3:
- return "bvec3";
- case SLANG_SPEC_BVEC4:
- return "bvec4";
- case SLANG_SPEC_INT:
- return "int";
- case SLANG_SPEC_IVEC2:
- return "ivec2";
- case SLANG_SPEC_IVEC3:
- return "ivec3";
- case SLANG_SPEC_IVEC4:
- return "ivec4";
- case SLANG_SPEC_FLOAT:
- return "float";
- case SLANG_SPEC_VEC2:
- return "vec2";
- case SLANG_SPEC_VEC3:
- return "vec3";
- case SLANG_SPEC_VEC4:
- return "vec4";
- case SLANG_SPEC_MAT2:
- return "mat2";
- case SLANG_SPEC_MAT3:
- return "mat3";
- case SLANG_SPEC_MAT4:
- return "mat4";
- case SLANG_SPEC_SAMPLER_1D:
- return "sampler1D";
- case SLANG_SPEC_SAMPLER_2D:
- return "sampler2D";
- case SLANG_SPEC_SAMPLER_3D:
- return "sampler3D";
- case SLANG_SPEC_SAMPLER_CUBE:
- return "samplerCube";
- case SLANG_SPEC_SAMPLER_1D_SHADOW:
- return "sampler1DShadow";
- case SLANG_SPEC_SAMPLER_2D_SHADOW:
- return "sampler2DShadow";
- case SLANG_SPEC_SAMPLER_RECT:
- return "sampler2DRect";
- case SLANG_SPEC_SAMPLER_RECT_SHADOW:
- return "sampler2DRectShadow";
- case SLANG_SPEC_STRUCT:
- return "struct";
- case SLANG_SPEC_ARRAY:
- return "array";
- default:
- return "type?";
- }
-}
-
-
-static const char *
-slang_fq_type_string(const slang_fully_specified_type *t)
-{
- static char str[1000];
- _mesa_snprintf(str, sizeof(str), "%s %s", slang_type_qual_string(t->qualifier),
- slang_type_string(t->specifier.type));
- return str;
-}
-
-
-void
-slang_print_type(const slang_fully_specified_type *t)
-{
- printf("%s %s", slang_type_qual_string(t->qualifier),
- slang_type_string(t->specifier.type));
-}
-
-
-#if 0
-static char *
-slang_var_string(const slang_variable *v)
-{
- static char str[1000];
- _mesa_snprintf(str, sizeof(str), "%s : %s",
- (char *) v->a_name,
- slang_fq_type_string(&v->type));
- return str;
-}
-#endif
-
-
-void
-slang_print_variable(const slang_variable *v)
-{
- printf("Name: %s\n", (char *) v->a_name);
- printf("Type: %s\n", slang_fq_type_string(&v->type));
-}
-
-
-void
-_slang_print_var_scope(const slang_variable_scope *vars, int indent)
-{
- GLuint i;
-
- spaces(indent);
- printf("Var scope %p %d vars:\n", (void *) vars, vars->num_variables);
- for (i = 0; i < vars->num_variables; i++) {
- spaces(indent + 3);
- printf("%s (at %p)\n", (char *) vars->variables[i]->a_name, (void*) (vars->variables + i));
- }
- spaces(indent + 3);
- printf("outer_scope = %p\n", (void*) vars->outer_scope);
-
- if (vars->outer_scope) {
- /*spaces(indent + 3);*/
- _slang_print_var_scope(vars->outer_scope, indent + 3);
- }
-}
-
-
-
-int
-slang_checksum_tree(const slang_operation *op)
-{
- int s = op->num_children;
- GLuint i;
-
- for (i = 0; i < op->num_children; i++) {
- s += slang_checksum_tree(&op->children[i]);
- }
- return s;
-}
+++ /dev/null
-
-
-#ifndef SLANG_PRINT
-#define SLANG_PRINT
-
-#include "main/glheader.h"
-#include "slang_compile_function.h"
-#include "slang_compile_operation.h"
-#include "slang_compile_variable.h"
-#include "slang_typeinfo.h"
-
-extern void
-slang_print_function(const slang_function *f, GLboolean body);
-
-extern void
-slang_print_tree(const slang_operation *op, int indent);
-
-extern const char *
-slang_type_qual_string(slang_type_qualifier q);
-
-extern void
-slang_print_type(const slang_fully_specified_type *t);
-
-extern void
-slang_print_variable(const slang_variable *v);
-
-extern void
-_slang_print_var_scope(const slang_variable_scope *s, int indent);
-
-
-extern int
-slang_checksum_tree(const slang_operation *op);
-
-#endif /* SLANG_PRINT */
-
+++ /dev/null
-/*
- * Mesa 3-D graphics library
- * Version: 7.1
- *
- * Copyright (C) 2005-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.
- */
-
-/**
- * Functions for constant folding, built-in constant lookup, and function
- * call casting.
- */
-
-
-#include "main/imports.h"
-#include "main/macros.h"
-#include "main/get.h"
-#include "slang_compile.h"
-#include "slang_codegen.h"
-#include "slang_simplify.h"
-#include "slang_print.h"
-
-
-#ifndef GL_MAX_FRAGMENT_UNIFORM_VECTORS
-#define GL_MAX_FRAGMENT_UNIFORM_VECTORS 0x8DFD
-#endif
-#ifndef GL_MAX_VERTEX_UNIFORM_VECTORS
-#define GL_MAX_VERTEX_UNIFORM_VECTORS 0x8DFB
-#endif
-#ifndef GL_MAX_VARYING_VECTORS
-#define GL_MAX_VARYING_VECTORS 0x8DFC
-#endif
-
-
-/**
- * Lookup the value of named constant, such as gl_MaxLights.
- * \return value of constant, or -1 if unknown
- */
-GLint
-_slang_lookup_constant(const char *name)
-{
- struct constant_info {
- const char *Name;
- const GLenum Token;
- };
- static const struct constant_info info[] = {
- { "gl_MaxClipPlanes", GL_MAX_CLIP_PLANES },
- { "gl_MaxCombinedTextureImageUnits", GL_MAX_COMBINED_TEXTURE_IMAGE_UNITS },
- { "gl_MaxDrawBuffers", GL_MAX_DRAW_BUFFERS },
- { "gl_MaxFragmentUniformComponents", GL_MAX_FRAGMENT_UNIFORM_COMPONENTS },
- { "gl_MaxLights", GL_MAX_LIGHTS },
- { "gl_MaxTextureUnits", GL_MAX_TEXTURE_UNITS },
- { "gl_MaxTextureCoords", GL_MAX_TEXTURE_COORDS },
- { "gl_MaxVertexAttribs", GL_MAX_VERTEX_ATTRIBS },
- { "gl_MaxVertexUniformComponents", GL_MAX_VERTEX_UNIFORM_COMPONENTS },
- { "gl_MaxVaryingFloats", GL_MAX_VARYING_FLOATS },
- { "gl_MaxVertexTextureImageUnits", GL_MAX_VERTEX_TEXTURE_IMAGE_UNITS },
- { "gl_MaxTextureImageUnits", GL_MAX_TEXTURE_IMAGE_UNITS },
-#if FEATURE_es2_glsl
- { "gl_MaxVertexUniformVectors", GL_MAX_VERTEX_UNIFORM_VECTORS },
- { "gl_MaxVaryingVectors", GL_MAX_VARYING_VECTORS },
- { "gl_MaxFragmentUniformVectors", GL_MAX_FRAGMENT_UNIFORM_VECTORS },
-#endif
- { NULL, 0 }
- };
- GLuint i;
-
- for (i = 0; info[i].Name; i++) {
- if (strcmp(info[i].Name, name) == 0) {
- /* found */
- GLint values[16];
- values[0] = -1;
- _mesa_GetIntegerv(info[i].Token, values);
- ASSERT(values[0] >= 0); /* sanity check that glGetFloatv worked */
- return values[0];
- }
- }
- return -1;
-}
-
-
-static slang_operation_type
-literal_type(slang_operation_type t1, slang_operation_type t2)
-{
- if (t1 == SLANG_OPER_LITERAL_FLOAT || t2 == SLANG_OPER_LITERAL_FLOAT)
- return SLANG_OPER_LITERAL_FLOAT;
- else
- return SLANG_OPER_LITERAL_INT;
-}
-
-
-/**
- * Recursively traverse an AST tree, applying simplifications wherever
- * possible.
- * At the least, we do constant folding. We need to do that much so that
- * compile-time expressions can be evaluated for things like array
- * declarations. I.e.: float foo[3 + 5];
- */
-void
-_slang_simplify(slang_operation *oper,
- const slang_name_space * space,
- slang_atom_pool * atoms)
-{
- GLboolean isFloat[4];
- GLboolean isBool[4];
- GLuint i, n;
-
- if (oper->type == SLANG_OPER_IDENTIFIER) {
- /* see if it's a named constant */
- GLint value = _slang_lookup_constant((char *) oper->a_id);
- /*printf("value[%s] = %d\n", (char*) oper->a_id, value);*/
- if (value >= 0) {
- oper->literal[0] =
- oper->literal[1] =
- oper->literal[2] =
- oper->literal[3] = (GLfloat) value;
- oper->type = SLANG_OPER_LITERAL_INT;
- return;
- }
- /* look for user-defined constant */
- {
- slang_variable *var;
- var = _slang_variable_locate(oper->locals, oper->a_id, GL_TRUE);
- if (var) {
- if (var->type.qualifier == SLANG_QUAL_CONST &&
- var->initializer &&
- (var->initializer->type == SLANG_OPER_LITERAL_INT ||
- var->initializer->type == SLANG_OPER_LITERAL_FLOAT)) {
- oper->literal[0] = var->initializer->literal[0];
- oper->literal[1] = var->initializer->literal[1];
- oper->literal[2] = var->initializer->literal[2];
- oper->literal[3] = var->initializer->literal[3];
- oper->literal_size = var->initializer->literal_size;
- oper->type = var->initializer->type;
- /*
- printf("value[%s] = %f\n",
- (char*) oper->a_id, oper->literal[0]);
- */
- return;
- }
- }
- }
- }
-
- /* first, simplify children */
- for (i = 0; i < oper->num_children; i++) {
- _slang_simplify(&oper->children[i], space, atoms);
- }
-
- /* examine children */
- n = MIN2(oper->num_children, 4);
- for (i = 0; i < n; i++) {
- isFloat[i] = (oper->children[i].type == SLANG_OPER_LITERAL_FLOAT ||
- oper->children[i].type == SLANG_OPER_LITERAL_INT);
- isBool[i] = (oper->children[i].type == SLANG_OPER_LITERAL_BOOL);
- }
-
- if (oper->num_children == 2 && isFloat[0] && isFloat[1]) {
- /* probably simple arithmetic */
- switch (oper->type) {
- case SLANG_OPER_ADD:
- for (i = 0; i < 4; i++) {
- oper->literal[i]
- = oper->children[0].literal[i] + oper->children[1].literal[i];
- }
- oper->literal_size = oper->children[0].literal_size;
- oper->type = literal_type(oper->children[0].type,
- oper->children[1].type);
- slang_operation_destruct(oper); /* frees unused children */
- return;
- case SLANG_OPER_SUBTRACT:
- for (i = 0; i < 4; i++) {
- oper->literal[i]
- = oper->children[0].literal[i] - oper->children[1].literal[i];
- }
- oper->literal_size = oper->children[0].literal_size;
- oper->type = literal_type(oper->children[0].type,
- oper->children[1].type);
- slang_operation_destruct(oper);
- return;
- case SLANG_OPER_MULTIPLY:
- for (i = 0; i < 4; i++) {
- oper->literal[i]
- = oper->children[0].literal[i] * oper->children[1].literal[i];
- }
- oper->literal_size = oper->children[0].literal_size;
- oper->type = literal_type(oper->children[0].type,
- oper->children[1].type);
- slang_operation_destruct(oper);
- return;
- case SLANG_OPER_DIVIDE:
- for (i = 0; i < 4; i++) {
- oper->literal[i]
- = oper->children[0].literal[i] / oper->children[1].literal[i];
- }
- oper->literal_size = oper->children[0].literal_size;
- oper->type = literal_type(oper->children[0].type,
- oper->children[1].type);
- slang_operation_destruct(oper);
- return;
- default:
- ; /* nothing */
- }
- }
-
- if (oper->num_children == 1 && isFloat[0]) {
- switch (oper->type) {
- case SLANG_OPER_MINUS:
- for (i = 0; i < 4; i++) {
- oper->literal[i] = -oper->children[0].literal[i];
- }
- oper->literal_size = oper->children[0].literal_size;
- slang_operation_destruct(oper);
- oper->type = SLANG_OPER_LITERAL_FLOAT;
- return;
- case SLANG_OPER_PLUS:
- COPY_4V(oper->literal, oper->children[0].literal);
- oper->literal_size = oper->children[0].literal_size;
- slang_operation_destruct(oper);
- oper->type = SLANG_OPER_LITERAL_FLOAT;
- return;
- default:
- ; /* nothing */
- }
- }
-
- if (oper->num_children == 2 && isBool[0] && isBool[1]) {
- /* simple boolean expression */
- switch (oper->type) {
- case SLANG_OPER_LOGICALAND:
- for (i = 0; i < 4; i++) {
- const GLint a = oper->children[0].literal[i] ? 1 : 0;
- const GLint b = oper->children[1].literal[i] ? 1 : 0;
- oper->literal[i] = (GLfloat) (a && b);
- }
- oper->literal_size = oper->children[0].literal_size;
- slang_operation_destruct(oper);
- oper->type = SLANG_OPER_LITERAL_BOOL;
- return;
- case SLANG_OPER_LOGICALOR:
- for (i = 0; i < 4; i++) {
- const GLint a = oper->children[0].literal[i] ? 1 : 0;
- const GLint b = oper->children[1].literal[i] ? 1 : 0;
- oper->literal[i] = (GLfloat) (a || b);
- }
- oper->literal_size = oper->children[0].literal_size;
- slang_operation_destruct(oper);
- oper->type = SLANG_OPER_LITERAL_BOOL;
- return;
- case SLANG_OPER_LOGICALXOR:
- for (i = 0; i < 4; i++) {
- const GLint a = oper->children[0].literal[i] ? 1 : 0;
- const GLint b = oper->children[1].literal[i] ? 1 : 0;
- oper->literal[i] = (GLfloat) (a ^ b);
- }
- oper->literal_size = oper->children[0].literal_size;
- slang_operation_destruct(oper);
- oper->type = SLANG_OPER_LITERAL_BOOL;
- return;
- default:
- ; /* nothing */
- }
- }
-
- if (oper->num_children == 4
- && isFloat[0] && isFloat[1] && isFloat[2] && isFloat[3]) {
- /* vec4(flt, flt, flt, flt) constructor */
- if (oper->type == SLANG_OPER_CALL) {
- if (strcmp((char *) oper->a_id, "vec4") == 0) {
- oper->literal[0] = oper->children[0].literal[0];
- oper->literal[1] = oper->children[1].literal[0];
- oper->literal[2] = oper->children[2].literal[0];
- oper->literal[3] = oper->children[3].literal[0];
- oper->literal_size = 4;
- slang_operation_destruct(oper);
- oper->type = SLANG_OPER_LITERAL_FLOAT;
- return;
- }
- }
- }
-
- if (oper->num_children == 3 && isFloat[0] && isFloat[1] && isFloat[2]) {
- /* vec3(flt, flt, flt) constructor */
- if (oper->type == SLANG_OPER_CALL) {
- if (strcmp((char *) oper->a_id, "vec3") == 0) {
- oper->literal[0] = oper->children[0].literal[0];
- oper->literal[1] = oper->children[1].literal[0];
- oper->literal[2] = oper->children[2].literal[0];
- oper->literal[3] = oper->literal[2];
- oper->literal_size = 3;
- slang_operation_destruct(oper);
- oper->type = SLANG_OPER_LITERAL_FLOAT;
- return;
- }
- }
- }
-
- if (oper->num_children == 2 && isFloat[0] && isFloat[1]) {
- /* vec2(flt, flt) constructor */
- if (oper->type == SLANG_OPER_CALL) {
- if (strcmp((char *) oper->a_id, "vec2") == 0) {
- oper->literal[0] = oper->children[0].literal[0];
- oper->literal[1] = oper->children[1].literal[0];
- oper->literal[2] = oper->literal[1];
- oper->literal[3] = oper->literal[1];
- oper->literal_size = 2;
- slang_operation_destruct(oper); /* XXX oper->locals goes NULL! */
- oper->type = SLANG_OPER_LITERAL_FLOAT;
- assert(oper->num_children == 0);
- return;
- }
- }
- }
-
- if (oper->num_children == 1 && isFloat[0]) {
- /* vec2/3/4(flt, flt) constructor */
- if (oper->type == SLANG_OPER_CALL) {
- const char *func = (const char *) oper->a_id;
- if (strncmp(func, "vec", 3) == 0 && func[3] >= '2' && func[3] <= '4') {
- oper->literal[0] =
- oper->literal[1] =
- oper->literal[2] =
- oper->literal[3] = oper->children[0].literal[0];
- oper->literal_size = func[3] - '0';
- assert(oper->literal_size >= 2);
- assert(oper->literal_size <= 4);
- slang_operation_destruct(oper); /* XXX oper->locals goes NULL! */
- oper->type = SLANG_OPER_LITERAL_FLOAT;
- assert(oper->num_children == 0);
- return;
- }
- }
- }
-}
-
-
-
-/**
- * Insert casts to try to adapt actual parameters to formal parameters for a
- * function call when an exact match for the parameter types is not found.
- * Example:
- * void foo(int i, bool b) {}
- * x = foo(3.15, 9);
- * Gets translated into:
- * x = foo(int(3.15), bool(9))
- */
-GLboolean
-_slang_cast_func_params(slang_operation *callOper, const slang_function *fun,
- const slang_name_space * space,
- slang_atom_pool * atoms, slang_info_log *log)
-{
- const GLboolean haveRetValue = _slang_function_has_return_value(fun);
- const int numParams = fun->param_count - haveRetValue;
- int i;
- int dbg = 0;
-
- if (dbg)
- printf("Adapt call of %d args to func %s (%d params)\n",
- callOper->num_children, (char*) fun->header.a_name, numParams);
-
- for (i = 0; i < numParams; i++) {
- slang_typeinfo argType;
- slang_variable *paramVar = fun->parameters->variables[i];
-
- /* Get type of arg[i] */
- if (!slang_typeinfo_construct(&argType))
- return GL_FALSE;
- if (!_slang_typeof_operation(&callOper->children[i], space,
- &argType, atoms, log)) {
- slang_typeinfo_destruct(&argType);
- return GL_FALSE;
- }
-
- /* see if arg type matches parameter type */
- if (!slang_type_specifier_equal(&argType.spec,
- ¶mVar->type.specifier)) {
- /* need to adapt arg type to match param type */
- const char *constructorName =
- slang_type_specifier_type_to_string(paramVar->type.specifier.type);
- slang_operation *child = slang_operation_new(1);
-
- if (dbg)
- printf("Need to adapt types of arg %d\n", i);
-
- slang_operation_copy(child, &callOper->children[i]);
- child->locals->outer_scope = callOper->children[i].locals;
-
-#if 0
- if (_slang_sizeof_type_specifier(&argType.spec) >
- _slang_sizeof_type_specifier(¶mVar->type.specifier)) {
- }
-#endif
-
- callOper->children[i].type = SLANG_OPER_CALL;
- callOper->children[i].a_id = slang_atom_pool_atom(atoms, constructorName);
- callOper->children[i].num_children = 1;
- callOper->children[i].children = child;
- }
-
- slang_typeinfo_destruct(&argType);
- }
-
- if (dbg) {
- printf("===== New call to %s with cast arguments ===============\n",
- (char*) fun->header.a_name);
- slang_print_tree(callOper, 5);
- }
-
- return GL_TRUE;
-}
-
-
-/**
- * Adapt the arguments for a function call to match the parameters of
- * the given function.
- * This is for:
- * 1. converting/casting argument types to match parameters
- * 2. breaking up vector/matrix types into individual components to
- * satisfy constructors.
- */
-GLboolean
-_slang_adapt_call(slang_operation *callOper, const slang_function *fun,
- const slang_name_space * space,
- slang_atom_pool * atoms, slang_info_log *log)
-{
- const GLboolean haveRetValue = _slang_function_has_return_value(fun);
- const int numParams = fun->param_count - haveRetValue;
- int i;
- int dbg = 0;
-
- if (dbg)
- printf("Adapt %d args to %d parameters for %s\n",
- callOper->num_children, numParams, (char *) fun->header.a_name);
-
- /* Only try adapting for constructors */
- if (fun->kind != SLANG_FUNC_CONSTRUCTOR)
- return GL_FALSE;
-
- if (callOper->num_children != numParams) {
- /* number of arguments doesn't match number of parameters */
-
- /* For constructor calls, we can try to unroll vector/matrix args
- * into individual floats/ints and try to match the function params.
- */
- for (i = 0; i < numParams; i++) {
- slang_typeinfo argType;
- GLint argSz, j;
-
- /* Get type of arg[i] */
- if (!slang_typeinfo_construct(&argType))
- return GL_FALSE;
- if (!_slang_typeof_operation(&callOper->children[i], space,
- &argType, atoms, log)) {
- slang_typeinfo_destruct(&argType);
- return GL_FALSE;
- }
-
- /*
- paramSz = _slang_sizeof_type_specifier(¶mVar->type.specifier);
- assert(paramSz == 1);
- */
- argSz = _slang_sizeof_type_specifier(&argType.spec);
- if (argSz > 1) {
- slang_operation origArg;
- /* break up arg[i] into components */
- if (dbg)
- printf("Break up arg %d from 1 to %d elements\n", i, argSz);
-
- slang_operation_construct(&origArg);
- slang_operation_copy(&origArg, &callOper->children[i]);
-
- /* insert argSz-1 new children/args */
- for (j = 0; j < argSz - 1; j++) {
- (void) slang_operation_insert(&callOper->num_children,
- &callOper->children, i);
- }
-
- /* replace arg[i+j] with subscript/index oper */
- for (j = 0; j < argSz; j++) {
- callOper->children[i + j].type = SLANG_OPER_SUBSCRIPT;
- callOper->children[i + j].locals = _slang_variable_scope_new(callOper->locals);
- callOper->children[i + j].num_children = 2;
- callOper->children[i + j].children = slang_operation_new(2);
- slang_operation_copy(&callOper->children[i + j].children[0],
- &origArg);
- callOper->children[i + j].children[1].type
- = SLANG_OPER_LITERAL_INT;
- callOper->children[i + j].children[1].literal[0] = (GLfloat) j;
- }
- }
- }
- }
-
- if (callOper->num_children < (GLuint) numParams) {
- /* still not enough args for all params */
- return GL_FALSE;
- }
- else if (callOper->num_children > (GLuint) numParams) {
- /* now too many arguments */
- /* just truncate */
- callOper->num_children = (GLuint) numParams;
- }
-
- if (dbg) {
- printf("===== New call to %s with adapted arguments ===============\n",
- (char*) fun->header.a_name);
- slang_print_tree(callOper, 5);
- }
-
- return GL_TRUE;
-}
+++ /dev/null
-/*
- * Mesa 3-D graphics library
- * Version: 7.1
- *
- * Copyright (C) 2005-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.
- */
-
-#ifndef SLANG_SIMPLIFY_H
-#define SLANG_SIMPLIFY_H
-
-
-#include "main/glheader.h"
-#include "slang_compile.h"
-#include "slang_compile_function.h"
-#include "slang_compile_operation.h"
-#include "slang_log.h"
-#include "slang_utility.h"
-
-extern GLint
-_slang_lookup_constant(const char *name);
-
-
-extern void
-_slang_simplify(slang_operation *oper,
- const slang_name_space * space,
- slang_atom_pool * atoms);
-
-
-extern GLboolean
-_slang_cast_func_params(slang_operation *callOper, const slang_function *fun,
- const slang_name_space * space,
- slang_atom_pool * atoms, slang_info_log *log);
-
-extern GLboolean
-_slang_adapt_call(slang_operation *callOper, const slang_function *fun,
- const slang_name_space * space,
- slang_atom_pool * atoms, slang_info_log *log);
-
-
-#endif /* SLANG_SIMPLIFY_H */
+++ /dev/null
-/*
- * Mesa 3-D graphics library
- * Version: 6.5
- *
- * Copyright (C) 2005-2006 Brian Paul All Rights Reserved.
- *
- * Permission is hereby granted, free of charge, to any person obtaining a
- * copy of this software and associated documentation files (the "Software"),
- * to deal in the Software without restriction, including without limitation
- * the rights to use, copy, modify, merge, publish, distribute, sublicense,
- * and/or sell copies of the Software, and to permit persons to whom the
- * Software is furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included
- * in all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
- * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
- * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
- * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
- * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
- */
-
-/**
- * \file slang_storage.c
- * slang variable storage
- * \author Michal Krol
- */
-
-#include "main/imports.h"
-#include "slang_storage.h"
-#include "slang_mem.h"
-
-/* slang_storage_array */
-
-GLboolean
-slang_storage_array_construct(slang_storage_array * arr)
-{
- arr->type = SLANG_STORE_AGGREGATE;
- arr->aggregate = NULL;
- arr->length = 0;
- return GL_TRUE;
-}
-
-GLvoid
-slang_storage_array_destruct(slang_storage_array * arr)
-{
- if (arr->aggregate != NULL) {
- slang_storage_aggregate_destruct(arr->aggregate);
- _slang_free(arr->aggregate);
- }
-}
-
-/* slang_storage_aggregate */
-
-GLboolean
-slang_storage_aggregate_construct(slang_storage_aggregate * agg)
-{
- agg->arrays = NULL;
- agg->count = 0;
- return GL_TRUE;
-}
-
-GLvoid
-slang_storage_aggregate_destruct(slang_storage_aggregate * agg)
-{
- GLuint i;
-
- for (i = 0; i < agg->count; i++)
- slang_storage_array_destruct(agg->arrays + i);
- _slang_free(agg->arrays);
-}
-
-static slang_storage_array *
-slang_storage_aggregate_push_new(slang_storage_aggregate * agg)
-{
- slang_storage_array *arr = NULL;
-
- agg->arrays = (slang_storage_array *)
- _slang_realloc(agg->arrays,
- agg->count * sizeof(slang_storage_array),
- (agg->count + 1) * sizeof(slang_storage_array));
- if (agg->arrays != NULL) {
- arr = agg->arrays + agg->count;
- if (!slang_storage_array_construct(arr))
- return NULL;
- agg->count++;
- }
- return arr;
-}
-
-/* _slang_aggregate_variable() */
-
-static GLboolean
-aggregate_vector(slang_storage_aggregate * agg, slang_storage_type basic_type,
- GLuint row_count)
-{
- slang_storage_array *arr = slang_storage_aggregate_push_new(agg);
- if (arr == NULL)
- return GL_FALSE;
- arr->type = basic_type;
- arr->length = row_count;
- return GL_TRUE;
-}
-
-static GLboolean
-aggregate_matrix(slang_storage_aggregate * agg, slang_storage_type basic_type,
- GLuint columns, GLuint rows)
-{
- slang_storage_array *arr = slang_storage_aggregate_push_new(agg);
- if (arr == NULL)
- return GL_FALSE;
- arr->type = SLANG_STORE_AGGREGATE;
- arr->length = columns;
- arr->aggregate = (slang_storage_aggregate *)
- _slang_alloc(sizeof(slang_storage_aggregate));
- if (arr->aggregate == NULL)
- return GL_FALSE;
- if (!slang_storage_aggregate_construct(arr->aggregate)) {
- _slang_free(arr->aggregate);
- arr->aggregate = NULL;
- return GL_FALSE;
- }
- if (!aggregate_vector(arr->aggregate, basic_type, rows))
- return GL_FALSE;
- return GL_TRUE;
-}
-
-
-static GLboolean
-aggregate_variables(slang_storage_aggregate * agg,
- slang_variable_scope * vars, slang_function_scope * funcs,
- slang_struct_scope * structs,
- slang_variable_scope * globals,
- slang_atom_pool * atoms)
-{
- GLuint i;
-
- for (i = 0; i < vars->num_variables; i++)
- if (!_slang_aggregate_variable(agg, &vars->variables[i]->type.specifier,
- vars->variables[i]->array_len, funcs,
- structs, globals, atoms))
- return GL_FALSE;
- return GL_TRUE;
-}
-
-
-GLboolean
-_slang_aggregate_variable(slang_storage_aggregate * agg,
- slang_type_specifier * spec, GLuint array_len,
- slang_function_scope * funcs,
- slang_struct_scope * structs,
- slang_variable_scope * vars,
- slang_atom_pool * atoms)
-{
- switch (spec->type) {
- case SLANG_SPEC_BOOL:
- return aggregate_vector(agg, SLANG_STORE_BOOL, 1);
- case SLANG_SPEC_BVEC2:
- return aggregate_vector(agg, SLANG_STORE_BOOL, 2);
- case SLANG_SPEC_BVEC3:
- return aggregate_vector(agg, SLANG_STORE_BOOL, 3);
- case SLANG_SPEC_BVEC4:
- return aggregate_vector(agg, SLANG_STORE_BOOL, 4);
- case SLANG_SPEC_INT:
- return aggregate_vector(agg, SLANG_STORE_INT, 1);
- case SLANG_SPEC_IVEC2:
- return aggregate_vector(agg, SLANG_STORE_INT, 2);
- case SLANG_SPEC_IVEC3:
- return aggregate_vector(agg, SLANG_STORE_INT, 3);
- case SLANG_SPEC_IVEC4:
- return aggregate_vector(agg, SLANG_STORE_INT, 4);
- case SLANG_SPEC_FLOAT:
- return aggregate_vector(agg, SLANG_STORE_FLOAT, 1);
- case SLANG_SPEC_VEC2:
- return aggregate_vector(agg, SLANG_STORE_FLOAT, 2);
- case SLANG_SPEC_VEC3:
- return aggregate_vector(agg, SLANG_STORE_FLOAT, 3);
- case SLANG_SPEC_VEC4:
- return aggregate_vector(agg, SLANG_STORE_FLOAT, 4);
- case SLANG_SPEC_MAT2:
- return aggregate_matrix(agg, SLANG_STORE_FLOAT, 2, 2);
- case SLANG_SPEC_MAT3:
- return aggregate_matrix(agg, SLANG_STORE_FLOAT, 3, 3);
- case SLANG_SPEC_MAT4:
- return aggregate_matrix(agg, SLANG_STORE_FLOAT, 4, 4);
-
- case SLANG_SPEC_MAT23:
- return aggregate_matrix(agg, SLANG_STORE_FLOAT, 2, 3);
- case SLANG_SPEC_MAT32:
- return aggregate_matrix(agg, SLANG_STORE_FLOAT, 3, 2);
- case SLANG_SPEC_MAT24:
- return aggregate_matrix(agg, SLANG_STORE_FLOAT, 2, 4);
- case SLANG_SPEC_MAT42:
- return aggregate_matrix(agg, SLANG_STORE_FLOAT, 4, 2);
- case SLANG_SPEC_MAT34:
- return aggregate_matrix(agg, SLANG_STORE_FLOAT, 3, 4);
- case SLANG_SPEC_MAT43:
- return aggregate_matrix(agg, SLANG_STORE_FLOAT, 4, 3);
-
- case SLANG_SPEC_SAMPLER_1D:
- case SLANG_SPEC_SAMPLER_2D:
- case SLANG_SPEC_SAMPLER_3D:
- case SLANG_SPEC_SAMPLER_CUBE:
- case SLANG_SPEC_SAMPLER_1D_SHADOW:
- case SLANG_SPEC_SAMPLER_2D_SHADOW:
- case SLANG_SPEC_SAMPLER_RECT:
- case SLANG_SPEC_SAMPLER_RECT_SHADOW:
- case SLANG_SPEC_SAMPLER_1D_ARRAY:
- case SLANG_SPEC_SAMPLER_2D_ARRAY:
- case SLANG_SPEC_SAMPLER_1D_ARRAY_SHADOW:
- case SLANG_SPEC_SAMPLER_2D_ARRAY_SHADOW:
-
- return aggregate_vector(agg, SLANG_STORE_INT, 1);
- case SLANG_SPEC_STRUCT:
- return aggregate_variables(agg, spec->_struct->fields, funcs, structs,
- vars, atoms);
- case SLANG_SPEC_ARRAY:
- {
- slang_storage_array *arr;
-
- arr = slang_storage_aggregate_push_new(agg);
- if (arr == NULL)
- return GL_FALSE;
- arr->type = SLANG_STORE_AGGREGATE;
- arr->aggregate = (slang_storage_aggregate *)
- _slang_alloc(sizeof(slang_storage_aggregate));
- if (arr->aggregate == NULL)
- return GL_FALSE;
- if (!slang_storage_aggregate_construct(arr->aggregate)) {
- _slang_free(arr->aggregate);
- arr->aggregate = NULL;
- return GL_FALSE;
- }
- if (!_slang_aggregate_variable(arr->aggregate, spec->_array, 0,
- funcs, structs, vars, atoms))
- return GL_FALSE;
- arr->length = array_len;
- /* TODO: check if 0 < arr->length <= 65535 */
- }
- return GL_TRUE;
- default:
- return GL_FALSE;
- }
-}
-
-
-GLuint
-_slang_sizeof_type(slang_storage_type type)
-{
- if (type == SLANG_STORE_AGGREGATE)
- return 0;
- if (type == SLANG_STORE_VEC4)
- return 4 * sizeof(GLfloat);
- return sizeof(GLfloat);
-}
-
-
-GLuint
-_slang_sizeof_aggregate(const slang_storage_aggregate * agg)
-{
- GLuint i, size = 0;
-
- for (i = 0; i < agg->count; i++) {
- slang_storage_array *arr = &agg->arrays[i];
- GLuint element_size;
-
- if (arr->type == SLANG_STORE_AGGREGATE)
- element_size = _slang_sizeof_aggregate(arr->aggregate);
- else
- element_size = _slang_sizeof_type(arr->type);
- size += element_size * arr->length;
- }
- return size;
-}
-
-
-#if 0
-GLboolean
-_slang_flatten_aggregate(slang_storage_aggregate * flat,
- const slang_storage_aggregate * agg)
-{
- GLuint i;
-
- for (i = 0; i < agg->count; i++) {
- GLuint j;
-
- for (j = 0; j < agg->arrays[i].length; j++) {
- if (agg->arrays[i].type == SLANG_STORE_AGGREGATE) {
- if (!_slang_flatten_aggregate(flat, agg->arrays[i].aggregate))
- return GL_FALSE;
- }
- else {
- GLuint k, count;
- slang_storage_type type;
-
- if (agg->arrays[i].type == SLANG_STORE_VEC4) {
- count = 4;
- type = SLANG_STORE_FLOAT;
- }
- else {
- count = 1;
- type = agg->arrays[i].type;
- }
-
- for (k = 0; k < count; k++) {
- slang_storage_array *arr;
-
- arr = slang_storage_aggregate_push_new(flat);
- if (arr == NULL)
- return GL_FALSE;
- arr->type = type;
- arr->length = 1;
- }
- }
- }
- }
- return GL_TRUE;
-}
-#endif
+++ /dev/null
-/*
- * Mesa 3-D graphics library
- * Version: 6.5
- *
- * Copyright (C) 2005-2006 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 SLANG_STORAGE_H
-#define SLANG_STORAGE_H
-
-#include "main/glheader.h"
-#include "slang_compile_function.h"
-#include "slang_compile_struct.h"
-#include "slang_compile_variable.h"
-#include "slang_typeinfo.h"
-#include "slang_utility.h"
-
-
-/*
- * Program variable data storage is kept completely transparent to the
- * front-end compiler. It is up to the back-end how the data is
- * actually allocated. The slang_storage_type enum provides the basic
- * information about how the memory is interpreted. This abstract
- * piece of memory is called a data slot. A data slot of a particular
- * type has a fixed size.
- *
- * For now, only the three basic types are supported, that is bool,
- * int and float. Other built-in types like vector or matrix can
- * easily be decomposed into a series of basic types.
- *
- * If the vec4 module is enabled, 4-component vectors of floats are
- * used when possible. 4x4 matrices are constructed of 4 vec4 slots.
- */
-typedef enum slang_storage_type_
-{
- /* core */
- SLANG_STORE_AGGREGATE,
- SLANG_STORE_BOOL,
- SLANG_STORE_INT,
- SLANG_STORE_FLOAT,
- /* vec4 */
- SLANG_STORE_VEC4
-} slang_storage_type;
-
-
-/**
- * The slang_storage_array structure groups data slots of the same
- * type into an array. This array has a fixed length. Arrays are
- * required to have a size equal to the sum of sizes of its
- * elements. They are also required to support indirect
- * addressing. That is, if B references first data slot in the array,
- * S is the size of the data slot and I is the integral index that is
- * not known at compile time, B+I*S references I-th data slot.
- *
- * This structure is also used to break down built-in data types that
- * are not supported directly. Vectors, like vec3, are constructed
- * from arrays of their basic types. Matrices are formed of an array
- * of column vectors, which are in turn processed as other vectors.
- */
-typedef struct slang_storage_array_
-{
- slang_storage_type type;
- struct slang_storage_aggregate_ *aggregate;
- GLuint length;
-} slang_storage_array;
-
-GLboolean slang_storage_array_construct (slang_storage_array *);
-GLvoid slang_storage_array_destruct (slang_storage_array *);
-
-
-/**
- * The slang_storage_aggregate structure relaxes the indirect
- * addressing requirement for slang_storage_array
- * structure. Aggregates are always accessed statically - its member
- * addresses are well-known at compile time. For example, user-defined
- * types are implemented as aggregates. Aggregates can collect data of
- * a different type.
- */
-typedef struct slang_storage_aggregate_
-{
- slang_storage_array *arrays;
- GLuint count;
-} slang_storage_aggregate;
-
-GLboolean slang_storage_aggregate_construct (slang_storage_aggregate *);
-GLvoid slang_storage_aggregate_destruct (slang_storage_aggregate *);
-
-
-extern GLboolean
-_slang_aggregate_variable(slang_storage_aggregate *agg,
- slang_type_specifier *spec,
- GLuint array_len,
- slang_function_scope *funcs,
- slang_struct_scope *structs,
- slang_variable_scope *vars,
- slang_atom_pool *atoms);
-
-/*
- * Returns the size (in machine units) of the given storage type.
- * It is an error to pass-in SLANG_STORE_AGGREGATE.
- * Returns 0 on error.
- */
-extern GLuint
-_slang_sizeof_type (slang_storage_type);
-
-
-/**
- * Returns total size (in machine units) of the given aggregate.
- * Returns 0 on error.
- */
-extern GLuint
-_slang_sizeof_aggregate (const slang_storage_aggregate *);
-
-
-#if 0
-/**
- * Converts structured aggregate to a flat one, with arrays of generic
- * type being one-element long. Returns GL_TRUE on success. Returns
- * GL_FALSE otherwise.
- */
-extern GLboolean
-_slang_flatten_aggregate (slang_storage_aggregate *,
- const slang_storage_aggregate *);
-
-#endif
-
-#endif /* SLANG_STORAGE_H */
+++ /dev/null
-/*
- * Mesa 3-D graphics library
- * Version: 6.5
- *
- * Copyright (C) 2005-2006 Brian Paul All Rights Reserved.
- *
- * Permission is hereby granted, free of charge, to any person obtaining a
- * copy of this software and associated documentation files (the "Software"),
- * to deal in the Software without restriction, including without limitation
- * the rights to use, copy, modify, merge, publish, distribute, sublicense,
- * and/or sell copies of the Software, and to permit persons to whom the
- * Software is furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included
- * in all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
- * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
- * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
- * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
- * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
- */
-
-/**
- * \file slang_typeinfo.c
- * slang type info
- * \author Michal Krol
- */
-
-#include "main/imports.h"
-#include "program/prog_instruction.h"
-#include "slang_typeinfo.h"
-#include "slang_compile.h"
-#include "slang_log.h"
-#include "slang_mem.h"
-
-
-/**
- * Checks if a field selector is a general swizzle (an r-value swizzle
- * with replicated components or an l-value swizzle mask) for a
- * vector. Returns GL_TRUE if this is the case, <swz> is filled with
- * swizzle information. Returns GL_FALSE otherwise.
- */
-GLboolean
-_slang_is_swizzle(const char *field, GLuint rows, slang_swizzle * swz)
-{
- GLuint i;
- GLboolean xyzw = GL_FALSE, rgba = GL_FALSE, stpq = GL_FALSE;
-
- /* init to undefined.
- * We rely on undefined/nil values to distinguish between
- * regular swizzles and writemasks.
- * For example, the swizzle ".xNNN" is the writemask ".x".
- * That's different than the swizzle ".xxxx".
- */
- for (i = 0; i < 4; i++)
- swz->swizzle[i] = SWIZZLE_NIL;
-
- /* the swizzle can be at most 4-component long */
- swz->num_components = slang_string_length(field);
- if (swz->num_components > 4)
- return GL_FALSE;
-
- for (i = 0; i < swz->num_components; i++) {
- /* mark which swizzle group is used */
- switch (field[i]) {
- case 'x':
- case 'y':
- case 'z':
- case 'w':
- xyzw = GL_TRUE;
- break;
- case 'r':
- case 'g':
- case 'b':
- case 'a':
- rgba = GL_TRUE;
- break;
- case 's':
- case 't':
- case 'p':
- case 'q':
- stpq = GL_TRUE;
- break;
- default:
- return GL_FALSE;
- }
-
- /* collect swizzle component */
- switch (field[i]) {
- case 'x':
- case 'r':
- case 's':
- swz->swizzle[i] = 0;
- break;
- case 'y':
- case 'g':
- case 't':
- swz->swizzle[i] = 1;
- break;
- case 'z':
- case 'b':
- case 'p':
- swz->swizzle[i] = 2;
- break;
- case 'w':
- case 'a':
- case 'q':
- swz->swizzle[i] = 3;
- break;
- }
-
- /* check if the component is valid for given vector's row count */
- if (rows <= swz->swizzle[i])
- return GL_FALSE;
- }
-
- /* only one swizzle group can be used */
- if ((xyzw && rgba) || (xyzw && stpq) || (rgba && stpq))
- return GL_FALSE;
-
- return GL_TRUE;
-}
-
-
-
-/**
- * Checks if a general swizzle is an l-value swizzle - these swizzles
- * do not have duplicated fields. Returns GL_TRUE if this is a
- * swizzle mask. Returns GL_FALSE otherwise
- */
-static GLboolean
-_slang_is_swizzle_mask(const slang_swizzle * swz, GLuint rows)
-{
- GLuint i, c = 0;
-
- /* the swizzle may not be longer than the vector dim */
- if (swz->num_components > rows)
- return GL_FALSE;
-
- /* the swizzle components cannot be duplicated */
- for (i = 0; i < swz->num_components; i++) {
- if ((c & (1 << swz->swizzle[i])) != 0)
- return GL_FALSE;
- c |= 1 << swz->swizzle[i];
- }
-
- return GL_TRUE;
-}
-
-
-/**
- * Combines (multiplies) two swizzles to form single swizzle.
- * Example: "vec.wzyx.yx" --> "vec.zw".
- */
-static void
-_slang_multiply_swizzles(slang_swizzle * dst, const slang_swizzle * left,
- const slang_swizzle * right)
-{
- GLuint i;
-
- dst->num_components = right->num_components;
- for (i = 0; i < right->num_components; i++)
- dst->swizzle[i] = left->swizzle[right->swizzle[i]];
-}
-
-
-typedef struct
-{
- const char *name;
- slang_type_specifier_type type;
-} type_specifier_type_name;
-
-static const type_specifier_type_name type_specifier_type_names[] = {
- {"void", SLANG_SPEC_VOID},
- {"bool", SLANG_SPEC_BOOL},
- {"bvec2", SLANG_SPEC_BVEC2},
- {"bvec3", SLANG_SPEC_BVEC3},
- {"bvec4", SLANG_SPEC_BVEC4},
- {"int", SLANG_SPEC_INT},
- {"ivec2", SLANG_SPEC_IVEC2},
- {"ivec3", SLANG_SPEC_IVEC3},
- {"ivec4", SLANG_SPEC_IVEC4},
- {"float", SLANG_SPEC_FLOAT},
- {"vec2", SLANG_SPEC_VEC2},
- {"vec3", SLANG_SPEC_VEC3},
- {"vec4", SLANG_SPEC_VEC4},
- {"mat2", SLANG_SPEC_MAT2},
- {"mat3", SLANG_SPEC_MAT3},
- {"mat4", SLANG_SPEC_MAT4},
- {"mat2x3", SLANG_SPEC_MAT23},
- {"mat3x2", SLANG_SPEC_MAT32},
- {"mat2x4", SLANG_SPEC_MAT24},
- {"mat4x2", SLANG_SPEC_MAT42},
- {"mat3x4", SLANG_SPEC_MAT34},
- {"mat4x3", SLANG_SPEC_MAT43},
- {"sampler1D", SLANG_SPEC_SAMPLER_1D},
- {"sampler2D", SLANG_SPEC_SAMPLER_2D},
- {"sampler3D", SLANG_SPEC_SAMPLER_3D},
- {"samplerCube", SLANG_SPEC_SAMPLER_CUBE},
- {"sampler1DShadow", SLANG_SPEC_SAMPLER_1D_SHADOW},
- {"sampler2DShadow", SLANG_SPEC_SAMPLER_2D_SHADOW},
- {"sampler2DRect", SLANG_SPEC_SAMPLER_RECT},
- {"sampler2DRectShadow", SLANG_SPEC_SAMPLER_RECT_SHADOW},
- {"sampler1DArray", SLANG_SPEC_SAMPLER_1D_ARRAY},
- {"sampler2DArray", SLANG_SPEC_SAMPLER_2D_ARRAY},
- {"sampler1DArrayShadow", SLANG_SPEC_SAMPLER_1D_ARRAY_SHADOW},
- {"sampler2DArrayShadow", SLANG_SPEC_SAMPLER_2D_ARRAY_SHADOW},
- {NULL, SLANG_SPEC_VOID}
-};
-
-slang_type_specifier_type
-slang_type_specifier_type_from_string(const char *name)
-{
- const type_specifier_type_name *p = type_specifier_type_names;
- while (p->name != NULL) {
- if (slang_string_compare(p->name, name) == 0)
- break;
- p++;
- }
- return p->type;
-}
-
-const char *
-slang_type_specifier_type_to_string(slang_type_specifier_type type)
-{
- const type_specifier_type_name *p = type_specifier_type_names;
- while (p->name != NULL) {
- if (p->type == type)
- break;
- p++;
- }
- return p->name;
-}
-
-/* slang_fully_specified_type */
-
-int
-slang_fully_specified_type_construct(slang_fully_specified_type * type)
-{
- type->qualifier = SLANG_QUAL_NONE;
- slang_type_specifier_ctr(&type->specifier);
- return 1;
-}
-
-void
-slang_fully_specified_type_destruct(slang_fully_specified_type * type)
-{
- slang_type_specifier_dtr(&type->specifier);
-}
-
-int
-slang_fully_specified_type_copy(slang_fully_specified_type * x,
- const slang_fully_specified_type * y)
-{
- slang_fully_specified_type z;
-
- if (!slang_fully_specified_type_construct(&z))
- return 0;
- z.qualifier = y->qualifier;
- z.precision = y->precision;
- z.variant = y->variant;
- z.centroid = y->centroid;
- z.layout = y->layout;
- z.array_len = y->array_len;
- if (!slang_type_specifier_copy(&z.specifier, &y->specifier)) {
- slang_fully_specified_type_destruct(&z);
- return 0;
- }
- slang_fully_specified_type_destruct(x);
- *x = z;
- return 1;
-}
-
-
-/**
- * Test if two fully specified types are compatible. This is a bit
- * looser than testing for equality. We don't check the precision,
- * variant, centroid, etc. information.
- * XXX this may need some tweaking.
- */
-GLboolean
-slang_fully_specified_types_compatible(const slang_fully_specified_type * x,
- const slang_fully_specified_type * y)
-{
- if (!slang_type_specifier_equal(&x->specifier, &y->specifier))
- return GL_FALSE;
-
- if (x->qualifier == SLANG_QUAL_FIXEDINPUT &&
- y->qualifier == SLANG_QUAL_VARYING)
- ; /* ok */
- else if (x->qualifier != y->qualifier)
- return GL_FALSE;
-
- /* Note: don't compare precision, variant, centroid */
-
- /* XXX array length? */
-
- return GL_TRUE;
-}
-
-
-GLvoid
-slang_type_specifier_ctr(slang_type_specifier * self)
-{
- self->type = SLANG_SPEC_VOID;
- self->_struct = NULL;
- self->_array = NULL;
-}
-
-GLvoid
-slang_type_specifier_dtr(slang_type_specifier * self)
-{
- if (self->_struct != NULL) {
- slang_struct_destruct(self->_struct);
- _slang_free(self->_struct);
- }
- if (self->_array != NULL) {
- slang_type_specifier_dtr(self->_array);
- _slang_free(self->_array);
- }
-}
-
-slang_type_specifier *
-slang_type_specifier_new(slang_type_specifier_type type,
- struct slang_struct_ *_struct,
- struct slang_type_specifier_ *_array)
-{
- slang_type_specifier *spec =
- (slang_type_specifier *) _slang_alloc(sizeof(slang_type_specifier));
- if (spec) {
- spec->type = type;
- spec->_struct = _struct;
- spec->_array = _array;
- }
- return spec;
-}
-
-GLboolean
-slang_type_specifier_copy(slang_type_specifier * x,
- const slang_type_specifier * y)
-{
- slang_type_specifier z;
-
- slang_type_specifier_ctr(&z);
- z.type = y->type;
- if (z.type == SLANG_SPEC_STRUCT) {
- z._struct = (slang_struct *) _slang_alloc(sizeof(slang_struct));
- if (z._struct == NULL) {
- slang_type_specifier_dtr(&z);
- return GL_FALSE;
- }
- if (!slang_struct_construct(z._struct)) {
- _slang_free(z._struct);
- slang_type_specifier_dtr(&z);
- return GL_FALSE;
- }
- if (!slang_struct_copy(z._struct, y->_struct)) {
- slang_type_specifier_dtr(&z);
- return GL_FALSE;
- }
- }
- else if (z.type == SLANG_SPEC_ARRAY) {
- z._array = (slang_type_specifier *)
- _slang_alloc(sizeof(slang_type_specifier));
- if (z._array == NULL) {
- slang_type_specifier_dtr(&z);
- return GL_FALSE;
- }
- slang_type_specifier_ctr(z._array);
- if (!slang_type_specifier_copy(z._array, y->_array)) {
- slang_type_specifier_dtr(&z);
- return GL_FALSE;
- }
- }
- slang_type_specifier_dtr(x);
- *x = z;
- return GL_TRUE;
-}
-
-
-/**
- * Test if two types are equal.
- */
-GLboolean
-slang_type_specifier_equal(const slang_type_specifier * x,
- const slang_type_specifier * y)
-{
- if (x->type != y->type)
- return GL_FALSE;
- if (x->type == SLANG_SPEC_STRUCT)
- return slang_struct_equal(x->_struct, y->_struct);
- if (x->type == SLANG_SPEC_ARRAY)
- return slang_type_specifier_equal(x->_array, y->_array);
- return GL_TRUE;
-}
-
-
-/**
- * As above, but allow float/int casting.
- */
-GLboolean
-slang_type_specifier_compatible(const slang_type_specifier * x,
- const slang_type_specifier * y)
-{
- /* special case: float == int */
- if (x->type == SLANG_SPEC_INT && y->type == SLANG_SPEC_FLOAT) {
- return GL_TRUE;
- }
- /* XXX may need to add bool/int compatibility, etc */
-
- if (x->type != y->type)
- return GL_FALSE;
- if (x->type == SLANG_SPEC_STRUCT)
- return slang_struct_equal(x->_struct, y->_struct);
- if (x->type == SLANG_SPEC_ARRAY)
- return slang_type_specifier_compatible(x->_array, y->_array);
- return GL_TRUE;
-}
-
-
-GLboolean
-slang_typeinfo_construct(slang_typeinfo * ti)
-{
- memset(ti, 0, sizeof(*ti));
- slang_type_specifier_ctr(&ti->spec);
- ti->array_len = 0;
- return GL_TRUE;
-}
-
-GLvoid
-slang_typeinfo_destruct(slang_typeinfo * ti)
-{
- slang_type_specifier_dtr(&ti->spec);
-}
-
-
-
-/**
- * Determine the return type of a function.
- * \param a_name the function name
- * \param param function parameters (overloading)
- * \param num_params number of parameters to function
- * \param space namespace to search
- * \param spec returns the type
- * \param funFound returns pointer to the function, or NULL if not found.
- * \return GL_TRUE for success, GL_FALSE if failure (bad function name)
- */
-static GLboolean
-_slang_typeof_function(slang_atom a_name,
- slang_operation * params, GLuint num_params,
- const slang_name_space * space,
- slang_type_specifier * spec,
- slang_function **funFound,
- slang_atom_pool *atoms, slang_info_log *log)
-{
- GLboolean error;
-
- *funFound = _slang_function_locate(space->funcs, a_name, params,
- num_params, space, atoms, log, &error);
- if (error)
- return GL_FALSE;
-
- if (!*funFound)
- return GL_TRUE; /* yes, not false */
-
- return slang_type_specifier_copy(spec, &(*funFound)->header.type.specifier);
-}
-
-
-/**
- * Determine the type of a math function.
- * \param name name of the operator, one of +,-,*,/ or unary -
- * \param params array of function parameters
- * \param num_params number of parameters
- * \param space namespace to use
- * \param spec returns the function's type
- * \param atoms atom pool
- * \return GL_TRUE for success, GL_FALSE if failure
- */
-static GLboolean
-typeof_math_call(const char *name, slang_operation *call,
- const slang_name_space * space,
- slang_type_specifier * spec,
- slang_atom_pool * atoms,
- slang_info_log *log)
-{
- if (call->fun) {
- /* we've previously resolved this function call */
- slang_type_specifier_copy(spec, &call->fun->header.type.specifier);
- return GL_TRUE;
- }
- else {
- slang_atom atom;
- slang_function *fun;
-
- /* number of params: */
- assert(call->num_children == 1 || call->num_children == 2);
-
- atom = slang_atom_pool_atom(atoms, name);
- if (!_slang_typeof_function(atom, call->children, call->num_children,
- space, spec, &fun, atoms, log))
- return GL_FALSE;
-
- if (fun) {
- /* Save pointer to save time in future */
- call->fun = fun;
- return GL_TRUE;
- }
- return GL_FALSE;
- }
-}
-
-
-/**
- * Determine the return type of an operation.
- * \param op the operation node
- * \param space the namespace to use
- * \param ti the returned type
- * \param atoms atom pool
- * \return GL_TRUE for success, GL_FALSE if failure
- */
-GLboolean
-_slang_typeof_operation(slang_operation * op,
- const slang_name_space * space,
- slang_typeinfo * ti,
- slang_atom_pool * atoms,
- slang_info_log *log)
-{
- ti->can_be_referenced = GL_FALSE;
- ti->is_swizzled = GL_FALSE;
-
- switch (op->type) {
- case SLANG_OPER_BLOCK_NO_NEW_SCOPE:
- case SLANG_OPER_BLOCK_NEW_SCOPE:
- case SLANG_OPER_ASM:
- case SLANG_OPER_BREAK:
- case SLANG_OPER_CONTINUE:
- case SLANG_OPER_DISCARD:
- case SLANG_OPER_RETURN:
- case SLANG_OPER_IF:
- case SLANG_OPER_WHILE:
- case SLANG_OPER_DO:
- case SLANG_OPER_FOR:
- case SLANG_OPER_VOID:
- ti->spec.type = SLANG_SPEC_VOID;
- break;
- case SLANG_OPER_EXPRESSION:
- case SLANG_OPER_ASSIGN:
- case SLANG_OPER_ADDASSIGN:
- case SLANG_OPER_SUBASSIGN:
- case SLANG_OPER_MULASSIGN:
- case SLANG_OPER_DIVASSIGN:
- case SLANG_OPER_PREINCREMENT:
- case SLANG_OPER_PREDECREMENT:
- if (!_slang_typeof_operation(op->children, space, ti, atoms, log))
- return GL_FALSE;
- break;
- case SLANG_OPER_LITERAL_BOOL:
- if (op->literal_size == 1)
- ti->spec.type = SLANG_SPEC_BOOL;
- else if (op->literal_size == 2)
- ti->spec.type = SLANG_SPEC_BVEC2;
- else if (op->literal_size == 3)
- ti->spec.type = SLANG_SPEC_BVEC3;
- else if (op->literal_size == 4)
- ti->spec.type = SLANG_SPEC_BVEC4;
- else {
- _mesa_problem(NULL,
- "Unexpected bool literal_size %d in _slang_typeof_operation()",
- op->literal_size);
- ti->spec.type = SLANG_SPEC_BOOL;
- }
- break;
- case SLANG_OPER_LOGICALOR:
- case SLANG_OPER_LOGICALXOR:
- case SLANG_OPER_LOGICALAND:
- case SLANG_OPER_EQUAL:
- case SLANG_OPER_NOTEQUAL:
- case SLANG_OPER_LESS:
- case SLANG_OPER_GREATER:
- case SLANG_OPER_LESSEQUAL:
- case SLANG_OPER_GREATEREQUAL:
- case SLANG_OPER_NOT:
- ti->spec.type = SLANG_SPEC_BOOL;
- break;
- case SLANG_OPER_LITERAL_INT:
- if (op->literal_size == 1)
- ti->spec.type = SLANG_SPEC_INT;
- else if (op->literal_size == 2)
- ti->spec.type = SLANG_SPEC_IVEC2;
- else if (op->literal_size == 3)
- ti->spec.type = SLANG_SPEC_IVEC3;
- else if (op->literal_size == 4)
- ti->spec.type = SLANG_SPEC_IVEC4;
- else {
- _mesa_problem(NULL,
- "Unexpected int literal_size %d in _slang_typeof_operation()",
- op->literal_size);
- ti->spec.type = SLANG_SPEC_INT;
- }
- break;
- case SLANG_OPER_LITERAL_FLOAT:
- if (op->literal_size == 1)
- ti->spec.type = SLANG_SPEC_FLOAT;
- else if (op->literal_size == 2)
- ti->spec.type = SLANG_SPEC_VEC2;
- else if (op->literal_size == 3)
- ti->spec.type = SLANG_SPEC_VEC3;
- else if (op->literal_size == 4)
- ti->spec.type = SLANG_SPEC_VEC4;
- else {
- _mesa_problem(NULL,
- "Unexpected float literal_size %d in _slang_typeof_operation()",
- op->literal_size);
- ti->spec.type = SLANG_SPEC_FLOAT;
- }
- break;
- case SLANG_OPER_IDENTIFIER:
- case SLANG_OPER_VARIABLE_DECL:
- {
- slang_variable *var;
- var = _slang_variable_locate(op->locals, op->a_id, GL_TRUE);
- if (!var) {
- slang_info_log_error(log, "undefined variable '%s'",
- (char *) op->a_id);
- return GL_FALSE;
- }
- if (!slang_type_specifier_copy(&ti->spec, &var->type.specifier)) {
- slang_info_log_memory(log);
- return GL_FALSE;
- }
- ti->can_be_referenced = GL_TRUE;
- if (var->type.specifier.type == SLANG_SPEC_ARRAY &&
- var->type.array_len >= 1) {
- /* the datatype is an array, ex: float[3] x; */
- ti->array_len = var->type.array_len;
- }
- else {
- /* the variable is an array, ex: float x[3]; */
- ti->array_len = var->array_len;
- }
- }
- break;
- case SLANG_OPER_SEQUENCE:
- /* TODO: check [0] and [1] if they match */
- if (!_slang_typeof_operation(&op->children[1], space, ti, atoms, log)) {
- return GL_FALSE;
- }
- ti->can_be_referenced = GL_FALSE;
- ti->is_swizzled = GL_FALSE;
- break;
- /*case SLANG_OPER_MODASSIGN: */
- /*case SLANG_OPER_LSHASSIGN: */
- /*case SLANG_OPER_RSHASSIGN: */
- /*case SLANG_OPER_ORASSIGN: */
- /*case SLANG_OPER_XORASSIGN: */
- /*case SLANG_OPER_ANDASSIGN: */
- case SLANG_OPER_SELECT:
- /* TODO: check [1] and [2] if they match */
- if (!_slang_typeof_operation(&op->children[1], space, ti, atoms, log)) {
- return GL_FALSE;
- }
- ti->can_be_referenced = GL_FALSE;
- ti->is_swizzled = GL_FALSE;
- break;
- /*case SLANG_OPER_BITOR: */
- /*case SLANG_OPER_BITXOR: */
- /*case SLANG_OPER_BITAND: */
- /*case SLANG_OPER_LSHIFT: */
- /*case SLANG_OPER_RSHIFT: */
- case SLANG_OPER_ADD:
- assert(op->num_children == 2);
- if (!typeof_math_call("+", op, space, &ti->spec, atoms, log))
- return GL_FALSE;
- break;
- case SLANG_OPER_SUBTRACT:
- assert(op->num_children == 2);
- if (!typeof_math_call("-", op, space, &ti->spec, atoms, log))
- return GL_FALSE;
- break;
- case SLANG_OPER_MULTIPLY:
- assert(op->num_children == 2);
- if (!typeof_math_call("*", op, space, &ti->spec, atoms, log))
- return GL_FALSE;
- break;
- case SLANG_OPER_DIVIDE:
- assert(op->num_children == 2);
- if (!typeof_math_call("/", op, space, &ti->spec, atoms, log))
- return GL_FALSE;
- break;
- /*case SLANG_OPER_MODULUS: */
- case SLANG_OPER_PLUS:
- if (!_slang_typeof_operation(op->children, space, ti, atoms, log))
- return GL_FALSE;
- ti->can_be_referenced = GL_FALSE;
- ti->is_swizzled = GL_FALSE;
- break;
- case SLANG_OPER_MINUS:
- assert(op->num_children == 1);
- if (!typeof_math_call("-", op, space, &ti->spec, atoms, log))
- return GL_FALSE;
- break;
- /*case SLANG_OPER_COMPLEMENT: */
- case SLANG_OPER_SUBSCRIPT:
- {
- slang_typeinfo _ti;
-
- if (!slang_typeinfo_construct(&_ti))
- return GL_FALSE;
- if (!_slang_typeof_operation(op->children, space, &_ti, atoms, log)) {
- slang_typeinfo_destruct(&_ti);
- return GL_FALSE;
- }
- ti->can_be_referenced = _ti.can_be_referenced;
- if (_ti.spec.type == SLANG_SPEC_ARRAY) {
- if (!slang_type_specifier_copy(&ti->spec, _ti.spec._array)) {
- slang_typeinfo_destruct(&_ti);
- return GL_FALSE;
- }
- }
- else {
- if (!_slang_type_is_vector(_ti.spec.type)
- && !_slang_type_is_matrix(_ti.spec.type)) {
- slang_typeinfo_destruct(&_ti);
- slang_info_log_error(log, "cannot index a non-array type");
- return GL_FALSE;
- }
- ti->spec.type = _slang_type_base(_ti.spec.type);
- }
- slang_typeinfo_destruct(&_ti);
- }
- break;
- case SLANG_OPER_CALL:
- if (op->array_constructor) {
- /* build array typeinfo */
- ti->spec.type = SLANG_SPEC_ARRAY;
- ti->spec._array = (slang_type_specifier *)
- _slang_alloc(sizeof(slang_type_specifier));
- slang_type_specifier_ctr(ti->spec._array);
-
- ti->spec._array->type =
- slang_type_specifier_type_from_string((char *) op->a_id);
- ti->array_len = op->num_children;
- }
- else if (op->fun) {
- /* we've resolved this call before */
- slang_type_specifier_copy(&ti->spec, &op->fun->header.type.specifier);
- }
- else {
- slang_function *fun;
- if (!_slang_typeof_function(op->a_id, op->children, op->num_children,
- space, &ti->spec, &fun, atoms, log))
- return GL_FALSE;
- if (fun) {
- /* save result for future use */
- op->fun = fun;
- }
- else {
- slang_struct *s =
- slang_struct_scope_find(space->structs, op->a_id, GL_TRUE);
- if (s) {
- /* struct initializer */
- ti->spec.type = SLANG_SPEC_STRUCT;
- ti->spec._struct =
- (slang_struct *) _slang_alloc(sizeof(slang_struct));
- if (ti->spec._struct == NULL)
- return GL_FALSE;
- if (!slang_struct_construct(ti->spec._struct)) {
- _slang_free(ti->spec._struct);
- ti->spec._struct = NULL;
- return GL_FALSE;
- }
- if (!slang_struct_copy(ti->spec._struct, s))
- return GL_FALSE;
- }
- else {
- /* float, int, vec4, mat3, etc. constructor? */
- const char *name;
- slang_type_specifier_type type;
-
- name = slang_atom_pool_id(atoms, op->a_id);
- type = slang_type_specifier_type_from_string(name);
- if (type == SLANG_SPEC_VOID) {
- slang_info_log_error(log, "undefined function '%s'", name);
- return GL_FALSE;
- }
- ti->spec.type = type;
- }
- }
- }
- break;
- case SLANG_OPER_METHOD:
- /* at this time, GLSL 1.20 only has one method: array.length()
- * which returns an integer.
- */
- ti->spec.type = SLANG_SPEC_INT;
- break;
- case SLANG_OPER_FIELD:
- {
- slang_typeinfo _ti;
-
- if (!slang_typeinfo_construct(&_ti))
- return GL_FALSE;
- if (!_slang_typeof_operation(op->children, space, &_ti, atoms, log)) {
- slang_typeinfo_destruct(&_ti);
- return GL_FALSE;
- }
- if (_ti.spec.type == SLANG_SPEC_STRUCT) {
- slang_variable *field;
-
- field = _slang_variable_locate(_ti.spec._struct->fields, op->a_id,
- GL_FALSE);
- if (field == NULL) {
- slang_typeinfo_destruct(&_ti);
- return GL_FALSE;
- }
- if (!slang_type_specifier_copy(&ti->spec, &field->type.specifier)) {
- slang_typeinfo_destruct(&_ti);
- return GL_FALSE;
- }
- ti->can_be_referenced = _ti.can_be_referenced;
- ti->array_len = field->array_len;
- }
- else {
- GLuint rows;
- const char *swizzle;
- slang_type_specifier_type base;
-
- /* determine the swizzle of the field expression */
- if (!_slang_type_is_vector(_ti.spec.type)) {
- slang_typeinfo_destruct(&_ti);
- slang_info_log_error(log, "Can't swizzle scalar expression");
- return GL_FALSE;
- }
- rows = _slang_type_dim(_ti.spec.type);
- swizzle = slang_atom_pool_id(atoms, op->a_id);
- if (!_slang_is_swizzle(swizzle, rows, &ti->swz)) {
- slang_typeinfo_destruct(&_ti);
- slang_info_log_error(log, "bad swizzle '%s'", swizzle);
- return GL_FALSE;
- }
- ti->is_swizzled = GL_TRUE;
- ti->can_be_referenced = _ti.can_be_referenced
- && _slang_is_swizzle_mask(&ti->swz, rows);
- if (_ti.is_swizzled) {
- slang_swizzle swz;
-
- /* swizzle the swizzle */
- _slang_multiply_swizzles(&swz, &_ti.swz, &ti->swz);
- ti->swz = swz;
- }
- base = _slang_type_base(_ti.spec.type);
- switch (ti->swz.num_components) {
- case 1:
- ti->spec.type = base;
- break;
- case 2:
- switch (base) {
- case SLANG_SPEC_FLOAT:
- ti->spec.type = SLANG_SPEC_VEC2;
- break;
- case SLANG_SPEC_INT:
- ti->spec.type = SLANG_SPEC_IVEC2;
- break;
- case SLANG_SPEC_BOOL:
- ti->spec.type = SLANG_SPEC_BVEC2;
- break;
- default:
- break;
- }
- break;
- case 3:
- switch (base) {
- case SLANG_SPEC_FLOAT:
- ti->spec.type = SLANG_SPEC_VEC3;
- break;
- case SLANG_SPEC_INT:
- ti->spec.type = SLANG_SPEC_IVEC3;
- break;
- case SLANG_SPEC_BOOL:
- ti->spec.type = SLANG_SPEC_BVEC3;
- break;
- default:
- break;
- }
- break;
- case 4:
- switch (base) {
- case SLANG_SPEC_FLOAT:
- ti->spec.type = SLANG_SPEC_VEC4;
- break;
- case SLANG_SPEC_INT:
- ti->spec.type = SLANG_SPEC_IVEC4;
- break;
- case SLANG_SPEC_BOOL:
- ti->spec.type = SLANG_SPEC_BVEC4;
- break;
- default:
- break;
- }
- break;
- default:
- break;
- }
- }
- slang_typeinfo_destruct(&_ti);
- }
- break;
- case SLANG_OPER_POSTINCREMENT:
- case SLANG_OPER_POSTDECREMENT:
- if (!_slang_typeof_operation(op->children, space, ti, atoms, log))
- return GL_FALSE;
- ti->can_be_referenced = GL_FALSE;
- ti->is_swizzled = GL_FALSE;
- break;
- default:
- return GL_FALSE;
- }
-
- return GL_TRUE;
-}
-
-
-/**
- * Determine if a type is a matrix.
- * \return GL_TRUE if is a matrix, GL_FALSE otherwise.
- */
-GLboolean
-_slang_type_is_matrix(slang_type_specifier_type ty)
-{
- switch (ty) {
- case SLANG_SPEC_MAT2:
- case SLANG_SPEC_MAT3:
- case SLANG_SPEC_MAT4:
- case SLANG_SPEC_MAT23:
- case SLANG_SPEC_MAT32:
- case SLANG_SPEC_MAT24:
- case SLANG_SPEC_MAT42:
- case SLANG_SPEC_MAT34:
- case SLANG_SPEC_MAT43:
- return GL_TRUE;
- default:
- return GL_FALSE;
- }
-}
-
-
-/**
- * Determine if a type is a vector.
- * \return GL_TRUE if is a vector, GL_FALSE otherwise.
- */
-GLboolean
-_slang_type_is_vector(slang_type_specifier_type ty)
-{
- switch (ty) {
- case SLANG_SPEC_VEC2:
- case SLANG_SPEC_VEC3:
- case SLANG_SPEC_VEC4:
- case SLANG_SPEC_IVEC2:
- case SLANG_SPEC_IVEC3:
- case SLANG_SPEC_IVEC4:
- case SLANG_SPEC_BVEC2:
- case SLANG_SPEC_BVEC3:
- case SLANG_SPEC_BVEC4:
- return GL_TRUE;
- default:
- return GL_FALSE;
- }
-}
-
-
-/**
- * Determine if a type is a float, float vector or float matrix.
- * \return GL_TRUE if so, GL_FALSE otherwise
- */
-GLboolean
-_slang_type_is_float_vec_mat(slang_type_specifier_type ty)
-{
- switch (ty) {
- case SLANG_SPEC_FLOAT:
- case SLANG_SPEC_VEC2:
- case SLANG_SPEC_VEC3:
- case SLANG_SPEC_VEC4:
- case SLANG_SPEC_MAT2:
- case SLANG_SPEC_MAT3:
- case SLANG_SPEC_MAT4:
- case SLANG_SPEC_MAT23:
- case SLANG_SPEC_MAT32:
- case SLANG_SPEC_MAT24:
- case SLANG_SPEC_MAT42:
- case SLANG_SPEC_MAT34:
- case SLANG_SPEC_MAT43:
- return GL_TRUE;
- default:
- return GL_FALSE;
- }
-}
-
-
-/**
- * Given a vector type, return the type of the vector's elements.
- * For a matrix, return the type of the columns.
- */
-slang_type_specifier_type
-_slang_type_base(slang_type_specifier_type ty)
-{
- switch (ty) {
- case SLANG_SPEC_FLOAT:
- case SLANG_SPEC_VEC2:
- case SLANG_SPEC_VEC3:
- case SLANG_SPEC_VEC4:
- return SLANG_SPEC_FLOAT;
- case SLANG_SPEC_INT:
- case SLANG_SPEC_IVEC2:
- case SLANG_SPEC_IVEC3:
- case SLANG_SPEC_IVEC4:
- return SLANG_SPEC_INT;
- case SLANG_SPEC_BOOL:
- case SLANG_SPEC_BVEC2:
- case SLANG_SPEC_BVEC3:
- case SLANG_SPEC_BVEC4:
- return SLANG_SPEC_BOOL;
- case SLANG_SPEC_MAT2:
- return SLANG_SPEC_VEC2;
- case SLANG_SPEC_MAT3:
- return SLANG_SPEC_VEC3;
- case SLANG_SPEC_MAT4:
- return SLANG_SPEC_VEC4;
- case SLANG_SPEC_MAT23:
- return SLANG_SPEC_VEC3;
- case SLANG_SPEC_MAT32:
- return SLANG_SPEC_VEC2;
- case SLANG_SPEC_MAT24:
- return SLANG_SPEC_VEC4;
- case SLANG_SPEC_MAT42:
- return SLANG_SPEC_VEC2;
- case SLANG_SPEC_MAT34:
- return SLANG_SPEC_VEC4;
- case SLANG_SPEC_MAT43:
- return SLANG_SPEC_VEC3;
- default:
- return SLANG_SPEC_VOID;
- }
-}
-
-
-/**
- * Return the dimensionality of a vector, or for a matrix, return number
- * of columns.
- */
-GLuint
-_slang_type_dim(slang_type_specifier_type ty)
-{
- switch (ty) {
- case SLANG_SPEC_FLOAT:
- case SLANG_SPEC_INT:
- case SLANG_SPEC_BOOL:
- return 1;
- case SLANG_SPEC_VEC2:
- case SLANG_SPEC_IVEC2:
- case SLANG_SPEC_BVEC2:
- case SLANG_SPEC_MAT2:
- return 2;
- case SLANG_SPEC_VEC3:
- case SLANG_SPEC_IVEC3:
- case SLANG_SPEC_BVEC3:
- case SLANG_SPEC_MAT3:
- return 3;
- case SLANG_SPEC_VEC4:
- case SLANG_SPEC_IVEC4:
- case SLANG_SPEC_BVEC4:
- case SLANG_SPEC_MAT4:
- return 4;
-
- case SLANG_SPEC_MAT23:
- return 2;
- case SLANG_SPEC_MAT32:
- return 3;
- case SLANG_SPEC_MAT24:
- return 2;
- case SLANG_SPEC_MAT42:
- return 4;
- case SLANG_SPEC_MAT34:
- return 3;
- case SLANG_SPEC_MAT43:
- return 4;
-
- default:
- return 0;
- }
-}
-
-
-/**
- * Return the GL_* type that corresponds to a SLANG_SPEC_* type.
- */
-GLenum
-_slang_gltype_from_specifier(const slang_type_specifier *type)
-{
- switch (type->type) {
- case SLANG_SPEC_BOOL:
- return GL_BOOL;
- case SLANG_SPEC_BVEC2:
- return GL_BOOL_VEC2;
- case SLANG_SPEC_BVEC3:
- return GL_BOOL_VEC3;
- case SLANG_SPEC_BVEC4:
- return GL_BOOL_VEC4;
- case SLANG_SPEC_INT:
- return GL_INT;
- case SLANG_SPEC_IVEC2:
- return GL_INT_VEC2;
- case SLANG_SPEC_IVEC3:
- return GL_INT_VEC3;
- case SLANG_SPEC_IVEC4:
- return GL_INT_VEC4;
- case SLANG_SPEC_FLOAT:
- return GL_FLOAT;
- case SLANG_SPEC_VEC2:
- return GL_FLOAT_VEC2;
- case SLANG_SPEC_VEC3:
- return GL_FLOAT_VEC3;
- case SLANG_SPEC_VEC4:
- return GL_FLOAT_VEC4;
- case SLANG_SPEC_MAT2:
- return GL_FLOAT_MAT2;
- case SLANG_SPEC_MAT3:
- return GL_FLOAT_MAT3;
- case SLANG_SPEC_MAT4:
- return GL_FLOAT_MAT4;
- case SLANG_SPEC_MAT23:
- return GL_FLOAT_MAT2x3;
- case SLANG_SPEC_MAT32:
- return GL_FLOAT_MAT3x2;
- case SLANG_SPEC_MAT24:
- return GL_FLOAT_MAT2x4;
- case SLANG_SPEC_MAT42:
- return GL_FLOAT_MAT4x2;
- case SLANG_SPEC_MAT34:
- return GL_FLOAT_MAT3x4;
- case SLANG_SPEC_MAT43:
- return GL_FLOAT_MAT4x3;
- case SLANG_SPEC_SAMPLER_1D:
- return GL_SAMPLER_1D;
- case SLANG_SPEC_SAMPLER_2D:
- return GL_SAMPLER_2D;
- case SLANG_SPEC_SAMPLER_3D:
- return GL_SAMPLER_3D;
- case SLANG_SPEC_SAMPLER_CUBE:
- return GL_SAMPLER_CUBE;
- case SLANG_SPEC_SAMPLER_1D_SHADOW:
- return GL_SAMPLER_1D_SHADOW;
- case SLANG_SPEC_SAMPLER_2D_SHADOW:
- return GL_SAMPLER_2D_SHADOW;
- case SLANG_SPEC_SAMPLER_RECT:
- return GL_SAMPLER_2D_RECT_ARB;
- case SLANG_SPEC_SAMPLER_RECT_SHADOW:
- return GL_SAMPLER_2D_RECT_SHADOW_ARB;
- case SLANG_SPEC_SAMPLER_1D_ARRAY:
- return GL_SAMPLER_1D_ARRAY_EXT;
- case SLANG_SPEC_SAMPLER_2D_ARRAY:
- return GL_SAMPLER_2D_ARRAY_EXT;
- case SLANG_SPEC_SAMPLER_1D_ARRAY_SHADOW:
- return GL_SAMPLER_1D_ARRAY_SHADOW_EXT;
- case SLANG_SPEC_SAMPLER_2D_ARRAY_SHADOW:
- return GL_SAMPLER_2D_ARRAY_SHADOW_EXT;
- case SLANG_SPEC_ARRAY:
- return _slang_gltype_from_specifier(type->_array);
- case SLANG_SPEC_STRUCT:
- /* fall-through */
- default:
- return GL_NONE;
- }
-}
-
+++ /dev/null
-/*
- * Mesa 3-D graphics library
- * Version: 6.5
- *
- * Copyright (C) 2005-2006 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 SLANG_TYPEINFO_H
-#define SLANG_TYPEINFO_H 1
-
-#include "main/glheader.h"
-#include "slang_log.h"
-#include "slang_utility.h"
-
-
-struct slang_operation_;
-
-struct slang_name_space_;
-
-
-
-/**
- * Holds complete information about vector swizzle - the <swizzle>
- * array contains vector component source indices, where 0 is "x", 1
- * is "y", 2 is "z" and 3 is "w".
- * Example: "xwz" --> { 3, { 0, 3, 2, not used } }.
- */
-typedef struct slang_swizzle_
-{
- GLuint num_components;
- GLuint swizzle[4];
-} slang_swizzle;
-
-extern GLboolean
-_slang_is_swizzle(const char *field, GLuint rows, slang_swizzle *swz);
-
-
-typedef enum slang_type_variant_
-{
- SLANG_VARIANT, /* the default */
- SLANG_INVARIANT /* indicates the "invariant" keyword */
-} slang_type_variant;
-
-
-typedef enum slang_type_centroid_
-{
- SLANG_CENTER, /* the default */
- SLANG_CENTROID /* indicates the "centroid" keyword */
-} slang_type_centroid;
-
-
-/**
- * These only apply to gl_FragCoord, but other layout qualifiers may
- * appear in the future.
- */
-typedef enum slang_layout_qualifier_
-{
- SLANG_LAYOUT_NONE = 0x0,
- SLANG_LAYOUT_UPPER_LEFT_BIT = 0x1,
- SLANG_LAYOUT_PIXEL_CENTER_INTEGER_BIT = 0x2
-} slang_layout_qualifier;
-
-
-typedef enum slang_type_qualifier_
-{
- SLANG_QUAL_NONE,
- SLANG_QUAL_CONST,
- SLANG_QUAL_ATTRIBUTE,
- SLANG_QUAL_VARYING,
- SLANG_QUAL_UNIFORM,
- SLANG_QUAL_OUT,
- SLANG_QUAL_INOUT,
- SLANG_QUAL_FIXEDOUTPUT, /* internal */
- SLANG_QUAL_FIXEDINPUT /* internal */
-} slang_type_qualifier;
-
-typedef enum slang_varying_kind_
-{
- SLANG_VARYING_IN,
- SLANG_VARYING_OUT,
-} slang_varying_kind;
-
-typedef enum slang_type_precision_
-{
- SLANG_PREC_DEFAULT,
- SLANG_PREC_LOW,
- SLANG_PREC_MEDIUM,
- SLANG_PREC_HIGH
-} slang_type_precision;
-
-
-/**
- * The basic shading language types (float, vec4, mat3, etc)
- */
-typedef enum slang_type_specifier_type_
-{
- SLANG_SPEC_VOID,
- SLANG_SPEC_BOOL,
- SLANG_SPEC_BVEC2,
- SLANG_SPEC_BVEC3,
- SLANG_SPEC_BVEC4,
- SLANG_SPEC_INT,
- SLANG_SPEC_IVEC2,
- SLANG_SPEC_IVEC3,
- SLANG_SPEC_IVEC4,
- SLANG_SPEC_FLOAT,
- SLANG_SPEC_VEC2,
- SLANG_SPEC_VEC3,
- SLANG_SPEC_VEC4,
- SLANG_SPEC_MAT2,
- SLANG_SPEC_MAT3,
- SLANG_SPEC_MAT4,
- SLANG_SPEC_MAT23,
- SLANG_SPEC_MAT32,
- SLANG_SPEC_MAT24,
- SLANG_SPEC_MAT42,
- SLANG_SPEC_MAT34,
- SLANG_SPEC_MAT43,
- SLANG_SPEC_SAMPLER_1D,
- SLANG_SPEC_SAMPLER_2D,
- SLANG_SPEC_SAMPLER_3D,
- SLANG_SPEC_SAMPLER_CUBE,
- SLANG_SPEC_SAMPLER_RECT,
- SLANG_SPEC_SAMPLER_1D_SHADOW,
- SLANG_SPEC_SAMPLER_2D_SHADOW,
- SLANG_SPEC_SAMPLER_RECT_SHADOW,
- SLANG_SPEC_SAMPLER_1D_ARRAY,
- SLANG_SPEC_SAMPLER_2D_ARRAY,
- SLANG_SPEC_SAMPLER_1D_ARRAY_SHADOW,
- SLANG_SPEC_SAMPLER_2D_ARRAY_SHADOW,
- SLANG_SPEC_STRUCT,
- SLANG_SPEC_ARRAY
-} slang_type_specifier_type;
-
-
-extern slang_type_specifier_type
-slang_type_specifier_type_from_string(const char *);
-
-extern const char *
-slang_type_specifier_type_to_string(slang_type_specifier_type);
-
-
-/**
- * Describes more sophisticated types, like structs and arrays.
- */
-typedef struct slang_type_specifier_
-{
- slang_type_specifier_type type;
- struct slang_struct_ *_struct; /**< if type == SLANG_SPEC_STRUCT */
- struct slang_type_specifier_ *_array; /**< if type == SLANG_SPEC_ARRAY */
-} slang_type_specifier;
-
-
-extern GLvoid
-slang_type_specifier_ctr(slang_type_specifier *);
-
-extern GLvoid
-slang_type_specifier_dtr(slang_type_specifier *);
-
-extern slang_type_specifier *
-slang_type_specifier_new(slang_type_specifier_type type,
- struct slang_struct_ *_struct,
- struct slang_type_specifier_ *_array);
-
-
-extern GLboolean
-slang_type_specifier_copy(slang_type_specifier *, const slang_type_specifier *);
-
-extern GLboolean
-slang_type_specifier_equal(const slang_type_specifier *,
- const slang_type_specifier *);
-
-
-extern GLboolean
-slang_type_specifier_compatible(const slang_type_specifier *x,
- const slang_type_specifier *y);
-
-
-typedef struct slang_fully_specified_type_
-{
- slang_type_qualifier qualifier;
- slang_type_specifier specifier;
- slang_type_precision precision;
- slang_type_variant variant;
- slang_type_centroid centroid;
- slang_layout_qualifier layout;
- GLint array_len; /**< -1 if not an array type */
- slang_varying_kind varying_kind;
-} slang_fully_specified_type;
-
-extern int
-slang_fully_specified_type_construct(slang_fully_specified_type *);
-
-extern void
-slang_fully_specified_type_destruct(slang_fully_specified_type *);
-
-extern int
-slang_fully_specified_type_copy(slang_fully_specified_type *,
- const slang_fully_specified_type *);
-
-GLboolean
-slang_fully_specified_types_compatible(const slang_fully_specified_type * x,
- const slang_fully_specified_type * y);
-
-
-typedef struct slang_typeinfo_
-{
- GLboolean can_be_referenced;
- GLboolean is_swizzled;
- slang_swizzle swz;
- slang_type_specifier spec;
- GLuint array_len;
-} slang_typeinfo;
-
-extern GLboolean
-slang_typeinfo_construct(slang_typeinfo *);
-
-extern GLvoid
-slang_typeinfo_destruct(slang_typeinfo *);
-
-
-extern GLboolean
-_slang_typeof_operation(struct slang_operation_ *,
- const struct slang_name_space_ *,
- slang_typeinfo *, slang_atom_pool *,
- slang_info_log *log);
-
-extern GLboolean
-_slang_type_is_matrix(slang_type_specifier_type);
-
-extern GLboolean
-_slang_type_is_vector(slang_type_specifier_type);
-
-extern GLboolean
-_slang_type_is_float_vec_mat(slang_type_specifier_type);
-
-extern slang_type_specifier_type
-_slang_type_base(slang_type_specifier_type);
-
-extern GLuint
-_slang_type_dim(slang_type_specifier_type);
-
-extern GLenum
-_slang_gltype_from_specifier(const slang_type_specifier *type);
-
-#endif
+++ /dev/null
-/*
- * Mesa 3-D graphics library
- * Version: 6.5.3
- *
- * Copyright (C) 2005-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.
- */
-
-/**
- * \file slang_utility.c
- * slang utilities
- * \author Michal Krol
- */
-
-#include "main/imports.h"
-#include "slang_utility.h"
-#include "slang_mem.h"
-
-char *
-slang_string_concat (char *dst, const char *src)
-{
- return strcpy (dst + strlen (dst), src);
-}
-
-
-/* slang_string */
-
-GLvoid
-slang_string_init (slang_string *self)
-{
- self->data = NULL;
- self->capacity = 0;
- self->length = 0;
- self->fail = GL_FALSE;
-}
-
-GLvoid
-slang_string_free (slang_string *self)
-{
- if (self->data != NULL)
- free(self->data);
-}
-
-GLvoid
-slang_string_reset (slang_string *self)
-{
- self->length = 0;
- self->fail = GL_FALSE;
-}
-
-static GLboolean
-grow (slang_string *self, GLuint size)
-{
- if (self->fail)
- return GL_FALSE;
- if (size > self->capacity) {
- /* do not overflow 32-bit range */
- assert (size < 0x80000000);
-
- self->data = (char *) (_mesa_realloc (self->data, self->capacity, size * 2));
- self->capacity = size * 2;
- if (self->data == NULL) {
- self->capacity = 0;
- self->fail = GL_TRUE;
- return GL_FALSE;
- }
- }
- return GL_TRUE;
-}
-
-GLvoid
-slang_string_push (slang_string *self, const slang_string *str)
-{
- if (str->fail) {
- self->fail = GL_TRUE;
- return;
- }
- if (grow (self, self->length + str->length)) {
- memcpy (&self->data[self->length], str->data, str->length);
- self->length += str->length;
- }
-}
-
-GLvoid
-slang_string_pushc (slang_string *self, const char c)
-{
- if (grow (self, self->length + 1)) {
- self->data[self->length] = c;
- self->length++;
- }
-}
-
-GLvoid
-slang_string_pushs (slang_string *self, const char *cstr, GLuint len)
-{
- if (grow (self, self->length + len)) {
- memcpy (&self->data[self->length], cstr, len);
- self->length += len;
- }
-}
-
-GLvoid
-slang_string_pushi (slang_string *self, GLint i)
-{
- char buffer[12];
-
- _mesa_snprintf (buffer, sizeof(buffer), "%d", i);
- slang_string_pushs (self, buffer, strlen (buffer));
-}
-
-const char *
-slang_string_cstr (slang_string *self)
-{
- if (grow (self, self->length + 1))
- self->data[self->length] = '\0';
- return self->data;
-}
-
-/* slang_atom_pool */
-
-void
-slang_atom_pool_construct(slang_atom_pool * pool)
-{
- GLuint i;
-
- for (i = 0; i < SLANG_ATOM_POOL_SIZE; i++)
- pool->entries[i] = NULL;
-}
-
-void
-slang_atom_pool_destruct (slang_atom_pool * pool)
-{
- GLuint i;
-
- for (i = 0; i < SLANG_ATOM_POOL_SIZE; i++) {
- slang_atom_entry * entry;
-
- entry = pool->entries[i];
- while (entry != NULL) {
- slang_atom_entry *next = entry->next;
- _slang_free(entry->id);
- _slang_free(entry);
- entry = next;
- }
- }
-}
-
-/*
- * Search the atom pool for an atom with a given name.
- * If atom is not found, create and add it to the pool.
- * Returns ATOM_NULL if the atom was not found and the function failed
- * to create a new atom.
- */
-slang_atom
-slang_atom_pool_atom(slang_atom_pool * pool, const char * id)
-{
- GLuint hash;
- const char * p = id;
- slang_atom_entry ** entry;
-
- /* Hash a given string to a number in the range [0, ATOM_POOL_SIZE). */
- hash = 0;
- while (*p != '\0') {
- GLuint g;
-
- hash = (hash << 4) + (GLuint) (*p++);
- g = hash & 0xf0000000;
- if (g != 0)
- hash ^= g >> 24;
- hash &= ~g;
- }
- hash %= SLANG_ATOM_POOL_SIZE;
-
- /* Now the hash points to a linked list of atoms with names that
- * have the same hash value. Search the linked list for a given
- * name.
- */
- entry = &pool->entries[hash];
- while (*entry != NULL) {
- /* If the same, return the associated atom. */
- if (slang_string_compare((**entry).id, id) == 0)
- return (slang_atom) (**entry).id;
- /* Grab the next atom in the linked list. */
- entry = &(**entry).next;
- }
-
- /* Okay, we have not found an atom. Create a new entry for it.
- * Note that the <entry> points to the last entry's <next> field.
- */
- *entry = (slang_atom_entry *) _slang_alloc(sizeof(slang_atom_entry));
- if (*entry == NULL)
- return SLANG_ATOM_NULL;
-
- /* Initialize a new entry. Because we'll need the actual name of
- * the atom, we use the pointer to this string as an actual atom's
- * value.
- */
- (**entry).next = NULL;
- (**entry).id = _slang_strdup(id);
- if ((**entry).id == NULL)
- return SLANG_ATOM_NULL;
- return (slang_atom) (**entry).id;
-}
-
-/**
- * Return the name of a given atom.
- */
-const char *
-slang_atom_pool_id(slang_atom_pool * pool, slang_atom atom)
-{
- return (const char *) (atom);
-}
+++ /dev/null
-/*
- * Mesa 3-D graphics library
- * Version: 6.5.3
- *
- * Copyright (C) 2005-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 SLANG_UTILITY_H
-#define SLANG_UTILITY_H
-
-
-#include "main/glheader.h"
-
-/* Compile-time assertions. If the expression is zero, try to declare an
- * array of size [-1] to cause compilation error.
- */
-#define static_assert(expr) do { int _array[(expr) ? 1 : -1]; (void) _array[0]; } while (0)
-
-
-#define slang_string_compare(str1, str2) strcmp (str1, str2)
-#define slang_string_copy(dst, src) strcpy (dst, src)
-#define slang_string_length(str) strlen (str)
-
-char *slang_string_concat (char *, const char *);
-
-/* slang_string */
-
-typedef struct
-{
- char *data;
- GLuint length;
- GLuint capacity;
- GLboolean fail;
-} slang_string;
-
-GLvoid
-slang_string_init (slang_string *);
-
-GLvoid
-slang_string_free (slang_string *);
-
-GLvoid
-slang_string_reset (slang_string *);
-
-GLvoid
-slang_string_push (slang_string *, const slang_string *);
-
-GLvoid
-slang_string_pushc (slang_string *, const char);
-
-GLvoid
-slang_string_pushs (slang_string *, const char *, GLuint);
-
-GLvoid
-slang_string_pushi (slang_string *, GLint);
-
-const char *
-slang_string_cstr (slang_string *);
-
-/* slang_atom */
-
-typedef GLvoid *slang_atom;
-
-#define SLANG_ATOM_NULL ((slang_atom) 0)
-
-typedef struct slang_atom_entry_
-{
- char *id;
- struct slang_atom_entry_ *next;
-} slang_atom_entry;
-
-#define SLANG_ATOM_POOL_SIZE 1023
-
-typedef struct slang_atom_pool_
-{
- slang_atom_entry *entries[SLANG_ATOM_POOL_SIZE];
-} slang_atom_pool;
-
-GLvoid slang_atom_pool_construct (slang_atom_pool *);
-GLvoid slang_atom_pool_destruct (slang_atom_pool *);
-slang_atom slang_atom_pool_atom (slang_atom_pool *, const char *);
-const char *slang_atom_pool_id (slang_atom_pool *, slang_atom);
-
-
-#endif
+++ /dev/null
-
-#include "main/imports.h"
-#include "program/program.h"
-#include "program/prog_print.h"
-#include "slang_compile.h"
-#include "slang_compile_variable.h"
-#include "slang_emit.h"
-#include "slang_mem.h"
-#include "slang_vartable.h"
-#include "slang_ir.h"
-
-
-static int dbg = 0;
-
-
-typedef enum {
- FREE,
- VAR,
- TEMP
-} TempState;
-
-
-/**
- * Variable/register info for one variable scope.
- */
-struct table
-{
- int Level;
- int NumVars;
- slang_variable **Vars; /* array [NumVars] */
-
- TempState Temps[MAX_PROGRAM_TEMPS * 4]; /* per-component state */
- int ValSize[MAX_PROGRAM_TEMPS * 4]; /**< For debug only */
-
- struct table *Parent; /** Parent scope table */
-};
-
-
-/**
- * A variable table is a stack of tables, one per scope.
- */
-struct slang_var_table_
-{
- GLint CurLevel;
- GLuint MaxRegisters;
- struct table *Top; /**< Table at top of stack */
-};
-
-
-
-slang_var_table *
-_slang_new_var_table(GLuint maxRegisters)
-{
- slang_var_table *vt
- = (slang_var_table *) _slang_alloc(sizeof(slang_var_table));
- if (vt) {
- vt->MaxRegisters = maxRegisters;
- }
- return vt;
-}
-
-
-void
-_slang_delete_var_table(slang_var_table *vt)
-{
- if (vt->Top) {
- _mesa_problem(NULL, "non-empty var table in _slang_delete_var_table()");
- return;
- }
- _slang_free(vt);
-}
-
-
-
-/**
- * Create new table on top of vartable stack.
- * Used when we enter a {} block.
- */
-void
-_slang_push_var_table(slang_var_table *vt)
-{
- struct table *t = (struct table *) _slang_alloc(sizeof(struct table));
- if (t) {
- t->Level = vt->CurLevel++;
- t->Parent = vt->Top;
- if (t->Parent) {
- /* copy the info indicating which temp regs are in use */
- memcpy(t->Temps, t->Parent->Temps, sizeof(t->Temps));
- memcpy(t->ValSize, t->Parent->ValSize, sizeof(t->ValSize));
- }
- vt->Top = t;
- if (dbg) printf("Pushing level %d\n", t->Level);
- }
-}
-
-
-/**
- * Pop top entry from variable table.
- * Used when we leave a {} block.
- */
-void
-_slang_pop_var_table(slang_var_table *vt)
-{
- struct table *t = vt->Top;
- int i;
-
- if (dbg) printf("Popping level %d\n", t->Level);
-
- /* free the storage allocated for each variable */
- for (i = 0; i < t->NumVars; i++) {
- slang_ir_storage *store = t->Vars[i]->store;
- GLint j;
- GLuint comp;
- if (dbg) printf(" Free var %s, size %d at %d.%s\n",
- (char*) t->Vars[i]->a_name, store->Size,
- store->Index,
- _mesa_swizzle_string(store->Swizzle, 0, 0));
-
- if (store->File == PROGRAM_SAMPLER) {
- /* samplers have no storage */
- continue;
- }
-
- if (store->Size == 1)
- comp = GET_SWZ(store->Swizzle, 0);
- else
- comp = 0;
-
- /* store->Index may be -1 if we run out of registers */
- if (store->Index >= 0) {
- for (j = 0; j < store->Size; j++) {
- assert(t->Temps[store->Index * 4 + j + comp] == VAR);
- t->Temps[store->Index * 4 + j + comp] = FREE;
- }
- }
- store->Index = -1;
- }
- if (t->Parent) {
- /* just verify that any remaining allocations in this scope
- * were for temps
- */
- for (i = 0; i < (int) vt->MaxRegisters * 4; i++) {
- if (t->Temps[i] != FREE && t->Parent->Temps[i] == FREE) {
- if (dbg) printf(" Free reg %d\n", i/4);
- assert(t->Temps[i] == TEMP);
- }
- }
- }
-
- if (t->Vars) {
- _slang_free(t->Vars);
- t->Vars = NULL;
- }
-
- vt->Top = t->Parent;
- _slang_free(t);
- vt->CurLevel--;
-}
-
-
-/**
- * Add a new variable to the given var/symbol table.
- */
-void
-_slang_add_variable(slang_var_table *vt, slang_variable *v)
-{
- struct table *t;
- assert(vt);
- t = vt->Top;
- assert(t);
- if (dbg) printf("Adding var %s, store %p\n", (char *) v->a_name, (void *) v->store);
- t->Vars = (slang_variable **)
- _slang_realloc(t->Vars,
- t->NumVars * sizeof(slang_variable *),
- (t->NumVars + 1) * sizeof(slang_variable *));
- t->Vars[t->NumVars] = v;
- t->NumVars++;
-}
-
-
-/**
- * Look for variable by name in given table.
- * If not found, Parent table will be searched.
- */
-slang_variable *
-_slang_find_variable(const slang_var_table *vt, slang_atom name)
-{
- struct table *t = vt->Top;
- while (1) {
- int i;
- for (i = 0; i < t->NumVars; i++) {
- if (t->Vars[i]->a_name == name)
- return t->Vars[i];
- }
- if (t->Parent)
- t = t->Parent;
- else
- return NULL;
- }
-}
-
-
-/**
- * Allocation helper.
- * \param size var size in floats
- * \return position for var, measured in floats
- */
-static GLint
-alloc_reg(slang_var_table *vt, GLint size, GLboolean isTemp)
-{
- struct table *t = vt->Top;
- /* if size == 1, allocate anywhere, else, pos must be multiple of 4 */
- const GLuint step = (size == 1) ? 1 : 4;
- GLuint i, j;
- assert(size > 0); /* number of floats */
-
- for (i = 0; i <= vt->MaxRegisters * 4 - size; i += step) {
- GLuint found = 0;
- for (j = 0; j < (GLuint) size; j++) {
- assert(i + j < 4 * MAX_PROGRAM_TEMPS);
- if (i + j < vt->MaxRegisters * 4 && t->Temps[i + j] == FREE) {
- found++;
- }
- else {
- break;
- }
- }
- if (found == size) {
- /* found block of size free regs */
- if (size > 1)
- assert(i % 4 == 0);
- for (j = 0; j < (GLuint) size; j++) {
- assert(i + j < 4 * MAX_PROGRAM_TEMPS);
- t->Temps[i + j] = isTemp ? TEMP : VAR;
- }
- assert(i < MAX_PROGRAM_TEMPS * 4);
- t->ValSize[i] = size;
- return i;
- }
- }
-
- /* if we get here, we ran out of registers */
- return -1;
-}
-
-
-/**
- * Allocate temp register(s) for storing a variable.
- * \param size size needed, in floats
- * \param swizzle returns swizzle mask for accessing var in register
- * \return register allocated, or -1
- */
-GLboolean
-_slang_alloc_var(slang_var_table *vt, slang_ir_storage *store)
-{
- struct table *t = vt->Top;
- int i;
-
- if (store->File == PROGRAM_SAMPLER) {
- /* don't really allocate storage */
- store->Index = 0;
- return GL_TRUE;
- }
-
- i = alloc_reg(vt, store->Size, GL_FALSE);
- if (i < 0)
- return GL_FALSE;
-
- store->Index = i / 4;
- store->Swizzle = _slang_var_swizzle(store->Size, i % 4);
-
- if (dbg)
- printf("Alloc var storage sz %d at %d.%s (level %d) store %p\n",
- store->Size, store->Index,
- _mesa_swizzle_string(store->Swizzle, 0, 0),
- t->Level,
- (void*) store);
-
- return GL_TRUE;
-}
-
-
-
-/**
- * Allocate temp register(s) for storing an unnamed intermediate value.
- */
-GLboolean
-_slang_alloc_temp(slang_var_table *vt, slang_ir_storage *store)
-{
- struct table *t = vt->Top;
- const int i = alloc_reg(vt, store->Size, GL_TRUE);
- if (i < 0)
- return GL_FALSE;
-
- assert(store->Index < 0);
-
- store->Index = i / 4;
- store->Swizzle = _slang_var_swizzle(store->Size, i % 4);
-
- if (dbg) printf("Alloc temp sz %d at %d.%s (level %d) store %p\n",
- store->Size, store->Index,
- _mesa_swizzle_string(store->Swizzle, 0, 0), t->Level,
- (void *) store);
-
- return GL_TRUE;
-}
-
-
-void
-_slang_free_temp(slang_var_table *vt, slang_ir_storage *store)
-{
- struct table *t = vt->Top;
- GLuint i;
- GLint r = store->Index;
- assert(store->Size > 0);
- assert(r >= 0);
- assert((GLuint)r + store->Size <= vt->MaxRegisters * 4);
- if (dbg) printf("Free temp sz %d at %d.%s (level %d) store %p\n",
- store->Size, r,
- _mesa_swizzle_string(store->Swizzle, 0, 0),
- t->Level, (void *) store);
- if (store->Size == 1) {
- const GLuint comp = GET_SWZ(store->Swizzle, 0);
- /* we can actually fail some of these assertions because of the
- * troublesome IR_SWIZZLE handling.
- */
-#if 0
- assert(store->Swizzle == MAKE_SWIZZLE4(comp, comp, comp, comp));
- assert(comp < 4);
- assert(t->ValSize[r * 4 + comp] == 1);
-#endif
- assert(t->Temps[r * 4 + comp] == TEMP);
- t->Temps[r * 4 + comp] = FREE;
- }
- else {
- /*assert(store->Swizzle == SWIZZLE_NOOP);*/
- assert(t->ValSize[r*4] == store->Size);
- for (i = 0; i < (GLuint) store->Size; i++) {
- assert(t->Temps[r * 4 + i] == TEMP);
- t->Temps[r * 4 + i] = FREE;
- }
- }
-}
-
-
-GLboolean
-_slang_is_temp(const slang_var_table *vt, const slang_ir_storage *store)
-{
- struct table *t = vt->Top;
- GLuint comp;
- assert(store->Index >= 0);
- assert(store->Index < (int) vt->MaxRegisters);
- if (store->Swizzle == SWIZZLE_NOOP)
- comp = 0;
- else
- comp = GET_SWZ(store->Swizzle, 0);
-
- if (t->Temps[store->Index * 4 + comp] == TEMP)
- return GL_TRUE;
- else
- return GL_FALSE;
-}
+++ /dev/null
-
-#ifndef SLANG_VARTABLE_H
-#define SLANG_VARTABLE_H
-
-#include "main/glheader.h"
-#include "slang_utility.h"
-
-struct slang_ir_storage_;
-
-typedef struct slang_var_table_ slang_var_table;
-
-struct slang_variable_;
-
-extern slang_var_table *
-_slang_new_var_table(GLuint maxRegisters);
-
-extern void
-_slang_delete_var_table(slang_var_table *vt);
-
-extern void
-_slang_push_var_table(slang_var_table *parent);
-
-extern void
-_slang_pop_var_table(slang_var_table *t);
-
-extern void
-_slang_add_variable(slang_var_table *t, struct slang_variable_ *v);
-
-extern struct slang_variable_ *
-_slang_find_variable(const slang_var_table *t, slang_atom name);
-
-extern GLboolean
-_slang_alloc_var(slang_var_table *t, struct slang_ir_storage_ *store);
-
-extern GLboolean
-_slang_alloc_temp(slang_var_table *t, struct slang_ir_storage_ *store);
-
-extern void
-_slang_free_temp(slang_var_table *t, struct slang_ir_storage_ *store);
-
-extern GLboolean
-_slang_is_temp(const slang_var_table *t, const struct slang_ir_storage_ *store);
-
-
-#endif /* SLANG_VARTABLE_H */