[ANN] CLX - Ahead-of-Time Lua 5.5 Compiler

335 views
Skip to first unread message

samir...@luart.org

unread,
Jun 21, 2026, 11:17:17 AM (12 days ago) Jun 21
to lu...@googlegroups.com

Hello,

CLX is a new open-source ahead-of-time compiler for Lua 5.5.
CLX compiles Lua source code to standalone native executables through modern C++20 toolchains (Clang, GCC, and MSVC).

Current features include:

  • Native standalone executable compilation

  • Support for most Lua 5.5 language features

  • Cross-platform support (Linux, Windows, and macOS)

  • Lightweight runtime designed for AOT compilation

  • C++ API for native modules

  • Example projects (a fully playable Pong game and a Mandelbrot fractal renderer)

Recent benchmarks show consistent speedups over the standard Lua interpreter and competitive performance with LuaJIT on a number of workloads.

The project is currently in beta and feedback is welcome.

Website:
https://samyeyo.github.io/clx

GitHub:
https://github.com/samyeyo/clx

Thank you,

Samir Tine

bil til

unread,
Jun 22, 2026, 1:13:02 AM (11 days ago) Jun 22
to lu...@googlegroups.com
Am So., 21. Juni 2026 um 17:17 Uhr schrieb <samir...@luart.org>:
> Support for most Lua 5.5 language features

Please excuse a "lazy question" (I did not look at your project in
detail, please excuse - currently too much different work):

Which are the main features your project does NOT support?

(because you do not like them / you think they are too cumbersome? or
because the produce any severe problems in your project?)
> --
> You received this message because you are subscribed to the Google Groups "lua-l" group.
> To unsubscribe from this group and stop receiving emails from it, send an email to lua-l+un...@googlegroups.com.
> To view this discussion visit https://groups.google.com/d/msgid/lua-l/b37b13c2128d9a27a854da270db19608%40luart.org.

Samir Tine

unread,
Jun 22, 2026, 3:58:07 AM (11 days ago) Jun 22
to lua-l

That's a fair question.
The goal is not to intentionally exclude Lua features. In fact, CLX already supports essentially all Lua 5.5 syntax (including global, <const> and <close>) and most of the standard library.

The main unsupported areas today are features that fundamentally depend on runtime code generation or deep interpreter introspection, such as load(), loadfile(), dofile(), string.dump(), and most of the debug module.

The traditional Lua C API is also not supported, as CLX uses its own C++ API designed around the AOT execution model (CLX don't use any stack or VM internally)

Apart from these limitations, the goal is full Lua 5.5 compatibility.

Pierre Chapuis

unread,
Jun 22, 2026, 4:58:03 AM (11 days ago) Jun 22
to lu...@googlegroups.com
Nice project.

FYI on an Arch Linux machine, out of the box, building and trying to use the result will fail:

```
/usr/bin/ld: /dcs/cwl/git/clx/build/libclx_size.a(runtime.cpp.o): plugin needed to handle lto object /usr/bin/ld: /dcs/cwl/git/clx/build/libclx_size.a(runtime.cpp.o): plugin needed to handle lto object /usr/bin/ld: /dcs/cwl/git/clx/build/libclx_size.a(openlibs.cpp.o): plugin needed to handle lto object /usr/bin/ld: /dcs/cwl/git/clx/build/libclx_size.a(openlibs.cpp.o): plugin needed to handle lto object /usr/bin/ld: /tmp/lto-llvm-d854bc.o: in function `luaopen_t(clx::LState*)': ld-temp.o:(.text._Z9luaopen_tPN3clx6LStateE+0x126): undefined reference to `clx::LTable::gettable(clx::LValue const&)' /usr/bin/ld: ld-temp.o:(.text._Z9luaopen_tPN3clx6LStateE+0x1bb): undefined reference to `clx::call_function(clx::LState*, clx::LValue const&, clx::LValue const*, unsigned long, char const*, int)' /usr/bin/ld: /tmp/lto-llvm-d854bc.o: in function `main': ld-temp.o:(.text.main+0x5): undefined reference to `clx::open(int, char**)' /usr/bin/ld: ld-temp.o:(.text.main+0x10): undefined reference to `clx::openlibs(clx::LState*)' /usr/bin/ld: ld-temp.o:(.text.main+0x20): undefined reference to `clx::close(clx::LState*)' /usr/bin/ld: ld-temp.o:(.text.main+0x6e): undefined reference to `clx::close(clx::LState*)' /usr/bin/ld: ld-temp.o:(.text.main+0xcc): undefined reference to `clx::close(clx::LState*)' clang++:
error:
linker command failed with exit code 1 (use -v to see invocation)
```

That is because it will build will GCC but compile the Lua program with clang and attempt to link with (GNU) ld.

Forcing it to use clang / lld for everything works.

-- 
Pierre Chapuis

Samir Tine

unread,
Jun 22, 2026, 5:05:59 AM (11 days ago) Jun 22
to lua-l

Thanks for testing CLX and for your detailed report !

You're absolutely right : CLX currently assumes a consistent toolchain throughout the build process, and the generated code was being linked against a runtime library built with GCC/LTO while the final executable was linked using clang/ld.
I'll investigate improving toolchain detection and handling mixed GCC/Clang environments more gracefully.

Thanks again for tracking this down.

Sergey Zakharchenko

unread,
Jun 22, 2026, 5:15:52 AM (11 days ago) Jun 22
to lu...@googlegroups.com
Hello,


On Mon, Jun 22, 2026, 12:06 Samir Tine <samir...@luart.org> wrote:

Thanks for testing CLX and for your detailed report !

You're absolutely right :


Could you please comment on the current pace of development, consistency of documentation, relevance of commit messages to the corresponding changes, the tools that you use and the future code maintenance model?

Best regards,

-- 
DoubleF

Samir Tine

unread,
Jun 22, 2026, 5:42:53 AM (11 days ago) Jun 22
to lua-l

Thank you for your questions.

CLX is still a very young project, so development is currently moving quite fast, with the main focus on Lua 5.5 compatibility, performance, and testing.


Documentation is already available in the doc/ folder in Markdown format (and on the website too): covering architecture, CLI use, C++ API, modules management...
Documentation is being expanded alongside the implementation and will continue to improve as the project matures.

Some recent commits reflect rapid prototyping, but I intend to improve commit quality and project documentation as development stabilizes.

CLX is currently developed by a single author (me) using modern C++20 & CMake, and the project is fully open source. I hope to attract contributors as the architecture and APIs become more stable.

My immediate goal is to build a robust foundation before expanding the contributor base.

eugeny gladkih

unread,
Jun 22, 2026, 3:13:26 PM (11 days ago) Jun 22
to lu...@googlegroups.com


> On 22 Jun 2026, at 10:58, Samir Tine <samir...@luart.org> wrote:
>
> That's a fair question.
> The goal is not to intentionally exclude Lua features. In fact, CLX already supports essentially all Lua 5.5 syntax (including global, <const> and <close>) and most of the standard library.
> The main unsupported areas today are features that fundamentally depend on runtime code generation or deep interpreter introspection, such as load(), loadfile(), dofile(), string.dump(), and most of the debug module.

what about meta tables and meta-methods? suddenly, a+b is not the same as b+a is :)

--
Yours sincerely, Eugeny.


samir...@luart.org

unread,
Jun 22, 2026, 4:10:40 PM (11 days ago) Jun 22
to lu...@googlegroups.com

Metatables and metamethods are supported and are an important part of Lua compatibility.

Optimizations are designed not to change observable Lua behavior.

If you have a specific metamethod edge case in mind, I'd be interested in testing it against CLX :)

David Sicilia

unread,
Jun 22, 2026, 8:05:25 PM (11 days ago) Jun 22
to lu...@googlegroups.com
Does it attempt to do type inference on code (e.g. function parameters, return values) to increase efficiency of generated code, or does it leave those values as boxed/generic values?

--
You received this message because you are subscribed to the Google Groups "lua-l" group.
To unsubscribe from this group and stop receiving emails from it, send an email to lua-l+un...@googlegroups.com.

samir...@luart.org

unread,
Jun 22, 2026, 8:26:06 PM (10 days ago) Jun 22
to lu...@googlegroups.com

Yes optimizations pass try to deduce types to generate more efficient C++ code. If inference is not possible then it uses boxed values.

You received this message because you are subscribed to a topic in the Google Groups "lua-l" group.
To unsubscribe from this topic, visit https://groups.google.com/d/topic/lua-l/ingMSR7EZZU/unsubscribe.
To unsubscribe from this group and all its topics, send an email to lua-l+un...@googlegroups.com.
To view this discussion visit https://groups.google.com/d/msgid/lua-l/CAGW0ud1B5%3DKB%3DBZG32GapKBsBrth_gf4BZoxxuoMsoQptoCQnQ%40mail.gmail.com.

Sewbacca

unread,
Jun 23, 2026, 2:07:29 AM (10 days ago) Jun 23
to lu...@googlegroups.com
What kind of optimizations do you have implemented and how do you infer parameter types? Are the resulting C++ signatures directly callable from C++? And is C API interop planned at some point (so one is not excluded from the already existing ecosystem?

A very interesting Project you have here =)

~ Sewbacca

23.06.2026 02:26:07 samir...@luart.org:

samir...@luart.org

unread,
Jun 23, 2026, 2:21:57 PM (10 days ago) Jun 23
to lu...@googlegroups.com

Thank you for your questions !

Current optimizations include constant folding, constant propagation, dead code elimination, function inlining, native number fastpaths, and tail-call optimizations when applicable. CLX also performs a number of Lua-specific simplifications during code generation.

CLX does not currently perform full static type inference. It relies primarily on compile-time analysis and specialization when types can be determined with sufficient confidence.

Generated functions currently operate on CLX runtime values rather than directly exposing native C++ signatures.

The Lua C API is not supported today. CLX provides its own C++ module API, although some form of compatibility layer may be explored in the future.

--
You received this message because you are subscribed to a topic in the Google Groups "lua-l" group.
To unsubscribe from this topic, visit https://groups.google.com/d/topic/lua-l/ingMSR7EZZU/unsubscribe.
To unsubscribe from this group and all its topics, send an email to lua-l+un...@googlegroups.com.

Viacheslav Usov

unread,
Jun 24, 2026, 7:57:25 AM (9 days ago) Jun 24
to lu...@googlegroups.com
On Sun, Jun 21, 2026 at 5:17 PM <samir...@luart.org> wrote:

> CLX is a new open-source ahead-of-time compiler for Lua 5.5.
> CLX compiles Lua source code to standalone native executables through modern C++20 toolchains (Clang, GCC, and MSVC).

Hi, some questions which I could not find good answers for yet.

1. GC. Is it based on some well known project? If so, could you
reference that? If not, well, where is its code?
2. Native multithreading. The original Lua VM ignores native OS
threads and keeps everything, including GC, in a Lua state. If
somebody wants to run a Lua state on multiple native threads it is
their problem. What about CLX? In particular, is GC shared or also per
state? What does "stop the world" mean then?
3. What is the strategic plan for dynamic Lua code?

Cheers,
V.
Message has been deleted
Message has been deleted

Samir Tine

unread,
Jun 25, 2026, 8:43:31 PM (7 days ago) Jun 25
to lua-l

Thank you for the questions.

  1. The GC is a custom implementation. It's an incremental mark-and-sweep collector designed specifically for CLX's runtime.

  2. Garbage collection is per LState, not shared globally. "Stop the world" therefore only applies to the state being collected, not to all application threads. Native threads can/should run independent states concurrently.

  3. Regarding dynamic Lua code, CLX currently takes a strict AOT approach. The current focus is on statically compiled Lua applications rather than interpreter/dynamic execution model (maybe in the future ?)

samir...@luart.org

unread,
Jun 25, 2026, 8:43:31 PM (7 days ago) Jun 25
to lu...@googlegroups.com

Thanks for those questions :

  1. The GC is a custom implementation. It's an incremental mark-and-sweep collector designed specifically for CLX runtime.

  1. Garbage collection is per LState, not shared globally. "Stop the world" therefore only applies to the state being collected, not to all application threads. Native threads can/should run independent states concurrently.

  1. Regarding dynamic Lua code, CLX currently takes a strict AOT approach. The current focus is on statically compiled Lua applications rather than hybrid AOT/interpreted execution model.

Samir Tine

unread,
Jun 25, 2026, 8:43:32 PM (7 days ago) Jun 25
to lua-l

Thank you for your questions : 

  1. The GC is a custom implementation. It's an incremental mark-and-sweep collector designed specifically for CLX's runtime.

  2. Garbage collection is per LState, not shared globally. "Stop the world" therefore only applies to the state being collected, not to all application threads. Native threads can run independent states concurrently. But there is no mechanism implemented for thread safety or for sharing values between LStates.

  3. Regarding dynamic Lua code, the current focus is on statically compiled Lua applications rather than hybrid interpreter execution models. Maybe in the future, an embbedded Lua interpreter could be used for this dynamic code (but it seems very complex at first sight, specifically when yielding from/to the interpreter to/from the CLX runtime) 


Le mercredi 24 juin 2026 à 13:57:25 UTC+2, Viacheslav Usov a écrit :

Sewbacca

unread,
Jun 26, 2026, 2:35:47 AM (7 days ago) Jun 26
to lu...@googlegroups.com
This peaks my interest: How did you implement yielding under the hood? Did you use longjmp or did you employ a different technique? And what does yielding mean for the C++ interface?

~ Sewbacca

samir...@luart.org

unread,
Jun 26, 2026, 12:02:05 PM (7 days ago) Jun 26
to lu...@googlegroups.com

CLX coroutines are stackful.

Internally they use ucontext (POSIX) or Windows Fibers (Windows), so yielding is implemented as a context switch between execution contexts rather than via longjmp.

This means local state and call frames remain intact across yields.

For native C++ modules, yielding follows the same coroutine semantics as Lua: execution can be suspended and resumed without manually preserving state.


Le 26/06/2026 08:35, 'Sewbacca' via lua-l a écrit :

This peaks my interest: How did you implement yielding under the hood? Did you use longjmp or did you employ a different technique? And what does yielding mean for the C++ interface?

~ Sewbacca


--
You received this message because you are subscribed to the Google Groups "lua-l" group.
To unsubscribe from this group and stop receiving emails from it, send an email to lua-l+un...@googlegroups.com.
To view this discussion visit https://groups.google.com/d/msgid/lua-l/1c10d7db-e7bb-4bc0-a39c-f1e83aca1995%40kolabnow.com.

David Given

unread,
Jun 27, 2026, 3:30:25 AM (6 days ago) Jun 27
to lu...@googlegroups.com
Just so you're aware, eons ago I wrote a program which used ucontext-based coroutines, and it was a total disaster. While it worked on most platforms, there appear to be some (certain Linux architectures, I recall vaguely) where ucontext interacted very badly with pthreads. From what I remember the platform would do something like ALIGNUP(stackpointer, 10MB) to find the TLS data structure for the running thread. As you might image, when switching to a ucontext stack allocated from the heap, Very Bad Things happened. I eventually had to give up and use threads, with a semaphore to ensure that only one thread was executing at a time. (This was actually pretty helpful, as I could have individual threads enter thread-safe sections for doing certain long-running operations while allowing other threads to execute.)

I do note that C++20 now has a feature which it calls coroutines, except they don't actually appear to be coroutines by any normal definition of the word. Coroutines are apparently now called fibres. Sigh. At least there do appear to be a number of supported fibre libraries.

On another note: are you aware of the Luau strong-typing extension to Lua? It was written by Roblox and is pretty good. I recent migrated my word processor WordGrinder to it and found so many bugs. If I could run Luau-annoted Lua though CLX and end up with a native executable, I would be extremely happy.

Samir Tine

unread,
Jun 27, 2026, 7:38:19 AM (6 days ago) Jun 27
to lua-l

Thanks for the feedback !

CLX currently uses ucontext on POSIX and Fibers on Windows for coroutines. I've heard similar reports about ucontext portability issues and it's something I'll keep in mind going forward.
For now it seems to work and I need more users feedback on it before changing coroutines implementation.

As for Luau, I agree that static typing can be very useful. However, CLX's goal is to compile standard Lua. Luau (and Nelua too) both introduce syntax that isn't valid Lua, which goes against that goal. I'd rather keep CLX focused on Lua itself and preserve compatibility with existing Lua code.

Reply all
Reply to author
Forward
0 new messages