<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN"
"http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head><meta http-equiv="content-type" content="text/html; charset=utf-8" />
<title>[209083] trunk</title>
</head>
<body>

<style type="text/css"><!--
#msg dl.meta { border: 1px #006 solid; background: #369; padding: 6px; color: #fff; }
#msg dl.meta dt { float: left; width: 6em; font-weight: bold; }
#msg dt:after { content:':';}
#msg dl, #msg dt, #msg ul, #msg li, #header, #footer, #logmsg { font-family: verdana,arial,helvetica,sans-serif; font-size: 10pt;  }
#msg dl a { font-weight: bold}
#msg dl a:link    { color:#fc3; }
#msg dl a:active  { color:#ff0; }
#msg dl a:visited { color:#cc6; }
h3 { font-family: verdana,arial,helvetica,sans-serif; font-size: 10pt; font-weight: bold; }
#msg pre { overflow: auto; background: #ffc; border: 1px #fa0 solid; padding: 6px; }
#logmsg { background: #ffc; border: 1px #fa0 solid; padding: 1em 1em 0 1em; }
#logmsg p, #logmsg pre, #logmsg blockquote { margin: 0 0 1em 0; }
#logmsg p, #logmsg li, #logmsg dt, #logmsg dd { line-height: 14pt; }
#logmsg h1, #logmsg h2, #logmsg h3, #logmsg h4, #logmsg h5, #logmsg h6 { margin: .5em 0; }
#logmsg h1:first-child, #logmsg h2:first-child, #logmsg h3:first-child, #logmsg h4:first-child, #logmsg h5:first-child, #logmsg h6:first-child { margin-top: 0; }
#logmsg ul, #logmsg ol { padding: 0; list-style-position: inside; margin: 0 0 0 1em; }
#logmsg ul { text-indent: -1em; padding-left: 1em; }#logmsg ol { text-indent: -1.5em; padding-left: 1.5em; }
#logmsg > ul, #logmsg > ol { margin: 0 0 1em 0; }
#logmsg pre { background: #eee; padding: 1em; }
#logmsg blockquote { border: 1px solid #fa0; border-left-width: 10px; padding: 1em 1em 0 1em; background: white;}
#logmsg dl { margin: 0; }
#logmsg dt { font-weight: bold; }
#logmsg dd { margin: 0; padding: 0 0 0.5em 0; }
#logmsg dd:before { content:'\00bb';}
#logmsg table { border-spacing: 0px; border-collapse: collapse; border-top: 4px solid #fa0; border-bottom: 1px solid #fa0; background: #fff; }
#logmsg table th { text-align: left; font-weight: normal; padding: 0.2em 0.5em; border-top: 1px dotted #fa0; }
#logmsg table td { text-align: right; border-top: 1px dotted #fa0; padding: 0.2em 0.5em; }
#logmsg table thead th { text-align: center; border-bottom: 1px solid #fa0; }
#logmsg table th.Corner { text-align: left; }
#logmsg hr { border: none 0; border-top: 2px dashed #fa0; height: 1px; }
#header, #footer { color: #fff; background: #636; border: 1px #300 solid; padding: 6px; }
#patch { width: 100%; }
#patch h4 {font-family: verdana,arial,helvetica,sans-serif;font-size:10pt;padding:8px;background:#369;color:#fff;margin:0;}
#patch .propset h4, #patch .binary h4 {margin:0;}
#patch pre {padding:0;line-height:1.2em;margin:0;}
#patch .diff {width:100%;background:#eee;padding: 0 0 10px 0;overflow:auto;}
#patch .propset .diff, #patch .binary .diff  {padding:10px 0;}
#patch span {display:block;padding:0 10px;}
#patch .modfile, #patch .addfile, #patch .delfile, #patch .propset, #patch .binary, #patch .copfile {border:1px solid #ccc;margin:10px 0;}
#patch ins {background:#dfd;text-decoration:none;display:block;padding:0 10px;}
#patch del {background:#fdd;text-decoration:none;display:block;padding:0 10px;}
#patch .lines, .info {color:#888;background:#fff;}
--></style>
<div id="msg">
<dl class="meta">
<dt>Revision</dt> <dd><a href="http://trac.webkit.org/projects/webkit/changeset/209083">209083</a></dd>
<dt>Author</dt> <dd>keith_miller@apple.com</dd>
<dt>Date</dt> <dd>2016-11-29 11:37:00 -0800 (Tue, 29 Nov 2016)</dd>
</dl>

<h3>Log Message</h3>
<pre>Add simple way to implement Wasm ops that require more than one B3 opcode
https://bugs.webkit.org/show_bug.cgi?id=165129

Reviewed by Geoffrey Garen.

JSTests:

* wasm/function-tests/eqz.js: Added.
* wasm/function-tests/max.js: Added.
* wasm/function-tests/min.js: Added.
* wasm/wasm.json:

Source/JavaScriptCore:

This patch adds a simple way to show the B3IRGenerator opcode script how
to generate code for Wasm opcodes that do not have a one to one mapping.
The syntax is pretty simple right now. There are only three things one
can use as of this patch (although more things might be added in the future)
1) Wasm opcode arguments: These are referred to as @&lt;argument_number&gt;. For example,
   I32.sub would map to Sub(@0, @1).
2) 32-bit int constants: These are reffered to as i32(&lt;value&gt;). For example, i32.inc
   would map to Add(@0, i32(1))
3) B3 opcodes: These are referred to as the B3 opcode name followed by the B3Value's constructor
   arguments. A value may take the result of another value as an argument. For example, you can do
   Div(Mul(@0, Add(@0, i32(1))), i32(2)) if there was a b3 opcode that computed the sum from 1 to n.

These scripts are used to implement Wasm's eqz and floating point max/min opcodes. This patch
also adds missing support for the Wasm Neg opcodes.

* jsc.cpp:
(box):
(functionTestWasmModuleFunctions):
* wasm/WasmB3IRGenerator.cpp:
(JSC::Wasm::toB3Op): Deleted.
* wasm/WasmFunctionParser.h:
(JSC::Wasm::FunctionParser&lt;Context&gt;::parseBody):
* wasm/WasmModuleParser.cpp:
(JSC::Wasm::ModuleParser::parseType):
* wasm/WasmParser.h:
(JSC::Wasm::Parser::parseUInt8):
(JSC::Wasm::Parser::parseValueType):
* wasm/generateWasmB3IRGeneratorInlinesHeader.py:
(Source):
(Source.__init__):
(read):
(lex):
(CodeGenerator):
(CodeGenerator.__init__):
(CodeGenerator.advance):
(CodeGenerator.token):
(CodeGenerator.parseError):
(CodeGenerator.consume):
(CodeGenerator.generateParameters):
(CodeGenerator.generateOpcode):
(CodeGenerator.generate):
(temp):
(generateB3OpCode):
(generateI32ConstCode):
(generateB3Code):
(generateSimpleCode):
* wasm/wasm.json:</pre>

<h3>Modified Paths</h3>
<ul>
<li><a href="#trunkJSTestsChangeLog">trunk/JSTests/ChangeLog</a></li>
<li><a href="#trunkJSTestswasmwasmjson">trunk/JSTests/wasm/wasm.json</a></li>
<li><a href="#trunkSourceJavaScriptCoreChangeLog">trunk/Source/JavaScriptCore/ChangeLog</a></li>
<li><a href="#trunkSourceJavaScriptCorejsccpp">trunk/Source/JavaScriptCore/jsc.cpp</a></li>
<li><a href="#trunkSourceJavaScriptCorewasmWasmB3IRGeneratorcpp">trunk/Source/JavaScriptCore/wasm/WasmB3IRGenerator.cpp</a></li>
<li><a href="#trunkSourceJavaScriptCorewasmWasmFunctionParserh">trunk/Source/JavaScriptCore/wasm/WasmFunctionParser.h</a></li>
<li><a href="#trunkSourceJavaScriptCorewasmWasmModuleParsercpp">trunk/Source/JavaScriptCore/wasm/WasmModuleParser.cpp</a></li>
<li><a href="#trunkSourceJavaScriptCorewasmWasmParserh">trunk/Source/JavaScriptCore/wasm/WasmParser.h</a></li>
<li><a href="#trunkSourceJavaScriptCorewasmgenerateWasmB3IRGeneratorInlinesHeaderpy">trunk/Source/JavaScriptCore/wasm/generateWasmB3IRGeneratorInlinesHeader.py</a></li>
<li><a href="#trunkSourceJavaScriptCorewasmwasmjson">trunk/Source/JavaScriptCore/wasm/wasm.json</a></li>
</ul>

<h3>Added Paths</h3>
<ul>
<li><a href="#trunkJSTestswasmfunctiontestseqzjs">trunk/JSTests/wasm/function-tests/eqz.js</a></li>
<li><a href="#trunkJSTestswasmfunctiontestsmaxjs">trunk/JSTests/wasm/function-tests/max.js</a></li>
<li><a href="#trunkJSTestswasmfunctiontestsminjs">trunk/JSTests/wasm/function-tests/min.js</a></li>
</ul>

</div>
<div id="patch">
<h3>Diff</h3>
<a id="trunkJSTestsChangeLog"></a>
<div class="modfile"><h4>Modified: trunk/JSTests/ChangeLog (209082 => 209083)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/JSTests/ChangeLog        2016-11-29 19:20:08 UTC (rev 209082)
+++ trunk/JSTests/ChangeLog        2016-11-29 19:37:00 UTC (rev 209083)
</span><span class="lines">@@ -1,3 +1,15 @@
</span><ins>+2016-11-29  Keith Miller  &lt;keith_miller@apple.com&gt;
+
+        Add simple way to implement Wasm ops that require more than one B3 opcode
+        https://bugs.webkit.org/show_bug.cgi?id=165129
+
+        Reviewed by Geoffrey Garen.
+
+        * wasm/function-tests/eqz.js: Added.
+        * wasm/function-tests/max.js: Added.
+        * wasm/function-tests/min.js: Added.
+        * wasm/wasm.json:
+
</ins><span class="cx"> 2016-11-21  Yusuke Suzuki  &lt;utatane.tea@gmail.com&gt;
</span><span class="cx"> 
</span><span class="cx">         Crash in com.apple.JavaScriptCore: WTF::ThreadSpecific&lt;WTF::WTFThreadData, + 142
</span></span></pre></div>
<a id="trunkJSTestswasmfunctiontestseqzjs"></a>
<div class="addfile"><h4>Added: trunk/JSTests/wasm/function-tests/eqz.js (0 => 209083)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/JSTests/wasm/function-tests/eqz.js                                (rev 0)
+++ trunk/JSTests/wasm/function-tests/eqz.js        2016-11-29 19:37:00 UTC (rev 209083)
</span><span class="lines">@@ -0,0 +1,21 @@
</span><ins>+import Builder from '../Builder.js'
+
+const b = new Builder();
+b.setChecked(false);
+b.Type().End()
+    .Function().End()
+    .Memory().InitialMaxPages(1, 1).End()
+    .Code()
+    .Function({ params: [&quot;i32&quot;], ret: &quot;i32&quot; }, [])
+    .GetLocal(0)
+    .I32Eqz()
+    .End()
+
+
+const bin = b.WebAssembly()
+bin.trim();
+testWasmModuleFunctions(bin.get(), 1,
+                        [[{type: &quot;i32&quot;, value: 0 }, [{ type: &quot;i32&quot;, value: 1 }]],
+                         [{type: &quot;i32&quot;, value: 1 }, [{ type: &quot;i32&quot;, value: 0 }]]
+                        ]
+                       );
</ins></span></pre></div>
<a id="trunkJSTestswasmfunctiontestsmaxjs"></a>
<div class="addfile"><h4>Added: trunk/JSTests/wasm/function-tests/max.js (0 => 209083)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/JSTests/wasm/function-tests/max.js                                (rev 0)
+++ trunk/JSTests/wasm/function-tests/max.js        2016-11-29 19:37:00 UTC (rev 209083)
</span><span class="lines">@@ -0,0 +1,34 @@
</span><ins>+import Builder from '../Builder.js'
+
+const b = new Builder();
+b.setChecked(false);
+b.Type().End()
+    .Function().End()
+    .Memory().InitialMaxPages(1, 1).End()
+    .Code()
+    .Function({ params: [&quot;f32&quot;, &quot;f32&quot;], ret: &quot;f32&quot; }, [])
+    .GetLocal(0)
+    .GetLocal(1)
+    .F32Max()
+    .End()
+
+    .Function({ params: [&quot;f64&quot;, &quot;f64&quot;], ret: &quot;f64&quot; }, [])
+    .GetLocal(0)
+    .GetLocal(1)
+    .F64Max()
+    .End()
+
+
+
+const bin = b.WebAssembly()
+bin.trim();
+testWasmModuleFunctions(bin.get(), 2,
+                        [[{type: &quot;f32&quot;, value: 100 }, [{ type: &quot;f32&quot;, value: 100 }, { type: &quot;f32&quot;, value: 1.5 }]],
+                         [{type: &quot;f32&quot;, value: 100 }, [{ type: &quot;f32&quot;, value: 100 }, { type: &quot;f32&quot;, value: -1.5 }]],
+                         [{type: &quot;f32&quot;, value: -1.5 }, [{ type: &quot;f32&quot;, value: -100 }, { type: &quot;f32&quot;, value: -1.5 }]]
+                        ],
+                        [[{type: &quot;f64&quot;, value: 100 }, [{ type: &quot;f64&quot;, value: 100 }, { type: &quot;f64&quot;, value: 1.5 }]],
+                         [{type: &quot;f64&quot;, value: 100 }, [{ type: &quot;f64&quot;, value: 100 }, { type: &quot;f64&quot;, value: -1.5 }]],
+                         [{type: &quot;f64&quot;, value: -1.5 }, [{ type: &quot;f64&quot;, value: -100 }, { type: &quot;f64&quot;, value: -1.5 }]]
+                        ]
+                       );
</ins></span></pre></div>
<a id="trunkJSTestswasmfunctiontestsminjs"></a>
<div class="addfile"><h4>Added: trunk/JSTests/wasm/function-tests/min.js (0 => 209083)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/JSTests/wasm/function-tests/min.js                                (rev 0)
+++ trunk/JSTests/wasm/function-tests/min.js        2016-11-29 19:37:00 UTC (rev 209083)
</span><span class="lines">@@ -0,0 +1,34 @@
</span><ins>+import Builder from '../Builder.js'
+
+const b = new Builder();
+b.setChecked(false);
+b.Type().End()
+    .Function().End()
+    .Memory().InitialMaxPages(1, 1).End()
+    .Code()
+    .Function({ params: [&quot;f32&quot;, &quot;f32&quot;], ret: &quot;f32&quot; }, [])
+    .GetLocal(0)
+    .GetLocal(1)
+    .F32Min()
+    .End()
+
+    .Function({ params: [&quot;f64&quot;, &quot;f64&quot;], ret: &quot;f64&quot; }, [])
+    .GetLocal(0)
+    .GetLocal(1)
+    .F64Min()
+    .End()
+
+
+
+const bin = b.WebAssembly()
+bin.trim();
+testWasmModuleFunctions(bin.get(), 2,
+                        [[{type: &quot;f32&quot;, value: 1.5 }, [{ type: &quot;f32&quot;, value: 100 }, { type: &quot;f32&quot;, value: 1.5 }]],
+                         [{type: &quot;f32&quot;, value: -1.5 }, [{ type: &quot;f32&quot;, value: 100 }, { type: &quot;f32&quot;, value: -1.5 }]],
+                         [{type: &quot;f32&quot;, value: -100 }, [{ type: &quot;f32&quot;, value: -100 }, { type: &quot;f32&quot;, value: 1.5 }]]
+                        ],
+                        [[{type: &quot;f64&quot;, value: 1.5 }, [{ type: &quot;f64&quot;, value: 100 }, { type: &quot;f64&quot;, value: 1.5 }]],
+                         [{type: &quot;f64&quot;, value: -1.5 }, [{ type: &quot;f64&quot;, value: 100 }, { type: &quot;f64&quot;, value: -1.5 }]],
+                         [{type: &quot;f64&quot;, value: -100 }, [{ type: &quot;f64&quot;, value: -100 }, { type: &quot;f64&quot;, value: 1.5 }]]
+                        ]
+                       );
</ins></span></pre></div>
<a id="trunkJSTestswasmwasmjson"></a>
<div class="modfile"><h4>Modified: trunk/JSTests/wasm/wasm.json (209082 => 209083)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/JSTests/wasm/wasm.json        2016-11-29 19:20:08 UTC (rev 209082)
+++ trunk/JSTests/wasm/wasm.json        2016-11-29 19:37:00 UTC (rev 209083)
</span><span class="lines">@@ -120,7 +120,7 @@
</span><span class="cx">         &quot;i32.clz&quot;:             { &quot;category&quot;: &quot;arithmetic&quot;, &quot;value&quot;:  87, &quot;return&quot;: [&quot;i32&quot;],      &quot;parameter&quot;: [&quot;i32&quot;],                  &quot;immediate&quot;: [], &quot;b3op&quot;: &quot;Clz&quot;          },
</span><span class="cx">         &quot;i32.ctz&quot;:             { &quot;category&quot;: &quot;arithmetic&quot;, &quot;value&quot;:  88, &quot;return&quot;: [&quot;i32&quot;],      &quot;parameter&quot;: [&quot;i32&quot;],                  &quot;immediate&quot;: []                         },
</span><span class="cx">         &quot;i32.popcnt&quot;:          { &quot;category&quot;: &quot;arithmetic&quot;, &quot;value&quot;:  89, &quot;return&quot;: [&quot;i32&quot;],      &quot;parameter&quot;: [&quot;i32&quot;],                  &quot;immediate&quot;: []                         },
</span><del>-        &quot;i32.eqz&quot;:             { &quot;category&quot;: &quot;comparison&quot;, &quot;value&quot;:  90, &quot;return&quot;: [&quot;bool&quot;],     &quot;parameter&quot;: [&quot;i32&quot;],                  &quot;immediate&quot;: []                         },
</del><ins>+        &quot;i32.eqz&quot;:             { &quot;category&quot;: &quot;comparison&quot;, &quot;value&quot;:  90, &quot;return&quot;: [&quot;bool&quot;],     &quot;parameter&quot;: [&quot;i32&quot;],                  &quot;immediate&quot;: [], &quot;b3op&quot;: &quot;Equal(i32(0), @0)&quot; },
</ins><span class="cx">         &quot;i64.add&quot;:             { &quot;category&quot;: &quot;arithmetic&quot;, &quot;value&quot;:  91, &quot;return&quot;: [&quot;i64&quot;],      &quot;parameter&quot;: [&quot;i64&quot;, &quot;i64&quot;],           &quot;immediate&quot;: [], &quot;b3op&quot;: &quot;Add&quot;          },
</span><span class="cx">         &quot;i64.sub&quot;:             { &quot;category&quot;: &quot;arithmetic&quot;, &quot;value&quot;:  92, &quot;return&quot;: [&quot;i64&quot;],      &quot;parameter&quot;: [&quot;i64&quot;, &quot;i64&quot;],           &quot;immediate&quot;: [], &quot;b3op&quot;: &quot;Sub&quot;          },
</span><span class="cx">         &quot;i64.mul&quot;:             { &quot;category&quot;: &quot;arithmetic&quot;, &quot;value&quot;:  93, &quot;return&quot;: [&quot;i64&quot;],      &quot;parameter&quot;: [&quot;i64&quot;, &quot;i64&quot;],           &quot;immediate&quot;: [], &quot;b3op&quot;: &quot;Mul&quot;          },
</span><span class="lines">@@ -149,15 +149,15 @@
</span><span class="cx">         &quot;i64.clz&quot;:             { &quot;category&quot;: &quot;arithmetic&quot;, &quot;value&quot;: 114, &quot;return&quot;: [&quot;i64&quot;],      &quot;parameter&quot;: [&quot;i64&quot;],                  &quot;immediate&quot;: [], &quot;b3op&quot;: &quot;Clz&quot;          },
</span><span class="cx">         &quot;i64.ctz&quot;:             { &quot;category&quot;: &quot;arithmetic&quot;, &quot;value&quot;: 115, &quot;return&quot;: [&quot;i64&quot;],      &quot;parameter&quot;: [&quot;i64&quot;],                  &quot;immediate&quot;: []                         },
</span><span class="cx">         &quot;i64.popcnt&quot;:          { &quot;category&quot;: &quot;arithmetic&quot;, &quot;value&quot;: 116, &quot;return&quot;: [&quot;i64&quot;],      &quot;parameter&quot;: [&quot;i64&quot;],                  &quot;immediate&quot;: []                         },
</span><del>-        &quot;i64.eqz&quot;:             { &quot;category&quot;: &quot;comparison&quot;, &quot;value&quot;: 186, &quot;return&quot;: [&quot;bool&quot;],     &quot;parameter&quot;: [&quot;i64&quot;],                  &quot;immediate&quot;: []                         },
</del><ins>+        &quot;i64.eqz&quot;:             { &quot;category&quot;: &quot;comparison&quot;, &quot;value&quot;: 186, &quot;return&quot;: [&quot;bool&quot;],     &quot;parameter&quot;: [&quot;i64&quot;],                  &quot;immediate&quot;: [], &quot;b3op&quot;: &quot;Equal(i32(0), @0)&quot; },
</ins><span class="cx">         &quot;f32.add&quot;:             { &quot;category&quot;: &quot;arithmetic&quot;, &quot;value&quot;: 117, &quot;return&quot;: [&quot;f32&quot;],      &quot;parameter&quot;: [&quot;f32&quot;, &quot;f32&quot;],           &quot;immediate&quot;: [], &quot;b3op&quot;: &quot;Add&quot;          },
</span><span class="cx">         &quot;f32.sub&quot;:             { &quot;category&quot;: &quot;arithmetic&quot;, &quot;value&quot;: 118, &quot;return&quot;: [&quot;f32&quot;],      &quot;parameter&quot;: [&quot;f32&quot;, &quot;f32&quot;],           &quot;immediate&quot;: [], &quot;b3op&quot;: &quot;Sub&quot;          },
</span><span class="cx">         &quot;f32.mul&quot;:             { &quot;category&quot;: &quot;arithmetic&quot;, &quot;value&quot;: 119, &quot;return&quot;: [&quot;f32&quot;],      &quot;parameter&quot;: [&quot;f32&quot;, &quot;f32&quot;],           &quot;immediate&quot;: [], &quot;b3op&quot;: &quot;Mul&quot;          },
</span><span class="cx">         &quot;f32.div&quot;:             { &quot;category&quot;: &quot;arithmetic&quot;, &quot;value&quot;: 120, &quot;return&quot;: [&quot;f32&quot;],      &quot;parameter&quot;: [&quot;f32&quot;, &quot;f32&quot;],           &quot;immediate&quot;: [], &quot;b3op&quot;: &quot;Div&quot;          },
</span><del>-        &quot;f32.min&quot;:             { &quot;category&quot;: &quot;arithmetic&quot;, &quot;value&quot;: 121, &quot;return&quot;: [&quot;f32&quot;],      &quot;parameter&quot;: [&quot;f32&quot;, &quot;f32&quot;],           &quot;immediate&quot;: []                         },
-        &quot;f32.max&quot;:             { &quot;category&quot;: &quot;arithmetic&quot;, &quot;value&quot;: 122, &quot;return&quot;: [&quot;f32&quot;],      &quot;parameter&quot;: [&quot;f32&quot;, &quot;f32&quot;],           &quot;immediate&quot;: []                         },
</del><ins>+        &quot;f32.min&quot;:             { &quot;category&quot;: &quot;arithmetic&quot;, &quot;value&quot;: 121, &quot;return&quot;: [&quot;f32&quot;],      &quot;parameter&quot;: [&quot;f32&quot;, &quot;f32&quot;],           &quot;immediate&quot;: [], &quot;b3op&quot;: &quot;Select(LessThan(@0, @1), @0, @1)&quot; },
+        &quot;f32.max&quot;:             { &quot;category&quot;: &quot;arithmetic&quot;, &quot;value&quot;: 122, &quot;return&quot;: [&quot;f32&quot;],      &quot;parameter&quot;: [&quot;f32&quot;, &quot;f32&quot;],           &quot;immediate&quot;: [], &quot;b3op&quot;: &quot;Select(LessThan(@0, @1), @1, @0)&quot; },
</ins><span class="cx">         &quot;f32.abs&quot;:             { &quot;category&quot;: &quot;arithmetic&quot;, &quot;value&quot;: 123, &quot;return&quot;: [&quot;f32&quot;],      &quot;parameter&quot;: [&quot;f32&quot;],                  &quot;immediate&quot;: [], &quot;b3op&quot;: &quot;Abs&quot;          },
</span><del>-        &quot;f32.neg&quot;:             { &quot;category&quot;: &quot;arithmetic&quot;, &quot;value&quot;: 124, &quot;return&quot;: [&quot;f32&quot;],      &quot;parameter&quot;: [&quot;f32&quot;],                  &quot;immediate&quot;: []                         },
</del><ins>+        &quot;f32.neg&quot;:             { &quot;category&quot;: &quot;arithmetic&quot;, &quot;value&quot;: 124, &quot;return&quot;: [&quot;f32&quot;],      &quot;parameter&quot;: [&quot;f32&quot;],                  &quot;immediate&quot;: [], &quot;b3op&quot;: &quot;Neg&quot;          },
</ins><span class="cx">         &quot;f32.copysign&quot;:        { &quot;category&quot;: &quot;arithmetic&quot;, &quot;value&quot;: 125, &quot;return&quot;: [&quot;f32&quot;],      &quot;parameter&quot;: [&quot;f32&quot;],                  &quot;immediate&quot;: []                         },
</span><span class="cx">         &quot;f32.ceil&quot;:            { &quot;category&quot;: &quot;arithmetic&quot;, &quot;value&quot;: 126, &quot;return&quot;: [&quot;f32&quot;],      &quot;parameter&quot;: [&quot;f32&quot;],                  &quot;immediate&quot;: [], &quot;b3op&quot;: &quot;Ceil&quot;         },
</span><span class="cx">         &quot;f32.floor&quot;:           { &quot;category&quot;: &quot;arithmetic&quot;, &quot;value&quot;: 127, &quot;return&quot;: [&quot;f32&quot;],      &quot;parameter&quot;: [&quot;f32&quot;],                  &quot;immediate&quot;: [], &quot;b3op&quot;: &quot;Floor&quot;        },
</span><span class="lines">@@ -174,10 +174,10 @@
</span><span class="cx">         &quot;f64.sub&quot;:             { &quot;category&quot;: &quot;arithmetic&quot;, &quot;value&quot;: 138, &quot;return&quot;: [&quot;f64&quot;],      &quot;parameter&quot;: [&quot;f64&quot;, &quot;f64&quot;],           &quot;immediate&quot;: [], &quot;b3op&quot;: &quot;Sub&quot;          },
</span><span class="cx">         &quot;f64.mul&quot;:             { &quot;category&quot;: &quot;arithmetic&quot;, &quot;value&quot;: 139, &quot;return&quot;: [&quot;f64&quot;],      &quot;parameter&quot;: [&quot;f64&quot;, &quot;f64&quot;],           &quot;immediate&quot;: [], &quot;b3op&quot;: &quot;Mul&quot;          },
</span><span class="cx">         &quot;f64.div&quot;:             { &quot;category&quot;: &quot;arithmetic&quot;, &quot;value&quot;: 140, &quot;return&quot;: [&quot;f64&quot;],      &quot;parameter&quot;: [&quot;f64&quot;, &quot;f64&quot;],           &quot;immediate&quot;: [], &quot;b3op&quot;: &quot;Div&quot;          },
</span><del>-        &quot;f64.min&quot;:             { &quot;category&quot;: &quot;arithmetic&quot;, &quot;value&quot;: 141, &quot;return&quot;: [&quot;f64&quot;],      &quot;parameter&quot;: [&quot;f64&quot;, &quot;f64&quot;],           &quot;immediate&quot;: []                         },
-        &quot;f64.max&quot;:             { &quot;category&quot;: &quot;arithmetic&quot;, &quot;value&quot;: 142, &quot;return&quot;: [&quot;f64&quot;],      &quot;parameter&quot;: [&quot;f64&quot;, &quot;f64&quot;],           &quot;immediate&quot;: []                         },
</del><ins>+        &quot;f64.min&quot;:             { &quot;category&quot;: &quot;arithmetic&quot;, &quot;value&quot;: 141, &quot;return&quot;: [&quot;f64&quot;],      &quot;parameter&quot;: [&quot;f64&quot;, &quot;f64&quot;],           &quot;immediate&quot;: [], &quot;b3op&quot;: &quot;Select(LessThan(@0, @1), @0, @1)&quot; },
+        &quot;f64.max&quot;:             { &quot;category&quot;: &quot;arithmetic&quot;, &quot;value&quot;: 142, &quot;return&quot;: [&quot;f64&quot;],      &quot;parameter&quot;: [&quot;f64&quot;, &quot;f64&quot;],           &quot;immediate&quot;: [], &quot;b3op&quot;: &quot;Select(LessThan(@0, @1), @1, @0)&quot; },
</ins><span class="cx">         &quot;f64.abs&quot;:             { &quot;category&quot;: &quot;arithmetic&quot;, &quot;value&quot;: 143, &quot;return&quot;: [&quot;f64&quot;],      &quot;parameter&quot;: [&quot;f64&quot;],                  &quot;immediate&quot;: [], &quot;b3op&quot;: &quot;Abs&quot;          },
</span><del>-        &quot;f64.neg&quot;:             { &quot;category&quot;: &quot;arithmetic&quot;, &quot;value&quot;: 144, &quot;return&quot;: [&quot;f64&quot;],      &quot;parameter&quot;: [&quot;f64&quot;],                  &quot;immediate&quot;: []                         },
</del><ins>+        &quot;f64.neg&quot;:             { &quot;category&quot;: &quot;arithmetic&quot;, &quot;value&quot;: 144, &quot;return&quot;: [&quot;f64&quot;],      &quot;parameter&quot;: [&quot;f64&quot;],                  &quot;immediate&quot;: [], &quot;b3op&quot;: &quot;Neg&quot;          },
</ins><span class="cx">         &quot;f64.copysign&quot;:        { &quot;category&quot;: &quot;arithmetic&quot;, &quot;value&quot;: 145, &quot;return&quot;: [&quot;f64&quot;],      &quot;parameter&quot;: [&quot;f64&quot;],                  &quot;immediate&quot;: []                         },
</span><span class="cx">         &quot;f64.ceil&quot;:            { &quot;category&quot;: &quot;arithmetic&quot;, &quot;value&quot;: 146, &quot;return&quot;: [&quot;f64&quot;],      &quot;parameter&quot;: [&quot;f64&quot;],                  &quot;immediate&quot;: [], &quot;b3op&quot;: &quot;Ceil&quot;         },
</span><span class="cx">         &quot;f64.floor&quot;:           { &quot;category&quot;: &quot;arithmetic&quot;, &quot;value&quot;: 147, &quot;return&quot;: [&quot;f64&quot;],      &quot;parameter&quot;: [&quot;f64&quot;],                  &quot;immediate&quot;: [], &quot;b3op&quot;: &quot;Floor&quot;        },
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreChangeLog"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/ChangeLog (209082 => 209083)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/ChangeLog        2016-11-29 19:20:08 UTC (rev 209082)
+++ trunk/Source/JavaScriptCore/ChangeLog        2016-11-29 19:37:00 UTC (rev 209083)
</span><span class="lines">@@ -1,3 +1,58 @@
</span><ins>+2016-11-29  Keith Miller  &lt;keith_miller@apple.com&gt;
+
+        Add simple way to implement Wasm ops that require more than one B3 opcode
+        https://bugs.webkit.org/show_bug.cgi?id=165129
+
+        Reviewed by Geoffrey Garen.
+
+        This patch adds a simple way to show the B3IRGenerator opcode script how
+        to generate code for Wasm opcodes that do not have a one to one mapping.
+        The syntax is pretty simple right now. There are only three things one
+        can use as of this patch (although more things might be added in the future)
+        1) Wasm opcode arguments: These are referred to as @&lt;argument_number&gt;. For example,
+           I32.sub would map to Sub(@0, @1).
+        2) 32-bit int constants: These are reffered to as i32(&lt;value&gt;). For example, i32.inc
+           would map to Add(@0, i32(1))
+        3) B3 opcodes: These are referred to as the B3 opcode name followed by the B3Value's constructor
+           arguments. A value may take the result of another value as an argument. For example, you can do
+           Div(Mul(@0, Add(@0, i32(1))), i32(2)) if there was a b3 opcode that computed the sum from 1 to n.
+
+        These scripts are used to implement Wasm's eqz and floating point max/min opcodes. This patch
+        also adds missing support for the Wasm Neg opcodes.
+
+        * jsc.cpp:
+        (box):
+        (functionTestWasmModuleFunctions):
+        * wasm/WasmB3IRGenerator.cpp:
+        (JSC::Wasm::toB3Op): Deleted.
+        * wasm/WasmFunctionParser.h:
+        (JSC::Wasm::FunctionParser&lt;Context&gt;::parseBody):
+        * wasm/WasmModuleParser.cpp:
+        (JSC::Wasm::ModuleParser::parseType):
+        * wasm/WasmParser.h:
+        (JSC::Wasm::Parser::parseUInt8):
+        (JSC::Wasm::Parser::parseValueType):
+        * wasm/generateWasmB3IRGeneratorInlinesHeader.py:
+        (Source):
+        (Source.__init__):
+        (read):
+        (lex):
+        (CodeGenerator):
+        (CodeGenerator.__init__):
+        (CodeGenerator.advance):
+        (CodeGenerator.token):
+        (CodeGenerator.parseError):
+        (CodeGenerator.consume):
+        (CodeGenerator.generateParameters):
+        (CodeGenerator.generateOpcode):
+        (CodeGenerator.generate):
+        (temp):
+        (generateB3OpCode):
+        (generateI32ConstCode):
+        (generateB3Code):
+        (generateSimpleCode):
+        * wasm/wasm.json:
+
</ins><span class="cx"> 2016-11-29  Mark Lam  &lt;mark.lam@apple.com&gt;
</span><span class="cx"> 
</span><span class="cx">         Fix exception scope verification failures in ProxyConstructor.cpp and ProxyObject.cpp.
</span></span></pre></div>
<a id="trunkSourceJavaScriptCorejsccpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/jsc.cpp (209082 => 209083)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/jsc.cpp        2016-11-29 19:20:08 UTC (rev 209082)
+++ trunk/Source/JavaScriptCore/jsc.cpp        2016-11-29 19:37:00 UTC (rev 209083)
</span><span class="lines">@@ -2509,7 +2509,7 @@
</span><span class="cx">         return JSValue::decode(bitwise_cast&lt;uint32_t&gt;(value.toFloat(exec)));
</span><span class="cx"> 
</span><span class="cx">     RELEASE_ASSERT(typeString == &quot;f64&quot;);
</span><del>-    return value;
</del><ins>+    return JSValue::decode(bitwise_cast&lt;uint64_t&gt;(value.asNumber()));
</ins><span class="cx"> }
</span><span class="cx"> 
</span><span class="cx"> static JSValue callWasmFunction(VM* vm, const B3::Compilation&amp; code, Vector&lt;JSValue&gt;&amp; boxedArgs)
</span><span class="lines">@@ -2548,8 +2548,10 @@
</span><span class="cx"> 
</span><span class="cx">     Wasm::Plan plan(&amp;vm, static_cast&lt;uint8_t*&gt;(source-&gt;vector()), source-&gt;length());
</span><span class="cx">     plan.run();
</span><del>-    if (plan.failed())
</del><ins>+    if (plan.failed()) {
+        dataLogLn(&quot;failed to parse module: &quot;, plan.errorMessage());
</ins><span class="cx">         CRASH();
</span><ins>+    }
</ins><span class="cx"> 
</span><span class="cx">     if (plan.compiledFunctionCount() != functionCount)
</span><span class="cx">         CRASH();
</span></span></pre></div>
<a id="trunkSourceJavaScriptCorewasmWasmB3IRGeneratorcpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/wasm/WasmB3IRGenerator.cpp (209082 => 209083)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/wasm/WasmB3IRGenerator.cpp        2016-11-29 19:20:08 UTC (rev 209082)
+++ trunk/Source/JavaScriptCore/wasm/WasmB3IRGenerator.cpp        2016-11-29 19:37:00 UTC (rev 209083)
</span><span class="lines">@@ -59,26 +59,6 @@
</span><span class="cx"> const bool verbose = false;
</span><span class="cx"> }
</span><span class="cx"> 
</span><del>-inline B3::Opcode toB3Op(BinaryOpType op)
-{
-    switch (op) {
-#define CREATE_CASE(name, op, b3op) case BinaryOpType::name: return b3op;
-    FOR_EACH_WASM_BINARY_OP(CREATE_CASE)
-#undef CREATE_CASE
-    }
-    RELEASE_ASSERT_NOT_REACHED();
-}
-
-inline B3::Opcode toB3Op(UnaryOpType op)
-{
-    switch (op) {
-#define CREATE_CASE(name, op, b3op) case UnaryOpType::name: return b3op;
-    FOR_EACH_WASM_UNARY_OP(CREATE_CASE)
-#undef CREATE_CASE
-    }
-    RELEASE_ASSERT_NOT_REACHED();
-}
-
</del><span class="cx"> class B3IRGenerator {
</span><span class="cx"> public:
</span><span class="cx">     struct ControlData {
</span></span></pre></div>
<a id="trunkSourceJavaScriptCorewasmWasmFunctionParserh"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/wasm/WasmFunctionParser.h (209082 => 209083)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/wasm/WasmFunctionParser.h        2016-11-29 19:20:08 UTC (rev 209082)
+++ trunk/Source/JavaScriptCore/wasm/WasmFunctionParser.h        2016-11-29 19:37:00 UTC (rev 209083)
</span><span class="lines">@@ -123,7 +123,7 @@
</span><span class="cx"> {
</span><span class="cx">     while (true) {
</span><span class="cx">         uint8_t op;
</span><del>-        if (!parseUInt7(op) || !isValidOpType(op)) {
</del><ins>+        if (!parseUInt8(op) || !isValidOpType(op)) {
</ins><span class="cx">             if (verbose)
</span><span class="cx">                 WTF::dataLogLn(&quot;attempted to decode invalid op: &quot;, RawPointer(reinterpret_cast&lt;void*&gt;(op)), &quot; at offset: &quot;, RawPointer(reinterpret_cast&lt;void*&gt;(m_offset)));
</span><span class="cx">             return false;
</span><span class="lines">@@ -350,7 +350,7 @@
</span><span class="cx"> 
</span><span class="cx">     case OpType::Block: {
</span><span class="cx">         Type inlineSignature;
</span><del>-        if (!parseValueType(inlineSignature))
</del><ins>+        if (!parseResultType(inlineSignature))
</ins><span class="cx">             return false;
</span><span class="cx"> 
</span><span class="cx">         m_controlStack.append({ WTFMove(m_expressionStack), m_context.addBlock(inlineSignature) });
</span><span class="lines">@@ -360,7 +360,7 @@
</span><span class="cx"> 
</span><span class="cx">     case OpType::Loop: {
</span><span class="cx">         Type inlineSignature;
</span><del>-        if (!parseValueType(inlineSignature))
</del><ins>+        if (!parseResultType(inlineSignature))
</ins><span class="cx">             return false;
</span><span class="cx"> 
</span><span class="cx">         m_controlStack.append({ WTFMove(m_expressionStack), m_context.addLoop(inlineSignature) });
</span><span class="lines">@@ -370,7 +370,7 @@
</span><span class="cx"> 
</span><span class="cx">     case OpType::If: {
</span><span class="cx">         Type inlineSignature;
</span><del>-        if (!parseValueType(inlineSignature))
</del><ins>+        if (!parseResultType(inlineSignature))
</ins><span class="cx">             return false;
</span><span class="cx"> 
</span><span class="cx">         ExpressionType condition;
</span></span></pre></div>
<a id="trunkSourceJavaScriptCorewasmWasmModuleParsercpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/wasm/WasmModuleParser.cpp (209082 => 209083)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/wasm/WasmModuleParser.cpp        2016-11-29 19:20:08 UTC (rev 209082)
+++ trunk/Source/JavaScriptCore/wasm/WasmModuleParser.cpp        2016-11-29 19:37:00 UTC (rev 209083)
</span><span class="lines">@@ -185,10 +185,10 @@
</span><span class="cx">             return false;
</span><span class="cx"> 
</span><span class="cx">         for (unsigned i = 0; i != argumentCount; ++i) {
</span><del>-            uint8_t argumentType;
-            if (!parseUInt7(argumentType) || !isValueType(static_cast&lt;Type&gt;(argumentType)))
</del><ins>+            Type argumentType;
+            if (!parseResultType(argumentType))
</ins><span class="cx">                 return false;
</span><del>-            argumentTypes.uncheckedAppend(static_cast&lt;Type&gt;(argumentType));
</del><ins>+            argumentTypes.uncheckedAppend(argumentType);
</ins><span class="cx">         }
</span><span class="cx"> 
</span><span class="cx">         uint8_t returnCount;
</span></span></pre></div>
<a id="trunkSourceJavaScriptCorewasmWasmParserh"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/wasm/WasmParser.h (209082 => 209083)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/wasm/WasmParser.h        2016-11-29 19:20:08 UTC (rev 209082)
+++ trunk/Source/JavaScriptCore/wasm/WasmParser.h        2016-11-29 19:37:00 UTC (rev 209083)
</span><span class="lines">@@ -49,10 +49,12 @@
</span><span class="cx">     bool WARN_UNUSED_RETURN parseVarUInt1(uint8_t&amp;);
</span><span class="cx">     bool WARN_UNUSED_RETURN parseInt7(int8_t&amp;);
</span><span class="cx">     bool WARN_UNUSED_RETURN parseUInt7(uint8_t&amp;);
</span><ins>+    bool WARN_UNUSED_RETURN parseUInt8(uint8_t&amp;);
</ins><span class="cx">     bool WARN_UNUSED_RETURN parseUInt32(uint32_t&amp;);
</span><span class="cx">     bool WARN_UNUSED_RETURN parseVarUInt32(uint32_t&amp;);
</span><span class="cx">     bool WARN_UNUSED_RETURN parseVarUInt64(uint64_t&amp;);
</span><span class="cx"> 
</span><ins>+    bool WARN_UNUSED_RETURN parseResultType(Type&amp;);
</ins><span class="cx">     bool WARN_UNUSED_RETURN parseValueType(Type&amp;);
</span><span class="cx">     bool WARN_UNUSED_RETURN parseExternalKind(External::Kind&amp;);
</span><span class="cx"> 
</span><span class="lines">@@ -131,6 +133,14 @@
</span><span class="cx">     return true;
</span><span class="cx"> }
</span><span class="cx"> 
</span><ins>+ALWAYS_INLINE bool Parser::parseUInt8(uint8_t&amp; result)
+{
+    if (m_offset &gt;= length())
+        return false;
+    result = source()[m_offset++];
+    return true;
+}
+
</ins><span class="cx"> ALWAYS_INLINE bool Parser::parseInt7(int8_t&amp; result)
</span><span class="cx"> {
</span><span class="cx">     if (m_offset &gt;= length())
</span><span class="lines">@@ -157,16 +167,21 @@
</span><span class="cx">     return temp &lt;= 1;
</span><span class="cx"> }
</span><span class="cx"> 
</span><del>-ALWAYS_INLINE bool Parser::parseValueType(Type&amp; result)
</del><ins>+ALWAYS_INLINE bool Parser::parseResultType(Type&amp; result)
</ins><span class="cx"> {
</span><span class="cx">     uint8_t value;
</span><span class="cx">     if (!parseUInt7(value))
</span><span class="cx">         return false;
</span><del>-    if (value &gt;= static_cast&lt;uint8_t&gt;(Type::LastValueType))
</del><ins>+    if (value &gt; static_cast&lt;uint8_t&gt;(Type::LastValueType))
</ins><span class="cx">         return false;
</span><span class="cx">     result = static_cast&lt;Type&gt;(value);
</span><span class="cx">     return true;
</span><span class="cx"> }
</span><ins>+
+ALWAYS_INLINE bool Parser::parseValueType(Type&amp; result)
+{
+    return parseResultType(result) &amp;&amp; isValueType(result);
+}
</ins><span class="cx">     
</span><span class="cx"> ALWAYS_INLINE bool Parser::parseExternalKind(External::Kind&amp; result)
</span><span class="cx"> {
</span></span></pre></div>
<a id="trunkSourceJavaScriptCorewasmgenerateWasmB3IRGeneratorInlinesHeaderpy"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/wasm/generateWasmB3IRGeneratorInlinesHeader.py (209082 => 209083)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/wasm/generateWasmB3IRGeneratorInlinesHeader.py        2016-11-29 19:20:08 UTC (rev 209082)
+++ trunk/Source/JavaScriptCore/wasm/generateWasmB3IRGeneratorInlinesHeader.py        2016-11-29 19:37:00 UTC (rev 209083)
</span><span class="lines">@@ -28,6 +28,7 @@
</span><span class="cx"> from generateWasm import *
</span><span class="cx"> import optparse
</span><span class="cx"> import sys
</span><ins>+import re
</ins><span class="cx"> 
</span><span class="cx"> parser = optparse.OptionParser(usage=&quot;usage: %prog &lt;wasm.json&gt; &lt;WasmOps.h&gt;&quot;)
</span><span class="cx"> (options, args) = parser.parse_args(sys.argv[0:])
</span><span class="lines">@@ -38,21 +39,161 @@
</span><span class="cx"> opcodes = wasm.opcodes
</span><span class="cx"> wasmB3IRGeneratorHFile = open(args[2], &quot;w&quot;)
</span><span class="cx"> 
</span><ins>+opcodeRegex = re.compile('([a-zA-Z0-9]+)')
+argumentRegex = re.compile('(\@[0-9]+)')
+decimalRegex = re.compile('([-]?[0-9]+)')
+whitespaceRegex = re.compile('\s+')
+commaRegex = re.compile('(,)')
+oparenRegex = re.compile('(\()')
+cparenRegex = re.compile('(\))')
</ins><span class="cx"> 
</span><ins>+
+class Source:
+    def __init__(self, contents, offset=0):
+        self.contents = contents
+        self.offset = offset
+
+
+def read(regex, source):
+    match = regex.match(source.contents, source.offset)
+    if not match:
+        return None
+    source.offset = match.end()
+    return match.group()
+
+
+def lex(source):
+    result = []
+    while source.offset != len(source.contents):
+        read(whitespaceRegex, source)
+        opcode = read(opcodeRegex, source)
+        if opcode:
+            result.append(opcode)
+            continue
+
+        argument = read(argumentRegex, source)
+        if argument:
+            result.append(argument)
+            continue
+
+        number = read(decimalRegex, source)
+        if number:
+            result.append(int(number))
+            continue
+
+        oparen = read(oparenRegex, source)
+        if oparen:
+            result.append(oparen)
+            continue
+
+        cparen = read(cparenRegex, source)
+        if cparen:
+            result.append(cparen)
+            continue
+
+        comma = read(commaRegex, source)
+        if comma:
+            # Skip commas
+            continue
+
+        raise Exception(&quot;Lexing Error: could not lex token from: &quot; + source.contents + &quot; at offset: &quot; + str(source.offset) + &quot; (&quot; + source.contents[source.offset:] + &quot;). With tokens: [&quot; + &quot;, &quot;.join(result) + &quot;]&quot;)
+    return result
+
+
+class CodeGenerator:
+    def __init__(self, tokens):
+        self.tokens = tokens
+        self.index = 0
+        self.code = []
+
+    def advance(self):
+        self.index += 1
+
+    def token(self):
+        return self.tokens[self.index]
+
+    def parseError(self, string):
+        raise Exception(&quot;Parse error &quot; + string)
+
+    def consume(self, string):
+        if self.token() != string:
+            self.parseError(&quot;Expected &quot; + string + &quot; but got &quot; + self.token())
+        self.advance()
+
+    def generateParameters(self):
+        self.advance()
+        params = []
+        tokens = self.tokens
+        while self.index &lt; len(tokens):
+            if self.token() == &quot;)&quot;:
+                self.advance()
+                return params
+            params.append(self.generateOpcode())
+        self.parseError(&quot;Parsing arguments fell off end&quot;)
+
+    def generateOpcode(self):
+        result = None
+        if self.token() == &quot;i32&quot;:
+            self.advance()
+            self.consume(&quot;(&quot;)
+            self.code.append(generateI32ConstCode(self.index, self.token()))
+            result = temp(self.index)
+            self.advance()
+            self.consume(&quot;)&quot;)
+        elif argumentRegex.match(self.token()):
+            result = &quot;arg&quot; + self.token()[1:]
+            self.advance()
+        else:
+            op = self.token()
+            index = self.index
+            self.advance()
+            params = self.generateParameters()
+            self.code.append(generateB3OpCode(index, op, params))
+            result = temp(index)
+
+        return result
+
+    def generate(self, wasmOp):
+        if len(self.tokens) == 1:
+            params = [&quot;arg&quot; + str(param) for param in range(len(wasmOp[&quot;parameter&quot;]))]
+            return &quot;    result = m_currentBlock-&gt;appendNew&lt;Value&gt;(m_proc, B3::&quot; + self.token() + &quot;, Origin(), &quot; + &quot;, &quot;.join(params) + &quot;)&quot;
+        result = self.generateOpcode()
+        self.code.append(&quot;result = &quot; + result)
+        return &quot;    &quot; + &quot;    \n&quot;.join(self.code)
+
+
+def temp(index):
+    return &quot;temp&quot; + str(index)
+
+
+def generateB3OpCode(index, op, params):
+    return &quot;Value* &quot; + temp(index) + &quot; = m_currentBlock-&gt;appendNew&lt;Value&gt;(m_proc, B3::&quot; + op + &quot;, Origin(), &quot; + &quot;, &quot;.join(params) + &quot;);&quot;
+
+
+def generateI32ConstCode(index, value):
+    return &quot;Value* &quot; + temp(index) + &quot; = m_currentBlock-&gt;appendIntConstant(m_proc, Origin(), B3::Int32, &quot; + value + &quot;);&quot;
+
+
+def generateB3Code(wasmOp, source):
+    tokens = lex(Source(source))
+    parser = CodeGenerator(tokens)
+    return parser.generate(wasmOp)
+
+
</ins><span class="cx"> def generateSimpleCode(op):
</span><span class="cx">     opcode = op[&quot;opcode&quot;]
</span><span class="cx">     b3op = opcode[&quot;b3op&quot;]
</span><span class="cx">     args = [&quot;ExpressionType arg&quot; + str(param) for param in range(len(opcode[&quot;parameter&quot;]))]
</span><span class="cx">     args.append(&quot;ExpressionType&amp; result&quot;)
</span><del>-    params = [&quot;arg&quot; + str(param) for param in range(len(opcode[&quot;parameter&quot;]))]
</del><span class="cx">     return &quot;&quot;&quot;
</span><span class="cx"> template&lt;&gt; bool B3IRGenerator::addOp&lt;OpType::&quot;&quot;&quot; + wasm.toCpp(op[&quot;name&quot;]) + &quot;&gt;(&quot; + &quot;, &quot;.join(args) + &quot;&quot;&quot;)
</span><span class="cx"> {
</span><del>-    result = m_currentBlock-&gt;appendNew&lt;Value&gt;(m_proc, B3::&quot;&quot;&quot; + opcode[&quot;b3op&quot;] + &quot;, Origin(), &quot; + &quot;, &quot;.join(params) + &quot;&quot;&quot;);
</del><ins>+&quot;&quot;&quot; + generateB3Code(opcode, b3op) + &quot;&quot;&quot;;
</ins><span class="cx">     return true;
</span><span class="cx"> }
</span><span class="cx"> &quot;&quot;&quot;
</span><span class="cx"> 
</span><ins>+
</ins><span class="cx"> definitions = [generateSimpleCode(op) for op in wasm.opcodeIterator(lambda op: isSimple(op) and (isBinary(op) or isUnary(op)))]
</span><span class="cx"> contents = wasm.header + &quot;&quot;&quot;
</span><span class="cx"> 
</span></span></pre></div>
<a id="trunkSourceJavaScriptCorewasmwasmjson"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/wasm/wasm.json (209082 => 209083)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/wasm/wasm.json        2016-11-29 19:20:08 UTC (rev 209082)
+++ trunk/Source/JavaScriptCore/wasm/wasm.json        2016-11-29 19:37:00 UTC (rev 209083)
</span><span class="lines">@@ -120,7 +120,7 @@
</span><span class="cx">         &quot;i32.clz&quot;:             { &quot;category&quot;: &quot;arithmetic&quot;, &quot;value&quot;:  87, &quot;return&quot;: [&quot;i32&quot;],      &quot;parameter&quot;: [&quot;i32&quot;],                  &quot;immediate&quot;: [], &quot;b3op&quot;: &quot;Clz&quot;          },
</span><span class="cx">         &quot;i32.ctz&quot;:             { &quot;category&quot;: &quot;arithmetic&quot;, &quot;value&quot;:  88, &quot;return&quot;: [&quot;i32&quot;],      &quot;parameter&quot;: [&quot;i32&quot;],                  &quot;immediate&quot;: []                         },
</span><span class="cx">         &quot;i32.popcnt&quot;:          { &quot;category&quot;: &quot;arithmetic&quot;, &quot;value&quot;:  89, &quot;return&quot;: [&quot;i32&quot;],      &quot;parameter&quot;: [&quot;i32&quot;],                  &quot;immediate&quot;: []                         },
</span><del>-        &quot;i32.eqz&quot;:             { &quot;category&quot;: &quot;comparison&quot;, &quot;value&quot;:  90, &quot;return&quot;: [&quot;bool&quot;],     &quot;parameter&quot;: [&quot;i32&quot;],                  &quot;immediate&quot;: []                         },
</del><ins>+        &quot;i32.eqz&quot;:             { &quot;category&quot;: &quot;comparison&quot;, &quot;value&quot;:  90, &quot;return&quot;: [&quot;bool&quot;],     &quot;parameter&quot;: [&quot;i32&quot;],                  &quot;immediate&quot;: [], &quot;b3op&quot;: &quot;Equal(i32(0), @0)&quot; },
</ins><span class="cx">         &quot;i64.add&quot;:             { &quot;category&quot;: &quot;arithmetic&quot;, &quot;value&quot;:  91, &quot;return&quot;: [&quot;i64&quot;],      &quot;parameter&quot;: [&quot;i64&quot;, &quot;i64&quot;],           &quot;immediate&quot;: [], &quot;b3op&quot;: &quot;Add&quot;          },
</span><span class="cx">         &quot;i64.sub&quot;:             { &quot;category&quot;: &quot;arithmetic&quot;, &quot;value&quot;:  92, &quot;return&quot;: [&quot;i64&quot;],      &quot;parameter&quot;: [&quot;i64&quot;, &quot;i64&quot;],           &quot;immediate&quot;: [], &quot;b3op&quot;: &quot;Sub&quot;          },
</span><span class="cx">         &quot;i64.mul&quot;:             { &quot;category&quot;: &quot;arithmetic&quot;, &quot;value&quot;:  93, &quot;return&quot;: [&quot;i64&quot;],      &quot;parameter&quot;: [&quot;i64&quot;, &quot;i64&quot;],           &quot;immediate&quot;: [], &quot;b3op&quot;: &quot;Mul&quot;          },
</span><span class="lines">@@ -149,15 +149,15 @@
</span><span class="cx">         &quot;i64.clz&quot;:             { &quot;category&quot;: &quot;arithmetic&quot;, &quot;value&quot;: 114, &quot;return&quot;: [&quot;i64&quot;],      &quot;parameter&quot;: [&quot;i64&quot;],                  &quot;immediate&quot;: [], &quot;b3op&quot;: &quot;Clz&quot;          },
</span><span class="cx">         &quot;i64.ctz&quot;:             { &quot;category&quot;: &quot;arithmetic&quot;, &quot;value&quot;: 115, &quot;return&quot;: [&quot;i64&quot;],      &quot;parameter&quot;: [&quot;i64&quot;],                  &quot;immediate&quot;: []                         },
</span><span class="cx">         &quot;i64.popcnt&quot;:          { &quot;category&quot;: &quot;arithmetic&quot;, &quot;value&quot;: 116, &quot;return&quot;: [&quot;i64&quot;],      &quot;parameter&quot;: [&quot;i64&quot;],                  &quot;immediate&quot;: []                         },
</span><del>-        &quot;i64.eqz&quot;:             { &quot;category&quot;: &quot;comparison&quot;, &quot;value&quot;: 186, &quot;return&quot;: [&quot;bool&quot;],     &quot;parameter&quot;: [&quot;i64&quot;],                  &quot;immediate&quot;: []                         },
</del><ins>+        &quot;i64.eqz&quot;:             { &quot;category&quot;: &quot;comparison&quot;, &quot;value&quot;: 186, &quot;return&quot;: [&quot;bool&quot;],     &quot;parameter&quot;: [&quot;i64&quot;],                  &quot;immediate&quot;: [], &quot;b3op&quot;: &quot;Equal(i32(0), @0)&quot; },
</ins><span class="cx">         &quot;f32.add&quot;:             { &quot;category&quot;: &quot;arithmetic&quot;, &quot;value&quot;: 117, &quot;return&quot;: [&quot;f32&quot;],      &quot;parameter&quot;: [&quot;f32&quot;, &quot;f32&quot;],           &quot;immediate&quot;: [], &quot;b3op&quot;: &quot;Add&quot;          },
</span><span class="cx">         &quot;f32.sub&quot;:             { &quot;category&quot;: &quot;arithmetic&quot;, &quot;value&quot;: 118, &quot;return&quot;: [&quot;f32&quot;],      &quot;parameter&quot;: [&quot;f32&quot;, &quot;f32&quot;],           &quot;immediate&quot;: [], &quot;b3op&quot;: &quot;Sub&quot;          },
</span><span class="cx">         &quot;f32.mul&quot;:             { &quot;category&quot;: &quot;arithmetic&quot;, &quot;value&quot;: 119, &quot;return&quot;: [&quot;f32&quot;],      &quot;parameter&quot;: [&quot;f32&quot;, &quot;f32&quot;],           &quot;immediate&quot;: [], &quot;b3op&quot;: &quot;Mul&quot;          },
</span><span class="cx">         &quot;f32.div&quot;:             { &quot;category&quot;: &quot;arithmetic&quot;, &quot;value&quot;: 120, &quot;return&quot;: [&quot;f32&quot;],      &quot;parameter&quot;: [&quot;f32&quot;, &quot;f32&quot;],           &quot;immediate&quot;: [], &quot;b3op&quot;: &quot;Div&quot;          },
</span><del>-        &quot;f32.min&quot;:             { &quot;category&quot;: &quot;arithmetic&quot;, &quot;value&quot;: 121, &quot;return&quot;: [&quot;f32&quot;],      &quot;parameter&quot;: [&quot;f32&quot;, &quot;f32&quot;],           &quot;immediate&quot;: []                         },
-        &quot;f32.max&quot;:             { &quot;category&quot;: &quot;arithmetic&quot;, &quot;value&quot;: 122, &quot;return&quot;: [&quot;f32&quot;],      &quot;parameter&quot;: [&quot;f32&quot;, &quot;f32&quot;],           &quot;immediate&quot;: []                         },
</del><ins>+        &quot;f32.min&quot;:             { &quot;category&quot;: &quot;arithmetic&quot;, &quot;value&quot;: 121, &quot;return&quot;: [&quot;f32&quot;],      &quot;parameter&quot;: [&quot;f32&quot;, &quot;f32&quot;],           &quot;immediate&quot;: [], &quot;b3op&quot;: &quot;Select(LessThan(@0, @1), @0, @1)&quot; },
+        &quot;f32.max&quot;:             { &quot;category&quot;: &quot;arithmetic&quot;, &quot;value&quot;: 122, &quot;return&quot;: [&quot;f32&quot;],      &quot;parameter&quot;: [&quot;f32&quot;, &quot;f32&quot;],           &quot;immediate&quot;: [], &quot;b3op&quot;: &quot;Select(LessThan(@0, @1), @1, @0)&quot; },
</ins><span class="cx">         &quot;f32.abs&quot;:             { &quot;category&quot;: &quot;arithmetic&quot;, &quot;value&quot;: 123, &quot;return&quot;: [&quot;f32&quot;],      &quot;parameter&quot;: [&quot;f32&quot;],                  &quot;immediate&quot;: [], &quot;b3op&quot;: &quot;Abs&quot;          },
</span><del>-        &quot;f32.neg&quot;:             { &quot;category&quot;: &quot;arithmetic&quot;, &quot;value&quot;: 124, &quot;return&quot;: [&quot;f32&quot;],      &quot;parameter&quot;: [&quot;f32&quot;],                  &quot;immediate&quot;: []                         },
</del><ins>+        &quot;f32.neg&quot;:             { &quot;category&quot;: &quot;arithmetic&quot;, &quot;value&quot;: 124, &quot;return&quot;: [&quot;f32&quot;],      &quot;parameter&quot;: [&quot;f32&quot;],                  &quot;immediate&quot;: [], &quot;b3op&quot;: &quot;Neg&quot;          },
</ins><span class="cx">         &quot;f32.copysign&quot;:        { &quot;category&quot;: &quot;arithmetic&quot;, &quot;value&quot;: 125, &quot;return&quot;: [&quot;f32&quot;],      &quot;parameter&quot;: [&quot;f32&quot;],                  &quot;immediate&quot;: []                         },
</span><span class="cx">         &quot;f32.ceil&quot;:            { &quot;category&quot;: &quot;arithmetic&quot;, &quot;value&quot;: 126, &quot;return&quot;: [&quot;f32&quot;],      &quot;parameter&quot;: [&quot;f32&quot;],                  &quot;immediate&quot;: [], &quot;b3op&quot;: &quot;Ceil&quot;         },
</span><span class="cx">         &quot;f32.floor&quot;:           { &quot;category&quot;: &quot;arithmetic&quot;, &quot;value&quot;: 127, &quot;return&quot;: [&quot;f32&quot;],      &quot;parameter&quot;: [&quot;f32&quot;],                  &quot;immediate&quot;: [], &quot;b3op&quot;: &quot;Floor&quot;        },
</span><span class="lines">@@ -174,10 +174,10 @@
</span><span class="cx">         &quot;f64.sub&quot;:             { &quot;category&quot;: &quot;arithmetic&quot;, &quot;value&quot;: 138, &quot;return&quot;: [&quot;f64&quot;],      &quot;parameter&quot;: [&quot;f64&quot;, &quot;f64&quot;],           &quot;immediate&quot;: [], &quot;b3op&quot;: &quot;Sub&quot;          },
</span><span class="cx">         &quot;f64.mul&quot;:             { &quot;category&quot;: &quot;arithmetic&quot;, &quot;value&quot;: 139, &quot;return&quot;: [&quot;f64&quot;],      &quot;parameter&quot;: [&quot;f64&quot;, &quot;f64&quot;],           &quot;immediate&quot;: [], &quot;b3op&quot;: &quot;Mul&quot;          },
</span><span class="cx">         &quot;f64.div&quot;:             { &quot;category&quot;: &quot;arithmetic&quot;, &quot;value&quot;: 140, &quot;return&quot;: [&quot;f64&quot;],      &quot;parameter&quot;: [&quot;f64&quot;, &quot;f64&quot;],           &quot;immediate&quot;: [], &quot;b3op&quot;: &quot;Div&quot;          },
</span><del>-        &quot;f64.min&quot;:             { &quot;category&quot;: &quot;arithmetic&quot;, &quot;value&quot;: 141, &quot;return&quot;: [&quot;f64&quot;],      &quot;parameter&quot;: [&quot;f64&quot;, &quot;f64&quot;],           &quot;immediate&quot;: []                         },
-        &quot;f64.max&quot;:             { &quot;category&quot;: &quot;arithmetic&quot;, &quot;value&quot;: 142, &quot;return&quot;: [&quot;f64&quot;],      &quot;parameter&quot;: [&quot;f64&quot;, &quot;f64&quot;],           &quot;immediate&quot;: []                         },
</del><ins>+        &quot;f64.min&quot;:             { &quot;category&quot;: &quot;arithmetic&quot;, &quot;value&quot;: 141, &quot;return&quot;: [&quot;f64&quot;],      &quot;parameter&quot;: [&quot;f64&quot;, &quot;f64&quot;],           &quot;immediate&quot;: [], &quot;b3op&quot;: &quot;Select(LessThan(@0, @1), @0, @1)&quot; },
+        &quot;f64.max&quot;:             { &quot;category&quot;: &quot;arithmetic&quot;, &quot;value&quot;: 142, &quot;return&quot;: [&quot;f64&quot;],      &quot;parameter&quot;: [&quot;f64&quot;, &quot;f64&quot;],           &quot;immediate&quot;: [], &quot;b3op&quot;: &quot;Select(LessThan(@0, @1), @1, @0)&quot; },
</ins><span class="cx">         &quot;f64.abs&quot;:             { &quot;category&quot;: &quot;arithmetic&quot;, &quot;value&quot;: 143, &quot;return&quot;: [&quot;f64&quot;],      &quot;parameter&quot;: [&quot;f64&quot;],                  &quot;immediate&quot;: [], &quot;b3op&quot;: &quot;Abs&quot;          },
</span><del>-        &quot;f64.neg&quot;:             { &quot;category&quot;: &quot;arithmetic&quot;, &quot;value&quot;: 144, &quot;return&quot;: [&quot;f64&quot;],      &quot;parameter&quot;: [&quot;f64&quot;],                  &quot;immediate&quot;: []                         },
</del><ins>+        &quot;f64.neg&quot;:             { &quot;category&quot;: &quot;arithmetic&quot;, &quot;value&quot;: 144, &quot;return&quot;: [&quot;f64&quot;],      &quot;parameter&quot;: [&quot;f64&quot;],                  &quot;immediate&quot;: [], &quot;b3op&quot;: &quot;Neg&quot;          },
</ins><span class="cx">         &quot;f64.copysign&quot;:        { &quot;category&quot;: &quot;arithmetic&quot;, &quot;value&quot;: 145, &quot;return&quot;: [&quot;f64&quot;],      &quot;parameter&quot;: [&quot;f64&quot;],                  &quot;immediate&quot;: []                         },
</span><span class="cx">         &quot;f64.ceil&quot;:            { &quot;category&quot;: &quot;arithmetic&quot;, &quot;value&quot;: 146, &quot;return&quot;: [&quot;f64&quot;],      &quot;parameter&quot;: [&quot;f64&quot;],                  &quot;immediate&quot;: [], &quot;b3op&quot;: &quot;Ceil&quot;         },
</span><span class="cx">         &quot;f64.floor&quot;:           { &quot;category&quot;: &quot;arithmetic&quot;, &quot;value&quot;: 147, &quot;return&quot;: [&quot;f64&quot;],      &quot;parameter&quot;: [&quot;f64&quot;],                  &quot;immediate&quot;: [], &quot;b3op&quot;: &quot;Floor&quot;        },
</span></span></pre>
</div>
</div>

</body>
</html>