Skip to content

Instantly share code, notes, and snippets.

@ScottTodd
Last active October 21, 2023 04:52
Show Gist options
  • Save ScottTodd/f30d9d26254de82648de37d5ed445cbc to your computer and use it in GitHub Desktop.
Save ScottTodd/f30d9d26254de82648de37d5ed445cbc to your computer and use it in GitHub Desktop.
Building MLIR through Emscripten

Goal: built mlir-opt through emscripten to run it interactively from documentation websites.

References:

Notes:

Set up emsdk following those docs (run source ./emsdk_env.sh)

Build host tools to ./build/:

cmake -G Ninja -B ./build/ -DLLVM_ENABLE_PROJECTS=mlir -DCMAKE_BUILD_TYPE=Release llvm/.
cmake --build ./build/ --target mlir-opt

(Could also build without --target)

Configure for emscripten to ./build-emscripten/.

Note: we want to use the host tablegen and other tools throughout the build. Emscripten or LLVM creates a NATIVE/ folder and tries to run tools from there... but the "executable binaries" in that directory are JavaScript files... which obviously can't be executed in a shell environment.

emcmake cmake -G Ninja -B ./build-emscripten/ -DLLVM_ENABLE_PROJECTS=mlir -DCMAKE_BUILD_TYPE=Release -DCMAKE_INSTALL_PREFIX=./install-emscripten/ -DLLVM_TABLEGEN=$PWD/build/bin/llvm-tblgen -DMLIR_TABLEGEN_EXE=$PWD/build/bin/mlir-tblgen -DLLVM_TOOLS_BINARY_DIR=$PWD/build/bin/ -Wno-dev llvm/.

** weird stuff happens here **

try building:

cmake --build ./build-emscripten --target mlir-opt

see errors about llvm-tblgen, mlir-tblgen, etc.

copy from host build to NATIVE/ folder:

cp ./build/bin/llvm-tblgen ./build-emscripten/NATIVE/bin && chmod +x build-emscripten/NATIVE/bin/llvm-tblgen
cp ./build/bin/mlir-tblgen ./build-emscripten/NATIVE/bin && chmod +x build-emscripten/NATIVE/bin/mlir-tblgen
cp ./build/bin/mlir-linalg-ods-gen ./build-emscripten/NATIVE/bin && chmod +x build-emscripten/NATIVE/bin/mlir-linalg-ods-gen
cp ./build/bin/mlir-linalg-ods-yaml-gen ./build-emscripten/NATIVE/bin && chmod +x build-emscripten/NATIVE/bin/mlir-linalg-ods-yaml-gen

try building again:

cmake --build ./build-emscripten --target mlir-opt

success ?

ls -la build-emscripten/bin

(should have mlir-opt.js and mlir-opt.wasm, among other files)
<html>
<head>
<title>MLIR Emscripten Demo</title>
</head>
<body>
<p>MLIR input:</p>
<textarea id="opt_input" name="opt_input" rows="6" cols="80">
func @simple_constant() -> (i32, i32) {
%0 = constant 1 : i32
%1 = constant 1 : i32
return %0, %1 : i32, i32
}</textarea>
<p>mlir-opt flags (space-delimited):</p>
<textarea id="opt_flags" name="opt_flags" rows="1" cols="80">-cse -canonicalize</textarea>
<p>MLIR output:</p>
<textarea id="opt_output" name="opt_output" rows="8" cols="80"></textarea>
<p><button onclick="runMlirOpt()">Run mlir-opt</button></p>
<script>
const optInput = document.getElementById("opt_input");
const optFlags = document.getElementById("opt_flags");
const optOutput = document.getElementById("opt_output");
var Module = {
print: function (text) {
optOutput.textContent += text + "\n";
},
printErr: function (text) { console.warn(text); },
onRuntimeInitialized: function () {
console.log("onRuntimeInitialized");
},
// https://emscripten.org/docs/api_reference/module.html#Module.noInitialRun
noInitialRun: true,
};
function runMlirOpt() {
// TODO(scotttodd): wait until initialized ;)
console.log("running mlir-opt...");
// https://emscripten.org/docs/api_reference/Filesystem-API.html#FS.writeFile
// We could also use stdin: https://stackoverflow.com/a/33119868
FS.writeFile("input.mlir", optInput.value);
// TODO(scotttodd): sanitize (remove trailing spaces, etc.)
const flags = optFlags.value.split(" ");
flags.push("input.mlir");
callMain(flags);
// TODO(scotttodd): dedicated binary with functions to call, rather than one-shot CLI
}
</script>
<script src="mlir-opt.js"></script>
</body>
</html>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment