WebAssembly to Lua translator, with runtime

Overview

This is a WIP (read: absolutely not ready for serious work) tool for translating WebAssembly into Lua. Support is specifically for LuaJIT, with the secondary objective being Lua 5.4 and Roblox's Luau.

The instructions are minimal; run the program as program to generate the translations into stdout. Editions currently supported are LuaJIT and Luau.

Comments
  • Tests with `assert_trap` not generated for `start`

    Tests with `assert_trap` not generated for `start`

    Due to it being kind of annoying, no code is currently generated for an assert_trap that takes a module argument. The intended behavior here is for its start function to run and trap.

    https://github.com/Rerumu/Wasynth/blob/master/dev-test/tests/luajit_translate.rs#L90 https://github.com/Rerumu/Wasynth/blob/master/dev-test/tests/luau_translate.rs#L103

    opened by Rerumu 4
  • (Luau-only) Many 32 bit tests fail due to 32 bit numbers using 64 bit APIs

    (Luau-only) Many 32 bit tests fail due to 32 bit numbers using 64 bit APIs

    Many 32 bit tests are only failing due to the usage of 64 bit libraries. For example, int_literals.wast.lua loads a constant 4294967295 and compares it with -1 in one of its tests, but this fails due to the usage of rt.eq.i64 in luau_assert.lua. There are several more complex cases like this.

    opened by Hexcede 2
  • (Luau) `br_table.wast.lua` test fails due to recursion depth limit

    (Luau) `br_table.wast.lua` test fails due to recursion depth limit

    I am making a note of this for discussion. I'm not sure if it relates to #8 or not, but the br_table.wast test fails to compile in luau due to the following error message:

    /home/hexcede/programming/Wasynth/target/tmp/br_table.wast.lua:1076: Exceeded allowed recursion depth; simplify your expression to make the code compile
    stacktrace:
    
    

    The referenced line is the creation of loaded["temp"] and my syntax highlighter fails to highlight this section making it difficult to tell exactly what's going on. My understanding of this error is that the wasm module is generating too many nested functions at compile time, however I could be wrong there.

    This would likely require some sort of codegen changes to account for.

    opened by Hexcede 2
  • `loop.wast` infinite loop (`luau_translate` only)

    `loop.wast` infinite loop (`luau_translate` only)

    When the loop.wast test is ran under luau, it hangs due to a non-breaking loop somewhere. Is this a regression, or is it due to better compatibility allowing the test to run far enough to hang?

    Perhaps loop.wast is added to the DO_NOT_RUN list.

    P.s. I am not familiar with rust tests, but, it should be possible to use rust's own test filtering instead of what is present, that way the number of skipped tests will be present in the log which would help with watching for regressions.

    opened by Hexcede 1
  • Extend num storage

    Extend num storage

    So far, this contains store.f32, store.f64, store.i64_n32, store.i64_n16, and store.i64_n8 implementations for luau.

    I would additionally like to implement all of these load variants:

    • load.i32_u16
    • load.i64_i32
    • load.i64_i16
    • load.i64_i8
    • load.i64_u32
    • load.i64_u16
    • load.i64_u8

    This would satisfy the conditions for address.wast.lua and align.wast.lua to both pass under luau.

    opened by Hexcede 1
  • Various Numeric & runtime improvements for `f64` and `u32`

    Various Numeric & runtime improvements for `f64` and `u32`

    This PR fixes several implementation issues in numeric.lua and runtime.lua and migrates math.min and math.max to runtime.lua to account for luau discrepancy (math.min(0, NaN) and math.max(0, NaN) return 0 instead of NaN)

    This allows the f64.wast test to pass along with three others (33 passing tests -> 37 including f64.wast)

    opened by Hexcede 1
  • Undefined behavior regarding bit32 truncation causes differences amongst x86 and other platforms

    Undefined behavior regarding bit32 truncation causes differences amongst x86 and other platforms

    We were noticing behavioral differences with our program transpiled with Wasynth running on Roblox on Windows and other platforms.

    @vegorov-rbx investigated this; thanks a ton! His (paraphrased) findings are below:

    In the Luau Wasynth runtime, to_u32 is defined as bit32.band.

    https://github.com/Rerumu/Wasynth/blob/0394aa8895e7f0429342adb2a88b3b3d6cbcf67c/codegen/luau/runtime/runtime.lua#L3

    In div.i32 and div.u32, the results of division is passed directly to to_u32.

    https://github.com/Rerumu/Wasynth/blob/0394aa8895e7f0429342adb2a88b3b3d6cbcf67c/codegen/luau/runtime/runtime.lua#L78-L91

    Luau 5.2, from which Luau was forked, specifies the following:

    Unless otherwise stated, all functions accept numeric arguments in the range (-251,+251); each argument is normalized to the remainder of its division by 232 and truncated to an integer (in some unspecified way), so that its final value falls in the range [0,232 - 1].

    The behavior varies based on platform:

    • Lua 5.2 x86 depends on processor rounding mode (default round to +Inf)
    • Lua 5.2 x64 uses round to +Inf
    • Luau x86 depends on processor rounding mode (default round to +Inf)
    • Luau x64/arm truncates (round to 0)

    Some differences can be observed in the Luau codebase. For example, here is how numbers are converted to unsigned integers on Windows x86.

    This can be fixed by changing the runtime to truncate the numbers before passing to bit32.band. One potential way of doing this is using modf:

    local i, _ = math.modf(lhs / rhs)
    return to_u32(i)
    

    The LuaJIT runtime also seems to have some truncation logic baked in which could be adopted for Luau as well.

    I can confirm adding the math.modf fix resolves the behavioral differences on the Windows Roblox client for our transpiled program. I was unable to get a minimal CLI repro as Luau Windows CLI appears to be compiled to an x64 target and the bug affects x86. It should be pretty straightforward to repro this in Roblox if necessary by observing the rounding/truncation on a published place on the Windows Roblox client (note that the bug doesn't repro in Studio.)

    opened by schmatz 0
  • LuaJIT `clz`, `ctz`, and `popcnt` are bad

    LuaJIT `clz`, `ctz`, and `popcnt` are bad

    There are better, much faster ways to calculate these. When I wrote them it was to get things working, and haven't had the time to properly revise it.

    https://github.com/Rerumu/Wasynth/blob/5eb85523adc5d532186a74c33c430b043f135c83/codegen/luajit/runtime/runtime.lua#L145-L213

    good first issue 
    opened by Rerumu 0
  • Non-emitted function usage from rust

    Non-emitted function usage from rust

    (Referencing luau codegen files) This was previously discussed in the Roblox Developer Discord server but I wanted to make a note of it here.

    In statement.rs line 277 and expression.rs line 95 there are usages of the i64_K_ZERO constant and the i64_from_u32 function which are not automatically emitted by these paths.

    The most likely solution that was discussed is to just emit these in the header from the rust side of things IIRC.

    opened by Hexcede 0
  • Lacking `BrTable` optimization

    Lacking `BrTable` optimization

    The BrTable AST node is currently not emitted with any form of optimization, as it used to be. The reason being that this causes problems consolidating the stack as different branches have different alignments that must be emitted before doing the jump.

    Nonetheless, it should still be possible to at least generate a binary search instead of a linear search for the branch or otherwise optimize the lookup.

    https://github.com/Rerumu/Wasynth/blob/master/codegen-luajit/src/backend/statement.rs#L31 https://github.com/Rerumu/Wasynth/blob/master/codegen-luau/src/backend/statement.rs#L42

    opened by Rerumu 0
  • Too much noise from `write_constant`

    Too much noise from `write_constant`

    The WebAssembly specification is not very clear on what a well-formed constant looks like, or how many constant instructions it may allow. As such, right now write_constant implementations for offsets and other values end up creating an entire function just to call it and receive its value.

    This makes would would otherwise be 1 line (the expression of the constant) turn into at least 5 lines. It would be great if all this noise could be removed without breaking any unspoken rules.

    https://github.com/Rerumu/Wasynth/blob/master/codegen-luajit/src/translator.rs#L51 https://github.com/Rerumu/Wasynth/blob/master/codegen-luau/src/translator.rs#L50

    opened by Rerumu 0
  • Luau register allocation runs out of registers

    Luau register allocation runs out of registers

    For very complex programs, often Wasynth will generate Lua code which exceeds the limit of 255 registers (local variables/function arguments.) For example, attached is a program which, when translated and run, tries to allocate 402 registers.

    Is there a way to work around this, either in Wasynth or upstream? Or is there no way to avoid this besides implementing more sophisticated algorithms in Wasynth to handle allocation and spilling?

    hello.zip

    opened by schmatz 3
  • Add memory.copy/fill

    Add memory.copy/fill

    I don't have much idea of what's going on here, but I think this is a step in the right direction. Please be very vigilant for mistakes as I'm sure they are present. I hope that I can quickly learn and become a net-positive contributor. I started working on this because of this issue.

    A few questions that came up when writing this:

    1. The source of the operators, wasmparser, seems to have some fields listed in the structs, but others are missing. For example, their struct for MemoryCopy only has the src and dst fields, whereas there is also a third parameter according to the spec, the amount of memory to copy n. I assumed that this was popped off the stack explicitly - I have no idea why it's like this. MemoryFill is even weirder, only containing one field in the struct, mem and having two more in the spec, value and len. Any context on this?

    2. Why are the parameters not listed in wasmparser Box<Expression> rather than u32, which I'm pretty sure they are according to the spec? Why are they visited in visit.rs?

    3. How do I test this? I try running cargo test but that seems to have a ton of failures. Not sure if it's like that normally. I inspected some of the generated files and I see code which looks approximately right but the tests still fail unfortunately. Not sure if there is a way that people usually manually test this.

    Thanks for your help in taking a look at this!

    opened by schmatz 2
  • WASM memory.copy instruction unimplemented

    WASM memory.copy instruction unimplemented

    Trying to compile CPython for a challenge and see the error

    thread 'main' panicked at 'Unsupported instruction: MemoryCopy { src: 0, dst: 0 }', wasm-ast/src/factory.rs:616:18
    

    The spec has more details about these instructions.

    For reference, the wasm file is here: python.wasm.zip

    Might have a go at implementing this if I have some spare time.

    opened by schmatz 1
  • Type LuaJIT code as much as possible

    Type LuaJIT code as much as possible

    Right now LuaJIT code suffers a performance penalty because the JIT is not always capable of inferring that operations on i32 are for integers. This causes a lot of f64-oriented native code to be generated that could have been i32 operations.

    I don't know of any good ways of passing in strong type hints to the JIT other than just replacing all uses of i32 with the i64 type and truncating results.

    enhancement 
    opened by Rerumu 0
  • Add `BrTable` optimization heuristic

    Add `BrTable` optimization heuristic

    Right now when BrTable is translated, it always uses a combination of a lookup table and binary search tree. This is efficient, but not necessarily optimal for when the number of targets is small. In this case it is preferable to just emit a binary search tree directly for about a dozen items or less.

    enhancement 
    opened by Rerumu 0
Releases(v0.12.0)
  • v0.12.0(Jul 22, 2022)

    What's Changed

    • Upgraded the test suite
    • Added block and jump elision when possible
    • Added non-trapping float-to-int conversions
    • Fixed Luau loops having malformed jumps
    • Re-licensed runtimes under MPL to allow distribution of translated code

    Full Changelog: https://github.com/Rerumu/Wasynth/compare/v0.11.0...v0.12.0

    Source code(tar.gz)
    Source code(zip)
    wasm2luajit(4.06 MB)
    wasm2luau(4.08 MB)
  • v0.11.0(Jul 4, 2022)

  • v0.10.0(Jul 4, 2022)

    What's Changed

    • Replace parity-wasm backend with wasmparser
    • Fix Luau branching not identifying loops properly
    • Various Numeric & runtime improvements for f64 and u32 by @Hexcede in https://github.com/Rerumu/Wasynth/pull/9

    New Contributors

    • @Hexcede made their first contribution in https://github.com/Rerumu/Wasynth/pull/9

    Full Changelog: https://github.com/Rerumu/Wasynth/compare/v0.9.0...v0.10.0

    Source code(tar.gz)
    Source code(zip)
    wasm2luajit(4.06 MB)
    wasm2luau(4.07 MB)
  • v0.9.0(Jul 4, 2022)

    What's Changed

    • Fixed #8, #11, and #13
    • Data strings are now escaped, greatly reducing output size in some instances
    • Branch tables now use a lookup table and binary search instead of plain linear search
    • Workflow now produces separate binaries for codegen backends

    Full Changelog: https://github.com/Rerumu/Wasynth/compare/v0.8.0...v0.9.0

    Source code(tar.gz)
    Source code(zip)
    wasm2luajit(4.05 MB)
    wasm2luau(4.06 MB)
  • v0.8.0(Jul 4, 2022)

    What's Changed

    • Much better IR building stage
    • Near-full support for LuaJIT translation
    • Passable support for Luau translation
    • WebAssembly test suite integration
    • More granular public APIs

    Full Changelog: https://github.com/Rerumu/Wasynth/compare/v0.4.0...v0.8.0

    Source code(tar.gz)
    Source code(zip)
    wasm-synth(4.20 MB)
  • v0.4.0(Jul 4, 2022)

    What's Changed

    • Luau fixes by @Fireboltofdeath in https://github.com/Rerumu/Wasynth/pull/1
    • Unaligned R/W by @Fireboltofdeath in https://github.com/Rerumu/Wasynth/pull/2
    • Luau runtime fixes by @Fireboltofdeath in https://github.com/Rerumu/Wasynth/pull/3
    • Fix typo by @NeoInversion in https://github.com/Rerumu/Wasynth/pull/5

    New Contributors

    • @Fireboltofdeath made their first contribution in https://github.com/Rerumu/Wasynth/pull/1
    • @NeoInversion made their first contribution in https://github.com/Rerumu/Wasynth/pull/5

    Full Changelog: https://github.com/Rerumu/Wasynth/commits/v0.4.0

    Source code(tar.gz)
    Source code(zip)
    wasm-synth(4.08 MB)
Owner
Forward and reverse engineering programming languages.
null
Wasmtime - Standalone JIT-style runtime for WebAssembly, using Cranelift

wasmtime A standalone runtime for WebAssembly A Bytecode Alliance project Guide | Contributing | Website | Chat Installation The Wasmtime CLI can be i

Bytecode Alliance 11.1k Jan 2, 2023
Standalone JIT-style runtime for WebAssembly, using Cranelift

wasmtime A standalone runtime for WebAssembly A Bytecode Alliance project Guide | Contributing | Website | Chat Installation The Wasmtime CLI can be i

Bytecode Alliance 11.1k Dec 31, 2022
Lunatic is an Erlang-inspired runtime for WebAssembly

Lunatic is a universal runtime for fast, robust and scalable server-side applications. It's inspired by Erlang and can be used from any language that

Lunatic 3.7k Jan 9, 2023
Lumen - A new compiler and runtime for BEAM languages

An alternative BEAM implementation, designed for WebAssembly

Lumen 3.1k Dec 26, 2022
A high-performance, secure, extensible, and OCI-complaint JavaScript runtime for WasmEdge.

Run JavaScript in WebAssembly Now supporting wasmedge socket for HTTP requests and Tensorflow in JavaScript programs! Prerequisites Install Rust and w

Second State 219 Jan 3, 2023
Wasm runtime written in Rust

Wasm runtime written in Rust

Teppei Fukuda 1 Oct 29, 2021
A prototype WebAssembly linker using module linking.

WebAssembly Module Linker Please note: this is an experimental project. wasmlink is a prototype WebAssembly module linker that can link together a mod

Peter Huene 19 Oct 28, 2022
Sealed boxes implementation for Rust/WebAssembly.

Sealed boxes for Rust/WebAssembly This Rust crate provides libsodium sealed boxes for WebAssembly. Usage: // Recipient: create a new key pair let reci

Frank Denis 16 Aug 28, 2022
WebAssembly on Rust is a bright future in making application runs at the Edge or on the Serverless technologies.

WebAssembly Tour WebAssembly on Rust is a bright future in making application runs at the Edge or on the Serverless technologies. We spend a lot of ti

Thang Chung 129 Dec 28, 2022
WebAssembly modules that use Azure services

This is an experimental repository containing WebAssembly modules running on top of WAGI (WebAssembly Gateway Interface, which allows you to run WebAssembly WASI binaries as HTTP handlers) and using Azure services.

null 7 Apr 18, 2022
WebAssembly Service Porter

WebAssembly Service Porter.

henrylee2cn 12 Dec 12, 2022
WAGI: WebAssembly Gateway Interface

Write HTTP handlers in WebAssembly with a minimal amount of work

null 724 Jan 6, 2023
A console and web-based Gomoku written in Rust and WebAssembly

?? rust-gomoku A console and web-based Gomoku written in Rust and WebAssembly Getting started with cargo & npm Install required program, run # install

namkyu1999 2 Jan 4, 2022
WebAssembly development with Trunk & Vite.js

Trunk & Vite.js Demo Trunk is a WASM web application bundler for Rust, and Vite.js is next Generation Frontend Tooling. Ok, they are together now for

Libing Chen 6 Nov 24, 2021
darkforest is a console and web-based Roguelike written in Rust and WebAssembly.

darkforest darkforest is a console and web-based Roguelike written in Rust and WebAssembly. Key Features TBA Quick Start TBA How To Contribute Contrib

Chris Ohk 5 Oct 5, 2021
A Rust ESP stack trace decoder that can also runs in your browser thanks to WebAssembly

ESP Stack Trace Decoder A Rust ESP stack trace decoder that can also runs in your browser thanks to WebAssembly. It is composed of a ⌨️ Rust library,

Maxime BORGES 20 Oct 5, 2022
Simple file sharing with client-side encryption, powered by Rust and WebAssembly

Hako Simple file sharing with client-side encryption, powered by Rust and WebAssembly Not feature-packed, but basic functionalities are just working.

Jaehyeon Park 30 Nov 25, 2022
bn.js bindings for Rust & WebAssembly with primitive-types support

bn.rs bn.js bindings for Rust & WebAssembly with primitive-types support Write Rust code that uses BN use std::str::FromStr; use primitive_types::{H1

Alexey Shekhirin 23 Nov 22, 2022
A handy calculator, based on Rust and WebAssembly.

qubit ?? Visit Website To Use Calculator Example ?? Visit Website To Use Calculator 2 + 2

Abhimanyu Sharma 55 Dec 26, 2022