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