rerumu / wasynth Goto Github PK
View Code? Open in Web Editor NEWWebAssembly to Lua translation library and tool
Home Page: https://discord.gg/sgm5YcmgyD
License: GNU General Public License v3.0
WebAssembly to Lua translation library and tool
Home Page: https://discord.gg/sgm5YcmgyD
License: GNU General Public License v3.0
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.
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.
Tracking this issue: LuaJIT/LuaJIT#775
When doing reads and writes on large outputs, odd behavior may very rarely occur. This could end in undefined behavior in the script and even segmentation faults.
thread 'main' panicked at codegen/luau/src/bin/wasm2luau.rs:6:40:
usage: wasm2luajit <file>
note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace
small text issue (mabey instead get argv 0 instead? so even if renamed it works)
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.
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.
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?
The README doesn't explain how to install this package. Are there any instructions for installation here?
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
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.
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
.
In div.i32
and div.u32
, the results of division is passed directly to to_u32
.
Wasynth/codegen/luau/runtime/runtime.lua
Lines 78 to 91 in 0394aa8
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:
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.)
I'm interested in using this as a way to ship a C library into a nvim plugin. Is there an example project so I can pick up quickly on how to use it?
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
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.
Wasynth/codegen/luajit/runtime/runtime.lua
Lines 145 to 213 in 5eb8552
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
(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.
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.
The codegens currently emit code using only spaces for separation. It would be good if tabs and newlines were produced to format statements at least.
A declarative, efficient, and flexible JavaScript library for building user interfaces.
๐ Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. ๐๐๐
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google โค๏ธ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.