unsigned.js 8.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325
  1. //-------------------------------------------------------------------------------------------------------
  2. // Copyright (C) Microsoft Corporation and contributors. All rights reserved.
  3. // Licensed under the MIT license. See LICENSE.txt file in the project root for full license information.
  4. //-------------------------------------------------------------------------------------------------------
  5. WScript.Flag("-wasmI64");
  6. const cliArgs = WScript.Arguments || [];
  7. if (cliArgs.indexOf("--help") !== -1) {
  8. print("usage: ch unsigned.js -args [start index] [end index] [-verbose] -endargs");
  9. WScript.quit(0);
  10. }
  11. // Parse arguments
  12. let verbose = 0;
  13. while (true) {
  14. const iVerbose = cliArgs.indexOf("-verbose");
  15. if (iVerbose === -1) {
  16. break;
  17. }
  18. cliArgs.splice(iVerbose, 1);
  19. ++verbose;
  20. }
  21. const start = cliArgs[0]|0;
  22. const end = cliArgs[1] === undefined ? undefined : cliArgs[1]|0;
  23. const moduleStart = cliArgs[2] === undefined ? undefined : cliArgs[2]|0;
  24. const moduleEnd = cliArgs[3] === undefined ? undefined : cliArgs[3]|0;
  25. const signatures = {
  26. I_II: ["i32", "i32", "i32"],
  27. I_LL: ["i32", "i64", "i64"],
  28. L_LL: ["i64", "i64", "i64"],
  29. };
  30. const ops = [
  31. {
  32. unsigned: "i32.lt_u",
  33. signed: "i32.lt_s",
  34. sig: signatures.I_II,
  35. },
  36. {
  37. unsigned: "i32.gt_u",
  38. signed: "i32.gt_s",
  39. sig: signatures.I_II,
  40. },
  41. {
  42. unsigned: "i32.le_u",
  43. signed: "i32.le_s",
  44. sig: signatures.I_II,
  45. },
  46. {
  47. unsigned: "i32.ge_u",
  48. signed: "i32.ge_s",
  49. sig: signatures.I_II,
  50. },
  51. {
  52. unsigned: "i64.lt_u",
  53. signed: "i64.lt_s",
  54. sig: signatures.I_LL,
  55. },
  56. {
  57. unsigned: "i64.gt_u",
  58. signed: "i64.gt_s",
  59. sig: signatures.I_LL,
  60. },
  61. {
  62. unsigned: "i64.le_u",
  63. signed: "i64.le_s",
  64. sig: signatures.I_LL,
  65. },
  66. {
  67. unsigned: "i64.ge_u",
  68. signed: "i64.ge_s",
  69. sig: signatures.I_LL,
  70. },
  71. {
  72. unsigned: "i32.div_u",
  73. signed: "i32.div_s",
  74. sig: signatures.I_II,
  75. },
  76. {
  77. unsigned: "i32.rem_u",
  78. signed: "i32.rem_s",
  79. sig: signatures.I_II,
  80. },
  81. {
  82. unsigned: "i32.shr_u",
  83. signed: "i32.shr_s",
  84. sig: signatures.I_II,
  85. },
  86. {
  87. unsigned: "i64.div_u",
  88. signed: "i64.div_s",
  89. sig: signatures.L_LL,
  90. },
  91. {
  92. unsigned: "i64.rem_u",
  93. signed: "i64.rem_s",
  94. sig: signatures.L_LL,
  95. },
  96. {
  97. unsigned: "i64.shr_u",
  98. signed: "i64.shr_s",
  99. sig: signatures.L_LL,
  100. },
  101. {
  102. unsigned: "i32.trunc_u/f32",
  103. signed: "i32.trunc_s/f32",
  104. sig: ["i32", "f32"],
  105. },
  106. {
  107. unsigned: "i32.trunc_u/f64",
  108. signed: "i32.trunc_s/f64",
  109. sig: ["i32", "f64"],
  110. },
  111. {
  112. unsigned: "i64.extend_u/i32",
  113. signed: "i64.extend_s/i32",
  114. sig: ["i64", "i32"],
  115. },
  116. {
  117. unsigned: "i64.trunc_u/f32",
  118. signed: "i64.trunc_s/f32",
  119. sig: ["i64", "f32"],
  120. },
  121. {
  122. unsigned: "i64.trunc_u/f64",
  123. signed: "i64.trunc_s/f64",
  124. sig: ["i64", "f64"],
  125. },
  126. {
  127. unsigned: "f32.convert_u/i32",
  128. signed: "f32.convert_s/i32",
  129. sig: ["f32", "i32"],
  130. },
  131. {
  132. unsigned: "f32.convert_u/i64",
  133. signed: "f32.convert_s/i64",
  134. sig: ["f32", "i64"],
  135. },
  136. {
  137. unsigned: "f64.convert_u/i32",
  138. signed: "f64.convert_s/i32",
  139. sig: ["f64", "i32"],
  140. },
  141. {
  142. unsigned: "f64.convert_u/i64",
  143. signed: "f64.convert_s/i64",
  144. sig: ["f64", "i64"],
  145. },
  146. ];
  147. const allValues = {
  148. i32: [0, 1, -1, 0x80000000, 0xCCCCCCCC],
  149. f32: [0, 1, -1, -Math.PI, Math.E]
  150. };
  151. allValues.i64 = allValues.i32.concat("0x8000000000000000", "0xCCCCCCCCCCCCCCCC");
  152. allValues.f64 = allValues.f32;
  153. let moduleId = 1;
  154. let scriptId = 1;
  155. function generateTest({unsigned, signed, sig}, hardCoded) {
  156. const [retType, ...argTypes] = sig;
  157. let nparam = 0;
  158. let callArgs = "";
  159. let params = "";
  160. const getParam = (type) => {
  161. const getLocal = `(get_local ${nparam++})`;
  162. callArgs += getLocal;
  163. params = (params || "(param ") + type + " ";
  164. return getLocal;
  165. };
  166. const args = (hardCoded
  167. ? hardCoded.map((val, i) => {
  168. if (val === null) {
  169. return getParam(argTypes[i]);
  170. }
  171. return `(${argTypes[i]}.const ${val.toString()})`;
  172. })
  173. : argTypes.map(getParam)
  174. ).join(" ");
  175. if (params.length > 0) params += ")";
  176. const funcSig = `${params} (result ${retType})`;
  177. const unsignedOp = `(${unsigned} ${args})`;
  178. const signedOp = `(${signed} ${args})`;
  179. return (
  180. ` ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  181. ;; Functions to test operator ${unsigned}
  182. ;; Range ${scriptId}.0-${scriptId}.7
  183. (func $${unsigned} ${funcSig} ${unsignedOp})
  184. (func $${signed} ${funcSig} ${signedOp})
  185. (func $${unsigned}-${signed} ${funcSig}
  186. (${retType}.add ${unsignedOp} ${signedOp})
  187. )
  188. (func $${signed}-${unsigned} ${funcSig}
  189. (${retType}.add ${signedOp} ${unsignedOp})
  190. )
  191. (func $${unsigned}-${unsigned} ${funcSig}
  192. (${retType}.add ${unsignedOp} ${unsignedOp})
  193. )
  194. (func $${signed}-${signed} ${funcSig}
  195. (${retType}.add ${signedOp} ${signedOp})
  196. )
  197. (func (export "test") ${params} (result i32)
  198. (${retType}.sub
  199. (call $${unsigned}-${signed} ${callArgs})
  200. (call $${signed}-${unsigned} ${callArgs})
  201. )
  202. (${retType}.ne (${retType}.const 0))
  203. (br_if 0 (i32.const 1)) (drop)
  204. ${[[unsigned, signed], [signed, unsigned], [unsigned, unsigned], [signed, signed]]
  205. .map(([o1, o2], i) => `
  206. (${retType}.ne
  207. (call $${o1}-${o2} ${callArgs})
  208. (${retType}.add (call $${o1} ${callArgs}) (call $${o2} ${callArgs}))
  209. )
  210. (br_if 0 (i32.const ${i + 2})) (drop)
  211. `).join("")}
  212. (i32.const 0)
  213. )`);
  214. }
  215. function generateModule(op, hardCoded) {
  216. const moduleTxt = `(module
  217. ${generateTest(op, hardCoded)}
  218. )`;
  219. ++moduleId;
  220. ++scriptId;
  221. if (verbose > 1) {
  222. print(moduleTxt);
  223. }
  224. const mod = new WebAssembly.Module(WebAssembly.wabt.convertWast2Wasm(moduleTxt));
  225. const {exports} = new WebAssembly.Instance(mod);
  226. return exports.test;
  227. }
  228. function shouldSkipModule() {
  229. if (moduleId < moduleStart || moduleId > moduleEnd) {
  230. ++moduleId;
  231. return true;
  232. }
  233. return false;
  234. }
  235. function run(op, testFn, ...args) {
  236. try {
  237. const res = testFn(...args);
  238. if (res !== 0) {
  239. print(`Error for operator ${op}(${args.join(" ")}): ${res}`);
  240. }
  241. } catch (e) {
  242. const str = e.toString().toLowerCase();
  243. if (!str.includes("overflow") && !str.includes("division by zero")) {
  244. print(`Unexpected error: ${e}`);
  245. }
  246. }
  247. }
  248. for (let i = 0; i < ops.length; ++i) {
  249. if (i < start || i > end) {
  250. continue;
  251. }
  252. const {unsigned, sig} = ops[i];
  253. const [ret, ...argTypes] = sig;
  254. let values = argTypes.map(t => allValues[t]);
  255. if (values.length === 1) {
  256. values = values[0].map(v => [v]);
  257. } else {
  258. const [a1, a2] = values;
  259. values = [];
  260. for (const v1 of a1) {
  261. for (const v2 of a2) {
  262. values.push([v1, v2]);
  263. }
  264. }
  265. }
  266. let paramFn, paramModuleId;
  267. if (!shouldSkipModule()) {
  268. paramModuleId = moduleId;
  269. if (verbose) {
  270. print(`${i}: Running arguments tests for ${unsigned}. Module #${paramModuleId}`);
  271. }
  272. paramFn = generateModule(ops[i]);
  273. }
  274. for (const arg of values) {
  275. // Default test
  276. if (paramFn) {
  277. if (verbose) {
  278. print(`${i}: Running arguments tests for ${unsigned}(${arg.join(", ")}). Module #${paramModuleId}`);
  279. }
  280. run(unsigned, paramFn, ...arg);
  281. }
  282. // Test with all hardcoded values
  283. if (!shouldSkipModule()) {
  284. if (verbose) {
  285. print(`${i}: Running hard coded constant tests for ${unsigned}(${arg.join(", ")}). Module #${moduleId}`);
  286. }
  287. const hardCodedFn = generateModule(ops[i], arg);
  288. run(unsigned, hardCodedFn);
  289. }
  290. if (arg.length === 2) {
  291. if (!shouldSkipModule()) {
  292. // Test with left hardcoded value
  293. const semiArg1 = [arg[0], null];
  294. if (verbose) {
  295. print(`${i}: Running left hard coded constant tests for ${unsigned}([${arg[0]}], ${arg[1]}). Module #${moduleId}`);
  296. }
  297. const hardCodedFn2 = generateModule(ops[i], semiArg1);
  298. run(unsigned, hardCodedFn2, arg[1]);
  299. }
  300. if (!shouldSkipModule()) {
  301. // Test with right hardcoded value
  302. const semiArg2 = [null, arg[1]];
  303. if (verbose) {
  304. print(`${i}: Running right hard coded constant tests for ${unsigned}(${arg[0]}, [${arg[1]}]). Module #${moduleId}`);
  305. }
  306. const hardCodedFn3 = generateModule(ops[i], semiArg2);
  307. run(unsigned, hardCodedFn3, arg[0]);
  308. }
  309. }
  310. }
  311. }
  312. print("pass");