Converting LLVM IR (Rust, C, C++, etc) to Luau.

You can also check out the discord server with more compilers for Roblox!

What is LLVM IR?

LLVM IR is pretty much a intermediate representation that is generated from Rust, C, C++, Mojo, Zig, Swift and many more languages that compile (not directly) to assembly source code.

Even some JIT languages use LLVM!

Most of the compilers expose the LLVM compiler, Not only that but there are projects such as remill which can take real executables (machine code or assembly) and turn it into LLVM IR.

Example:

@.hello = constant [14 x i8] c"Hello, World!\00"

define i32 @add(i32 %a, i32 %b) {
    %result = add i32 %a, %b
    ret i32 %result
}

define i32 @sub(i32 %a, i32 %b) {
    %result = sub i32 %a, %b
    ret i32 %result
}

define i32 @mul(i32 %a, i32 %b) {
    %result = mul i32 %a, %b
    ret i32 %result
}

define i32 @div(i32 %a, i32 %b) {
    %result = sdiv i32 %a, %b
    ret i32 %result
}

define i32 @mod(i32 %a, i32 %b) {
    %result = srem i32 %a, %b
    ret i32 %result
}

declare void @print()
define i32 @main() {
    call void @print()
    ret i32 0
}
--!optimize 2
--!nolint
--!nocheck
--!native
--# selene: allow(global_usage, multiple_statements, incorrect_standard_library_use, unused_variable)

-- Generated by roblox-llvm 0.0.0 beta

local lshift = bit32.lshift
local rshift = bit32.rshift
local arshift = bit32.arshift
local band = bit32.band
local bor = bit32.bor
local bxor = bit32.bxor

local _hello = "Hello, World!\00"
function add(a, b)
    local result = a + b
    return result
end
function sub(a, b)
    local result = a - b
    return result
end
function mul(a, b)
    local result = a * b
    return result
end
function div(a, b)
    local result = a / b
    return result
end
function mod(a, b)
    local result = a % b
    return result
end
if not print then print = _G.llvm_print or error("roblox-llvm | function 'print' not found") end
function main()
    print()
    return 0
end

return {add, sub, mul, div, mod, main, _hello}

Explanation:

The compiler uses llvmlite to parse source code, LLVM IR doesn’t have any “depth” so a tree visitor isn’t required. Most of the difficulties are that gotos are used thus we need to implement a relooper.

2 Likes