Bug 74026

Summary: Compiler rejects chained assignments involving array dereferences
Product: Mesa Reporter: Ian Romanick <idr>
Component: glsl-compilerAssignee: Kenneth Graunke <kenneth>
Status: RESOLVED FIXED QA Contact: Intel 3D Bugs Mailing List <intel-3d-bugs>
Severity: normal    
Priority: medium    
Version: git   
Hardware: Other   
OS: All   
URL: http://lists.freedesktop.org/archives/piglit/2014-January/009223.html
Whiteboard:
i915 platform: i915 features:

Description Ian Romanick 2014-01-24 18:33:51 UTC
Shaders of the form:

void foo(inout vec4 a, float b)
{
	a[0] = a[1] = a[2] = b;
}

generate errors like:

0:5(12): error: value of type vec4 cannot be assigned to variable of type float
Comment 1 Kenneth Graunke 2014-01-24 19:08:14 UTC
Patch incoming momentarily, assuming it passes Piglit.
Comment 2 Kenneth Graunke 2014-01-25 18:37:32 UTC
commit 44a86e2b4fca7c7cab243dfa62dc17f4379fc8e3
Author: Kenneth Graunke <kenneth@whitecape.org>
Date:   Fri Jan 24 10:47:49 2014 -0800

    glsl: Fix chained assignments of vector channels.
    
    Simple shaders such as:
    
        void splat(vec2 v, float f) {
            v[0] = v[1] = f;
        }
    
    failed to compile with the following error:
    error: value of type vec2 cannot be assigned to variable of type float
    
    First, we would process v[1] = f, and transform:
    LHS: (expression float vector_extract (var_ref v) (constant int (1)))
    RHS: (var_ref f)
    into:
    LHS: (var_ref v)
    RHS: (expression vec2 vector_insert (var_ref v) (constant int (1))
                     (var_ref f))
    
    Note that the LHS type is now vec2, not a float.  This is surprising,
    but not the real problem.
    
    After emitting assignments, this ultimately becomes:
    (declare (temporary) vec2 assignment_tmp)
    (assign (xy)
      (var_ref assignment_tmp)
      (expression vec2 vector_insert (var_ref v) (constant int (1))
                  (var_ref f)))
      (assign (xy) (var_ref v) (var_ref assignment_tmp))
    
    We would then return (var_ref assignment_tmp) as the rvalue, which has
    the wrong type---it should be float, but is instead a vec2.
    
    To fix this, we simply return (vector_extract (var_ref assignment_temp)
    <the appropriate channel>) to pull out the desired float value.
    
    Fixes Piglit's chained-assignment-with-vector-constant-index.vert and
    chained-assignment-with-vector-dynamic-index.vert tests.
    
    Cc: mesa-stable@lists.freedesktop.org
    Bugzilla: https://bugs.freedesktop.org/show_bug.cgi?id=74026
    Reported-by: Dan Ginsburg <dang@valvesoftware.com>
    Reviewed-by: Ian Romanick <ian.d.romanick@intel.com>
    Reviewed-by: Matt Turner <mattst88@gmail.com>
    Signed-off-by: Kenneth Graunke <kenneth@whitecape.org>

Use of freedesktop.org services, including Bugzilla, is subject to our Code of Conduct. How we collect and use information is described in our Privacy Policy.