RESOLVED FIXED 177031
Figure out how WSL will support field overloads like float4.xz and friends
https://bugs.webkit.org/show_bug.cgi?id=177031
Summary Figure out how WSL will support field overloads like float4.xz and friends
Filip Pizlo
Reported 2017-09-15 19:09:00 PDT
I think that we do need operator[] and operator[]=, unlike what I concluded in https://bugs.webkit.org/show_bug.cgi?id=176958#c2 and subsequently landed. Otherwise, what does this return: ? operator&.xz(thread float4^) It cannot return float2, because it needs to return a pointer to a field. It cannot return float2^, because xz are not next to each other. But it would work if we could instead override: float2 operator.xz(float4) void operator.xz=(float4, float2)
Attachments
more (38.91 KB, patch)
2017-09-16 11:09 PDT, Filip Pizlo
no flags
most of it is written (68.02 KB, patch)
2017-09-16 14:08 PDT, Filip Pizlo
no flags
starting to test it (83.41 KB, patch)
2017-09-16 16:19 PDT, Filip Pizlo
no flags
it passes so many tests (106.97 KB, patch)
2017-09-16 18:06 PDT, Filip Pizlo
no flags
passes all of our current tests (107.33 KB, patch)
2017-09-16 18:18 PDT, Filip Pizlo
no flags
it's passing significant tests (126.40 KB, patch)
2017-09-16 21:12 PDT, Filip Pizlo
no flags
the patch (143.57 KB, patch)
2017-09-16 21:58 PDT, Filip Pizlo
no flags
added another substantial test (157.95 KB, patch)
2017-09-17 12:00 PDT, Filip Pizlo
no flags
more tests (163.44 KB, patch)
2017-09-17 13:15 PDT, Filip Pizlo
no flags
the patch (164.97 KB, patch)
2017-09-17 14:02 PDT, Filip Pizlo
no flags
wrote more tests (177.16 KB, patch)
2017-09-17 16:09 PDT, Filip Pizlo
no flags
more tests (183.74 KB, patch)
2017-09-17 16:26 PDT, Filip Pizlo
no flags
the patch (185.47 KB, patch)
2017-09-17 17:46 PDT, Filip Pizlo
no flags
the patch (186.17 KB, patch)
2017-09-17 22:11 PDT, Filip Pizlo
no flags
the patch (186.21 KB, patch)
2017-09-18 10:35 PDT, Filip Pizlo
jfbastien: review+
Filip Pizlo
Comment 1 2017-09-15 22:23:37 PDT
Here are some notes I took while pondering this. I think I have an algorithm now. -- array[index] += foo(); 1. ptr = &array[index]; 2. load from ptr 3. foo() 4. store to ptr native struct Foo; native struct Bar; native struct Baz; Bar operator.bar(Foo); Foo operator.bar=(Foo, Bar); thread Baz^ operator&.baz(thread Foo^); Foo foo; RMW(foo.bar, anonVar<0>, anonVar<1>, newValueExp(anonVar<0>), anonVar<1>) => RMW(foo, anonVar<2>, anonVar<3>, (anonVar<0>, anonVar<1>, anonVar<0> = operator.bar(anonVar<2>), anonVar<1> = newValueExp(anonVar<0>), operator.bar=(anonVar<2>, anonVar<1>)), anonVar<1>) RMW(foo.baz, anonVar<0>, anonVar<1>, newValueExp(anonVar<0>), anonVar<1>) => (anonVar<0>, anonVar<1>, anonVar<2>, anonVar<2> = &foo.baz, anonVar<0> = ^anonVar<2>, anonVar<1> = newValueExp(anonVar<0>), ^anonVar<2> = anonVar<1>) native struct Thingy; Thingy operator.thingy(Bar); Bar operator.thingy=(Bar, Thingy); RMW(foo.bar.thingy, anonVar<0>, anonVar<1>, newValueExp(anonVar<0>), anonVar<1>) => RMW(foo.bar, anonVar<2>, anonVar<3>, (anonVar<0>, anonVar<1>, anonVar<0> = operator.thingy(anonVar<2>), anonVar<1> = newValueExp(anonVar<0>), operator.thingy=(anonVar<2>, anonVar<1>)), anonVar<1>) => RMW(foo, anonVar<4>, anonVar<5>, (anonVar<2>, anonVar<3>, anonVar<2> = operator.bar(anonVar<4>), anonVar<3> = (anonVar<0>, anonVar<1>, anonVar<0> = operator.thingy(anonVar<2>), anonVar<1> = newValueExp(anonVar<0>), operator.thingy=(anonVar<2>, anonVar<1>)), operator.bar=(anonVar<4>, anonVar<3>)), anonVar<1>) foo.bar = thingy => RMW(foo, anonVar<0>, anonVar<1>, (anonVar<2>, anonVar<2> = thingy, operator.bar=(anonVar<0>, anonVar<2>)), anonVar<2>) foo.baz = thingy => ^operator&.baz(&foo) = thingy foo.bar => operator.bar(foo) foo.baz => ^operator&.bar(&foo) foo.bar.thingy => operator.bar(foo).thingy => operator.thingy(operator.bar(foo)) foo.baz.stuff => ^operator&.baz(&foo) => ^operator&.stuff(operator&.baz(&foo)) load assign dereference rmw 1. figure out what the load conversion would do 2. if it yields a Dereference, then use the pointer deconstruction 3. otherwise use the normal deconstruction It's not clear if this deconstruction should happen in Checker or later. Might be easier if it happens later. That would require factoring visitCallExpression out. That shouldn't be hard. First the checker would do its thing pretending that DotExpression and IndexExpression are just valid lvalues. Then a subsequent pass will convert those into calls or other things depending on context. This would mean that the only places that have to know the & and @ tricks that CallExpression currently does are the places that handle the load case. We'll need both IndexExpression and DotExpression to know how to do it.
Filip Pizlo
Comment 2 2017-09-16 11:09:43 PDT
Filip Pizlo
Comment 3 2017-09-16 14:08:39 PDT
Created attachment 321010 [details] most of it is written This isn't done yet. I still have to drag RMWExpression and IndexExpression through all of the visitors. But, I think the hard parts are done.
Filip Pizlo
Comment 4 2017-09-16 16:19:04 PDT
Created attachment 321017 [details] starting to test it
Filip Pizlo
Comment 5 2017-09-16 18:06:00 PDT
Created attachment 321018 [details] it passes so many tests
Filip Pizlo
Comment 6 2017-09-16 18:18:15 PDT
Created attachment 321019 [details] passes all of our current tests
Filip Pizlo
Comment 7 2017-09-16 21:12:13 PDT
Created attachment 321023 [details] it's passing significant tests Passes all old tests plus some large new ones.
Filip Pizlo
Comment 8 2017-09-16 21:58:43 PDT
Created attachment 321025 [details] the patch
Filip Pizlo
Comment 9 2017-09-17 12:00:17 PDT
Created attachment 321050 [details] added another substantial test
Filip Pizlo
Comment 10 2017-09-17 13:15:04 PDT
Created attachment 321052 [details] more tests
Filip Pizlo
Comment 11 2017-09-17 14:02:17 PDT
Created attachment 321053 [details] the patch Even more crazy testing.
Filip Pizlo
Comment 12 2017-09-17 16:09:37 PDT
Created attachment 321057 [details] wrote more tests
Filip Pizlo
Comment 13 2017-09-17 16:26:59 PDT
Created attachment 321058 [details] more tests One easy way to create new tests is to take an existing test and try to make its functions as generic as possible.
Filip Pizlo
Comment 14 2017-09-17 17:46:48 PDT
Created attachment 321059 [details] the patch
Filip Pizlo
Comment 15 2017-09-17 22:11:35 PDT
Created attachment 321076 [details] the patch
Filip Pizlo
Comment 16 2017-09-18 10:35:50 PDT
Created attachment 321106 [details] the patch
JF Bastien
Comment 17 2017-09-18 11:32:25 PDT
Comment on attachment 321106 [details] the patch View in context: https://bugs.webkit.org/attachment.cgi?id=321106&action=review Lots of this is over my head for now, first look at WSL :) r=me with that caveat. > Tools/WebGPUShadingLanguageRI/Checker.js:40 > } Ah no semicolon! > Tools/WebGPUShadingLanguageRI/Checker.js:160 > + throw new WTypeError(node.origin.originString, "LHS of read-modify-write is not an LValue: " + node.lVale); Typo "node.lVale" > Tools/WebGPUShadingLanguageRI/Checker.js:236 > + throw new Error("Cannot get typeForAnd"); Is there some context that can be thrown here? Looked like you have origin laying around that helps figure out where in the source this comes from? > Tools/WebGPUShadingLanguageRI/FindHighZombies.js:27 > +function findHighZombies(program) 👍 > Tools/WebGPUShadingLanguageRI/Parse.js:784 > + let token = consume("+", "-", "*", "/", "%", "^", "&", "|", "<", ">", "<=", ">=", "==", "++", "--", "&", ".", "~", "<<", ">>", "["); Does order in "consume" matter here? Because you have "<" before "<<", would it consume "<" first? I guess you already had "-" before "--" so no? You also have "&" twice.
Filip Pizlo
Comment 18 2017-09-18 11:51:13 PDT
(In reply to JF Bastien from comment #17) > Comment on attachment 321106 [details] > the patch > > View in context: > https://bugs.webkit.org/attachment.cgi?id=321106&action=review > > Lots of this is over my head for now, first look at WSL :) > > r=me with that caveat. > > > Tools/WebGPUShadingLanguageRI/Checker.js:40 > > } > > Ah no semicolon! > > > Tools/WebGPUShadingLanguageRI/Checker.js:160 > > + throw new WTypeError(node.origin.originString, "LHS of read-modify-write is not an LValue: " + node.lVale); > > Typo "node.lVale" fixed > > > Tools/WebGPUShadingLanguageRI/Checker.js:236 > > + throw new Error("Cannot get typeForAnd"); > > Is there some context that can be thrown here? Looked like you have origin > laying around that helps figure out where in the source this comes from? We throw Error when it's an ICE, not an error to be reported to the user. I put this in there as basically an assertion; I don't expect it to ever fire. > > > Tools/WebGPUShadingLanguageRI/FindHighZombies.js:27 > > +function findHighZombies(program) > > 👍 > > > Tools/WebGPUShadingLanguageRI/Parse.js:784 > > + let token = consume("+", "-", "*", "/", "%", "^", "&", "|", "<", ">", "<=", ">=", "==", "++", "--", "&", ".", "~", "<<", ">>", "["); > > Does order in "consume" matter here? Because you have "<" before "<<", would > it consume "<" first? I guess you already had "-" before "--" so no? > > You also have "&" twice. The order doesn't matter. The lexer takes care of having the right regexp's to parse these. I'll clean up this list.
Filip Pizlo
Comment 19 2017-09-21 14:14:56 PDT
Radar WebKit Bug Importer
Comment 20 2017-09-27 12:29:37 PDT
Myles C. Maxfield
Comment 21 2018-10-13 16:37:54 PDT
Note You need to log in before you can comment on or make changes to this bug.