Skip to content

Instantly share code, notes, and snippets.

@luc-tielen
Last active September 26, 2022 08:58
Show Gist options
  • Save luc-tielen/909c97083b09ef8745b872bcca0de51d to your computer and use it in GitHub Desktop.
Save luc-tielen/909c97083b09ef8745b872bcca0de51d to your computer and use it in GitHub Desktop.
Compiling Eclair to WASM using walloc
#!/bin/bash
# This assumes eclair, clang and wasm-ld are installed,
# and that walloc (https://github.com/wingo/walloc) is compiled,
# and that walloc.o is copied to the current directory.
# Compiling (note: bulk memory needed for memset call)
eclair c program.eclair > program.ll
clang -DNDEBUG -Oz --target=wasm32 -mbulk-memory -nostdlib -c -o program.o program.ll
clang -DNDEBUG -Oz --target=wasm32 -mbulk-memory -nostdlib -c -o driver.o driver.c
# Linking
wasm-ld --no-entry --import-memory -o hello_world.wasm driver.o program.o walloc.o
# Running it
node run_eclair.js
#include <stdbool.h>
#include <stdint.h>
typedef uint32_t size_t;
struct program;
extern struct program *eclair_program_init();
extern void eclair_program_destroy(struct program *);
extern void eclair_program_run(struct program *);
extern void eclair_add_facts(struct program *, uint16_t fact_type,
uint32_t *data, size_t fact_count);
extern void eclair_add_fact(struct program *, uint16_t fact_type,
uint32_t *data);
extern uint32_t *eclair_get_facts(struct program *, uint16_t fact_type);
extern void eclair_free_buffer(uint32_t *data);
#define WASM_EXPORT(name) __attribute__((export_name(#name))) name
uint32_t WASM_EXPORT(run)(uint32_t result_index) {
struct program *prog = eclair_program_init();
// edge(1,2), edge(2,3)
uint32_t data[] = {1, 2, 2, 3};
eclair_add_facts(prog, 0, data, 2);
eclair_program_run(prog);
// NOTE: normally you call btree_size here to figure out the size, but I know
// there are only 3 facts
uint32_t *data_out = eclair_get_facts(prog, 1);
uint32_t result = data_out[result_index]; // dirty hack, since idk yet how to return arrays to JS
eclair_free_buffer(data_out);
eclair_program_destroy(prog);
return result;
}
@def edge(u32, u32).
@def path(u32, u32).
path(x, y) :-
edge(x, y).
path(x, z) :-
edge(x, y),
path(y, z).
const fs = require("fs");
const bytes = fs.readFileSync("hello_world.wasm");
const mod = new WebAssembly.Module(bytes);
const imports = {
env: { memory: new WebAssembly.Memory({ initial: 2, maximum: 256 }) },
};
const instance = new WebAssembly.Instance(mod, imports);
// This is a dirty hack, for now. This indexes into the results array of running Eclair.
// Not that familiar with WASM<->JS interface yet.
// Maybe we can directly use the full uint32 array?
for (const x of [0, 1, 2, 3, 4, 5]) {
console.log(instance.exports.run(x));
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment