<?xml version="1.0" encoding="UTF-8" standalone="yes" ?>
<!DOCTYPE bugzilla SYSTEM "https://bugs.webkit.org/page.cgi?id=bugzilla.dtd">

<bugzilla version="5.0.4.1"
          urlbase="https://bugs.webkit.org/"
          
          maintainer="admin@webkit.org"
>

    <bug>
          <bug_id>176967</bug_id>
          
          <creation_ts>2017-09-14 16:30:31 -0700</creation_ts>
          <short_desc>[WHLSL] Verify &quot;logical mode&quot; properties hold</short_desc>
          <delta_ts>2018-10-13 16:45:22 -0700</delta_ts>
          <reporter_accessible>1</reporter_accessible>
          <cclist_accessible>1</cclist_accessible>
          <classification_id>1</classification_id>
          <classification>Unclassified</classification>
          <product>WebKit</product>
          <component>WebGPU</component>
          <version>WebKit Nightly Build</version>
          <rep_platform>All</rep_platform>
          <op_sys>All</op_sys>
          <bug_status>RESOLVED</bug_status>
          <resolution>MOVED</resolution>
          
          <see_also>https://bugs.webkit.org/show_bug.cgi?id=176973</see_also>
    
    <see_also>https://bugs.webkit.org/show_bug.cgi?id=178986</see_also>
          <bug_file_loc></bug_file_loc>
          <status_whiteboard></status_whiteboard>
          <keywords></keywords>
          <priority>P2</priority>
          <bug_severity>Normal</bug_severity>
          <target_milestone>---</target_milestone>
          <dependson>177303</dependson>
          <blocked>176199</blocked>
    
    <blocked>189202</blocked>
          <everconfirmed>1</everconfirmed>
          <reporter name="Filip Pizlo">fpizlo</reporter>
          <assigned_to name="Myles C. Maxfield">mmaxfield</assigned_to>
          <cc>mmaxfield</cc>
          

      

      

      

          <comment_sort_order>oldest_to_newest</comment_sort_order>  
          <long_desc isprivate="0" >
    <commentid>1349078</commentid>
    <comment_count>0</comment_count>
    <who name="Filip Pizlo">fpizlo</who>
    <bug_when>2017-09-14 16:30:31 -0700</bug_when>
    <thetext>In this mode:

- thread references (thread T^ and thread T[]) no longer get exempted from the isPrimitive check.  Currently it&apos;s OK to have a pointer to a pointer, if it&apos;s a thread pointer.  So, thread T^^ is OK but device T^^ is not OK. But, neither of these things are OK in logical, since storing to a pointer to a pointer would break the no-Phi rule of the underlying pointer. It would be like an assignment.

- bunch of control flow constraints on how pointers flow through the program.</thetext>
  </long_desc><long_desc isprivate="0" >
    <commentid>1349090</commentid>
    <comment_count>1</comment_count>
    <who name="Filip Pizlo">fpizlo</who>
    <bug_when>2017-09-14 16:46:31 -0700</bug_when>
    <thetext>I think that to lower to something like GLSL, we need to inline everything and then give each value node in the AST its own variable.

Then you can do pointer erasure. Every time you see a use of a pointer, figure out where it points, and then you will emit code that directly talks to that variable.</thetext>
  </long_desc><long_desc isprivate="0" >
    <commentid>1349096</commentid>
    <comment_count>2</comment_count>
    <who name="Filip Pizlo">fpizlo</who>
    <bug_when>2017-09-14 16:57:45 -0700</bug_when>
    <thetext>(In reply to Filip Pizlo from comment #1)
&gt; I think that to lower to something like GLSL, we need to inline everything
&gt; and then give each value node in the AST its own variable.

Actually, I think that the interpreter needs to do this as well - but only when the language is *not* in logical mode.

I&apos;m about to make the storage locations of temporary expressions slightly observable.

Consider this:

    thread T^ operator&amp;[]&lt;T&gt;(thread T[], uint);

Obviously, we&apos;d want this to work in this case:

    int[42] foo() { ... }
    
    void bar()
    {
        int x = foo()[5];
        ...
    }

I think that the easiest way to get there is to say that every temporary storage location gets its own predetermined EBuffer, as opposed to allocating EBuffers dynamically during execution.  This ensures that if you do this:

    thread Foo^ g_ptr;

    thread Foo^ operator&amp;[](thread Foo[] array, uint index)
    {
        return g_ptr = &amp;array[index];
    }

    void fuzz()
    {
        ^g_ptr = Foo(...);
    }
    
    Foo buzz()
    {
        return ^g_ptr;
    }

and then this:

    Foo[42] foo;
    return foo[5]; // This will cause g_ptr to point to &amp;foo[5]

or even this:

    Foo[10] makeFoos() { .. }
    
    Foo foo = makeFoos()[5]; // This will cause g_ptr to point to a temporary location associated with the call expression &quot;makeFoos()&quot;.

then at least you will get very well defined behavior:

- the language defines exactly where g_ptr points.
- operator&amp;[] is always called immediately before a load, store, or address-of operation in the source.

I think that the places where storage locations are created are exactly those places where the interpreter currently calls snapshot().</thetext>
  </long_desc><long_desc isprivate="0" >
    <commentid>1349159</commentid>
    <comment_count>3</comment_count>
    <who name="Filip Pizlo">fpizlo</who>
    <bug_when>2017-09-14 19:08:59 -0700</bug_when>
    <thetext>(In reply to Filip Pizlo from comment #2)
&gt; (In reply to Filip Pizlo from comment #1)
&gt; &gt; I think that to lower to something like GLSL, we need to inline everything
&gt; &gt; and then give each value node in the AST its own variable.
&gt; 
&gt; Actually, I think that the interpreter needs to do this as well - but only
&gt; when the language is *not* in logical mode.
&gt; 
&gt; I&apos;m about to make the storage locations of temporary expressions slightly
&gt; observable.
&gt; 
&gt; Consider this:
&gt; 
&gt;     thread T^ operator&amp;[]&lt;T&gt;(thread T[], uint);
&gt; 
&gt; Obviously, we&apos;d want this to work in this case:
&gt; 
&gt;     int[42] foo() { ... }
&gt;     
&gt;     void bar()
&gt;     {
&gt;         int x = foo()[5];
&gt;         ...
&gt;     }
&gt; 
&gt; I think that the easiest way to get there is to say that every temporary
&gt; storage location gets its own predetermined EBuffer, as opposed to
&gt; allocating EBuffers dynamically during execution.  This ensures that if you
&gt; do this:
&gt; 
&gt;     thread Foo^ g_ptr;
&gt; 
&gt;     thread Foo^ operator&amp;[](thread Foo[] array, uint index)
&gt;     {
&gt;         return g_ptr = &amp;array[index];
&gt;     }
&gt; 
&gt;     void fuzz()
&gt;     {
&gt;         ^g_ptr = Foo(...);
&gt;     }
&gt;     
&gt;     Foo buzz()
&gt;     {
&gt;         return ^g_ptr;
&gt;     }
&gt; 
&gt; and then this:
&gt; 
&gt;     Foo[42] foo;
&gt;     return foo[5]; // This will cause g_ptr to point to &amp;foo[5]
&gt; 
&gt; or even this:
&gt; 
&gt;     Foo[10] makeFoos() { .. }
&gt;     
&gt;     Foo foo = makeFoos()[5]; // This will cause g_ptr to point to a
&gt; temporary location associated with the call expression &quot;makeFoos()&quot;.
&gt; 
&gt; then at least you will get very well defined behavior:
&gt; 
&gt; - the language defines exactly where g_ptr points.
&gt; - operator&amp;[] is always called immediately before a load, store, or
&gt; address-of operation in the source.
&gt; 
&gt; I think that the places where storage locations are created are exactly
&gt; those places where the interpreter currently calls snapshot().

Filed: https://bugs.webkit.org/show_bug.cgi?id=176973</thetext>
  </long_desc><long_desc isprivate="0" >
    <commentid>1365595</commentid>
    <comment_count>4</comment_count>
    <who name="Myles C. Maxfield">mmaxfield</who>
    <bug_when>2017-10-27 17:23:42 -0700</bug_when>
    <thetext>I think the current design of anders are incompatible with logical addressing mode. One of the tenants of logical addressing mode is that each function which returns a pointer only has a single return statement. However, vec2&apos;s ander looks like this:

thread T* operator&amp;[]&lt;T&gt;(thread vec2&lt;T&gt;* foo, uint index)
{
    if (index == 0)
        return &amp;foo-&gt;x;
    if (index == 1)
        return &amp;foo-&gt;y;
    trap;
}</thetext>
  </long_desc><long_desc isprivate="0" >
    <commentid>1365598</commentid>
    <comment_count>5</comment_count>
    <who name="Filip Pizlo">fpizlo</who>
    <bug_when>2017-10-27 17:37:22 -0700</bug_when>
    <thetext>(In reply to Myles C. Maxfield from comment #4)
&gt; I think the current design of anders are incompatible with logical
&gt; addressing mode. One of the tenants of logical addressing mode is that each
&gt; function which returns a pointer only has a single return statement.
&gt; However, vec2&apos;s ander looks like this:
&gt; 
&gt; thread T* operator&amp;[]&lt;T&gt;(thread vec2&lt;T&gt;* foo, uint index)
&gt; {
&gt;     if (index == 0)
&gt;         return &amp;foo-&gt;x;
&gt;     if (index == 1)
&gt;         return &amp;foo-&gt;y;
&gt;     trap;
&gt; }

vec2’s ander will be compiled as an intrinsic anyway. 

Therefore, I recommend just turning off logical validation in the stdlib.</thetext>
  </long_desc><long_desc isprivate="0" >
    <commentid>1365599</commentid>
    <comment_count>6</comment_count>
    <who name="Myles C. Maxfield">mmaxfield</who>
    <bug_when>2017-10-27 17:46:45 -0700</bug_when>
    <thetext>(In reply to Myles C. Maxfield from comment #4)
&gt; I think the current design of anders are incompatible with logical
&gt; addressing mode. One of the tenants of logical addressing mode is that each
&gt; function which returns a pointer only has a single return statement.
&gt; However, vec2&apos;s ander looks like this:
&gt; 
&gt; thread T* operator&amp;[]&lt;T&gt;(thread vec2&lt;T&gt;* foo, uint index)
&gt; {
&gt;     if (index == 0)
&gt;         return &amp;foo-&gt;x;
&gt;     if (index == 1)
&gt;         return &amp;foo-&gt;y;
&gt;     trap;
&gt; }

I guess we could fix this by:
1) Enforcing that anders only get called by IndexExpressions. We wouldn&apos;t let the programmer just call an ander directly. This means that every call to an ander will be wrapped by a DereferenceExpression
2) Enforcing that every return site in an ander is of the form &quot;return &amp;thing;&quot;

If we enforce these two rules, we can, in the compiler, special-case these resultant patterns, and make the DereferenceExpressions and the MakePtrExpressions cancel out.

Or, maybe since we inline everything anyway, we could just punch through any FunctionLikeBlocks and cancel out any pairs of DereferenceExpressions and the MakePtrExpressions we find.</thetext>
  </long_desc><long_desc isprivate="0" >
    <commentid>1365600</commentid>
    <comment_count>7</comment_count>
    <who name="Myles C. Maxfield">mmaxfield</who>
    <bug_when>2017-10-27 17:47:01 -0700</bug_when>
    <thetext>(In reply to Filip Pizlo from comment #5)
&gt; (In reply to Myles C. Maxfield from comment #4)
&gt; &gt; I think the current design of anders are incompatible with logical
&gt; &gt; addressing mode. One of the tenants of logical addressing mode is that each
&gt; &gt; function which returns a pointer only has a single return statement.
&gt; &gt; However, vec2&apos;s ander looks like this:
&gt; &gt; 
&gt; &gt; thread T* operator&amp;[]&lt;T&gt;(thread vec2&lt;T&gt;* foo, uint index)
&gt; &gt; {
&gt; &gt;     if (index == 0)
&gt; &gt;         return &amp;foo-&gt;x;
&gt; &gt;     if (index == 1)
&gt; &gt;         return &amp;foo-&gt;y;
&gt; &gt;     trap;
&gt; &gt; }
&gt; 
&gt; vec2’s ander will be compiled as an intrinsic anyway. 
&gt; 
&gt; Therefore, I recommend just turning off logical validation in the stdlib.

I think we&apos;re supporting anders for arbitrary user-defined structs, right?</thetext>
  </long_desc><long_desc isprivate="0" >
    <commentid>1365614</commentid>
    <comment_count>8</comment_count>
      <attachid>325228</attachid>
    <who name="Myles C. Maxfield">mmaxfield</who>
    <bug_when>2017-10-27 18:37:47 -0700</bug_when>
    <thetext>Created attachment 325228
Start</thetext>
  </long_desc><long_desc isprivate="0" >
    <commentid>1365628</commentid>
    <comment_count>9</comment_count>
    <who name="Myles C. Maxfield">mmaxfield</who>
    <bug_when>2017-10-27 19:37:35 -0700</bug_when>
    <thetext>If we do go the route of simply removing pairs of DereferenceExpressions MakePtrExpressions throughout the entire program (and punching through function calls to do it), there are a few interesting cases to test:

1) *&amp;foo = 3
2) foo = *&amp;bar
3) foo = *&amp;bar = 3
4) **&amp;&amp;foo = 3
5) int* foo() {} ... *foo() = bar()
6) int[10]* foo() {} ... (*foo())[3] = 4

We&apos;d need to be able punch through:
1) function calls
2) IdentityExpressions
3) nothing (when the MakePtrExpression is a direct child of the DereferenceExpression)</thetext>
  </long_desc><long_desc isprivate="0" >
    <commentid>1365629</commentid>
    <comment_count>10</comment_count>
    <who name="Myles C. Maxfield">mmaxfield</who>
    <bug_when>2017-10-27 19:49:40 -0700</bug_when>
    <thetext>(In reply to Myles C. Maxfield from comment #9)
&gt; If we do go the route of simply removing pairs of DereferenceExpressions
&gt; MakePtrExpressions throughout the entire program (and punching through
&gt; function calls to do it), there are a few interesting cases to test:
&gt; 
&gt; 1) *&amp;foo = 3
&gt; 2) foo = *&amp;bar
&gt; 3) foo = *&amp;bar = 3
&gt; 4) **&amp;&amp;foo = 3
&gt; 5) int* foo() {} ... *foo() = bar()
&gt; 6) int[10]* foo() {} ... (*foo())[3] = 4
&gt; 
&gt; We&apos;d need to be able punch through:
&gt; 1) function calls
&gt; 2) IdentityExpressions
&gt; 3) nothing (when the MakePtrExpression is a direct child of the
&gt; DereferenceExpression)

Presumably we&apos;d also want to punch through nested function calls</thetext>
  </long_desc><long_desc isprivate="0" >
    <commentid>1365630</commentid>
    <comment_count>11</comment_count>
    <who name="Myles C. Maxfield">mmaxfield</who>
    <bug_when>2017-10-27 19:57:29 -0700</bug_when>
    <thetext>(In reply to Myles C. Maxfield from comment #10)
&gt; (In reply to Myles C. Maxfield from comment #9)
&gt; &gt; If we do go the route of simply removing pairs of DereferenceExpressions
&gt; &gt; MakePtrExpressions throughout the entire program (and punching through
&gt; &gt; function calls to do it), there are a few interesting cases to test:
&gt; &gt; 
&gt; &gt; 1) *&amp;foo = 3
&gt; &gt; 2) foo = *&amp;bar
&gt; &gt; 3) foo = *&amp;bar = 3
&gt; &gt; 4) **&amp;&amp;foo = 3
&gt; &gt; 5) int* foo() {} ... *foo() = bar()
&gt; &gt; 6) int[10]* foo() {} ... (*foo())[3] = 4
&gt; &gt; 
&gt; &gt; We&apos;d need to be able punch through:
&gt; &gt; 1) function calls
&gt; &gt; 2) IdentityExpressions
&gt; &gt; 3) nothing (when the MakePtrExpression is a direct child of the
&gt; &gt; DereferenceExpression)
&gt; 
&gt; Presumably we&apos;d also want to punch through nested function calls

Also things like *foo() = *bar()</thetext>
  </long_desc><long_desc isprivate="0" >
    <commentid>1365651</commentid>
    <comment_count>12</comment_count>
    <who name="Myles C. Maxfield">mmaxfield</who>
    <bug_when>2017-10-27 21:09:15 -0700</bug_when>
    <thetext>It would also probably also have to handle the case of something like this:

thread int** foo(thread int** x, thread int** y, ...) {
    bool b = /* some computation that the compiler can&apos;t reduce */
    return b ? x : y;
}

thread int* bar(thread int* x, thread int* y, ...) {
    return *foo(&amp;x, &amp;y, ...);
}

...

int x;
int y;
*bar(&amp;x, &amp;y, ...) = 5;</thetext>
  </long_desc><long_desc isprivate="0" >
    <commentid>1365656</commentid>
    <comment_count>13</comment_count>
    <who name="Myles C. Maxfield">mmaxfield</who>
    <bug_when>2017-10-27 21:27:34 -0700</bug_when>
    <thetext>(In reply to Myles C. Maxfield from comment #12)
&gt; It would also probably also have to handle the case of something like this:
&gt; 
&gt; thread int** foo(thread int** x, thread int** y, ...) {
&gt;     bool b = /* some computation that the compiler can&apos;t reduce */
&gt;     return b ? x : y;
&gt; }
&gt; 
&gt; thread int* bar(thread int* x, thread int* y, ...) {
&gt;     return *foo(&amp;x, &amp;y, ...);
&gt; }
&gt; 
&gt; ...
&gt; 
&gt; int x;
&gt; int y;
&gt; *bar(&amp;x, &amp;y, ...) = 5;

If you&apos;re allowed to put pointers inside structs, this would be something like

StructA foo(StructB x, ...) {
    bool b = /* some computation that the compiler can&apos;t reduce */
    return b ? x.a : x.b;
}

StructC bar(StructD y, ...) {
    return foo(y.c, ...).d;
}

...

bar(instanceOfStructD, ...).e = 5;</thetext>
  </long_desc><long_desc isprivate="0" >
    <commentid>1365657</commentid>
    <comment_count>14</comment_count>
    <who name="Myles C. Maxfield">mmaxfield</who>
    <bug_when>2017-10-27 21:30:22 -0700</bug_when>
    <thetext>(In reply to Myles C. Maxfield from comment #13)
&gt; (In reply to Myles C. Maxfield from comment #12)
&gt; &gt; It would also probably also have to handle the case of something like this:
&gt; &gt; 
&gt; &gt; thread int** foo(thread int** x, thread int** y, ...) {
&gt; &gt;     bool b = /* some computation that the compiler can&apos;t reduce */
&gt; &gt;     return b ? x : y;
&gt; &gt; }
&gt; &gt; 
&gt; &gt; thread int* bar(thread int* x, thread int* y, ...) {
&gt; &gt;     return *foo(&amp;x, &amp;y, ...);
&gt; &gt; }
&gt; &gt; 
&gt; &gt; ...
&gt; &gt; 
&gt; &gt; int x;
&gt; &gt; int y;
&gt; &gt; *bar(&amp;x, &amp;y, ...) = 5;
&gt; 
&gt; If you&apos;re allowed to put pointers inside structs, this would be something
&gt; like
&gt; 
&gt; StructA foo(StructB x, ...) {
&gt;     bool b = /* some computation that the compiler can&apos;t reduce */
&gt;     return b ? x.a : x.b;
&gt; }
&gt; 
&gt; StructC bar(StructD y, ...) {
&gt;     return foo(y.c, ...).d;
&gt; }
&gt; 
&gt; ...
&gt; 
&gt; bar(instanceOfStructD, ...).e = 5;

whoops, I meant

*bar(instanceOfStructD, ...).e = 5;</thetext>
  </long_desc><long_desc isprivate="0" >
    <commentid>1365660</commentid>
    <comment_count>15</comment_count>
    <who name="Myles C. Maxfield">mmaxfield</who>
    <bug_when>2017-10-27 21:36:17 -0700</bug_when>
    <thetext>(In reply to Myles C. Maxfield from comment #14)
&gt; (In reply to Myles C. Maxfield from comment #13)
&gt; &gt; (In reply to Myles C. Maxfield from comment #12)
&gt; &gt; &gt; It would also probably also have to handle the case of something like this:
&gt; &gt; &gt; 
&gt; &gt; &gt; thread int** foo(thread int** x, thread int** y, ...) {
&gt; &gt; &gt;     bool b = /* some computation that the compiler can&apos;t reduce */
&gt; &gt; &gt;     return b ? x : y;
&gt; &gt; &gt; }
&gt; &gt; &gt; 
&gt; &gt; &gt; thread int* bar(thread int* x, thread int* y, ...) {
&gt; &gt; &gt;     return *foo(&amp;x, &amp;y, ...);
&gt; &gt; &gt; }
&gt; &gt; &gt; 
&gt; &gt; &gt; ...
&gt; &gt; &gt; 
&gt; &gt; &gt; int x;
&gt; &gt; &gt; int y;
&gt; &gt; &gt; *bar(&amp;x, &amp;y, ...) = 5;
&gt; &gt; 
&gt; &gt; If you&apos;re allowed to put pointers inside structs, this would be something
&gt; &gt; like
&gt; &gt; 
&gt; &gt; StructA foo(StructB x, ...) {
&gt; &gt;     bool b = /* some computation that the compiler can&apos;t reduce */
&gt; &gt;     return b ? x.a : x.b;
&gt; &gt; }
&gt; &gt; 
&gt; &gt; StructC bar(StructD y, ...) {
&gt; &gt;     return foo(y.c, ...).d;
&gt; &gt; }
&gt; &gt; 
&gt; &gt; ...
&gt; &gt; 
&gt; &gt; bar(instanceOfStructD, ...).e = 5;
&gt; 
&gt; whoops, I meant
&gt; 
&gt; *bar(instanceOfStructD, ...).e = 5;

I guess it could be

(*(bar(instanceOfStructD, ...).e)).f = 5;</thetext>
  </long_desc><long_desc isprivate="0" >
    <commentid>1365663</commentid>
    <comment_count>16</comment_count>
    <who name="Myles C. Maxfield">mmaxfield</who>
    <bug_when>2017-10-27 21:52:07 -0700</bug_when>
    <thetext>So it seems like, if you move the Assignment all the way to the innermost return statements, you can have functions which return pointers and which have multiple return statements.

The requirement of not being able to assign to a pointer, however, still stands.</thetext>
  </long_desc><long_desc isprivate="0" >
    <commentid>1365666</commentid>
    <comment_count>17</comment_count>
    <who name="Myles C. Maxfield">mmaxfield</who>
    <bug_when>2017-10-27 22:10:19 -0700</bug_when>
    <thetext>(In reply to Myles C. Maxfield from comment #16)
&gt; So it seems like, if you move the Assignment all the way to the innermost
&gt; return statements, you can have functions which return pointers and which
&gt; have multiple return statements.
&gt; 
&gt; The requirement of not being able to assign to a pointer, however, still
&gt; stands.

I guess this is a little bit moot because right now we don&apos;t have object literals, so a pointer inside an object will always be null. However, we want to add object literals. https://bugs.webkit.org/show_bug.cgi?id=178978

This will be pretty powerful. For example, you can have a struct with a pointer inside it, pass that by reference to a function (by taking a pointer to it), then that function can return a pointer to a field inside the struct, and the caller can then assign to that field (as long as the field doesn&apos;t itself contain a pointer).</thetext>
  </long_desc><long_desc isprivate="0" >
    <commentid>1365936</commentid>
    <comment_count>18</comment_count>
    <who name="Myles C. Maxfield">mmaxfield</who>
    <bug_when>2017-10-30 00:20:48 -0700</bug_when>
    <thetext>I think I&apos;ve almost finished this at https://bugs.webkit.org/show_bug.cgi?id=178986</thetext>
  </long_desc><long_desc isprivate="0" >
    <commentid>1455031</commentid>
    <comment_count>19</comment_count>
    <who name="Myles C. Maxfield">mmaxfield</who>
    <bug_when>2018-08-29 17:06:06 -0700</bug_when>
    <thetext>*** Bug 189064 has been marked as a duplicate of this bug. ***</thetext>
  </long_desc><long_desc isprivate="0" >
    <commentid>1455033</commentid>
    <comment_count>20</comment_count>
    <who name="Myles C. Maxfield">mmaxfield</who>
    <bug_when>2018-08-29 17:06:09 -0700</bug_when>
    <thetext>*** Bug 179036 has been marked as a duplicate of this bug. ***</thetext>
  </long_desc><long_desc isprivate="0" >
    <commentid>1462759</commentid>
    <comment_count>21</comment_count>
    <who name="Myles C. Maxfield">mmaxfield</who>
    <bug_when>2018-09-24 10:41:49 -0700</bug_when>
    <thetext>We need to determine what the restrictions are on textures. Should they have the same restrictions as pointers? Maybe not, because arrays of textures are useful. Perhaps arrays of textures must only be passed in via the API, and cannot be built in the shader (like samplers)?</thetext>
  </long_desc><long_desc isprivate="0" >
    <commentid>1468937</commentid>
    <comment_count>22</comment_count>
    <who name="Myles C. Maxfield">mmaxfield</who>
    <bug_when>2018-10-13 16:45:22 -0700</bug_when>
    <thetext>Migrated to https://github.com/gpuweb/WHLSL/issues/138</thetext>
  </long_desc>
      
          <attachment
              isobsolete="0"
              ispatch="1"
              isprivate="0"
          >
            <attachid>325228</attachid>
            <date>2017-10-27 18:37:47 -0700</date>
            <delta_ts>2017-10-27 18:37:47 -0700</delta_ts>
            <desc>Start</desc>
            <filename>bug-176967-20171027183747.patch</filename>
            <type>text/plain</type>
            <size>8324</size>
            <attacher name="Myles C. Maxfield">mmaxfield</attacher>
            
              <data encoding="base64">U3VidmVyc2lvbiBSZXZpc2lvbjogMjI0MTI5CmRpZmYgLS1naXQgYS9Ub29scy9XZWJHUFVTaGFk
aW5nTGFuZ3VhZ2VSSS9BbGwuanMgYi9Ub29scy9XZWJHUFVTaGFkaW5nTGFuZ3VhZ2VSSS9BbGwu
anMKaW5kZXggMzBhMGIwOTk2NTVjYjUwYjkyYWNkMTZkYjc0NTFlNWIzOTdiZTMzMi4uZDFkZWIw
OWE2ODNhNzc0NWQxYjAwZTVlZTI1ZGJiZjllMzYzMTFlZiAxMDA2NDQKLS0tIGEvVG9vbHMvV2Vi
R1BVU2hhZGluZ0xhbmd1YWdlUkkvQWxsLmpzCisrKyBiL1Rvb2xzL1dlYkdQVVNoYWRpbmdMYW5n
dWFnZVJJL0FsbC5qcwpAQCAtMTIzLDYgKzEyMyw3IEBAIGxvYWQoIk51bGxUeXBlLmpzIik7CiBs
b2FkKCJPcmlnaW5LaW5kLmpzIik7CiBsb2FkKCJPdmVybG9hZFJlc29sdXRpb25GYWlsdXJlLmpz
Iik7CiBsb2FkKCJQYXJzZS5qcyIpOworbG9hZCgiUG9pbnRlclJlc29sdmVyLmpzIik7CiBsb2Fk
KCJQcmVwYXJlLmpzIik7CiBsb2FkKCJQcm9ncmFtLmpzIik7CiBsb2FkKCJQcm9ncmFtV2l0aFVu
bmVjZXNzYXJ5VGhpbmdzUmVtb3ZlZC5qcyIpOwpAQCAtMTM3LDYgKzEzOCw3IEBAIGxvYWQoIlJl
Y3Vyc2lvbkNoZWNrZXIuanMiKTsKIGxvYWQoIlJlY3Vyc2l2ZVR5cGVDaGVja2VyLmpzIik7CiBs
b2FkKCJSZXNvbHZlTmFtZXMuanMiKTsKIGxvYWQoIlJlc29sdmVPdmVybG9hZEltcGwuanMiKTsK
K2xvYWQoIlJlc29sdmVQb2ludGVycy5qcyIpOwogbG9hZCgiUmVzb2x2ZVByb3BlcnRpZXMuanMi
KTsKIGxvYWQoIlJlc29sdmVUeXBlRGVmcy5qcyIpOwogbG9hZCgiUmV0dXJuLmpzIik7CmRpZmYg
LS1naXQgYS9Ub29scy9XZWJHUFVTaGFkaW5nTGFuZ3VhZ2VSSS9Qb2ludGVyUmVzb2x2ZXIuanMg
Yi9Ub29scy9XZWJHUFVTaGFkaW5nTGFuZ3VhZ2VSSS9Qb2ludGVyUmVzb2x2ZXIuanMKbmV3IGZp
bGUgbW9kZSAxMDA2NDQKaW5kZXggMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAw
MDAwMC4uZGIwMGMxYjgxMTlkMjJhMmRjNzY5M2ZlODRiYjRkODllOTQ1MGM5NQotLS0gL2Rldi9u
dWxsCisrKyBiL1Rvb2xzL1dlYkdQVVNoYWRpbmdMYW5ndWFnZVJJL1BvaW50ZXJSZXNvbHZlci5q
cwpAQCAtMCwwICsxLDI5IEBACisvKgorICogQ29weXJpZ2h0IChDKSAyMDE3IEFwcGxlIEluYy4g
QWxsIHJpZ2h0cyByZXNlcnZlZC4KKyAqCisgKiBSZWRpc3RyaWJ1dGlvbiBhbmQgdXNlIGluIHNv
dXJjZSBhbmQgYmluYXJ5IGZvcm1zLCB3aXRoIG9yIHdpdGhvdXQKKyAqIG1vZGlmaWNhdGlvbiwg
YXJlIHBlcm1pdHRlZCBwcm92aWRlZCB0aGF0IHRoZSBmb2xsb3dpbmcgY29uZGl0aW9ucworICog
YXJlIG1ldDoKKyAqIDEuIFJlZGlzdHJpYnV0aW9ucyBvZiBzb3VyY2UgY29kZSBtdXN0IHJldGFp
biB0aGUgYWJvdmUgY29weXJpZ2h0CisgKiAgICBub3RpY2UsIHRoaXMgbGlzdCBvZiBjb25kaXRp
b25zIGFuZCB0aGUgZm9sbG93aW5nIGRpc2NsYWltZXIuCisgKiAyLiBSZWRpc3RyaWJ1dGlvbnMg
aW4gYmluYXJ5IGZvcm0gbXVzdCByZXByb2R1Y2UgdGhlIGFib3ZlIGNvcHlyaWdodAorICogICAg
bm90aWNlLCB0aGlzIGxpc3Qgb2YgY29uZGl0aW9ucyBhbmQgdGhlIGZvbGxvd2luZyBkaXNjbGFp
bWVyIGluIHRoZQorICogICAgZG9jdW1lbnRhdGlvbiBhbmQvb3Igb3RoZXIgbWF0ZXJpYWxzIHBy
b3ZpZGVkIHdpdGggdGhlIGRpc3RyaWJ1dGlvbi4KKyAqCisgKiBUSElTIFNPRlRXQVJFIElTIFBS
T1ZJREVEIEJZIEFQUExFIElOQy4gYGBBUyBJUycnIEFORCBBTlkKKyAqIEVYUFJFU1MgT1IgSU1Q
TElFRCBXQVJSQU5USUVTLCBJTkNMVURJTkcsIEJVVCBOT1QgTElNSVRFRCBUTywgVEhFCisgKiBJ
TVBMSUVEIFdBUlJBTlRJRVMgT0YgTUVSQ0hBTlRBQklMSVRZIEFORCBGSVRORVNTIEZPUiBBIFBB
UlRJQ1VMQVIKKyAqIFBVUlBPU0UgQVJFIERJU0NMQUlNRUQuICBJTiBOTyBFVkVOVCBTSEFMTCBB
UFBMRSBJTkMuIE9SCisgKiBDT05UUklCVVRPUlMgQkUgTElBQkxFIEZPUiBBTlkgRElSRUNULCBJ
TkRJUkVDVCwgSU5DSURFTlRBTCwgU1BFQ0lBTCwKKyAqIEVYRU1QTEFSWSwgT1IgQ09OU0VRVUVO
VElBTCBEQU1BR0VTIChJTkNMVURJTkcsIEJVVCBOT1QgTElNSVRFRCBUTywKKyAqIFBST0NVUkVN
RU5UIE9GIFNVQlNUSVRVVEUgR09PRFMgT1IgU0VSVklDRVM7IExPU1MgT0YgVVNFLCBEQVRBLCBP
UgorICogUFJPRklUUzsgT1IgQlVTSU5FU1MgSU5URVJSVVBUSU9OKSBIT1dFVkVSIENBVVNFRCBB
TkQgT04gQU5ZIFRIRU9SWQorICogT0YgTElBQklMSVRZLCBXSEVUSEVSIElOIENPTlRSQUNULCBT
VFJJQ1QgTElBQklMSVRZLCBPUiBUT1JUCisgKiAoSU5DTFVESU5HIE5FR0xJR0VOQ0UgT1IgT1RI
RVJXSVNFKSBBUklTSU5HIElOIEFOWSBXQVkgT1VUIE9GIFRIRSBVU0UKKyAqIE9GIFRISVMgU09G
VFdBUkUsIEVWRU4gSUYgQURWSVNFRCBPRiBUSEUgUE9TU0lCSUxJVFkgT0YgU1VDSCBEQU1BR0Uu
IAorICovCisidXNlIHN0cmljdCI7CisKK2NsYXNzIFBvaW50ZXJSZXNvbHZlciBleHRlbmRzIFZp
c2l0b3IgeworfQorCmRpZmYgLS1naXQgYS9Ub29scy9XZWJHUFVTaGFkaW5nTGFuZ3VhZ2VSSS9Q
cmVwYXJlLmpzIGIvVG9vbHMvV2ViR1BVU2hhZGluZ0xhbmd1YWdlUkkvUHJlcGFyZS5qcwppbmRl
eCBhMjA0OGE5YWQzZTgzYmQxOGI3NjQ0NGNhNTU0NmU0OGZlMDExOWEwLi44MWQ0YWQyYmI2NTI1
ZWYyY2UzOThjYjY4YmU1YWU5ZDNkMmMxNDk0IDEwMDY0NAotLS0gYS9Ub29scy9XZWJHUFVTaGFk
aW5nTGFuZ3VhZ2VSSS9QcmVwYXJlLmpzCisrKyBiL1Rvb2xzL1dlYkdQVVNoYWRpbmdMYW5ndWFn
ZVJJL1ByZXBhcmUuanMKQEAgLTY2LDYgKzY2LDggQEAgbGV0IHByZXBhcmUgPSAoKCkgPT4gewog
ICAgICAgICBmaW5kSGlnaFpvbWJpZXMocHJvZ3JhbSk7CiAgICAgICAgIGlubGluZShwcm9ncmFt
KTsKICAgICAgICAgCisgICAgICAgIHJlc29sdmVQb2ludGVycyhwcm9ncmFtKTsKKyAgICAgICAg
CiAgICAgICAgIHJldHVybiBwcm9ncmFtOwogICAgIH07CiB9KSgpOwpkaWZmIC0tZ2l0IGEvVG9v
bHMvV2ViR1BVU2hhZGluZ0xhbmd1YWdlUkkvUmVzb2x2ZVBvaW50ZXJzLmpzIGIvVG9vbHMvV2Vi
R1BVU2hhZGluZ0xhbmd1YWdlUkkvUmVzb2x2ZVBvaW50ZXJzLmpzCm5ldyBmaWxlIG1vZGUgMTAw
NjQ0CmluZGV4IDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAuLmE4ZTJm
Y2FiYTc2ZWZhNWNmOWQ0ZGQyZWJiZTRjMzI5YjZiZTk5YjkKLS0tIC9kZXYvbnVsbAorKysgYi9U
b29scy9XZWJHUFVTaGFkaW5nTGFuZ3VhZ2VSSS9SZXNvbHZlUG9pbnRlcnMuanMKQEAgLTAsMCAr
MSwzMCBAQAorLyoKKyAqIENvcHlyaWdodCAoQykgMjAxNyBBcHBsZSBJbmMuIEFsbCByaWdodHMg
cmVzZXJ2ZWQuCisgKgorICogUmVkaXN0cmlidXRpb24gYW5kIHVzZSBpbiBzb3VyY2UgYW5kIGJp
bmFyeSBmb3Jtcywgd2l0aCBvciB3aXRob3V0CisgKiBtb2RpZmljYXRpb24sIGFyZSBwZXJtaXR0
ZWQgcHJvdmlkZWQgdGhhdCB0aGUgZm9sbG93aW5nIGNvbmRpdGlvbnMKKyAqIGFyZSBtZXQ6Cisg
KiAxLiBSZWRpc3RyaWJ1dGlvbnMgb2Ygc291cmNlIGNvZGUgbXVzdCByZXRhaW4gdGhlIGFib3Zl
IGNvcHlyaWdodAorICogICAgbm90aWNlLCB0aGlzIGxpc3Qgb2YgY29uZGl0aW9ucyBhbmQgdGhl
IGZvbGxvd2luZyBkaXNjbGFpbWVyLgorICogMi4gUmVkaXN0cmlidXRpb25zIGluIGJpbmFyeSBm
b3JtIG11c3QgcmVwcm9kdWNlIHRoZSBhYm92ZSBjb3B5cmlnaHQKKyAqICAgIG5vdGljZSwgdGhp
cyBsaXN0IG9mIGNvbmRpdGlvbnMgYW5kIHRoZSBmb2xsb3dpbmcgZGlzY2xhaW1lciBpbiB0aGUK
KyAqICAgIGRvY3VtZW50YXRpb24gYW5kL29yIG90aGVyIG1hdGVyaWFscyBwcm92aWRlZCB3aXRo
IHRoZSBkaXN0cmlidXRpb24uCisgKgorICogVEhJUyBTT0ZUV0FSRSBJUyBQUk9WSURFRCBCWSBB
UFBMRSBJTkMuIGBgQVMgSVMnJyBBTkQgQU5ZCisgKiBFWFBSRVNTIE9SIElNUExJRUQgV0FSUkFO
VElFUywgSU5DTFVESU5HLCBCVVQgTk9UIExJTUlURUQgVE8sIFRIRQorICogSU1QTElFRCBXQVJS
QU5USUVTIE9GIE1FUkNIQU5UQUJJTElUWSBBTkQgRklUTkVTUyBGT1IgQSBQQVJUSUNVTEFSCisg
KiBQVVJQT1NFIEFSRSBESVNDTEFJTUVELiAgSU4gTk8gRVZFTlQgU0hBTEwgQVBQTEUgSU5DLiBP
UgorICogQ09OVFJJQlVUT1JTIEJFIExJQUJMRSBGT1IgQU5ZIERJUkVDVCwgSU5ESVJFQ1QsIElO
Q0lERU5UQUwsIFNQRUNJQUwsCisgKiBFWEVNUExBUlksIE9SIENPTlNFUVVFTlRJQUwgREFNQUdF
UyAoSU5DTFVESU5HLCBCVVQgTk9UIExJTUlURUQgVE8sCisgKiBQUk9DVVJFTUVOVCBPRiBTVUJT
VElUVVRFIEdPT0RTIE9SIFNFUlZJQ0VTOyBMT1NTIE9GIFVTRSwgREFUQSwgT1IKKyAqIFBST0ZJ
VFM7IE9SIEJVU0lORVNTIElOVEVSUlVQVElPTikgSE9XRVZFUiBDQVVTRUQgQU5EIE9OIEFOWSBU
SEVPUlkKKyAqIE9GIExJQUJJTElUWSwgV0hFVEhFUiBJTiBDT05UUkFDVCwgU1RSSUNUIExJQUJJ
TElUWSwgT1IgVE9SVAorICogKElOQ0xVRElORyBORUdMSUdFTkNFIE9SIE9USEVSV0lTRSkgQVJJ
U0lORyBJTiBBTlkgV0FZIE9VVCBPRiBUSEUgVVNFCisgKiBPRiBUSElTIFNPRlRXQVJFLCBFVkVO
IElGIEFEVklTRUQgT0YgVEhFIFBPU1NJQklMSVRZIE9GIFNVQ0ggREFNQUdFLiAKKyAqLworInVz
ZSBzdHJpY3QiOworCitmdW5jdGlvbiByZXNvbHZlUG9pbnRlcnMocHJvZ3JhbSkKK3sKKyAgICBw
cm9ncmFtLnZpc2l0KG5ldyBQb2ludGVyUmVzb2x2ZXIoKSk7Cit9CmRpZmYgLS1naXQgYS9Ub29s
cy9XZWJHUFVTaGFkaW5nTGFuZ3VhZ2VSSS9TUElSVi5odG1sIGIvVG9vbHMvV2ViR1BVU2hhZGlu
Z0xhbmd1YWdlUkkvU1BJUlYuaHRtbAppbmRleCBkMTczZjdlNzI1MWVhOTg1YTZmOWI1NjUzNGZk
YTQ1OGZkMjE2MGYxLi5hYjUxMDc3ZmYzODM1MWUyYjljY2EwOWUxZTI0OTJmYmIyNzYxYTQyIDEw
MDY0NAotLS0gYS9Ub29scy9XZWJHUFVTaGFkaW5nTGFuZ3VhZ2VSSS9TUElSVi5odG1sCisrKyBi
L1Rvb2xzL1dlYkdQVVNoYWRpbmdMYW5ndWFnZVJJL1NQSVJWLmh0bWwKQEAgLTEwNiw2ICsxMDYs
NyBAQCB0ZCB7CiAgICAgPHNjcmlwdCBzcmM9Ik9yaWdpbktpbmQuanMiPjwvc2NyaXB0PgogICAg
IDxzY3JpcHQgc3JjPSJPdmVybG9hZFJlc29sdXRpb25GYWlsdXJlLmpzIj48L3NjcmlwdD4KICAg
ICA8c2NyaXB0IHNyYz0iUGFyc2UuanMiPjwvc2NyaXB0PgorICAgIDxzY3JpcHQgc3JjPSJQb2lu
dGVyUmVzb2x2ZXIuanMiPjwvc2NyaXB0PgogICAgIDxzY3JpcHQgc3JjPSJQcmVwYXJlLmpzIj48
L3NjcmlwdD4KICAgICA8c2NyaXB0IHNyYz0iUHJvcGVydHlSZXNvbHZlci5qcyI+PC9zY3JpcHQ+
CiAgICAgPHNjcmlwdCBzcmM9IlByb2dyYW0uanMiPjwvc2NyaXB0PgpAQCAtMTIwLDYgKzEyMSw3
IEBAIHRkIHsKICAgICA8c2NyaXB0IHNyYz0iUmVjdXJzaXZlVHlwZUNoZWNrZXIuanMiPjwvc2Ny
aXB0PgogICAgIDxzY3JpcHQgc3JjPSJSZXNvbHZlTmFtZXMuanMiPjwvc2NyaXB0PgogICAgIDxz
Y3JpcHQgc3JjPSJSZXNvbHZlT3ZlcmxvYWRJbXBsLmpzIj48L3NjcmlwdD4KKyAgICA8c2NyaXB0
IHNyYz0iUmVzb2x2ZXJQb2ludGVycy5qcyI+PC9zY3JpcHQ+CiAgICAgPHNjcmlwdCBzcmM9IlJl
c29sdmVQcm9wZXJ0aWVzLmpzIj48L3NjcmlwdD4KICAgICA8c2NyaXB0IHNyYz0iUmVzb2x2ZVR5
cGVEZWZzLmpzIj48L3NjcmlwdD4KICAgICA8c2NyaXB0IHNyYz0iUmV0dXJuLmpzIj48L3Njcmlw
dD4KZGlmZiAtLWdpdCBhL1Rvb2xzL1dlYkdQVVNoYWRpbmdMYW5ndWFnZVJJL1Rlc3QuaHRtbCBi
L1Rvb2xzL1dlYkdQVVNoYWRpbmdMYW5ndWFnZVJJL1Rlc3QuaHRtbAppbmRleCAzMjBmYmE5OWQ1
NWM5NDdjZDRmZDAzODVjYWFiYjhlOWRkYWY5ZTkzLi5kNDhmMjc3NzE2Y2YyM2I2MThkMGFhNDk4
YzQwNzNlYzVkMjc3OGYyIDEwMDY0NAotLS0gYS9Ub29scy9XZWJHUFVTaGFkaW5nTGFuZ3VhZ2VS
SS9UZXN0Lmh0bWwKKysrIGIvVG9vbHMvV2ViR1BVU2hhZGluZ0xhbmd1YWdlUkkvVGVzdC5odG1s
CkBAIC0xMDAsNiArMTAwLDcgQEAKIDxzY3JpcHQgc3JjPSJPcmlnaW5LaW5kLmpzIj48L3Njcmlw
dD4KIDxzY3JpcHQgc3JjPSJPdmVybG9hZFJlc29sdXRpb25GYWlsdXJlLmpzIj48L3NjcmlwdD4K
IDxzY3JpcHQgc3JjPSJQYXJzZS5qcyI+PC9zY3JpcHQ+Cis8c2NyaXB0IHNyYz0iUG9pbnRlclJl
c29sdmVyLmpzIj48L3NjcmlwdD4KIDxzY3JpcHQgc3JjPSJQcmVwYXJlLmpzIj48L3NjcmlwdD4K
IDxzY3JpcHQgc3JjPSJQcm9wZXJ0eVJlc29sdmVyLmpzIj48L3NjcmlwdD4KIDxzY3JpcHQgc3Jj
PSJQcm9ncmFtLmpzIj48L3NjcmlwdD4KQEAgLTExNCw2ICsxMTUsNyBAQAogPHNjcmlwdCBzcmM9
IlJlY3Vyc2l2ZVR5cGVDaGVja2VyLmpzIj48L3NjcmlwdD4KIDxzY3JpcHQgc3JjPSJSZXNvbHZl
TmFtZXMuanMiPjwvc2NyaXB0PgogPHNjcmlwdCBzcmM9IlJlc29sdmVPdmVybG9hZEltcGwuanMi
Pjwvc2NyaXB0PgorPHNjcmlwdCBzcmM9IlJlc29sdmVQb2ludGVycy5qcyI+PC9zY3JpcHQ+CiA8
c2NyaXB0IHNyYz0iUmVzb2x2ZVByb3BlcnRpZXMuanMiPjwvc2NyaXB0PgogPHNjcmlwdCBzcmM9
IlJlc29sdmVUeXBlRGVmcy5qcyI+PC9zY3JpcHQ+CiA8c2NyaXB0IHNyYz0iUmV0dXJuLmpzIj48
L3NjcmlwdD4KZGlmZiAtLWdpdCBhL1Rvb2xzL1dlYkdQVVNoYWRpbmdMYW5ndWFnZVJJL1Rlc3Qu
anMgYi9Ub29scy9XZWJHUFVTaGFkaW5nTGFuZ3VhZ2VSSS9UZXN0LmpzCmluZGV4IDE1OWZhMDBl
MmRhOTgyMmEwNzc4ZTVmMDcyYmQ1Y2RkMTY2NzdhMTQuLmMwZTM2YjU3YjViNzg1MjJkY2UxZWIy
NThiMjdmYmNhZmJlMzFiNmIgMTAwNjQ0Ci0tLSBhL1Rvb2xzL1dlYkdQVVNoYWRpbmdMYW5ndWFn
ZVJJL1Rlc3QuanMKKysrIGIvVG9vbHMvV2ViR1BVU2hhZGluZ0xhbmd1YWdlUkkvVGVzdC5qcwpA
QCAtNjU3MSw2ICs2NTcxLDE5IEBAIHRlc3RzLmFuZFJldHVybmVkQXJyYXlSZWYgPSBmdW5jdGlv
bigpCiAgICAgY2hlY2tJbnQocHJvZ3JhbSwgY2FsbEZ1bmN0aW9uKHByb2dyYW0sICJmb28iLCBb
XSwgW10pLCAzNTQpOwogfQogCit0ZXN0cy5wb2ludGVyUmVzb2x1dGlvbiA9IGZ1bmN0aW9uKCkK
K3sKKyAgICBsZXQgcHJvZ3JhbSA9IGRvUHJlcChgCisgICAgICAgIGludCBmb28oKQorICAgICAg
ICB7CisgICAgICAgICAgICBpbnQgdmFsdWUgPSAxNzsKKyAgICAgICAgICAgIHRocmVhZCBpbnQq
IHB0ciA9ICZ2YWx1ZTsKKyAgICAgICAgICAgICpwdHIgPSAxODsKKyAgICAgICAgICAgIHJldHVy
biAqcHRyOworICAgICAgICB9CisgICAgYCk7Cit9CisKIG9rVG9UZXN0ID0gdHJ1ZTsKIAogbGV0
IHRlc3RGaWx0ZXIgPSAvLiovOyAvLyBydW4gZXZlcnl0aGluZyBieSBkZWZhdWx0CmRpZmYgLS1n
aXQgYS9Ub29scy9XZWJHUFVTaGFkaW5nTGFuZ3VhZ2VSSS9pbmRleC5odG1sIGIvVG9vbHMvV2Vi
R1BVU2hhZGluZ0xhbmd1YWdlUkkvaW5kZXguaHRtbAppbmRleCAzYTdlOTQ4YmU2N2QwYjVjMDVi
YjE5YzJlZjE0MzA5YTExOTczOGU0Li5iYTkyNTY2ZDJmNzlmN2M1OGMwYmRjNTdhYTkxZjdlYjE0
MjVhY2QwIDEwMDY0NAotLS0gYS9Ub29scy9XZWJHUFVTaGFkaW5nTGFuZ3VhZ2VSSS9pbmRleC5o
dG1sCisrKyBiL1Rvb2xzL1dlYkdQVVNoYWRpbmdMYW5ndWFnZVJJL2luZGV4Lmh0bWwKQEAgLTEw
MCw2ICsxMDAsNyBAQAogPHNjcmlwdCBzcmM9Ik9yaWdpbktpbmQuanMiPjwvc2NyaXB0PgogPHNj
cmlwdCBzcmM9Ik92ZXJsb2FkUmVzb2x1dGlvbkZhaWx1cmUuanMiPjwvc2NyaXB0PgogPHNjcmlw
dCBzcmM9IlBhcnNlLmpzIj48L3NjcmlwdD4KKzxzY3JpcHQgc3JjPSJQb2ludGVyUmVzb2x2ZXIu
anMiPjwvc2NyaXB0PgogPHNjcmlwdCBzcmM9IlByZXBhcmUuanMiPjwvc2NyaXB0PgogPHNjcmlw
dCBzcmM9IlByb3BlcnR5UmVzb2x2ZXIuanMiPjwvc2NyaXB0PgogPHNjcmlwdCBzcmM9IlByb2dy
YW0uanMiPjwvc2NyaXB0PgpAQCAtMTE0LDYgKzExNSw3IEBACiA8c2NyaXB0IHNyYz0iUmVjdXJz
aXZlVHlwZUNoZWNrZXIuanMiPjwvc2NyaXB0PgogPHNjcmlwdCBzcmM9IlJlc29sdmVOYW1lcy5q
cyI+PC9zY3JpcHQ+CiA8c2NyaXB0IHNyYz0iUmVzb2x2ZU92ZXJsb2FkSW1wbC5qcyI+PC9zY3Jp
cHQ+Cis8c2NyaXB0IHNyYz0iUmVzb2x2ZVBvaW50ZXJzLmpzIj48L3NjcmlwdD4KIDxzY3JpcHQg
c3JjPSJSZXNvbHZlUHJvcGVydGllcy5qcyI+PC9zY3JpcHQ+CiA8c2NyaXB0IHNyYz0iUmVzb2x2
ZVR5cGVEZWZzLmpzIj48L3NjcmlwdD4KIDxzY3JpcHQgc3JjPSJSZXR1cm4uanMiPjwvc2NyaXB0
Pgo=
</data>

          </attachment>
      

    </bug>

</bugzilla>