You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

899 lines
17 KiB

4 years ago
  1. function _typeof(obj) { if (typeof Symbol === "function" && typeof Symbol.iterator === "symbol") { _typeof = function _typeof(obj) { return typeof obj; }; } else { _typeof = function _typeof(obj) { return obj && typeof Symbol === "function" && obj.constructor === Symbol && obj !== Symbol.prototype ? "symbol" : typeof obj; }; } return _typeof(obj); }
  2. function _sliceIterator(arr, i) { var _arr = []; var _n = true; var _d = false; var _e = undefined; try { for (var _i = arr[Symbol.iterator](), _s; !(_n = (_s = _i.next()).done); _n = true) { _arr.push(_s.value); if (i && _arr.length === i) break; } } catch (err) { _d = true; _e = err; } finally { try { if (!_n && _i["return"] != null) _i["return"](); } finally { if (_d) throw _e; } } return _arr; }
  3. function _slicedToArray(arr, i) { if (Array.isArray(arr)) { return arr; } else if (Symbol.iterator in Object(arr)) { return _sliceIterator(arr, i); } else { throw new TypeError("Invalid attempt to destructure non-iterable instance"); } }
  4. import { isAnonymous, isInstruction } from "@webassemblyjs/ast";
  5. import Long from "@xtuc/long";
  6. var compact = false;
  7. var space = " ";
  8. var quote = function quote(str) {
  9. return "\"".concat(str, "\"");
  10. };
  11. function indent(nb) {
  12. return Array(nb).fill(space + space).join("");
  13. } // TODO(sven): allow arbitrary ast nodes
  14. export function print(n) {
  15. if (n.type === "Program") {
  16. return printProgram(n, 0);
  17. } else {
  18. throw new Error("Unsupported node in print of type: " + String(n.type));
  19. }
  20. }
  21. function printProgram(n, depth) {
  22. return n.body.reduce(function (acc, child) {
  23. if (child.type === "Module") {
  24. acc += printModule(child, depth + 1);
  25. }
  26. if (child.type === "Func") {
  27. acc += printFunc(child, depth + 1);
  28. }
  29. if (child.type === "BlockComment") {
  30. acc += printBlockComment(child);
  31. }
  32. if (child.type === "LeadingComment") {
  33. acc += printLeadingComment(child);
  34. }
  35. if (compact === false) {
  36. acc += "\n";
  37. }
  38. return acc;
  39. }, "");
  40. }
  41. function printTypeInstruction(n) {
  42. var out = "";
  43. out += "(";
  44. out += "type";
  45. out += space;
  46. if (n.id != null) {
  47. out += printIndex(n.id);
  48. out += space;
  49. }
  50. out += "(";
  51. out += "func";
  52. n.functype.params.forEach(function (param) {
  53. out += space;
  54. out += "(";
  55. out += "param";
  56. out += space;
  57. out += printFuncParam(param);
  58. out += ")";
  59. });
  60. n.functype.results.forEach(function (result) {
  61. out += space;
  62. out += "(";
  63. out += "result";
  64. out += space;
  65. out += result;
  66. out += ")";
  67. });
  68. out += ")"; // func
  69. out += ")";
  70. return out;
  71. }
  72. function printModule(n, depth) {
  73. var out = "(";
  74. out += "module";
  75. if (typeof n.id === "string") {
  76. out += space;
  77. out += n.id;
  78. }
  79. if (compact === false) {
  80. out += "\n";
  81. } else {
  82. out += space;
  83. }
  84. n.fields.forEach(function (field) {
  85. if (compact === false) {
  86. out += indent(depth);
  87. }
  88. switch (field.type) {
  89. case "Func":
  90. {
  91. out += printFunc(field, depth + 1);
  92. break;
  93. }
  94. case "TypeInstruction":
  95. {
  96. out += printTypeInstruction(field);
  97. break;
  98. }
  99. case "Table":
  100. {
  101. out += printTable(field);
  102. break;
  103. }
  104. case "Global":
  105. {
  106. out += printGlobal(field, depth + 1);
  107. break;
  108. }
  109. case "ModuleExport":
  110. {
  111. out += printModuleExport(field);
  112. break;
  113. }
  114. case "ModuleImport":
  115. {
  116. out += printModuleImport(field);
  117. break;
  118. }
  119. case "Memory":
  120. {
  121. out += printMemory(field);
  122. break;
  123. }
  124. case "BlockComment":
  125. {
  126. out += printBlockComment(field);
  127. break;
  128. }
  129. case "LeadingComment":
  130. {
  131. out += printLeadingComment(field);
  132. break;
  133. }
  134. case "Start":
  135. {
  136. out += printStart(field);
  137. break;
  138. }
  139. case "Elem":
  140. {
  141. out += printElem(field, depth);
  142. break;
  143. }
  144. case "Data":
  145. {
  146. out += printData(field, depth);
  147. break;
  148. }
  149. default:
  150. throw new Error("Unsupported node in printModule: " + String(field.type));
  151. }
  152. if (compact === false) {
  153. out += "\n";
  154. }
  155. });
  156. out += ")";
  157. return out;
  158. }
  159. function printData(n, depth) {
  160. var out = "";
  161. out += "(";
  162. out += "data";
  163. out += space;
  164. out += printIndex(n.memoryIndex);
  165. out += space;
  166. out += printInstruction(n.offset, depth);
  167. out += space;
  168. out += '"';
  169. n.init.values.forEach(function (byte) {
  170. // Avoid non-displayable characters
  171. if (byte <= 31 || byte == 34 || byte == 92 || byte >= 127) {
  172. out += "\\";
  173. out += ("00" + byte.toString(16)).substr(-2);
  174. } else if (byte > 255) {
  175. throw new Error("Unsupported byte in data segment: " + byte);
  176. } else {
  177. out += String.fromCharCode(byte);
  178. }
  179. });
  180. out += '"';
  181. out += ")";
  182. return out;
  183. }
  184. function printElem(n, depth) {
  185. var out = "";
  186. out += "(";
  187. out += "elem";
  188. out += space;
  189. out += printIndex(n.table);
  190. var _n$offset = _slicedToArray(n.offset, 1),
  191. firstOffset = _n$offset[0];
  192. out += space;
  193. out += "(";
  194. out += "offset";
  195. out += space;
  196. out += printInstruction(firstOffset, depth);
  197. out += ")";
  198. n.funcs.forEach(function (func) {
  199. out += space;
  200. out += printIndex(func);
  201. });
  202. out += ")";
  203. return out;
  204. }
  205. function printStart(n) {
  206. var out = "";
  207. out += "(";
  208. out += "start";
  209. out += space;
  210. out += printIndex(n.index);
  211. out += ")";
  212. return out;
  213. }
  214. function printLeadingComment(n) {
  215. // Don't print leading comments in compact mode
  216. if (compact === true) {
  217. return "";
  218. }
  219. var out = "";
  220. out += ";;";
  221. out += n.value;
  222. out += "\n";
  223. return out;
  224. }
  225. function printBlockComment(n) {
  226. // Don't print block comments in compact mode
  227. if (compact === true) {
  228. return "";
  229. }
  230. var out = "";
  231. out += "(;";
  232. out += n.value;
  233. out += ";)";
  234. out += "\n";
  235. return out;
  236. }
  237. function printSignature(n) {
  238. var out = "";
  239. n.params.forEach(function (param) {
  240. out += space;
  241. out += "(";
  242. out += "param";
  243. out += space;
  244. out += printFuncParam(param);
  245. out += ")";
  246. });
  247. n.results.forEach(function (result) {
  248. out += space;
  249. out += "(";
  250. out += "result";
  251. out += space;
  252. out += result;
  253. out += ")";
  254. });
  255. return out;
  256. }
  257. function printModuleImportDescr(n) {
  258. var out = "";
  259. if (n.type === "FuncImportDescr") {
  260. out += "(";
  261. out += "func";
  262. if (isAnonymous(n.id) === false) {
  263. out += space;
  264. out += printIdentifier(n.id);
  265. }
  266. out += printSignature(n.signature);
  267. out += ")";
  268. }
  269. if (n.type === "GlobalType") {
  270. out += "(";
  271. out += "global";
  272. out += space;
  273. out += printGlobalType(n);
  274. out += ")";
  275. }
  276. if (n.type === "Table") {
  277. out += printTable(n);
  278. }
  279. return out;
  280. }
  281. function printModuleImport(n) {
  282. var out = "";
  283. out += "(";
  284. out += "import";
  285. out += space;
  286. out += quote(n.module);
  287. out += space;
  288. out += quote(n.name);
  289. out += space;
  290. out += printModuleImportDescr(n.descr);
  291. out += ")";
  292. return out;
  293. }
  294. function printGlobalType(n) {
  295. var out = "";
  296. if (n.mutability === "var") {
  297. out += "(";
  298. out += "mut";
  299. out += space;
  300. out += n.valtype;
  301. out += ")";
  302. } else {
  303. out += n.valtype;
  304. }
  305. return out;
  306. }
  307. function printGlobal(n, depth) {
  308. var out = "";
  309. out += "(";
  310. out += "global";
  311. out += space;
  312. if (n.name != null && isAnonymous(n.name) === false) {
  313. out += printIdentifier(n.name);
  314. out += space;
  315. }
  316. out += printGlobalType(n.globalType);
  317. out += space;
  318. n.init.forEach(function (i) {
  319. out += printInstruction(i, depth + 1);
  320. });
  321. out += ")";
  322. return out;
  323. }
  324. function printTable(n) {
  325. var out = "";
  326. out += "(";
  327. out += "table";
  328. out += space;
  329. if (n.name != null && isAnonymous(n.name) === false) {
  330. out += printIdentifier(n.name);
  331. out += space;
  332. }
  333. out += printLimit(n.limits);
  334. out += space;
  335. out += n.elementType;
  336. out += ")";
  337. return out;
  338. }
  339. function printFuncParam(n) {
  340. var out = "";
  341. if (typeof n.id === "string") {
  342. out += "$" + n.id;
  343. out += space;
  344. }
  345. out += n.valtype;
  346. return out;
  347. }
  348. function printFunc(n, depth) {
  349. var out = "";
  350. out += "(";
  351. out += "func";
  352. if (n.name != null) {
  353. if (n.name.type === "Identifier" && isAnonymous(n.name) === false) {
  354. out += space;
  355. out += printIdentifier(n.name);
  356. }
  357. }
  358. if (n.signature.type === "Signature") {
  359. out += printSignature(n.signature);
  360. } else {
  361. var index = n.signature;
  362. out += space;
  363. out += "(";
  364. out += "type";
  365. out += space;
  366. out += printIndex(index);
  367. out += ")";
  368. }
  369. if (n.body.length > 0) {
  370. // func is empty since we ignore the default end instruction
  371. if (n.body.length === 1 && n.body[0].id === "end") {
  372. out += ")";
  373. return out;
  374. }
  375. if (compact === false) {
  376. out += "\n";
  377. }
  378. n.body.forEach(function (i) {
  379. if (i.id !== "end") {
  380. out += indent(depth);
  381. out += printInstruction(i, depth);
  382. if (compact === false) {
  383. out += "\n";
  384. }
  385. }
  386. });
  387. out += indent(depth - 1) + ")";
  388. } else {
  389. out += ")";
  390. }
  391. return out;
  392. }
  393. function printInstruction(n, depth) {
  394. switch (n.type) {
  395. case "Instr":
  396. // $FlowIgnore
  397. return printGenericInstruction(n, depth + 1);
  398. case "BlockInstruction":
  399. // $FlowIgnore
  400. return printBlockInstruction(n, depth + 1);
  401. case "IfInstruction":
  402. // $FlowIgnore
  403. return printIfInstruction(n, depth + 1);
  404. case "CallInstruction":
  405. // $FlowIgnore
  406. return printCallInstruction(n, depth + 1);
  407. case "CallIndirectInstruction":
  408. // $FlowIgnore
  409. return printCallIndirectIntruction(n, depth + 1);
  410. case "LoopInstruction":
  411. // $FlowIgnore
  412. return printLoopInstruction(n, depth + 1);
  413. default:
  414. throw new Error("Unsupported instruction: " + JSON.stringify(n.type));
  415. }
  416. }
  417. function printCallIndirectIntruction(n, depth) {
  418. var out = "";
  419. out += "(";
  420. out += "call_indirect";
  421. if (n.signature.type === "Signature") {
  422. out += printSignature(n.signature);
  423. } else if (n.signature.type === "Identifier") {
  424. out += space;
  425. out += "(";
  426. out += "type";
  427. out += space;
  428. out += printIdentifier(n.signature);
  429. out += ")";
  430. } else {
  431. throw new Error("CallIndirectInstruction: unsupported signature " + JSON.stringify(n.signature.type));
  432. }
  433. out += space;
  434. if (n.intrs != null) {
  435. // $FlowIgnore
  436. n.intrs.forEach(function (i, index) {
  437. // $FlowIgnore
  438. out += printInstruction(i, depth + 1); // $FlowIgnore
  439. if (index !== n.intrs.length - 1) {
  440. out += space;
  441. }
  442. });
  443. }
  444. out += ")";
  445. return out;
  446. }
  447. function printLoopInstruction(n, depth) {
  448. var out = "";
  449. out += "(";
  450. out += "loop";
  451. if (n.label != null && isAnonymous(n.label) === false) {
  452. out += space;
  453. out += printIdentifier(n.label);
  454. }
  455. if (typeof n.resulttype === "string") {
  456. out += space;
  457. out += "(";
  458. out += "result";
  459. out += space;
  460. out += n.resulttype;
  461. out += ")";
  462. }
  463. if (n.instr.length > 0) {
  464. n.instr.forEach(function (e) {
  465. if (compact === false) {
  466. out += "\n";
  467. }
  468. out += indent(depth);
  469. out += printInstruction(e, depth + 1);
  470. });
  471. if (compact === false) {
  472. out += "\n";
  473. out += indent(depth - 1);
  474. }
  475. }
  476. out += ")";
  477. return out;
  478. }
  479. function printCallInstruction(n, depth) {
  480. var out = "";
  481. out += "(";
  482. out += "call";
  483. out += space;
  484. out += printIndex(n.index);
  485. if (_typeof(n.instrArgs) === "object") {
  486. // $FlowIgnore
  487. n.instrArgs.forEach(function (arg) {
  488. out += space;
  489. out += printFuncInstructionArg(arg, depth + 1);
  490. });
  491. }
  492. out += ")";
  493. return out;
  494. }
  495. function printIfInstruction(n, depth) {
  496. var out = "";
  497. out += "(";
  498. out += "if";
  499. if (n.testLabel != null && isAnonymous(n.testLabel) === false) {
  500. out += space;
  501. out += printIdentifier(n.testLabel);
  502. }
  503. if (typeof n.result === "string") {
  504. out += space;
  505. out += "(";
  506. out += "result";
  507. out += space;
  508. out += n.result;
  509. out += ")";
  510. }
  511. if (n.test.length > 0) {
  512. out += space;
  513. n.test.forEach(function (i) {
  514. out += printInstruction(i, depth + 1);
  515. });
  516. }
  517. if (n.consequent.length > 0) {
  518. if (compact === false) {
  519. out += "\n";
  520. }
  521. out += indent(depth);
  522. out += "(";
  523. out += "then";
  524. depth++;
  525. n.consequent.forEach(function (i) {
  526. if (compact === false) {
  527. out += "\n";
  528. }
  529. out += indent(depth);
  530. out += printInstruction(i, depth + 1);
  531. });
  532. depth--;
  533. if (compact === false) {
  534. out += "\n";
  535. out += indent(depth);
  536. }
  537. out += ")";
  538. } else {
  539. if (compact === false) {
  540. out += "\n";
  541. out += indent(depth);
  542. }
  543. out += "(";
  544. out += "then";
  545. out += ")";
  546. }
  547. if (n.alternate.length > 0) {
  548. if (compact === false) {
  549. out += "\n";
  550. }
  551. out += indent(depth);
  552. out += "(";
  553. out += "else";
  554. depth++;
  555. n.alternate.forEach(function (i) {
  556. if (compact === false) {
  557. out += "\n";
  558. }
  559. out += indent(depth);
  560. out += printInstruction(i, depth + 1);
  561. });
  562. depth--;
  563. if (compact === false) {
  564. out += "\n";
  565. out += indent(depth);
  566. }
  567. out += ")";
  568. } else {
  569. if (compact === false) {
  570. out += "\n";
  571. out += indent(depth);
  572. }
  573. out += "(";
  574. out += "else";
  575. out += ")";
  576. }
  577. if (compact === false) {
  578. out += "\n";
  579. out += indent(depth - 1);
  580. }
  581. out += ")";
  582. return out;
  583. }
  584. function printBlockInstruction(n, depth) {
  585. var out = "";
  586. out += "(";
  587. out += "block";
  588. if (n.label != null && isAnonymous(n.label) === false) {
  589. out += space;
  590. out += printIdentifier(n.label);
  591. }
  592. if (typeof n.result === "string") {
  593. out += space;
  594. out += "(";
  595. out += "result";
  596. out += space;
  597. out += n.result;
  598. out += ")";
  599. }
  600. if (n.instr.length > 0) {
  601. n.instr.forEach(function (i) {
  602. if (compact === false) {
  603. out += "\n";
  604. }
  605. out += indent(depth);
  606. out += printInstruction(i, depth + 1);
  607. });
  608. if (compact === false) {
  609. out += "\n";
  610. }
  611. out += indent(depth - 1);
  612. out += ")";
  613. } else {
  614. out += ")";
  615. }
  616. return out;
  617. }
  618. function printGenericInstruction(n, depth) {
  619. var out = "";
  620. out += "(";
  621. if (typeof n.object === "string") {
  622. out += n.object;
  623. out += ".";
  624. }
  625. out += n.id;
  626. n.args.forEach(function (arg) {
  627. out += space;
  628. out += printFuncInstructionArg(arg, depth + 1);
  629. });
  630. out += ")";
  631. return out;
  632. }
  633. function printLongNumberLiteral(n) {
  634. if (typeof n.raw === "string") {
  635. return n.raw;
  636. }
  637. var _n$value = n.value,
  638. low = _n$value.low,
  639. high = _n$value.high;
  640. var v = new Long(low, high);
  641. return v.toString();
  642. }
  643. function printFloatLiteral(n) {
  644. if (typeof n.raw === "string") {
  645. return n.raw;
  646. }
  647. return String(n.value);
  648. }
  649. function printFuncInstructionArg(n, depth) {
  650. var out = "";
  651. if (n.type === "NumberLiteral") {
  652. out += printNumberLiteral(n);
  653. }
  654. if (n.type === "LongNumberLiteral") {
  655. out += printLongNumberLiteral(n);
  656. }
  657. if (n.type === "Identifier" && isAnonymous(n) === false) {
  658. out += printIdentifier(n);
  659. }
  660. if (n.type === "ValtypeLiteral") {
  661. out += n.name;
  662. }
  663. if (n.type === "FloatLiteral") {
  664. out += printFloatLiteral(n);
  665. }
  666. if (isInstruction(n)) {
  667. out += printInstruction(n, depth + 1);
  668. }
  669. return out;
  670. }
  671. function printNumberLiteral(n) {
  672. if (typeof n.raw === "string") {
  673. return n.raw;
  674. }
  675. return String(n.value);
  676. }
  677. function printModuleExport(n) {
  678. var out = "";
  679. out += "(";
  680. out += "export";
  681. out += space;
  682. out += quote(n.name);
  683. if (n.descr.exportType === "Func") {
  684. out += space;
  685. out += "(";
  686. out += "func";
  687. out += space;
  688. out += printIndex(n.descr.id);
  689. out += ")";
  690. } else if (n.descr.exportType === "Global") {
  691. out += space;
  692. out += "(";
  693. out += "global";
  694. out += space;
  695. out += printIndex(n.descr.id);
  696. out += ")";
  697. } else if (n.descr.exportType === "Memory" || n.descr.exportType === "Mem") {
  698. out += space;
  699. out += "(";
  700. out += "memory";
  701. out += space;
  702. out += printIndex(n.descr.id);
  703. out += ")";
  704. } else if (n.descr.exportType === "Table") {
  705. out += space;
  706. out += "(";
  707. out += "table";
  708. out += space;
  709. out += printIndex(n.descr.id);
  710. out += ")";
  711. } else {
  712. throw new Error("printModuleExport: unknown type: " + n.descr.exportType);
  713. }
  714. out += ")";
  715. return out;
  716. }
  717. function printIdentifier(n) {
  718. return "$" + n.value;
  719. }
  720. function printIndex(n) {
  721. if (n.type === "Identifier") {
  722. return printIdentifier(n);
  723. } else if (n.type === "NumberLiteral") {
  724. return printNumberLiteral(n);
  725. } else {
  726. throw new Error("Unsupported index: " + n.type);
  727. }
  728. }
  729. function printMemory(n) {
  730. var out = "";
  731. out += "(";
  732. out += "memory";
  733. if (n.id != null) {
  734. out += space;
  735. out += printIndex(n.id);
  736. out += space;
  737. }
  738. out += printLimit(n.limits);
  739. out += ")";
  740. return out;
  741. }
  742. function printLimit(n) {
  743. var out = "";
  744. out += n.min + "";
  745. if (n.max != null) {
  746. out += space;
  747. out += String(n.max);
  748. }
  749. return out;
  750. }