Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

wasm2c example for Bytecode Alliance's Javy #2521

Closed
guest271314 opened this issue Dec 20, 2024 · 23 comments
Closed

wasm2c example for Bytecode Alliance's Javy #2521

guest271314 opened this issue Dec 20, 2024 · 23 comments

Comments

@guest271314
Copy link

Kindly include a wasm2c example where the input is a WASM produced by Bytecode Alliance's Javy. There's no roadmap for compiling C output by wasm2c to an executable where we need to include wasi_snapshot_preview1 in the process.

cc @shravanrn @sbc100 @keithw

@keithw
Copy link
Member

keithw commented Dec 30, 2024

wasm2c is basically agnostic to a Wasm module's imports and whether those imports come from the host or from another Wasm module. If you want to run a Wasm module that imports from the wasi_snapshot_preview1 namespace, you'll need an implementation of the WASI p1 API that comes from somewhere (probably from the host). wasm2c doesn't provide that (or any API) itself.

There was a PR started to contribute an implementation of WASI p1 for a POSIX host (#2002) but it looks like it hasn't been touched in a while.

@guest271314
Copy link
Author

I've been sitting on the .h and c. files produced by wasm2c for Javy produced WASM for a couple weeks now. I'll figure out that wasi_snaptshot_preview1 dependency, too.

I'm just trying to figure out how to create the main.c like you do for the Hello world example.

There's no roadmap.

@guest271314
Copy link
Author

This is what I'm doing in JavaScript

printf '4 5' | deno -A run-wasi.js
5 of 23 (0-indexed, factorial 24) => [0,3,2,1]
import { readFile } from "node:fs/promises";
import process from "node:process";
import { WASI } from "./wasi-minimal-min.js"; // https://gitlab.com/-/snippets/4782260/raw/main/wasi-minimal.js
import * as fs from "node:fs";
try {
  const [embeddedModule, pluginModule] = await Promise.all([
    compileModule("./nm_javy_permutations.wasm"),
    compileModule("./plugin.wasm"),
  ]);
  const result = await runJavy(embeddedModule, pluginModule);
} catch (e) {
  process.stdout.write(e.message, "utf8");
} finally {
  process.exit();
}
async function compileModule(wasmPath) {
  const bytes = await readFile(new URL(wasmPath, import.meta.url));
  return WebAssembly.compile(bytes);
}
async function runJavy(embeddedModule, pluginModule) {
  try {
    let wasi = new WASI({
      env: {},
      args: [],
      fds: [
        {
          type: 2,
          handle: fs,
        },
        {
          type: 2,
          handle: fs,
        },
        {
          type: 2,
          handle: fs,
        },
      ],
    });

    const pluginInstance = await WebAssembly.instantiate(
      pluginModule,
      { "wasi_snapshot_preview1": wasi.exports },
    );
    const instance = await WebAssembly.instantiate(embeddedModule, {
      "javy_quickjs_provider_v3": pluginInstance.exports,
    });

    wasi.memory = pluginInstance.exports.memory;
    instance.exports._start();
    return;
  } catch (e) {
    if (e instanceof WebAssembly.RuntimeError) {
      if (e) {
        throw new Error(e);
      }
    }
    throw e;
  }
}

Using wasmtime

echo '9 362879' |  wasmtime run --preload javy_quickjs_provider_v3=plugin.wasm nm_javy_permutations.wasm
362879 of 362879 (0-indexed, factorial 362880) => [8,7,6,5,4,3,2,1,0]

The code produced by wasm2c.
javy.tar.gz

@guest271314
Copy link
Author

Trying to create main.c blindly using the main from fac examples as template

#include <stdio.h>
#include <stdlib.h>

#include "javy-permutations.h"
#include "plugin.h"

int main(int argc, char** argv) {
  /* Make sure there is at least one command-line argument. */
  if (argc < 2) {
    printf("Invalid argument. Expected '%s NUMBER'\n", argv[0]);
    return 1;
  }

  /* Convert the argument from a string to an int. We'll implicitly cast the int
  to a `u32`, which is what `fac` expects. */
  // u32 x = atoi(argv[1]);

  /* Initialize the Wasm runtime. */
  wasm_rt_init();

  /* Declare an instance of the `fac` module. */
  w2c_array__nth__permutation array__nth__permutation;

  w2c_javy__quickjs__provider__v3 provider;

  /* Construct the module instance. */
  wasm2c_array__nth__permutation_instantiate(&array__nth__permutation, &provider);

  /* Call `fac`, using the mangled name. */
  // u32 result = w2c_fac_fac(&fac, x);

  /* Print the result. */
  // printf("fac(%u) -> %u\n", x, result);
  w2c_array__nth__permutation_0x5Fstart(array__nth__permutation*)
  /* Free the fac module. */
  w2c_w2c__javy__0x5Fquickjs__0x5Fprovider__0x5Fv3_canonical_abi_free(w2c_w2c__javy__0x5Fquickjs__0x5Fprovider__0x5Fv3*, u32, u32, u32);

  /* Free the Wasm runtime state. */
  wasm_rt_free();

  return 0;
}

@SoniEx2
Copy link
Collaborator

SoniEx2 commented Dec 30, 2024

hmm maybe we should add a wasm2c example for imports and exports...

@guest271314
Copy link
Author

There was a PR started to contribute an implementation of WASI p1 for a POSIX host (#2002) but it looks like it hasn't been touched in a while.

Yeah, I read that during my research. No clue why you folks have not merged that, yet.

I will say that uvwasi is what node:wasi depends on, and there's a big 'ole vague disclaimer on the Node.js wasi module re "sandbox" and preopens https://nodejs.org/api/wasi.html

The node:wasi module does not currently provide the comprehensive file system security properties provided by some WASI runtimes. Full support for secure file system sandboxing may or may not be implemented in future. In the mean time, do not rely on it to run untrusted code.

That's why I wrote https://gitlab.com/-/snippets/4782260/raw/main/wasi-minimal.js - without intending to access the filesystem using preopens. See node-wasi-preopens-escape

Proof of concept showcasing how a WASM program can access files outside node:wasi's preopens dir.

I'm trying to figure out how to create the main.c for WASM that includes WASI expectations. I started with the fac example described here https://github.com/WebAssembly/wabt/blob/main/wasm2c/README.md and completed that.

There's zero guidance on how to do that for WASM compiled with WASI-SDK that uses wasi_snapshot_preview1. There's enough Preview 1 source code floating around to fill that in, I think, that leaves how to write that main.c so that the C can be compiled to an executable.

@sbc100
Copy link
Member

sbc100 commented Dec 31, 2024

As @keithw already mentioned above, wasm2c (and wabt in general) are generic tools that work on all wasm files without prejudice as to which SDK to toolchain produces them.

If a wasm file has host imports (e.g. wasi_snapshot_preview1) then its up to the embedder (you) to provide those imports, either via something like uvwasi or by writing your own.

@guest271314
Copy link
Author

I can find a wasi_snapshot_preview1 to import. I think.

What I'm asking for here is a roadmap on how to create that main.c for such code.

The only examples you have do not happen to use WASI at all. https://github.com/WebAssembly/wabt/blob/main/wasm2c/README.md.

I managed to get the fac example compiled, and later compiled to JavaScript with wasm2js.

@keithw
Copy link
Member

keithw commented Dec 31, 2024

The rot13 example (and the bottom of the wasm2c README) shows how to instantiate a module that takes imports. Please see https://github.com/WebAssembly/wabt/tree/main/wasm2c/examples/rot13 -- does this help?

@guest271314
Copy link
Author

The rot13 example (and the bottom of the wasm2c README) shows how to instantiate a module that takes imports. Please see https://github.com/WebAssembly/wabt/tree/main/wasm2c/examples/rot13 -- does this help?

I read that, and all of your examples before I filed this issue. Kind of helps. But doesn't really provide a complete roadmap for WASM to C using WASI Preview 1. And you folks are already messing around with components and Preview 2.

So, let's say you compiled that fac.c example to WASM using WASI-SDK, associated work under the umbrella of WebAssembly. That would necessitate you using at least a bare bones WASI Preview 1 implementation - doesn't even have to have preopens or file system access. Then you'd have to create a main.c, like you do for the fac.c example. That's what I'm trying to spy on and use as a template.

@guest271314
Copy link
Author

But hey, if you folks ain't in to it, and don't see the lack of such an example as being an omission, there's nowhere else for me to go. Already tried w2c2. No luck. Already emailed folks who said ask here. I mean, y'll are the experts and gurus in this domain. Don't want to make it seem like I'm putting you out asking for an example of wasm2c using WASM projects; it's all under the WASM umbrella as I see it.

@guest271314
Copy link
Author

What Alan Watts said kind of always plays out, no matter the domain:

Anybody who goes to a guru ought to given 30 blows with a stick.

@sbc100
Copy link
Member

sbc100 commented Dec 31, 2024

Perhaps you could elaborate on the specific difficulties you have in implementing the wasi_snapshot_preview1 and hooking them up to the wasm2c generated code. If there are specific techniques (e.g. dealing with pointers or memory) that are not covered by the existing docs/examples then perhaps we would add to the docs/examples.

I agree that providing an example of using using wasi_snapshot_preview1 (likely via uvwasi) would be nice, but I don't think we want to be implementing our own versions of all those wasi APIs here.. that seems out-of-scope for wabt.

@guest271314
Copy link
Author

You have a complete example with the fac example. You went from WAT to WASM, I presume, to avoid dealing with WASI-SDK.

Anyway, I already used wasm2c to get the files I posted above. However, your wasm2c doesn't implement the main.c. Your README.md does that manually. There's no instructions for doing the same thing, that is, specifically, creating a main.c when WASI is involved.

What I'm basically doing is a full loop from JavaScript to C to WASM/native executable, back to JavaScript.

Here's original Javy source code back to JavaScript from WASM using wasm2js

// import * as javy_quickjs_provider_v3 from 'javy_quickjs_provider_v3';
// ./javy emit-plugin -o plugin.wasm
// ./javy build -C dynamic -C plugin=plugin.wasm -o javy-permutations.wasm permutations.js
// wasmtime run --preload javy_quickjs_provider_v3=plugin.wasm javy-permutations.wasm
// ./binaryen/bin/wasm2js javy-permutations.wasm --enable-bulk-memory -o javy-permutations.js

import { readFile } from "node:fs/promises";
import { WASI } from "node:wasi";

var bufferView;
var memorySegments = {};
var base64ReverseLookup = new Uint8Array(123 /*'z'+1*/);
for (var i = 25; i >= 0; --i) {
  base64ReverseLookup[48 + i] = 52 + i; // '0-9'
  base64ReverseLookup[65 + i] = i; // 'A-Z'
  base64ReverseLookup[97 + i] = 26 + i; // 'a-z'
}
base64ReverseLookup[43] = 62; // '+'
base64ReverseLookup[47] = 63; // '/'
/** @noinline Inlining this function would mean expanding the base64 string 4x times in the source code, which Closure seems to be happy to do. */
function base64DecodeToExistingUint8Array(uint8Array, offset, b64) {
  var b1,
    b2,
    i = 0,
    j = offset,
    bLength = b64.length,
    end = offset + (bLength * 3 >> 2) - (b64[bLength - 2] == "=") -
      (b64[bLength - 1] == "=");
  for (; i < bLength; i += 4) {
    b1 = base64ReverseLookup[b64.charCodeAt(i + 1)];
    b2 = base64ReverseLookup[b64.charCodeAt(i + 2)];
    uint8Array[j++] = base64ReverseLookup[b64.charCodeAt(i)] << 2 | b1 >> 4;
    if (j < end) uint8Array[j++] = b1 << 4 | b2 >> 2;
    if (j < end) {
      uint8Array[j++] = b2 << 6 | base64ReverseLookup[b64.charCodeAt(i + 3)];
    }
  }
  return uint8Array;
}
memorySegments[0] = base64DecodeToExistingUint8Array(
  new Uint8Array(620),
  0,
  "QxIYZnVuY3Rpb24ubWpzBmxleCphcnJheV9udGhfcGVybXV0YXRpb24OY29uc29sZQZsb2cCWwJdEnN0cmluZ2lmeQJhAm4CYgJ4BmxlbgZyZXMCaQJmCHB1c2gMc3BsaWNlDcgDAAAAAAAMIAYBpAEAAAAIAwFAALQBAAHKAwEBzAMCAQjsBcIA5Sm3uLm6uyYFAOO85DjnAAAAQugAAAAE6QAAAOCeBOoAAACeOKEAAABC6wAAAOHf4PIkAQAkAgAOBi7IAwEGASgwAAJGADUABxgDCgoKCgAFMQAAFAACEwAFEAAFCAAFDAACDAAGCgAFCgAFFAABLAABDgABOQABEwADMwxDBgHMAwIGAgYAAHgI2AMAAQDaAwABANwDAAAA3gMAAQDgAwACAOIDAAMA5AMABADmAwAFACYAAMu3zMjT66TsDMfIc9PIR0mUAe7w0+vNuMYExQXEBMml7AzEBcQEm8UFlATu8NS3p+xC1MQFpOw8JgAAzsm3puwzxAXJnMUF1NTEBZ2fxAWcxQTKQvQAAADHQvUAAADEBLgkAgC3RyQBAA7UxAWd2JMC7srKKMgDBRIDFysmFwADCjomGTsyIjt9HRkAnwEEAAAQAAQPAAAaDwABCAkABBoAAEEJAAIKCQADJgAEOQEAABQJAAIXAAAKAAAIAAAIHgACCgAEFAAAOQACCgAFJgAEMwAACAABCgAECgABCB4AACUAAAoAAAwABAgAAQwABBQAADkAAgoABAkAAAgDAAEIAAEIAAQKAAUjAAEIAAUKCQAFDg8AARMAAxoAAicABAcAAQoABCIABDMAAA4=",
);

function wasm2js_memory_init(segment, dest, offset, size) {
  // TODO: traps on invalid things
  bufferView.set(memorySegments[segment].subarray(offset, offset + size), dest);
}

function asmFunc(imports) {
  var javy_quickjs_provider_v3 = imports.javy_quickjs_provider_v3;
  var memory = javy_quickjs_provider_v3.memory;
  var buffer = memory.buffer;
  memory.grow = __wasm_memory_grow;
  var HEAP8 = new Int8Array(buffer);
  var HEAP16 = new Int16Array(buffer);
  var HEAP32 = new Int32Array(buffer);
  var HEAPU8 = new Uint8Array(buffer);
  var HEAPU16 = new Uint16Array(buffer);
  var HEAPU32 = new Uint32Array(buffer);
  var HEAPF32 = new Float32Array(buffer);
  var HEAPF64 = new Float64Array(buffer);
  var Math_imul = Math.imul;
  var Math_fround = Math.fround;
  var Math_abs = Math.abs;
  var Math_clz32 = Math.clz32;
  var Math_min = Math.min;
  var Math_max = Math.max;
  var Math_floor = Math.floor;
  var Math_ceil = Math.ceil;
  var Math_trunc = Math.trunc;
  var Math_sqrt = Math.sqrt;
  console.log(javy_quickjs_provider_v3);
  var fimport$0 = javy_quickjs_provider_v3.canonical_abi_realloc;
  var fimport$1 = javy_quickjs_provider_v3.invoke;
  function $0() {
    var $0_1 = 0;
    $0_1 = fimport$0(0 | 0, 0 | 0, 1 | 0, 620 | 0) | 0;
    wasm2js_memory_init(0, $0_1, 0, 620);
    fimport$1($0_1 | 0, 620 | 0, 0 | 0, 0 | 0);
  }

  bufferView = HEAPU8;
  function __wasm_memory_size() {
    return buffer.byteLength / 65536 | 0;
  }

  function __wasm_memory_grow(pagesToAdd) {
    pagesToAdd = pagesToAdd | 0;
    var oldPages = __wasm_memory_size() | 0;
    var newPages = oldPages + pagesToAdd | 0;
    if ((oldPages < newPages) && (newPages < 65536)) {
      var newBuffer = new ArrayBuffer(Math_imul(newPages, 65536));
      var newHEAP8 = new Int8Array(newBuffer);
      newHEAP8.set(HEAP8);
      HEAP8 = new Int8Array(newBuffer);
      HEAP16 = new Int16Array(newBuffer);
      HEAP32 = new Int32Array(newBuffer);
      HEAPU8 = new Uint8Array(newBuffer);
      HEAPU16 = new Uint16Array(newBuffer);
      HEAPU32 = new Uint32Array(newBuffer);
      HEAPF32 = new Float32Array(newBuffer);
      HEAPF64 = new Float64Array(newBuffer);
      buffer = newBuffer;
      memory.buffer = buffer;
      bufferView = HEAPU8;
    }
    return oldPages;
  }

  return {
    "_start": $0,
  };
}

var memasmFunc = new ArrayBuffer(0);

const pluginBytes = await readFile(new URL("./plugin.wasm", import.meta.url));
const pluginModule = await WebAssembly.compile(pluginBytes);
/*
const snapshotBytes = await readFile(new URL("./wasi_snapshot_preview1.reactor.wasm", import.meta.url));
const snapshot = await WebAssembly.compile(snapshotBytes);
*/
const wasi = new WASI({
  version: "preview1",
  returnOnExit: true,
});

console.log(wasi.wasiImport);

const pluginInstance = await WebAssembly.instantiate(
  pluginModule,
  { "wasi_snapshot_preview1": wasi.wasiImport },
);

wasi.initialize(pluginInstance);

var retasmFunc = asmFunc({
  "javy_quickjs_provider_v3": {
    memory: { buffer: memasmFunc },
    ...pluginInstance.exports,
  },
});

export var _start = retasmFunc._start;
_start();

Now, I can compile JavaScript to C with QuickJS qjsc or Facebook's Static Hermes. Hermes just implemented compiling using WASI-SDK instead of Emscripten, however, when I tried, things failed facebook/hermes#1588 (reply in thread).

So, what's my motivation?

Well, in research compiling JavaScript to C I found that there's no FOSS code that can do that. I found a random Web site that says it uses "artificial intelligence" to convert JavaScript to C, and actually does a rather good job.

That's difficult for me to accept. There has to be a way to convert JavaScript to C - and back, and branch to WASM and/or native executable in the middle if desired - without slapping a "artificial intelligence" label on the gear, and gating the gear behind IPR labels and such - an unobservable box.

So, I'm looking into the WebAssembly world because I know there's wabt's wasm2c and Binaryen's wasm2js.

Emscripten doesn't really compile to WASM standalone, that I can see. It's expecting JavaScript to be the caller.

WASI-SDK works. WASI is a thing. So that's how I wound up here.

Assume I don't know C at all. No clue about how to construct that main.c for code in C that imports WASI preview.

What's the roadmap?

@guest271314
Copy link
Author

Perhaps you could elaborate on the specific difficulties you have in implementing the wasi_snapshot_preview1 and hooking them up to the wasm2c generated code.

Assume you have a generic wasi_snapshot_preview1 implemented in C already on hand.

Assume you compile that fac.c example to WASM in WASI with WASI-SDK.

What I'm basically asking here is how you arrange the necessary code in a generic main.c, given you already have the fac.c and fac.h produced by wasm2c.

Just write out which function calls what in C. A generic example in C code that will result in an executable when compiled with gcc or clang. You can even name the example "theoretical example compiling WASI to executable from wasm2c output" or something like that.

Again, write the README.md like the individual doesn't know C.

@SoniEx2
Copy link
Collaborator

SoniEx2 commented Dec 31, 2024

we don't believe such a thing is possible - wasm2c has a specialized API due to being a specialized wasm runtime, it's not gonna be easily compatible with an arbitrary WASI implementation.

@sbc100
Copy link
Member

sbc100 commented Dec 31, 2024

I'm afraid that if you don't know C at all then its going to be hard for your successfully create the required embedding code that is needed (e.g. main.c). What you are looking for (IIUC) is some kind of off-the-shelf solution for wiring up wasm2c output with an existing host API (in this case the WASI API), but AFAIK that doesn't exist.

Wiring up wasm2c-generated code to an existing host APIs is fairly tricky because the wasm2c-generated code uses pointers from its own internal address space whereas the host APIs using expects/uses real host pointers. Any time you have pointers at the boundary (very common in wasi_snapshot_preview1) you would need to some kind of data marshaling/copying. The upshot of this is that what you are asking for is fairly non-trivial and involves a pretty deep understanding of C.

We can leave this issue open as a feature request if you like, but its not something that exists today.

@guest271314
Copy link
Author

we don't believe such a thing is possible - wasm2c has a specialized API due to being a specialized wasm runtime, it's not gonna be easily compatible with an arbitrary WASI implementation.

Um, every wasi_snapshot_preview1 I've looked at in the past month basically all have the same functions.

I'm afraid that if you don't know C at all then its going to be hard for your successfully create the required embedding code that is needed (e.g. main.c). What you are looking for (IIUC) is some kind of off-the-shelf solution for wiring up wasm2c output with an existing host API (in this case the WASI API), but AFAIK that doesn't exist.

I already did that and you already have that with the fac example.

I didn't know C, C++, Rust, Python, Bash, WebAssembly, and multiple JavaScript engines and runtimes either. I still managed to write a Native Messaging host for each https://github.com/guest271314/NativeMessagingHosts.

I'm saying the lack of a WASI example is an omission. You're the experts. Make it so No. 1.

I don't think you need to do much here.

Just take the main.c example for the fac example and slap in the WASI parts

#include <stdio.h>
#include <stdlib.h>

#include "fac.h"

int main(int argc, char** argv) {
  /* Make sure there is at least one command-line argument. */
  if (argc < 2) {
    printf("Invalid argument. Expected '%s NUMBER'\n", argv[0]);
    return 1;
  }

  /* Convert the argument from a string to an int. We'll implicitly cast the int
  to a `u32`, which is what `fac` expects. */
  u32 x = atoi(argv[1]);

  /* Initialize the Wasm runtime. */
  wasm_rt_init();

  /* Declare an instance of the `fac` module. */
  w2c_fac fac;

  /* Construct the module instance. */
  wasm2c_fac_instantiate(&fac);

  /* Call `fac`, using the mangled name. */
  u32 result = w2c_fac_fac(&fac, x);

  /* Print the result. */
  printf("fac(%u) -> %u\n", x, result);

  /* Free the fac module. */
  wasm2c_fac_free(&fac);

  /* Free the Wasm runtime state. */
  wasm_rt_free();

  return 0;
}

@guest271314
Copy link
Author

I know what I'm asking for doesn't exist now.

Yeah, leavin' it open as a feature request works, too.

I'm most highly motivated to answer my own questions. If you folks on here or somebody else in the wild doesn't get here first, for other people to test and improve if necessary.

Thanks for your time. Carry on. But keep this one in mind.

@guest271314
Copy link
Author

If you want to run a Wasm module that imports from the wasi_snapshot_preview1 namespace, you'll need an implementation of the WASI p1 API that comes from somewhere (probably from the host). wasm2c doesn't provide that (or any API) itself.

If a wasm file has host imports (e.g. wasi_snapshot_preview1) then its up to the embedder (you) to provide those imports, either via something like uvwasi or by writing your own.

Doesn't WASI support shipped in LLVM? https://github.com/tmikov/hermes/tree/shermes-wasm/external/llvh/lib/Support/Wasi.

@shravanrn
Copy link
Collaborator

The repo has an example of using wasi (uvwasi) under the benchmarks
https://github.com/WebAssembly/wabt/blob/main/wasm2c/benchmarks/dhrystone/main.c

Doesn't WASI support shipped in LLVM

LLVM supports the WASI interface, so you can compile Wasm modules that rely on WASI. What is being discussed above is a WASI implementation, which is different.

At some point, I may add an easy-to-use optional adapter for uvwasi, but I am unlikely to get to this for a while.

Closing this bug, because an example already exists.

@guest271314
Copy link
Author

@shravanrn Thanks.

At some point, I may add an easy-to-use optional adapter for uvwasi, but I am unlikely to get to this for a while.

That would be helpful.

I started exploring WebAssembly because I remembered something somebody wrote a while ago about the goal being a "universal executable".

I asked the Javy folks about a wasm2c example. They referred me over here. It appears the "universal executable" goal might have faded somewhat and folks are in their own camps doing what they do.

In the interim I started exploring other options.

Facebook's Static Hermes has an emit-c option. That emitted C has a main function. That emitted C can then be compiled to WASM with WASI support, and that emitted C can also be compiled to a native executable - that is, JavaScript as source for a "universal executable".

I was thinking this would be something the WebAssembly folks would want to explore and make so in furtherance of the original WebAssembly concept, coming from Native Client, et al.

Instead I have met resistance to some degree to putting all the pieces together from the WebAssembly folks. I'm not a WebAssembly expert. I'm in JavaScript world, mostly. However, I too, have the goal of JavaScript as a universal executable, at least the source code that universal executables can be made from. Compiling JavaScript to WASM with WASI support using Static Hermes. I would think that Bytecode Alliance and WebAssembly projects would be the ones making these easy-to-use examples, with documentation of what is going on an why. Instead, I'm in the field trying to put pieces together myself.

I look forward to reading and testing what you might eventually publish. Thanks, again.

@guest271314
Copy link
Author

What I have so far running and taking apart the dhrystone example

int main(int argc, char const* argv[]) {
  w2c_nm__javy__permutations__standalone javy;
  struct w2c_wasi__snapshot__preview1 wasi;
  uvwasi_t local_uvwasi_state;
  uvwasi_options_t init_options;

  // pass in standard descriptors
  // ...

  wasi.w2c_memory = &javy.w2c_memory;
  wasi.uvwasi = &local_uvwasi_state,

  wasm2c_nm__javy__permutations__standalone_instantiate(&javy, &wasi);

  w2c_nm__javy__permutations__standalone_0x5Fstart(&javy);

  w2c_nm__javy__permutations__standalone_canonical_abi_free(&javy);

  uvwasi_destroy(&local_uvwasi_state);
  wasm_rt_free();

  return 0;
}
WABT_ROOT=../../..
CC=//home/user/1234/llvm-project/build/bin/clang
CFLAGS=-I$(WABT_ROOT)/wasm2c -I $(WABT_ROOT)/third_party/uvwasi/include/ -O3
CFLAGS_SEGUE=-DWASM_RT_ALLOW_SEGUE=1 -mfsgsbase
LDFLAGS=-L$(WABT_ROOT)/third_party/uvwasi/out/cmake/_deps/libuv-build -L$(WABT_ROOT)/third_party/uvwasi/out/cmake
LDLIBS=-luvwasi_a -luv_a -lm

all: javy_permutations

clean:
	rm -rf nm_javy_permutations_standalone nm_javy_permutations_standalone.c nm_javy_permutations_standalone.h

nm_javy_permutations_standalone: javy_main.c nm_javy_permutations_standalone.c $(WABT_ROOT)/wasm2c/wasm-rt-impl.c $(WABT_ROOT)/wasm2c/wasm-rt-mem-impl.c
	$(CC) $(LDFLAGS) $(CFLAGS) $^ -o $@ $(LDLIBS)

nm_javy_permutations_standalone_segue: javy_main.c nm_javy_permutations_standalone.c $(WABT_ROOT)/wasm2c/wasm-rt-impl.c $(WABT_ROOT)/wasm2c/wasm-rt-mem-impl.c
	$(CC) $(LDFLAGS) $(CFLAGS) $(CFLAGS_SEGUE) $^ -o $@ $(LDLIBS)

javy_permutations: nm_javy_permutations_standalone nm_javy_permutations_standalone_segue
make --makefile=Makefile.javy
//home/user/1234/llvm-project/build/bin/clang -L../../../third_party/uvwasi/out/cmake/_deps/libuv-build -L../../../third_party/uvwasi/out/cmake -I../../../wasm2c -I ../../../third_party/uvwasi/include/ -O3 javy_main.c nm_javy_permutations_standalone.c ../../../wasm2c/wasm-rt-impl.c ../../../wasm2c/wasm-rt-mem-impl.c -o nm_javy_permutations_standalone -luvwasi_a -luv_a -lm
javy_main.c:259:66: error: too few arguments to function call, expected 4, have 1
  259 |   w2c_nm__javy__permutations__standalone_canonical_abi_free(&javy);
      |   ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~      ^
./nm_javy_permutations_standalone.h:72:6: note: 'w2c_nm__javy__permutations__standalone_canonical_abi_free' declared here
   72 | void w2c_nm__javy__permutations__standalone_canonical_abi_free(w2c_nm__javy__permutations__standalone*, u32, u32, u32);
      |      ^                                                         ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
1 error generated.
nm_javy_permutations_standalone.c:753:10: fatal error: 'simde/wasm/simd128.h' file not found
  753 | #include <simde/wasm/simd128.h>
      |          ^~~~~~~~~~~~~~~~~~~~~~
1 error generated.
make: *** [Makefile.javy:14: nm_javy_permutations_standalone] Error 1

With --disable-simd, as appears in the dhrystone original Makefil

 ../../../bin/wasm2c ../../../../nm_javy_permutations_standalone.wasm --disable-simd -o nm_javy_permutations_standalone.c
0015f5e: error: expected valid local type

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

5 participants