From 22ee095773b6fe13ea6251e10f7424774804922d Mon Sep 17 00:00:00 2001 From: Shaikh Ubaid Date: Mon, 20 Feb 2023 19:47:52 +0530 Subject: [PATCH 1/5] Support LFortran WASI Fix import object --- components/LoadLFortran.js | 33 +++++++++++++++++---------------- 1 file changed, 17 insertions(+), 16 deletions(-) diff --git a/components/LoadLFortran.js b/components/LoadLFortran.js index 1973529..32abb7a 100644 --- a/components/LoadLFortran.js +++ b/components/LoadLFortran.js @@ -42,14 +42,18 @@ function getLfortranExportedFuncs() { } function define_imports(memory, outputBuffer, exit_code, stdout_print) { - const printNum = (num) => outputBuffer.push(num.toString()); - const printStr = (startIdx, strSize) => outputBuffer.push( - new TextDecoder("utf8").decode(new Uint8Array(memory.buffer, startIdx, strSize))); const flushBuffer = () => { - stdout_print(outputBuffer.join(" ") + "\n"); + stdout_print(outputBuffer.join("")); outputBuffer.length = 0; } - const set_exit_code = (exit_code_val) => exit_code.val = exit_code_val; + const fd_write = (file_type, iov_location, no_of_iovs, return_val_mem_loc) => { + const mem_data = new DataView(memory.buffer, iov_location, Int32Array.BYTES_PER_ELEMENT * 2); + const strLoc = mem_data.getInt32(0, true); + const strLen = mem_data.getInt32(4, true); + const s = new TextDecoder("utf8").decode(new Uint8Array(memory.buffer, strLoc, strLen)); + outputBuffer.push(s); + } + const proc_exit = (exit_code_val) => exit_code.val = exit_code_val; const cpu_time = (time) => (Date.now() / 1000); // Date.now() returns milliseconds, so divide by 1000 const show_image = (cols, rows, arr) => { var arr2D_data = new DataView(memory.buffer, arr, Int32Array.BYTES_PER_ELEMENT * rows * cols); @@ -65,7 +69,7 @@ function define_imports(memory, outputBuffer, exit_code, stdout_print) { imgData.data[i + 3] = 255; // alpha channel (from 0-255), 0 is transparent and 255 is fully visible } ctx.putImageData(imgData, 0, 0); - outputBuffer.push(`constructed image`) + outputBuffer.push(`constructed image\n`) flushBuffer(); } const show_image_color = (cols, rows, arr) => { @@ -83,20 +87,17 @@ function define_imports(memory, outputBuffer, exit_code, stdout_print) { imgData.data[i] = arr2D_data.getInt32(4*i, true); } ctx.putImageData(imgData, 0, 0); - outputBuffer.push(`constructed image`) + outputBuffer.push(`constructed image\n`) flushBuffer(); } var imports = { + wasi_snapshot_preview1: { + /* wasi functions */ + fd_write: fd_write, + proc_exit: proc_exit, + }, js: { - memory: memory, - /* functions */ - print_i32: printNum, - print_i64: printNum, - print_f32: printNum, - print_f64: printNum, - print_str: printStr, - flush_buf: flushBuffer, - set_exit_code: set_exit_code, + /* custom functions */ cpu_time: cpu_time, show_img: show_image, show_img_color: show_image_color From e55981858cfb095bc7ff7e6c91be139fb5e386fe Mon Sep 17 00:00:00 2001 From: Shaikh Ubaid Date: Mon, 20 Feb 2023 20:32:38 +0530 Subject: [PATCH 2/5] Always print the collected output (even if the code failed during execution) --- components/LoadLFortran.js | 5 +++-- pages/index.js | 4 +--- 2 files changed, 4 insertions(+), 5 deletions(-) diff --git a/components/LoadLFortran.js b/components/LoadLFortran.js index 32abb7a..2df71bd 100644 --- a/components/LoadLFortran.js +++ b/components/LoadLFortran.js @@ -161,11 +161,12 @@ async function setup_lfortran_funcs(lfortran_funcs, myPrint) { var memory = new WebAssembly.Memory({ initial: 100, maximum: 100 }); // fixed 6.4 Mb memory currently var imports = define_imports(memory, outputBuffer, exit_code, stdout_print); var err_msg = await run_wasm(bytes, imports); + stdout_print(outputBuffer.join("")); if (exit_code.val == 0) { - return 1; + return; } console.log(err_msg); - myPrint(err_msg + "\nERROR: The code could not be executed. Either there is a runtime error or there is an issue at our end."); + stdout_print(`\n${err_msg}\nERROR: The code could not be executed. Either there is a runtime error or there is an issue at our end.`); return 0; }; } diff --git a/pages/index.js b/pages/index.js index 9855f27..6acae47 100644 --- a/pages/index.js +++ b/pages/index.js @@ -67,9 +67,7 @@ export default function Home() { new Uint8Array(compile_result), (text) => stdout.push(text) ); - if (exec_res) { - setOutput(stdout.join("")); - } + setOutput(stdout.join("")); } } } else if (key == "AST") { From 4d78999f18095d8157e5d343a437dc2877cb113a Mon Sep 17 00:00:00 2001 From: Shaikh Ubaid Date: Mon, 20 Feb 2023 20:50:52 +0530 Subject: [PATCH 3/5] Fix Memory: Use exported memory --- components/LoadLFortran.js | 34 +++++++++++++++------------------- 1 file changed, 15 insertions(+), 19 deletions(-) diff --git a/components/LoadLFortran.js b/components/LoadLFortran.js index 2df71bd..0724fb3 100644 --- a/components/LoadLFortran.js +++ b/components/LoadLFortran.js @@ -41,7 +41,8 @@ function getLfortranExportedFuncs() { }); } -function define_imports(memory, outputBuffer, exit_code, stdout_print) { +var memory; +function define_imports(outputBuffer, exit_code, stdout_print) { const flushBuffer = () => { stdout_print(outputBuffer.join("")); outputBuffer.length = 0; @@ -106,15 +107,6 @@ function define_imports(memory, outputBuffer, exit_code, stdout_print) { return imports; } -async function run_wasm(bytes, imports) { - try { - var res = await WebAssembly.instantiate(bytes, imports); - const { _lcompilers_main } = res.instance.exports; - _lcompilers_main(); - } catch(e) { return e; } - return "Success" -} - async function setup_lfortran_funcs(lfortran_funcs, myPrint) { const compiler_funcs = await getLfortranExportedFuncs(); @@ -158,16 +150,20 @@ async function setup_lfortran_funcs(lfortran_funcs, myPrint) { lfortran_funcs.execute_code = async function (bytes, stdout_print) { var exit_code = {val: 1}; /* non-zero exit code */ var outputBuffer = []; - var memory = new WebAssembly.Memory({ initial: 100, maximum: 100 }); // fixed 6.4 Mb memory currently - var imports = define_imports(memory, outputBuffer, exit_code, stdout_print); - var err_msg = await run_wasm(bytes, imports); - stdout_print(outputBuffer.join("")); - if (exit_code.val == 0) { - return; + var imports = define_imports(outputBuffer, exit_code, stdout_print); + try { + var res = await WebAssembly.instantiate(bytes, imports); + memory = res.instance.exports.memory; + res.instance.exports._start(); + stdout_print(outputBuffer.join("")); + } catch(err_msg) { + stdout_print(outputBuffer.join("")); + if (exit_code.val == 0) { + return; + } + console.log(err_msg); + stdout_print(`\n${err_msg}\nERROR: The code could not be executed. Either there is a runtime error or there is an issue at our end.`); } - console.log(err_msg); - stdout_print(`\n${err_msg}\nERROR: The code could not be executed. Either there is a runtime error or there is an issue at our end.`); - return 0; }; } From e44c831668169b0f58c869cf7824368de0681aa5 Mon Sep 17 00:00:00 2001 From: Shaikh Ubaid Date: Mon, 20 Feb 2023 23:34:26 +0530 Subject: [PATCH 4/5] Fix return value for define_imports() --- components/LoadLFortran.js | 1 + 1 file changed, 1 insertion(+) diff --git a/components/LoadLFortran.js b/components/LoadLFortran.js index 0724fb3..7bed1ad 100644 --- a/components/LoadLFortran.js +++ b/components/LoadLFortran.js @@ -53,6 +53,7 @@ function define_imports(outputBuffer, exit_code, stdout_print) { const strLen = mem_data.getInt32(4, true); const s = new TextDecoder("utf8").decode(new Uint8Array(memory.buffer, strLoc, strLen)); outputBuffer.push(s); + return 0; } const proc_exit = (exit_code_val) => exit_code.val = exit_code_val; const cpu_time = (time) => (Date.now() / 1000); // Date.now() returns milliseconds, so divide by 1000 From d3dea2eab4c27526b79b7efae5d38e738ceebae4 Mon Sep 17 00:00:00 2001 From: Shaikh Ubaid Date: Tue, 21 Feb 2023 22:28:36 +0530 Subject: [PATCH 5/5] Update lfortran version This uses the latest lfortran where the wasm backend supports/utilizes wasi functions --- build.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/build.sh b/build.sh index 078e782..cda2056 100755 --- a/build.sh +++ b/build.sh @@ -5,7 +5,7 @@ set -ex # curl https://lfortran.github.io/wasm_builds/data.json -o data.json #latest_commit=`curl https://lfortran.github.io/wasm_builds/dev/latest_commit` # Set a specific commit to use: -latest_commit="df33df422" +latest_commit="c969e0bc3" curl "https://lfortran.github.io/wasm_builds/dev/$latest_commit/lfortran.js" -o public/lfortran.js curl "https://lfortran.github.io/wasm_builds/dev/$latest_commit/lfortran.wasm" -o public/lfortran.wasm curl "https://lfortran.github.io/wasm_builds/dev/$latest_commit/lfortran.data" -o public/lfortran.data