101e04c3fSmrg/* 201e04c3fSmrg * Copyright © 2010 Intel Corporation 301e04c3fSmrg * 401e04c3fSmrg * Permission is hereby granted, free of charge, to any person obtaining a 501e04c3fSmrg * copy of this software and associated documentation files (the "Software"), 601e04c3fSmrg * to deal in the Software without restriction, including without limitation 701e04c3fSmrg * the rights to use, copy, modify, merge, publish, distribute, sublicense, 801e04c3fSmrg * and/or sell copies of the Software, and to permit persons to whom the 901e04c3fSmrg * Software is furnished to do so, subject to the following conditions: 1001e04c3fSmrg * 1101e04c3fSmrg * The above copyright notice and this permission notice (including the next 1201e04c3fSmrg * paragraph) shall be included in all copies or substantial portions of the 1301e04c3fSmrg * Software. 1401e04c3fSmrg * 1501e04c3fSmrg * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 1601e04c3fSmrg * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 1701e04c3fSmrg * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 1801e04c3fSmrg * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 1901e04c3fSmrg * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 2001e04c3fSmrg * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 2101e04c3fSmrg * DEALINGS IN THE SOFTWARE. 2201e04c3fSmrg */ 2301e04c3fSmrg 2401e04c3fSmrg/** 2501e04c3fSmrg * \file ir_constant_expression.cpp 2601e04c3fSmrg * Evaluate and process constant valued expressions 2701e04c3fSmrg * 2801e04c3fSmrg * In GLSL, constant valued expressions are used in several places. These 2901e04c3fSmrg * must be processed and evaluated very early in the compilation process. 3001e04c3fSmrg * 3101e04c3fSmrg * * Sizes of arrays 3201e04c3fSmrg * * Initializers for uniforms 3301e04c3fSmrg * * Initializers for \c const variables 3401e04c3fSmrg */ 3501e04c3fSmrg 3601e04c3fSmrg#include <math.h> 3701e04c3fSmrg#include "util/rounding.h" /* for _mesa_roundeven */ 3801e04c3fSmrg#include "util/half_float.h" 3901e04c3fSmrg#include "ir.h" 4001e04c3fSmrg#include "compiler/glsl_types.h" 4101e04c3fSmrg#include "util/hash_table.h" 4201e04c3fSmrg#include "util/u_math.h" 4301e04c3fSmrg 4401e04c3fSmrgstatic float 4501e04c3fSmrgdot_f(ir_constant *op0, ir_constant *op1) 4601e04c3fSmrg{ 4701e04c3fSmrg assert(op0->type->is_float() && op1->type->is_float()); 4801e04c3fSmrg 4901e04c3fSmrg float result = 0; 5001e04c3fSmrg for (unsigned c = 0; c < op0->type->components(); c++) 5101e04c3fSmrg result += op0->value.f[c] * op1->value.f[c]; 5201e04c3fSmrg 5301e04c3fSmrg return result; 5401e04c3fSmrg} 5501e04c3fSmrg 5601e04c3fSmrgstatic double 5701e04c3fSmrgdot_d(ir_constant *op0, ir_constant *op1) 5801e04c3fSmrg{ 5901e04c3fSmrg assert(op0->type->is_double() && op1->type->is_double()); 6001e04c3fSmrg 6101e04c3fSmrg double result = 0; 6201e04c3fSmrg for (unsigned c = 0; c < op0->type->components(); c++) 6301e04c3fSmrg result += op0->value.d[c] * op1->value.d[c]; 6401e04c3fSmrg 6501e04c3fSmrg return result; 6601e04c3fSmrg} 6701e04c3fSmrg 6801e04c3fSmrg/* This method is the only one supported by gcc. Unions in particular 6901e04c3fSmrg * are iffy, and read-through-converted-pointer is killed by strict 7001e04c3fSmrg * aliasing. OTOH, the compiler sees through the memcpy, so the 7101e04c3fSmrg * resulting asm is reasonable. 7201e04c3fSmrg */ 7301e04c3fSmrgstatic float 7401e04c3fSmrgbitcast_u2f(unsigned int u) 7501e04c3fSmrg{ 767ec681f3Smrg static_assert(sizeof(float) == sizeof(unsigned int), 777ec681f3Smrg "float and unsigned int size mismatch"); 7801e04c3fSmrg float f; 7901e04c3fSmrg memcpy(&f, &u, sizeof(f)); 8001e04c3fSmrg return f; 8101e04c3fSmrg} 8201e04c3fSmrg 8301e04c3fSmrgstatic unsigned int 8401e04c3fSmrgbitcast_f2u(float f) 8501e04c3fSmrg{ 867ec681f3Smrg static_assert(sizeof(float) == sizeof(unsigned int), 877ec681f3Smrg "float and unsigned int size mismatch"); 8801e04c3fSmrg unsigned int u; 8901e04c3fSmrg memcpy(&u, &f, sizeof(f)); 9001e04c3fSmrg return u; 9101e04c3fSmrg} 9201e04c3fSmrg 9301e04c3fSmrgstatic double 9401e04c3fSmrgbitcast_u642d(uint64_t u) 9501e04c3fSmrg{ 967ec681f3Smrg static_assert(sizeof(double) == sizeof(uint64_t), 977ec681f3Smrg "double and uint64_t size mismatch"); 9801e04c3fSmrg double d; 9901e04c3fSmrg memcpy(&d, &u, sizeof(d)); 10001e04c3fSmrg return d; 10101e04c3fSmrg} 10201e04c3fSmrg 10301e04c3fSmrgstatic double 10401e04c3fSmrgbitcast_i642d(int64_t i) 10501e04c3fSmrg{ 1067ec681f3Smrg static_assert(sizeof(double) == sizeof(int64_t), 1077ec681f3Smrg "double and int64_t size mismatch"); 10801e04c3fSmrg double d; 10901e04c3fSmrg memcpy(&d, &i, sizeof(d)); 11001e04c3fSmrg return d; 11101e04c3fSmrg} 11201e04c3fSmrg 1137ec681f3Smrgstatic uint64_t 11401e04c3fSmrgbitcast_d2u64(double d) 11501e04c3fSmrg{ 1167ec681f3Smrg static_assert(sizeof(double) == sizeof(uint64_t), 1177ec681f3Smrg "double and uint64_t size mismatch"); 11801e04c3fSmrg uint64_t u; 11901e04c3fSmrg memcpy(&u, &d, sizeof(d)); 12001e04c3fSmrg return u; 12101e04c3fSmrg} 12201e04c3fSmrg 1237ec681f3Smrgstatic int64_t 12401e04c3fSmrgbitcast_d2i64(double d) 12501e04c3fSmrg{ 1267ec681f3Smrg static_assert(sizeof(double) == sizeof(int64_t), 1277ec681f3Smrg "double and int64_t size mismatch"); 12801e04c3fSmrg int64_t i; 12901e04c3fSmrg memcpy(&i, &d, sizeof(d)); 13001e04c3fSmrg return i; 13101e04c3fSmrg} 13201e04c3fSmrg 13301e04c3fSmrg/** 13401e04c3fSmrg * Evaluate one component of a floating-point 4x8 unpacking function. 13501e04c3fSmrg */ 13601e04c3fSmrgtypedef uint8_t 13701e04c3fSmrg(*pack_1x8_func_t)(float); 13801e04c3fSmrg 13901e04c3fSmrg/** 14001e04c3fSmrg * Evaluate one component of a floating-point 2x16 unpacking function. 14101e04c3fSmrg */ 14201e04c3fSmrgtypedef uint16_t 14301e04c3fSmrg(*pack_1x16_func_t)(float); 14401e04c3fSmrg 14501e04c3fSmrg/** 14601e04c3fSmrg * Evaluate one component of a floating-point 4x8 unpacking function. 14701e04c3fSmrg */ 14801e04c3fSmrgtypedef float 14901e04c3fSmrg(*unpack_1x8_func_t)(uint8_t); 15001e04c3fSmrg 15101e04c3fSmrg/** 15201e04c3fSmrg * Evaluate one component of a floating-point 2x16 unpacking function. 15301e04c3fSmrg */ 15401e04c3fSmrgtypedef float 15501e04c3fSmrg(*unpack_1x16_func_t)(uint16_t); 15601e04c3fSmrg 15701e04c3fSmrg/** 15801e04c3fSmrg * Evaluate a 2x16 floating-point packing function. 15901e04c3fSmrg */ 16001e04c3fSmrgstatic uint32_t 16101e04c3fSmrgpack_2x16(pack_1x16_func_t pack_1x16, 16201e04c3fSmrg float x, float y) 16301e04c3fSmrg{ 16401e04c3fSmrg /* From section 8.4 of the GLSL ES 3.00 spec: 16501e04c3fSmrg * 16601e04c3fSmrg * packSnorm2x16 16701e04c3fSmrg * ------------- 16801e04c3fSmrg * The first component of the vector will be written to the least 16901e04c3fSmrg * significant bits of the output; the last component will be written to 17001e04c3fSmrg * the most significant bits. 17101e04c3fSmrg * 17201e04c3fSmrg * The specifications for the other packing functions contain similar 17301e04c3fSmrg * language. 17401e04c3fSmrg */ 17501e04c3fSmrg uint32_t u = 0; 17601e04c3fSmrg u |= ((uint32_t) pack_1x16(x) << 0); 17701e04c3fSmrg u |= ((uint32_t) pack_1x16(y) << 16); 17801e04c3fSmrg return u; 17901e04c3fSmrg} 18001e04c3fSmrg 18101e04c3fSmrg/** 18201e04c3fSmrg * Evaluate a 4x8 floating-point packing function. 18301e04c3fSmrg */ 18401e04c3fSmrgstatic uint32_t 18501e04c3fSmrgpack_4x8(pack_1x8_func_t pack_1x8, 18601e04c3fSmrg float x, float y, float z, float w) 18701e04c3fSmrg{ 18801e04c3fSmrg /* From section 8.4 of the GLSL 4.30 spec: 18901e04c3fSmrg * 19001e04c3fSmrg * packSnorm4x8 19101e04c3fSmrg * ------------ 19201e04c3fSmrg * The first component of the vector will be written to the least 19301e04c3fSmrg * significant bits of the output; the last component will be written to 19401e04c3fSmrg * the most significant bits. 19501e04c3fSmrg * 19601e04c3fSmrg * The specifications for the other packing functions contain similar 19701e04c3fSmrg * language. 19801e04c3fSmrg */ 19901e04c3fSmrg uint32_t u = 0; 20001e04c3fSmrg u |= ((uint32_t) pack_1x8(x) << 0); 20101e04c3fSmrg u |= ((uint32_t) pack_1x8(y) << 8); 20201e04c3fSmrg u |= ((uint32_t) pack_1x8(z) << 16); 20301e04c3fSmrg u |= ((uint32_t) pack_1x8(w) << 24); 20401e04c3fSmrg return u; 20501e04c3fSmrg} 20601e04c3fSmrg 20701e04c3fSmrg/** 20801e04c3fSmrg * Evaluate a 2x16 floating-point unpacking function. 20901e04c3fSmrg */ 21001e04c3fSmrgstatic void 21101e04c3fSmrgunpack_2x16(unpack_1x16_func_t unpack_1x16, 21201e04c3fSmrg uint32_t u, 21301e04c3fSmrg float *x, float *y) 21401e04c3fSmrg{ 21501e04c3fSmrg /* From section 8.4 of the GLSL ES 3.00 spec: 21601e04c3fSmrg * 21701e04c3fSmrg * unpackSnorm2x16 21801e04c3fSmrg * --------------- 21901e04c3fSmrg * The first component of the returned vector will be extracted from 22001e04c3fSmrg * the least significant bits of the input; the last component will be 22101e04c3fSmrg * extracted from the most significant bits. 22201e04c3fSmrg * 22301e04c3fSmrg * The specifications for the other unpacking functions contain similar 22401e04c3fSmrg * language. 22501e04c3fSmrg */ 22601e04c3fSmrg *x = unpack_1x16((uint16_t) (u & 0xffff)); 22701e04c3fSmrg *y = unpack_1x16((uint16_t) (u >> 16)); 22801e04c3fSmrg} 22901e04c3fSmrg 23001e04c3fSmrg/** 23101e04c3fSmrg * Evaluate a 4x8 floating-point unpacking function. 23201e04c3fSmrg */ 23301e04c3fSmrgstatic void 23401e04c3fSmrgunpack_4x8(unpack_1x8_func_t unpack_1x8, uint32_t u, 23501e04c3fSmrg float *x, float *y, float *z, float *w) 23601e04c3fSmrg{ 23701e04c3fSmrg /* From section 8.4 of the GLSL 4.30 spec: 23801e04c3fSmrg * 23901e04c3fSmrg * unpackSnorm4x8 24001e04c3fSmrg * -------------- 24101e04c3fSmrg * The first component of the returned vector will be extracted from 24201e04c3fSmrg * the least significant bits of the input; the last component will be 24301e04c3fSmrg * extracted from the most significant bits. 24401e04c3fSmrg * 24501e04c3fSmrg * The specifications for the other unpacking functions contain similar 24601e04c3fSmrg * language. 24701e04c3fSmrg */ 24801e04c3fSmrg *x = unpack_1x8((uint8_t) (u & 0xff)); 24901e04c3fSmrg *y = unpack_1x8((uint8_t) (u >> 8)); 25001e04c3fSmrg *z = unpack_1x8((uint8_t) (u >> 16)); 25101e04c3fSmrg *w = unpack_1x8((uint8_t) (u >> 24)); 25201e04c3fSmrg} 25301e04c3fSmrg 25401e04c3fSmrg/** 25501e04c3fSmrg * Evaluate one component of packSnorm4x8. 25601e04c3fSmrg */ 25701e04c3fSmrgstatic uint8_t 25801e04c3fSmrgpack_snorm_1x8(float x) 25901e04c3fSmrg{ 26001e04c3fSmrg /* From section 8.4 of the GLSL 4.30 spec: 26101e04c3fSmrg * 26201e04c3fSmrg * packSnorm4x8 26301e04c3fSmrg * ------------ 26401e04c3fSmrg * The conversion for component c of v to fixed point is done as 26501e04c3fSmrg * follows: 26601e04c3fSmrg * 26701e04c3fSmrg * packSnorm4x8: round(clamp(c, -1, +1) * 127.0) 26801e04c3fSmrg */ 26901e04c3fSmrg return (uint8_t) 27001e04c3fSmrg _mesa_lroundevenf(CLAMP(x, -1.0f, +1.0f) * 127.0f); 27101e04c3fSmrg} 27201e04c3fSmrg 27301e04c3fSmrg/** 27401e04c3fSmrg * Evaluate one component of packSnorm2x16. 27501e04c3fSmrg */ 27601e04c3fSmrgstatic uint16_t 27701e04c3fSmrgpack_snorm_1x16(float x) 27801e04c3fSmrg{ 27901e04c3fSmrg /* From section 8.4 of the GLSL ES 3.00 spec: 28001e04c3fSmrg * 28101e04c3fSmrg * packSnorm2x16 28201e04c3fSmrg * ------------- 28301e04c3fSmrg * The conversion for component c of v to fixed point is done as 28401e04c3fSmrg * follows: 28501e04c3fSmrg * 28601e04c3fSmrg * packSnorm2x16: round(clamp(c, -1, +1) * 32767.0) 28701e04c3fSmrg */ 28801e04c3fSmrg return (uint16_t) 28901e04c3fSmrg _mesa_lroundevenf(CLAMP(x, -1.0f, +1.0f) * 32767.0f); 29001e04c3fSmrg} 29101e04c3fSmrg 29201e04c3fSmrg/** 29301e04c3fSmrg * Evaluate one component of unpackSnorm4x8. 29401e04c3fSmrg */ 29501e04c3fSmrgstatic float 29601e04c3fSmrgunpack_snorm_1x8(uint8_t u) 29701e04c3fSmrg{ 29801e04c3fSmrg /* From section 8.4 of the GLSL 4.30 spec: 29901e04c3fSmrg * 30001e04c3fSmrg * unpackSnorm4x8 30101e04c3fSmrg * -------------- 30201e04c3fSmrg * The conversion for unpacked fixed-point value f to floating point is 30301e04c3fSmrg * done as follows: 30401e04c3fSmrg * 30501e04c3fSmrg * unpackSnorm4x8: clamp(f / 127.0, -1, +1) 30601e04c3fSmrg */ 30701e04c3fSmrg return CLAMP((int8_t) u / 127.0f, -1.0f, +1.0f); 30801e04c3fSmrg} 30901e04c3fSmrg 31001e04c3fSmrg/** 31101e04c3fSmrg * Evaluate one component of unpackSnorm2x16. 31201e04c3fSmrg */ 31301e04c3fSmrgstatic float 31401e04c3fSmrgunpack_snorm_1x16(uint16_t u) 31501e04c3fSmrg{ 31601e04c3fSmrg /* From section 8.4 of the GLSL ES 3.00 spec: 31701e04c3fSmrg * 31801e04c3fSmrg * unpackSnorm2x16 31901e04c3fSmrg * --------------- 32001e04c3fSmrg * The conversion for unpacked fixed-point value f to floating point is 32101e04c3fSmrg * done as follows: 32201e04c3fSmrg * 32301e04c3fSmrg * unpackSnorm2x16: clamp(f / 32767.0, -1, +1) 32401e04c3fSmrg */ 32501e04c3fSmrg return CLAMP((int16_t) u / 32767.0f, -1.0f, +1.0f); 32601e04c3fSmrg} 32701e04c3fSmrg 32801e04c3fSmrg/** 32901e04c3fSmrg * Evaluate one component packUnorm4x8. 33001e04c3fSmrg */ 33101e04c3fSmrgstatic uint8_t 33201e04c3fSmrgpack_unorm_1x8(float x) 33301e04c3fSmrg{ 33401e04c3fSmrg /* From section 8.4 of the GLSL 4.30 spec: 33501e04c3fSmrg * 33601e04c3fSmrg * packUnorm4x8 33701e04c3fSmrg * ------------ 33801e04c3fSmrg * The conversion for component c of v to fixed point is done as 33901e04c3fSmrg * follows: 34001e04c3fSmrg * 34101e04c3fSmrg * packUnorm4x8: round(clamp(c, 0, +1) * 255.0) 34201e04c3fSmrg */ 3437ec681f3Smrg return (uint8_t) (int) _mesa_roundevenf(SATURATE(x) * 255.0f); 34401e04c3fSmrg} 34501e04c3fSmrg 34601e04c3fSmrg/** 34701e04c3fSmrg * Evaluate one component packUnorm2x16. 34801e04c3fSmrg */ 34901e04c3fSmrgstatic uint16_t 35001e04c3fSmrgpack_unorm_1x16(float x) 35101e04c3fSmrg{ 35201e04c3fSmrg /* From section 8.4 of the GLSL ES 3.00 spec: 35301e04c3fSmrg * 35401e04c3fSmrg * packUnorm2x16 35501e04c3fSmrg * ------------- 35601e04c3fSmrg * The conversion for component c of v to fixed point is done as 35701e04c3fSmrg * follows: 35801e04c3fSmrg * 35901e04c3fSmrg * packUnorm2x16: round(clamp(c, 0, +1) * 65535.0) 36001e04c3fSmrg */ 36101e04c3fSmrg return (uint16_t) (int) 3627ec681f3Smrg _mesa_roundevenf(SATURATE(x) * 65535.0f); 36301e04c3fSmrg} 36401e04c3fSmrg 36501e04c3fSmrg/** 36601e04c3fSmrg * Evaluate one component of unpackUnorm4x8. 36701e04c3fSmrg */ 36801e04c3fSmrgstatic float 36901e04c3fSmrgunpack_unorm_1x8(uint8_t u) 37001e04c3fSmrg{ 37101e04c3fSmrg /* From section 8.4 of the GLSL 4.30 spec: 37201e04c3fSmrg * 37301e04c3fSmrg * unpackUnorm4x8 37401e04c3fSmrg * -------------- 37501e04c3fSmrg * The conversion for unpacked fixed-point value f to floating point is 37601e04c3fSmrg * done as follows: 37701e04c3fSmrg * 37801e04c3fSmrg * unpackUnorm4x8: f / 255.0 37901e04c3fSmrg */ 38001e04c3fSmrg return (float) u / 255.0f; 38101e04c3fSmrg} 38201e04c3fSmrg 38301e04c3fSmrg/** 38401e04c3fSmrg * Evaluate one component of unpackUnorm2x16. 38501e04c3fSmrg */ 38601e04c3fSmrgstatic float 38701e04c3fSmrgunpack_unorm_1x16(uint16_t u) 38801e04c3fSmrg{ 38901e04c3fSmrg /* From section 8.4 of the GLSL ES 3.00 spec: 39001e04c3fSmrg * 39101e04c3fSmrg * unpackUnorm2x16 39201e04c3fSmrg * --------------- 39301e04c3fSmrg * The conversion for unpacked fixed-point value f to floating point is 39401e04c3fSmrg * done as follows: 39501e04c3fSmrg * 39601e04c3fSmrg * unpackUnorm2x16: f / 65535.0 39701e04c3fSmrg */ 39801e04c3fSmrg return (float) u / 65535.0f; 39901e04c3fSmrg} 40001e04c3fSmrg 40101e04c3fSmrg/** 40201e04c3fSmrg * Evaluate one component of packHalf2x16. 40301e04c3fSmrg */ 40401e04c3fSmrgstatic uint16_t 40501e04c3fSmrgpack_half_1x16(float x) 40601e04c3fSmrg{ 40701e04c3fSmrg return _mesa_float_to_half(x); 40801e04c3fSmrg} 40901e04c3fSmrg 41001e04c3fSmrg/** 41101e04c3fSmrg * Evaluate one component of unpackHalf2x16. 41201e04c3fSmrg */ 41301e04c3fSmrgstatic float 41401e04c3fSmrgunpack_half_1x16(uint16_t u) 41501e04c3fSmrg{ 41601e04c3fSmrg return _mesa_half_to_float(u); 41701e04c3fSmrg} 41801e04c3fSmrg 4197ec681f3Smrgstatic int32_t 4207ec681f3Smrgiadd_saturate(int32_t a, int32_t b) 4217ec681f3Smrg{ 4227ec681f3Smrg return CLAMP(int64_t(a) + int64_t(b), INT32_MIN, INT32_MAX); 4237ec681f3Smrg} 4247ec681f3Smrg 4257ec681f3Smrgstatic int64_t 4267ec681f3Smrgiadd64_saturate(int64_t a, int64_t b) 4277ec681f3Smrg{ 4287ec681f3Smrg if (a < 0 && b < INT64_MIN - a) 4297ec681f3Smrg return INT64_MIN; 4307ec681f3Smrg 4317ec681f3Smrg if (a > 0 && b > INT64_MAX - a) 4327ec681f3Smrg return INT64_MAX; 4337ec681f3Smrg 4347ec681f3Smrg return a + b; 4357ec681f3Smrg} 4367ec681f3Smrg 4377ec681f3Smrgstatic int32_t 4387ec681f3Smrgisub_saturate(int32_t a, int32_t b) 4397ec681f3Smrg{ 4407ec681f3Smrg return CLAMP(int64_t(a) - int64_t(b), INT32_MIN, INT32_MAX); 4417ec681f3Smrg} 4427ec681f3Smrg 4437ec681f3Smrgstatic int64_t 4447ec681f3Smrgisub64_saturate(int64_t a, int64_t b) 4457ec681f3Smrg{ 4467ec681f3Smrg if (b > 0 && a < INT64_MIN + b) 4477ec681f3Smrg return INT64_MIN; 4487ec681f3Smrg 4497ec681f3Smrg if (b < 0 && a > INT64_MAX + b) 4507ec681f3Smrg return INT64_MAX; 4517ec681f3Smrg 4527ec681f3Smrg return a - b; 4537ec681f3Smrg} 4547ec681f3Smrg 4557ec681f3Smrgstatic uint64_t 4567ec681f3Smrgpack_2x32(uint32_t a, uint32_t b) 4577ec681f3Smrg{ 4587ec681f3Smrg uint64_t v = a; 4597ec681f3Smrg v |= (uint64_t)b << 32; 4607ec681f3Smrg return v; 4617ec681f3Smrg} 4627ec681f3Smrg 4637ec681f3Smrgstatic void 4647ec681f3Smrgunpack_2x32(uint64_t p, uint32_t *a, uint32_t *b) 4657ec681f3Smrg{ 4667ec681f3Smrg *a = p & 0xffffffff; 4677ec681f3Smrg *b = (p >> 32); 4687ec681f3Smrg} 4697ec681f3Smrg 47001e04c3fSmrg/** 47101e04c3fSmrg * Get the constant that is ultimately referenced by an r-value, in a constant 47201e04c3fSmrg * expression evaluation context. 47301e04c3fSmrg * 47401e04c3fSmrg * The offset is used when the reference is to a specific column of a matrix. 47501e04c3fSmrg */ 47601e04c3fSmrgstatic bool 47701e04c3fSmrgconstant_referenced(const ir_dereference *deref, 47801e04c3fSmrg struct hash_table *variable_context, 47901e04c3fSmrg ir_constant *&store, int &offset) 48001e04c3fSmrg{ 48101e04c3fSmrg store = NULL; 48201e04c3fSmrg offset = 0; 48301e04c3fSmrg 48401e04c3fSmrg if (variable_context == NULL) 48501e04c3fSmrg return false; 48601e04c3fSmrg 48701e04c3fSmrg switch (deref->ir_type) { 48801e04c3fSmrg case ir_type_dereference_array: { 48901e04c3fSmrg const ir_dereference_array *const da = 49001e04c3fSmrg (const ir_dereference_array *) deref; 49101e04c3fSmrg 49201e04c3fSmrg ir_constant *const index_c = 49301e04c3fSmrg da->array_index->constant_expression_value(variable_context); 49401e04c3fSmrg 4957ec681f3Smrg if (!index_c || !index_c->type->is_scalar() || 4967ec681f3Smrg !index_c->type->is_integer_32()) 49701e04c3fSmrg break; 49801e04c3fSmrg 49901e04c3fSmrg const int index = index_c->type->base_type == GLSL_TYPE_INT ? 50001e04c3fSmrg index_c->get_int_component(0) : 50101e04c3fSmrg index_c->get_uint_component(0); 50201e04c3fSmrg 50301e04c3fSmrg ir_constant *substore; 50401e04c3fSmrg int suboffset; 50501e04c3fSmrg 50601e04c3fSmrg const ir_dereference *const deref = da->array->as_dereference(); 50701e04c3fSmrg if (!deref) 50801e04c3fSmrg break; 50901e04c3fSmrg 51001e04c3fSmrg if (!constant_referenced(deref, variable_context, substore, suboffset)) 51101e04c3fSmrg break; 51201e04c3fSmrg 51301e04c3fSmrg const glsl_type *const vt = da->array->type; 51401e04c3fSmrg if (vt->is_array()) { 51501e04c3fSmrg store = substore->get_array_element(index); 51601e04c3fSmrg offset = 0; 51701e04c3fSmrg } else if (vt->is_matrix()) { 51801e04c3fSmrg store = substore; 51901e04c3fSmrg offset = index * vt->vector_elements; 52001e04c3fSmrg } else if (vt->is_vector()) { 52101e04c3fSmrg store = substore; 52201e04c3fSmrg offset = suboffset + index; 52301e04c3fSmrg } 52401e04c3fSmrg 52501e04c3fSmrg break; 52601e04c3fSmrg } 52701e04c3fSmrg 52801e04c3fSmrg case ir_type_dereference_record: { 52901e04c3fSmrg const ir_dereference_record *const dr = 53001e04c3fSmrg (const ir_dereference_record *) deref; 53101e04c3fSmrg 53201e04c3fSmrg const ir_dereference *const deref = dr->record->as_dereference(); 53301e04c3fSmrg if (!deref) 53401e04c3fSmrg break; 53501e04c3fSmrg 53601e04c3fSmrg ir_constant *substore; 53701e04c3fSmrg int suboffset; 53801e04c3fSmrg 53901e04c3fSmrg if (!constant_referenced(deref, variable_context, substore, suboffset)) 54001e04c3fSmrg break; 54101e04c3fSmrg 54201e04c3fSmrg /* Since we're dropping it on the floor... 54301e04c3fSmrg */ 54401e04c3fSmrg assert(suboffset == 0); 54501e04c3fSmrg 54601e04c3fSmrg store = substore->get_record_field(dr->field_idx); 54701e04c3fSmrg break; 54801e04c3fSmrg } 54901e04c3fSmrg 55001e04c3fSmrg case ir_type_dereference_variable: { 55101e04c3fSmrg const ir_dereference_variable *const dv = 55201e04c3fSmrg (const ir_dereference_variable *) deref; 55301e04c3fSmrg 55401e04c3fSmrg hash_entry *entry = _mesa_hash_table_search(variable_context, dv->var); 55501e04c3fSmrg if (entry) 55601e04c3fSmrg store = (ir_constant *) entry->data; 55701e04c3fSmrg break; 55801e04c3fSmrg } 55901e04c3fSmrg 56001e04c3fSmrg default: 56101e04c3fSmrg assert(!"Should not get here."); 56201e04c3fSmrg break; 56301e04c3fSmrg } 56401e04c3fSmrg 56501e04c3fSmrg return store != NULL; 56601e04c3fSmrg} 56701e04c3fSmrg 56801e04c3fSmrg 56901e04c3fSmrgir_constant * 57001e04c3fSmrgir_rvalue::constant_expression_value(void *, struct hash_table *) 57101e04c3fSmrg{ 57201e04c3fSmrg assert(this->type->is_error()); 57301e04c3fSmrg return NULL; 57401e04c3fSmrg} 57501e04c3fSmrg 57601e04c3fSmrgstatic uint32_t 57701e04c3fSmrgbitfield_reverse(uint32_t v) 57801e04c3fSmrg{ 57901e04c3fSmrg /* http://graphics.stanford.edu/~seander/bithacks.html#BitReverseObvious */ 58001e04c3fSmrg uint32_t r = v; // r will be reversed bits of v; first get LSB of v 58101e04c3fSmrg int s = sizeof(v) * CHAR_BIT - 1; // extra shift needed at end 58201e04c3fSmrg 58301e04c3fSmrg for (v >>= 1; v; v >>= 1) { 58401e04c3fSmrg r <<= 1; 58501e04c3fSmrg r |= v & 1; 58601e04c3fSmrg s--; 58701e04c3fSmrg } 58801e04c3fSmrg r <<= s; // shift when v's highest bits are zero 58901e04c3fSmrg 59001e04c3fSmrg return r; 59101e04c3fSmrg} 59201e04c3fSmrg 59301e04c3fSmrgstatic int 59401e04c3fSmrgfind_msb_uint(uint32_t v) 59501e04c3fSmrg{ 59601e04c3fSmrg int count = 0; 59701e04c3fSmrg 59801e04c3fSmrg /* If v == 0, then the loop will terminate when count == 32. In that case 59901e04c3fSmrg * 31-count will produce the -1 result required by GLSL findMSB(). 60001e04c3fSmrg */ 60101e04c3fSmrg while (((v & (1u << 31)) == 0) && count != 32) { 60201e04c3fSmrg count++; 60301e04c3fSmrg v <<= 1; 60401e04c3fSmrg } 60501e04c3fSmrg 60601e04c3fSmrg return 31 - count; 60701e04c3fSmrg} 60801e04c3fSmrg 60901e04c3fSmrgstatic int 61001e04c3fSmrgfind_msb_int(int32_t v) 61101e04c3fSmrg{ 61201e04c3fSmrg /* If v is signed, findMSB() returns the position of the most significant 61301e04c3fSmrg * zero bit. 61401e04c3fSmrg */ 61501e04c3fSmrg return find_msb_uint(v < 0 ? ~v : v); 61601e04c3fSmrg} 61701e04c3fSmrg 61801e04c3fSmrgstatic float 61901e04c3fSmrgldexpf_flush_subnormal(float x, int exp) 62001e04c3fSmrg{ 62101e04c3fSmrg const float result = ldexpf(x, exp); 62201e04c3fSmrg 62301e04c3fSmrg /* Flush subnormal values to zero. */ 62401e04c3fSmrg return !isnormal(result) ? copysignf(0.0f, x) : result; 62501e04c3fSmrg} 62601e04c3fSmrg 62701e04c3fSmrgstatic double 62801e04c3fSmrgldexp_flush_subnormal(double x, int exp) 62901e04c3fSmrg{ 63001e04c3fSmrg const double result = ldexp(x, exp); 63101e04c3fSmrg 63201e04c3fSmrg /* Flush subnormal values to zero. */ 63301e04c3fSmrg return !isnormal(result) ? copysign(0.0, x) : result; 63401e04c3fSmrg} 63501e04c3fSmrg 63601e04c3fSmrgstatic uint32_t 63701e04c3fSmrgbitfield_extract_uint(uint32_t value, int offset, int bits) 63801e04c3fSmrg{ 63901e04c3fSmrg if (bits == 0) 64001e04c3fSmrg return 0; 64101e04c3fSmrg else if (offset < 0 || bits < 0) 64201e04c3fSmrg return 0; /* Undefined, per spec. */ 64301e04c3fSmrg else if (offset + bits > 32) 64401e04c3fSmrg return 0; /* Undefined, per spec. */ 64501e04c3fSmrg else { 64601e04c3fSmrg value <<= 32 - bits - offset; 64701e04c3fSmrg value >>= 32 - bits; 64801e04c3fSmrg return value; 64901e04c3fSmrg } 65001e04c3fSmrg} 65101e04c3fSmrg 65201e04c3fSmrgstatic int32_t 65301e04c3fSmrgbitfield_extract_int(int32_t value, int offset, int bits) 65401e04c3fSmrg{ 65501e04c3fSmrg if (bits == 0) 65601e04c3fSmrg return 0; 65701e04c3fSmrg else if (offset < 0 || bits < 0) 65801e04c3fSmrg return 0; /* Undefined, per spec. */ 65901e04c3fSmrg else if (offset + bits > 32) 66001e04c3fSmrg return 0; /* Undefined, per spec. */ 66101e04c3fSmrg else { 66201e04c3fSmrg value <<= 32 - bits - offset; 66301e04c3fSmrg value >>= 32 - bits; 66401e04c3fSmrg return value; 66501e04c3fSmrg } 66601e04c3fSmrg} 66701e04c3fSmrg 66801e04c3fSmrgstatic uint32_t 66901e04c3fSmrgbitfield_insert(uint32_t base, uint32_t insert, int offset, int bits) 67001e04c3fSmrg{ 67101e04c3fSmrg if (bits == 0) 67201e04c3fSmrg return base; 67301e04c3fSmrg else if (offset < 0 || bits < 0) 67401e04c3fSmrg return 0; /* Undefined, per spec. */ 67501e04c3fSmrg else if (offset + bits > 32) 67601e04c3fSmrg return 0; /* Undefined, per spec. */ 67701e04c3fSmrg else { 67801e04c3fSmrg unsigned insert_mask = ((1ull << bits) - 1) << offset; 67901e04c3fSmrg 68001e04c3fSmrg insert <<= offset; 68101e04c3fSmrg insert &= insert_mask; 68201e04c3fSmrg base &= ~insert_mask; 68301e04c3fSmrg 68401e04c3fSmrg return base | insert; 68501e04c3fSmrg } 68601e04c3fSmrg} 68701e04c3fSmrg 68801e04c3fSmrgir_constant * 68901e04c3fSmrgir_expression::constant_expression_value(void *mem_ctx, 69001e04c3fSmrg struct hash_table *variable_context) 69101e04c3fSmrg{ 69201e04c3fSmrg assert(mem_ctx); 69301e04c3fSmrg 69401e04c3fSmrg if (this->type->is_error()) 69501e04c3fSmrg return NULL; 69601e04c3fSmrg 6977ec681f3Smrg const glsl_type *return_type = this->type; 69801e04c3fSmrg ir_constant *op[ARRAY_SIZE(this->operands)] = { NULL, }; 69901e04c3fSmrg ir_constant_data data; 70001e04c3fSmrg 70101e04c3fSmrg memset(&data, 0, sizeof(data)); 70201e04c3fSmrg 70301e04c3fSmrg for (unsigned operand = 0; operand < this->num_operands; operand++) { 70401e04c3fSmrg op[operand] = 70501e04c3fSmrg this->operands[operand]->constant_expression_value(mem_ctx, 70601e04c3fSmrg variable_context); 70701e04c3fSmrg if (!op[operand]) 70801e04c3fSmrg return NULL; 70901e04c3fSmrg } 71001e04c3fSmrg 7117ec681f3Smrg for (unsigned operand = 0; operand < this->num_operands; operand++) { 7127ec681f3Smrg switch (op[operand]->type->base_type) { 7137ec681f3Smrg case GLSL_TYPE_FLOAT16: { 7147ec681f3Smrg const struct glsl_type *float_type = 7157ec681f3Smrg glsl_type::get_instance(GLSL_TYPE_FLOAT, 7167ec681f3Smrg op[operand]->type->vector_elements, 7177ec681f3Smrg op[operand]->type->matrix_columns, 7187ec681f3Smrg op[operand]->type->explicit_stride, 7197ec681f3Smrg op[operand]->type->interface_row_major); 7207ec681f3Smrg 7217ec681f3Smrg ir_constant_data f; 7227ec681f3Smrg for (unsigned i = 0; i < ARRAY_SIZE(f.f); i++) 7237ec681f3Smrg f.f[i] = _mesa_half_to_float(op[operand]->value.f16[i]); 7247ec681f3Smrg 7257ec681f3Smrg op[operand] = new(mem_ctx) ir_constant(float_type, &f); 7267ec681f3Smrg break; 7277ec681f3Smrg } 7287ec681f3Smrg case GLSL_TYPE_INT16: { 7297ec681f3Smrg const struct glsl_type *int_type = 7307ec681f3Smrg glsl_type::get_instance(GLSL_TYPE_INT, 7317ec681f3Smrg op[operand]->type->vector_elements, 7327ec681f3Smrg op[operand]->type->matrix_columns, 7337ec681f3Smrg op[operand]->type->explicit_stride, 7347ec681f3Smrg op[operand]->type->interface_row_major); 7357ec681f3Smrg 7367ec681f3Smrg ir_constant_data d; 7377ec681f3Smrg for (unsigned i = 0; i < ARRAY_SIZE(d.i); i++) 7387ec681f3Smrg d.i[i] = op[operand]->value.i16[i]; 7397ec681f3Smrg 7407ec681f3Smrg op[operand] = new(mem_ctx) ir_constant(int_type, &d); 7417ec681f3Smrg break; 7427ec681f3Smrg } 7437ec681f3Smrg case GLSL_TYPE_UINT16: { 7447ec681f3Smrg const struct glsl_type *uint_type = 7457ec681f3Smrg glsl_type::get_instance(GLSL_TYPE_UINT, 7467ec681f3Smrg op[operand]->type->vector_elements, 7477ec681f3Smrg op[operand]->type->matrix_columns, 7487ec681f3Smrg op[operand]->type->explicit_stride, 7497ec681f3Smrg op[operand]->type->interface_row_major); 7507ec681f3Smrg 7517ec681f3Smrg ir_constant_data d; 7527ec681f3Smrg for (unsigned i = 0; i < ARRAY_SIZE(d.u); i++) 7537ec681f3Smrg d.u[i] = op[operand]->value.u16[i]; 7547ec681f3Smrg 7557ec681f3Smrg op[operand] = new(mem_ctx) ir_constant(uint_type, &d); 7567ec681f3Smrg break; 7577ec681f3Smrg } 7587ec681f3Smrg default: 7597ec681f3Smrg /* nothing to do */ 7607ec681f3Smrg break; 7617ec681f3Smrg } 7627ec681f3Smrg } 7637ec681f3Smrg 7647ec681f3Smrg switch (return_type->base_type) { 7657ec681f3Smrg case GLSL_TYPE_FLOAT16: 7667ec681f3Smrg return_type = glsl_type::get_instance(GLSL_TYPE_FLOAT, 7677ec681f3Smrg return_type->vector_elements, 7687ec681f3Smrg return_type->matrix_columns, 7697ec681f3Smrg return_type->explicit_stride, 7707ec681f3Smrg return_type->interface_row_major); 7717ec681f3Smrg break; 7727ec681f3Smrg case GLSL_TYPE_INT16: 7737ec681f3Smrg return_type = glsl_type::get_instance(GLSL_TYPE_INT, 7747ec681f3Smrg return_type->vector_elements, 7757ec681f3Smrg return_type->matrix_columns, 7767ec681f3Smrg return_type->explicit_stride, 7777ec681f3Smrg return_type->interface_row_major); 7787ec681f3Smrg break; 7797ec681f3Smrg case GLSL_TYPE_UINT16: 7807ec681f3Smrg return_type = glsl_type::get_instance(GLSL_TYPE_UINT, 7817ec681f3Smrg return_type->vector_elements, 7827ec681f3Smrg return_type->matrix_columns, 7837ec681f3Smrg return_type->explicit_stride, 7847ec681f3Smrg return_type->interface_row_major); 7857ec681f3Smrg break; 7867ec681f3Smrg default: 7877ec681f3Smrg /* nothing to do */ 7887ec681f3Smrg break; 7897ec681f3Smrg } 7907ec681f3Smrg 79101e04c3fSmrg if (op[1] != NULL) 79201e04c3fSmrg switch (this->operation) { 79301e04c3fSmrg case ir_binop_lshift: 79401e04c3fSmrg case ir_binop_rshift: 79501e04c3fSmrg case ir_binop_ldexp: 79601e04c3fSmrg case ir_binop_interpolate_at_offset: 79701e04c3fSmrg case ir_binop_interpolate_at_sample: 79801e04c3fSmrg case ir_binop_vector_extract: 79901e04c3fSmrg case ir_triop_csel: 80001e04c3fSmrg case ir_triop_bitfield_extract: 80101e04c3fSmrg break; 80201e04c3fSmrg 80301e04c3fSmrg default: 80401e04c3fSmrg assert(op[0]->type->base_type == op[1]->type->base_type); 80501e04c3fSmrg break; 80601e04c3fSmrg } 80701e04c3fSmrg 80801e04c3fSmrg bool op0_scalar = op[0]->type->is_scalar(); 80901e04c3fSmrg bool op1_scalar = op[1] != NULL && op[1]->type->is_scalar(); 81001e04c3fSmrg 81101e04c3fSmrg /* When iterating over a vector or matrix's components, we want to increase 81201e04c3fSmrg * the loop counter. However, for scalars, we want to stay at 0. 81301e04c3fSmrg */ 81401e04c3fSmrg unsigned c0_inc = op0_scalar ? 0 : 1; 81501e04c3fSmrg unsigned c1_inc = op1_scalar ? 0 : 1; 81601e04c3fSmrg unsigned components; 81701e04c3fSmrg if (op1_scalar || !op[1]) { 81801e04c3fSmrg components = op[0]->type->components(); 81901e04c3fSmrg } else { 82001e04c3fSmrg components = op[1]->type->components(); 82101e04c3fSmrg } 82201e04c3fSmrg 82301e04c3fSmrg /* Handle array operations here, rather than below. */ 82401e04c3fSmrg if (op[0]->type->is_array()) { 82501e04c3fSmrg assert(op[1] != NULL && op[1]->type->is_array()); 82601e04c3fSmrg switch (this->operation) { 82701e04c3fSmrg case ir_binop_all_equal: 82801e04c3fSmrg return new(mem_ctx) ir_constant(op[0]->has_value(op[1])); 82901e04c3fSmrg case ir_binop_any_nequal: 83001e04c3fSmrg return new(mem_ctx) ir_constant(!op[0]->has_value(op[1])); 83101e04c3fSmrg default: 83201e04c3fSmrg break; 83301e04c3fSmrg } 83401e04c3fSmrg return NULL; 83501e04c3fSmrg } 83601e04c3fSmrg 83701e04c3fSmrg#include "ir_expression_operation_constant.h" 83801e04c3fSmrg 8397ec681f3Smrg switch (type->base_type) { 8407ec681f3Smrg case GLSL_TYPE_FLOAT16: { 8417ec681f3Smrg ir_constant_data f; 8427ec681f3Smrg for (unsigned i = 0; i < ARRAY_SIZE(f.f16); i++) 8437ec681f3Smrg f.f16[i] = _mesa_float_to_half(data.f[i]); 8447ec681f3Smrg 8457ec681f3Smrg return new(mem_ctx) ir_constant(this->type, &f); 8467ec681f3Smrg } 8477ec681f3Smrg case GLSL_TYPE_INT16: { 8487ec681f3Smrg ir_constant_data d; 8497ec681f3Smrg for (unsigned i = 0; i < ARRAY_SIZE(d.i16); i++) 8507ec681f3Smrg d.i16[i] = data.i[i]; 8517ec681f3Smrg 8527ec681f3Smrg return new(mem_ctx) ir_constant(this->type, &d); 8537ec681f3Smrg } 8547ec681f3Smrg case GLSL_TYPE_UINT16: { 8557ec681f3Smrg ir_constant_data d; 8567ec681f3Smrg for (unsigned i = 0; i < ARRAY_SIZE(d.u16); i++) 8577ec681f3Smrg d.u16[i] = data.u[i]; 8587ec681f3Smrg 8597ec681f3Smrg return new(mem_ctx) ir_constant(this->type, &d); 8607ec681f3Smrg } 8617ec681f3Smrg default: 8627ec681f3Smrg return new(mem_ctx) ir_constant(this->type, &data); 8637ec681f3Smrg } 86401e04c3fSmrg} 86501e04c3fSmrg 86601e04c3fSmrg 86701e04c3fSmrgir_constant * 86801e04c3fSmrgir_texture::constant_expression_value(void *, struct hash_table *) 86901e04c3fSmrg{ 87001e04c3fSmrg /* texture lookups aren't constant expressions */ 87101e04c3fSmrg return NULL; 87201e04c3fSmrg} 87301e04c3fSmrg 87401e04c3fSmrg 87501e04c3fSmrgir_constant * 87601e04c3fSmrgir_swizzle::constant_expression_value(void *mem_ctx, 87701e04c3fSmrg struct hash_table *variable_context) 87801e04c3fSmrg{ 87901e04c3fSmrg assert(mem_ctx); 88001e04c3fSmrg 88101e04c3fSmrg ir_constant *v = this->val->constant_expression_value(mem_ctx, 88201e04c3fSmrg variable_context); 88301e04c3fSmrg 88401e04c3fSmrg if (v != NULL) { 88501e04c3fSmrg ir_constant_data data = { { 0 } }; 88601e04c3fSmrg 88701e04c3fSmrg const unsigned swiz_idx[4] = { 88801e04c3fSmrg this->mask.x, this->mask.y, this->mask.z, this->mask.w 88901e04c3fSmrg }; 89001e04c3fSmrg 89101e04c3fSmrg for (unsigned i = 0; i < this->mask.num_components; i++) { 89201e04c3fSmrg switch (v->type->base_type) { 8937ec681f3Smrg case GLSL_TYPE_UINT16: 8947ec681f3Smrg case GLSL_TYPE_INT16: data.u16[i] = v->value.u16[swiz_idx[i]]; break; 89501e04c3fSmrg case GLSL_TYPE_UINT: 89601e04c3fSmrg case GLSL_TYPE_INT: data.u[i] = v->value.u[swiz_idx[i]]; break; 89701e04c3fSmrg case GLSL_TYPE_FLOAT: data.f[i] = v->value.f[swiz_idx[i]]; break; 8987ec681f3Smrg case GLSL_TYPE_FLOAT16: data.f16[i] = v->value.f16[swiz_idx[i]]; break; 89901e04c3fSmrg case GLSL_TYPE_BOOL: data.b[i] = v->value.b[swiz_idx[i]]; break; 90001e04c3fSmrg case GLSL_TYPE_DOUBLE:data.d[i] = v->value.d[swiz_idx[i]]; break; 90101e04c3fSmrg case GLSL_TYPE_UINT64:data.u64[i] = v->value.u64[swiz_idx[i]]; break; 90201e04c3fSmrg case GLSL_TYPE_INT64: data.i64[i] = v->value.i64[swiz_idx[i]]; break; 90301e04c3fSmrg default: assert(!"Should not get here."); break; 90401e04c3fSmrg } 90501e04c3fSmrg } 90601e04c3fSmrg 90701e04c3fSmrg return new(mem_ctx) ir_constant(this->type, &data); 90801e04c3fSmrg } 90901e04c3fSmrg return NULL; 91001e04c3fSmrg} 91101e04c3fSmrg 91201e04c3fSmrg 91301e04c3fSmrgir_constant * 91401e04c3fSmrgir_dereference_variable::constant_expression_value(void *mem_ctx, 91501e04c3fSmrg struct hash_table *variable_context) 91601e04c3fSmrg{ 91701e04c3fSmrg assert(var); 91801e04c3fSmrg assert(mem_ctx); 91901e04c3fSmrg 92001e04c3fSmrg /* Give priority to the context hashtable, if it exists */ 92101e04c3fSmrg if (variable_context) { 92201e04c3fSmrg hash_entry *entry = _mesa_hash_table_search(variable_context, var); 92301e04c3fSmrg 92401e04c3fSmrg if(entry) 92501e04c3fSmrg return (ir_constant *) entry->data; 92601e04c3fSmrg } 92701e04c3fSmrg 92801e04c3fSmrg /* The constant_value of a uniform variable is its initializer, 92901e04c3fSmrg * not the lifetime constant value of the uniform. 93001e04c3fSmrg */ 93101e04c3fSmrg if (var->data.mode == ir_var_uniform) 93201e04c3fSmrg return NULL; 93301e04c3fSmrg 93401e04c3fSmrg if (!var->constant_value) 93501e04c3fSmrg return NULL; 93601e04c3fSmrg 93701e04c3fSmrg return var->constant_value->clone(mem_ctx, NULL); 93801e04c3fSmrg} 93901e04c3fSmrg 94001e04c3fSmrg 94101e04c3fSmrgir_constant * 94201e04c3fSmrgir_dereference_array::constant_expression_value(void *mem_ctx, 94301e04c3fSmrg struct hash_table *variable_context) 94401e04c3fSmrg{ 94501e04c3fSmrg assert(mem_ctx); 94601e04c3fSmrg 94701e04c3fSmrg ir_constant *array = this->array->constant_expression_value(mem_ctx, variable_context); 94801e04c3fSmrg ir_constant *idx = this->array_index->constant_expression_value(mem_ctx, variable_context); 94901e04c3fSmrg 95001e04c3fSmrg if ((array != NULL) && (idx != NULL)) { 95101e04c3fSmrg if (array->type->is_matrix()) { 95201e04c3fSmrg /* Array access of a matrix results in a vector. 95301e04c3fSmrg */ 95401e04c3fSmrg const unsigned column = idx->value.u[0]; 95501e04c3fSmrg 95601e04c3fSmrg const glsl_type *const column_type = array->type->column_type(); 95701e04c3fSmrg 9587ec681f3Smrg /* Section 5.11 (Out-of-Bounds Accesses) of the GLSL 4.60 spec says: 9597ec681f3Smrg * 9607ec681f3Smrg * In the subsections described above for array, vector, matrix and 9617ec681f3Smrg * structure accesses, any out-of-bounds access produced undefined 9627ec681f3Smrg * behavior....Out-of-bounds reads return undefined values, which 9637ec681f3Smrg * include values from other variables of the active program or zero. 9647ec681f3Smrg */ 9657ec681f3Smrg if (idx->value.i[0] < 0 || column >= array->type->matrix_columns) { 9667ec681f3Smrg ir_constant_data data = { { 0 } }; 9677ec681f3Smrg 9687ec681f3Smrg return new(mem_ctx) ir_constant(column_type, &data); 9697ec681f3Smrg } 9707ec681f3Smrg 97101e04c3fSmrg /* Offset in the constant matrix to the first element of the column 97201e04c3fSmrg * to be extracted. 97301e04c3fSmrg */ 97401e04c3fSmrg const unsigned mat_idx = column * column_type->vector_elements; 97501e04c3fSmrg 97601e04c3fSmrg ir_constant_data data = { { 0 } }; 97701e04c3fSmrg 97801e04c3fSmrg switch (column_type->base_type) { 9797ec681f3Smrg case GLSL_TYPE_FLOAT16: 98001e04c3fSmrg for (unsigned i = 0; i < column_type->vector_elements; i++) 9817ec681f3Smrg data.f16[i] = array->value.f16[mat_idx + i]; 98201e04c3fSmrg 98301e04c3fSmrg break; 98401e04c3fSmrg 98501e04c3fSmrg case GLSL_TYPE_FLOAT: 98601e04c3fSmrg for (unsigned i = 0; i < column_type->vector_elements; i++) 98701e04c3fSmrg data.f[i] = array->value.f[mat_idx + i]; 98801e04c3fSmrg 98901e04c3fSmrg break; 99001e04c3fSmrg 99101e04c3fSmrg case GLSL_TYPE_DOUBLE: 99201e04c3fSmrg for (unsigned i = 0; i < column_type->vector_elements; i++) 99301e04c3fSmrg data.d[i] = array->value.d[mat_idx + i]; 99401e04c3fSmrg 99501e04c3fSmrg break; 99601e04c3fSmrg 99701e04c3fSmrg default: 9987ec681f3Smrg unreachable("Matrix types are either float or double."); 99901e04c3fSmrg } 100001e04c3fSmrg 100101e04c3fSmrg return new(mem_ctx) ir_constant(column_type, &data); 100201e04c3fSmrg } else if (array->type->is_vector()) { 100301e04c3fSmrg const unsigned component = idx->value.u[0]; 100401e04c3fSmrg 100501e04c3fSmrg return new(mem_ctx) ir_constant(array, component); 100601e04c3fSmrg } else if (array->type->is_array()) { 100701e04c3fSmrg const unsigned index = idx->value.u[0]; 100801e04c3fSmrg return array->get_array_element(index)->clone(mem_ctx, NULL); 100901e04c3fSmrg } 101001e04c3fSmrg } 101101e04c3fSmrg return NULL; 101201e04c3fSmrg} 101301e04c3fSmrg 101401e04c3fSmrg 101501e04c3fSmrgir_constant * 101601e04c3fSmrgir_dereference_record::constant_expression_value(void *mem_ctx, 101701e04c3fSmrg struct hash_table *) 101801e04c3fSmrg{ 101901e04c3fSmrg assert(mem_ctx); 102001e04c3fSmrg 102101e04c3fSmrg ir_constant *v = this->record->constant_expression_value(mem_ctx); 102201e04c3fSmrg 102301e04c3fSmrg return (v != NULL) ? v->get_record_field(this->field_idx) : NULL; 102401e04c3fSmrg} 102501e04c3fSmrg 102601e04c3fSmrg 102701e04c3fSmrgir_constant * 102801e04c3fSmrgir_assignment::constant_expression_value(void *, struct hash_table *) 102901e04c3fSmrg{ 103001e04c3fSmrg /* FINISHME: Handle CEs involving assignment (return RHS) */ 103101e04c3fSmrg return NULL; 103201e04c3fSmrg} 103301e04c3fSmrg 103401e04c3fSmrg 103501e04c3fSmrgir_constant * 103601e04c3fSmrgir_constant::constant_expression_value(void *, struct hash_table *) 103701e04c3fSmrg{ 103801e04c3fSmrg return this; 103901e04c3fSmrg} 104001e04c3fSmrg 104101e04c3fSmrg 104201e04c3fSmrgir_constant * 104301e04c3fSmrgir_call::constant_expression_value(void *mem_ctx, struct hash_table *variable_context) 104401e04c3fSmrg{ 104501e04c3fSmrg assert(mem_ctx); 104601e04c3fSmrg 104701e04c3fSmrg return this->callee->constant_expression_value(mem_ctx, 104801e04c3fSmrg &this->actual_parameters, 104901e04c3fSmrg variable_context); 105001e04c3fSmrg} 105101e04c3fSmrg 105201e04c3fSmrg 105301e04c3fSmrgbool ir_function_signature::constant_expression_evaluate_expression_list(void *mem_ctx, 105401e04c3fSmrg const struct exec_list &body, 105501e04c3fSmrg struct hash_table *variable_context, 105601e04c3fSmrg ir_constant **result) 105701e04c3fSmrg{ 105801e04c3fSmrg assert(mem_ctx); 105901e04c3fSmrg 106001e04c3fSmrg foreach_in_list(ir_instruction, inst, &body) { 106101e04c3fSmrg switch(inst->ir_type) { 106201e04c3fSmrg 106301e04c3fSmrg /* (declare () type symbol) */ 106401e04c3fSmrg case ir_type_variable: { 106501e04c3fSmrg ir_variable *var = inst->as_variable(); 106601e04c3fSmrg _mesa_hash_table_insert(variable_context, var, ir_constant::zero(this, var->type)); 106701e04c3fSmrg break; 106801e04c3fSmrg } 106901e04c3fSmrg 107001e04c3fSmrg /* (assign [condition] (write-mask) (ref) (value)) */ 107101e04c3fSmrg case ir_type_assignment: { 107201e04c3fSmrg ir_assignment *asg = inst->as_assignment(); 107301e04c3fSmrg if (asg->condition) { 107401e04c3fSmrg ir_constant *cond = 107501e04c3fSmrg asg->condition->constant_expression_value(mem_ctx, 107601e04c3fSmrg variable_context); 107701e04c3fSmrg if (!cond) 107801e04c3fSmrg return false; 107901e04c3fSmrg if (!cond->get_bool_component(0)) 108001e04c3fSmrg break; 108101e04c3fSmrg } 108201e04c3fSmrg 108301e04c3fSmrg ir_constant *store = NULL; 108401e04c3fSmrg int offset = 0; 108501e04c3fSmrg 108601e04c3fSmrg if (!constant_referenced(asg->lhs, variable_context, store, offset)) 108701e04c3fSmrg return false; 108801e04c3fSmrg 108901e04c3fSmrg ir_constant *value = 109001e04c3fSmrg asg->rhs->constant_expression_value(mem_ctx, variable_context); 109101e04c3fSmrg 109201e04c3fSmrg if (!value) 109301e04c3fSmrg return false; 109401e04c3fSmrg 109501e04c3fSmrg store->copy_masked_offset(value, offset, asg->write_mask); 109601e04c3fSmrg break; 109701e04c3fSmrg } 109801e04c3fSmrg 109901e04c3fSmrg /* (return (expression)) */ 110001e04c3fSmrg case ir_type_return: 110101e04c3fSmrg assert (result); 110201e04c3fSmrg *result = 110301e04c3fSmrg inst->as_return()->value->constant_expression_value(mem_ctx, 110401e04c3fSmrg variable_context); 110501e04c3fSmrg return *result != NULL; 110601e04c3fSmrg 110701e04c3fSmrg /* (call name (ref) (params))*/ 110801e04c3fSmrg case ir_type_call: { 110901e04c3fSmrg ir_call *call = inst->as_call(); 111001e04c3fSmrg 111101e04c3fSmrg /* Just say no to void functions in constant expressions. We 111201e04c3fSmrg * don't need them at that point. 111301e04c3fSmrg */ 111401e04c3fSmrg 111501e04c3fSmrg if (!call->return_deref) 111601e04c3fSmrg return false; 111701e04c3fSmrg 111801e04c3fSmrg ir_constant *store = NULL; 111901e04c3fSmrg int offset = 0; 112001e04c3fSmrg 112101e04c3fSmrg if (!constant_referenced(call->return_deref, variable_context, 112201e04c3fSmrg store, offset)) 112301e04c3fSmrg return false; 112401e04c3fSmrg 112501e04c3fSmrg ir_constant *value = 112601e04c3fSmrg call->constant_expression_value(mem_ctx, variable_context); 112701e04c3fSmrg 112801e04c3fSmrg if(!value) 112901e04c3fSmrg return false; 113001e04c3fSmrg 113101e04c3fSmrg store->copy_offset(value, offset); 113201e04c3fSmrg break; 113301e04c3fSmrg } 113401e04c3fSmrg 113501e04c3fSmrg /* (if condition (then-instructions) (else-instructions)) */ 113601e04c3fSmrg case ir_type_if: { 113701e04c3fSmrg ir_if *iif = inst->as_if(); 113801e04c3fSmrg 113901e04c3fSmrg ir_constant *cond = 114001e04c3fSmrg iif->condition->constant_expression_value(mem_ctx, 114101e04c3fSmrg variable_context); 114201e04c3fSmrg if (!cond || !cond->type->is_boolean()) 114301e04c3fSmrg return false; 114401e04c3fSmrg 114501e04c3fSmrg exec_list &branch = cond->get_bool_component(0) ? iif->then_instructions : iif->else_instructions; 114601e04c3fSmrg 114701e04c3fSmrg *result = NULL; 114801e04c3fSmrg if (!constant_expression_evaluate_expression_list(mem_ctx, branch, 114901e04c3fSmrg variable_context, 115001e04c3fSmrg result)) 115101e04c3fSmrg return false; 115201e04c3fSmrg 115301e04c3fSmrg /* If there was a return in the branch chosen, drop out now. */ 115401e04c3fSmrg if (*result) 115501e04c3fSmrg return true; 115601e04c3fSmrg 115701e04c3fSmrg break; 115801e04c3fSmrg } 115901e04c3fSmrg 116001e04c3fSmrg /* Every other expression type, we drop out. */ 116101e04c3fSmrg default: 116201e04c3fSmrg return false; 116301e04c3fSmrg } 116401e04c3fSmrg } 116501e04c3fSmrg 116601e04c3fSmrg /* Reaching the end of the block is not an error condition */ 116701e04c3fSmrg if (result) 116801e04c3fSmrg *result = NULL; 116901e04c3fSmrg 117001e04c3fSmrg return true; 117101e04c3fSmrg} 117201e04c3fSmrg 117301e04c3fSmrgir_constant * 117401e04c3fSmrgir_function_signature::constant_expression_value(void *mem_ctx, 117501e04c3fSmrg exec_list *actual_parameters, 117601e04c3fSmrg struct hash_table *variable_context) 117701e04c3fSmrg{ 117801e04c3fSmrg assert(mem_ctx); 117901e04c3fSmrg 118001e04c3fSmrg const glsl_type *type = this->return_type; 118101e04c3fSmrg if (type == glsl_type::void_type) 118201e04c3fSmrg return NULL; 118301e04c3fSmrg 118401e04c3fSmrg /* From the GLSL 1.20 spec, page 23: 118501e04c3fSmrg * "Function calls to user-defined functions (non-built-in functions) 118601e04c3fSmrg * cannot be used to form constant expressions." 118701e04c3fSmrg */ 118801e04c3fSmrg if (!this->is_builtin()) 118901e04c3fSmrg return NULL; 119001e04c3fSmrg 119101e04c3fSmrg /* 119201e04c3fSmrg * Of the builtin functions, only the texture lookups and the noise 11937ec681f3Smrg * ones must not be used in constant expressions. Texture instructions 11947ec681f3Smrg * include special ir_texture opcodes which can't be constant-folded (see 11957ec681f3Smrg * ir_texture::constant_expression_value). Noise functions, however, we 11967ec681f3Smrg * have to special case here. 119701e04c3fSmrg */ 11987ec681f3Smrg if (strcmp(this->function_name(), "noise1") == 0 || 11997ec681f3Smrg strcmp(this->function_name(), "noise2") == 0 || 12007ec681f3Smrg strcmp(this->function_name(), "noise3") == 0 || 12017ec681f3Smrg strcmp(this->function_name(), "noise4") == 0) 12027ec681f3Smrg return NULL; 120301e04c3fSmrg 120401e04c3fSmrg /* Initialize the table of dereferencable names with the function 120501e04c3fSmrg * parameters. Verify their const-ness on the way. 120601e04c3fSmrg * 120701e04c3fSmrg * We expect the correctness of the number of parameters to have 120801e04c3fSmrg * been checked earlier. 120901e04c3fSmrg */ 12107e102996Smaya hash_table *deref_hash = _mesa_pointer_hash_table_create(NULL); 121101e04c3fSmrg 121201e04c3fSmrg /* If "origin" is non-NULL, then the function body is there. So we 121301e04c3fSmrg * have to use the variable objects from the object with the body, 121401e04c3fSmrg * but the parameter instanciation on the current object. 121501e04c3fSmrg */ 121601e04c3fSmrg const exec_node *parameter_info = origin ? origin->parameters.get_head_raw() : parameters.get_head_raw(); 121701e04c3fSmrg 121801e04c3fSmrg foreach_in_list(ir_rvalue, n, actual_parameters) { 121901e04c3fSmrg ir_constant *constant = 122001e04c3fSmrg n->constant_expression_value(mem_ctx, variable_context); 122101e04c3fSmrg if (constant == NULL) { 122201e04c3fSmrg _mesa_hash_table_destroy(deref_hash, NULL); 122301e04c3fSmrg return NULL; 122401e04c3fSmrg } 122501e04c3fSmrg 122601e04c3fSmrg 122701e04c3fSmrg ir_variable *var = (ir_variable *)parameter_info; 122801e04c3fSmrg _mesa_hash_table_insert(deref_hash, var, constant); 122901e04c3fSmrg 123001e04c3fSmrg parameter_info = parameter_info->next; 123101e04c3fSmrg } 123201e04c3fSmrg 123301e04c3fSmrg ir_constant *result = NULL; 123401e04c3fSmrg 123501e04c3fSmrg /* Now run the builtin function until something non-constant 123601e04c3fSmrg * happens or we get the result. 123701e04c3fSmrg */ 123801e04c3fSmrg if (constant_expression_evaluate_expression_list(mem_ctx, origin ? origin->body : body, deref_hash, &result) && 123901e04c3fSmrg result) 124001e04c3fSmrg result = result->clone(mem_ctx, NULL); 124101e04c3fSmrg 124201e04c3fSmrg _mesa_hash_table_destroy(deref_hash, NULL); 124301e04c3fSmrg 124401e04c3fSmrg return result; 124501e04c3fSmrg} 1246