runtime.js 4.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154
  1. class WasmMemoryInterface {
  2. constructor() {
  3. this.memory = null;
  4. }
  5. setMemory(memory) {
  6. this.memory = memory;
  7. }
  8. get mem() {
  9. return new DataView(this.memory.buffer);
  10. }
  11. loadF32Array(addr, len) {
  12. let array = new Float32Array(this.memory.buffer, addr, len);
  13. return array;
  14. }
  15. loadU32Array(addr, len) {
  16. let array = new Uint32Array(this.memory.buffer, addr, len);
  17. return array;
  18. }
  19. loadI32Array(addr, len) {
  20. let array = new Int32Array(this.memory.buffer, addr, len);
  21. return array;
  22. }
  23. loadU8(addr) { return this.mem.getUint8 (addr, true); }
  24. loadI8(addr) { return this.mem.getInt8 (addr, true); }
  25. loadU16(addr) { return this.mem.getUint16 (addr, true); }
  26. loadI16(addr) { return this.mem.getInt16 (addr, true); }
  27. loadU32(addr) { return this.mem.getUint32 (addr, true); }
  28. loadI32(addr) { return this.mem.getInt32 (addr, true); }
  29. loadU64(addr) {
  30. const lo = this.mem.getUint32(addr + 0, true);
  31. const hi = this.mem.getUint32(addr + 4, true);
  32. return lo + hi*4294967296;
  33. };
  34. loadI64(addr) {
  35. // TODO(bill): loadI64 correctly
  36. const lo = this.mem.getUint32(addr + 0, true);
  37. const hi = this.mem.getUint32(addr + 4, true);
  38. return lo + hi*4294967296;
  39. };
  40. loadF32(addr) { return this.mem.getFloat32(addr, true); }
  41. loadF64(addr) { return this.mem.getFloat64(addr, true); }
  42. loadInt(addr) { return this.mem.getInt32 (addr, true); }
  43. loadUint(addr) { return this.mem.getUint32 (addr, true); }
  44. loadPtr(addr) { return this.loadUint(addr); }
  45. loadBytes(ptr, len) {
  46. return new Uint8Array(this.memory.buffer, ptr, len);
  47. }
  48. loadString(ptr, len) {
  49. const bytes = this.loadBytes(ptr, len);
  50. return new TextDecoder("utf-8").decode(bytes);
  51. }
  52. storeU8(addr, value) { this.mem.setUint8 (addr, value, true); }
  53. storeI8(addr, value) { this.mem.setInt8 (addr, value, true); }
  54. storeU16(addr, value) { this.mem.setUint16 (addr, value, true); }
  55. storeI16(addr, value) { this.mem.setInt16 (addr, value, true); }
  56. storeU32(addr, value) { this.mem.setUint32 (addr, value, true); }
  57. storeI32(addr, value) { this.mem.setInt32 (addr, value, true); }
  58. storeU64(addr, value) {
  59. this.mem.setUint32(addr + 0, value, true);
  60. this.mem.setUint32(addr + 4, Math.floor(value / 4294967296), true);
  61. }
  62. storeI64(addr, value) {
  63. // TODO(bill): storeI64 correctly
  64. this.mem.setUint32(addr + 0, value, true);
  65. this.mem.setUint32(addr + 4, Math.floor(value / 4294967296), true);
  66. }
  67. storeF32(addr, value) { this.mem.setFloat32(addr, value, true); }
  68. storeF64(addr, value) { this.mem.setFloat64(addr, value, true); }
  69. storeInt(addr, value) { this.mem.setInt32 (addr, value, true); }
  70. storeUint(addr, value) { this.mem.setUint32 (addr, value, true); }
  71. };
  72. function odinSetupDefaultImports(wasmMemoryInterface, consoleElement) {
  73. const MAX_INFO_CONSOLE_LINES = 512;
  74. let infoConsoleLines = new Array();
  75. const addConsoleLine = (line) => {
  76. if (line === undefined) {
  77. return;
  78. }
  79. if (line.endsWith("\n")) {
  80. line = line.substring(0, line.length-1);
  81. } else if (infoConsoleLines.length > 0) {
  82. let prev_line = infoConsoleLines.pop();
  83. line = prev_line.concat(line);
  84. }
  85. infoConsoleLines.push(line);
  86. if (infoConsoleLines.length > MAX_INFO_CONSOLE_LINES) {
  87. infoConsoleLines.shift();
  88. }
  89. let data = "";
  90. for (let i = 0; i < infoConsoleLines.length; i++) {
  91. if (i != 0) {
  92. data = data.concat("\n");
  93. }
  94. data = data.concat(infoConsoleLines[i]);
  95. }
  96. if (consoleElement !== undefined) {
  97. let info = consoleElement;
  98. info.innerHTML = data;
  99. info.scrollTop = info.scrollHeight;
  100. }
  101. };
  102. return {
  103. "env": {},
  104. "odin_env": {
  105. write: (fd, ptr, len) => {
  106. const str = wasmMemoryInterface.loadString(ptr, len);
  107. if (fd == 1) {
  108. addConsoleLine(str);
  109. return;
  110. } else if (fd == 2) {
  111. addConsoleLine(str);
  112. return;
  113. } else {
  114. throw new Error("Invalid fd to 'write'" + stripNewline(str));
  115. }
  116. },
  117. trap: () => { throw new Error() },
  118. alert: (ptr, len) => { alert(wasmMemoryInterface.loadString(ptr, len)) },
  119. abort: () => { Module.abort() },
  120. evaluate: (str_ptr, str_len) => { eval.call(null, wasmMemoryInterface.loadString(str_ptr, str_len)); },
  121. time_now: () => {
  122. return performance.now() * 1e6;
  123. },
  124. sqrt: (x) => Math.sqrt(x),
  125. sin: (x) => Math.sin(x),
  126. cos: (x) => Math.cos(x),
  127. pow: (x) => Math.pow(x),
  128. fmuladd: (x, y, z) => x*y + z,
  129. ln: (x) => Math.log(x),
  130. exp: (x) => Math.exp(x),
  131. ldexp: (x) => Math.ldexp(x),
  132. },
  133. };
  134. }
  135. export {WasmMemoryInterface, odinSetupDefaultImports};