Skip to content

Commit

Permalink
Add initial LuaJIT support
Browse files Browse the repository at this point in the history
Adds the latest release of LuaJIT v2.1 and all necessary build file
changes to build as a static library.

Currently this only works an aarch64 macos, but should be
straightforward to extend to other targets.

Uses the Lua 51 library bindings, so some additional LuaJIT functions
may be missing. These will be audited and added at a later time.
  • Loading branch information
natecraddock committed Jan 20, 2024
1 parent 41a6156 commit 809e41e
Show file tree
Hide file tree
Showing 4 changed files with 253 additions and 27 deletions.
216 changes: 216 additions & 0 deletions build.zig
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ pub const Language = enum {
lua52,
lua53,
lua54,
luajit,
luau,
};

Expand All @@ -34,6 +35,7 @@ pub fn build(b: *Build) void {
.lua52 => .{ .path = "src/lib52.zig" },
.lua53 => .{ .path = "src/lib53.zig" },
.lua54 => .{ .path = "src/lib54.zig" },
.luajit => .{ .path = "src/lib51.zig" },
.luau => .{ .path = "src/libluau.zig" },
},
});
Expand All @@ -50,6 +52,7 @@ pub fn build(b: *Build) void {
}

const lib = switch (lang) {
.luajit => buildLuaJIT(b, target, optimize, upstream, shared),
.luau => buildLuau(b, target, optimize, upstream, luau_use_4_vector),
else => buildLua(b, target, optimize, upstream, lang, shared),
};
Expand Down Expand Up @@ -118,6 +121,7 @@ pub fn build(b: *Build) void {
.lua52 => .{ .path = "src/lib52.zig" },
.lua53 => .{ .path = "src/lib53.zig" },
.lua54 => .{ .path = "src/lib54.zig" },
.luajit => .{ .path = "src/lib51.zig" },
.luau => .{ .path = "src/libluau.zig" },
},
});
Expand All @@ -131,6 +135,7 @@ pub fn build(b: *Build) void {
.lua52 => "docs/lua52",
.lua53 => "docs/lua53",
.lua54 => "docs/lua54",
.luajit => "docs/luajit",
.luau => "docs/luau",
},
});
Expand Down Expand Up @@ -246,6 +251,142 @@ fn buildLuau(b: *Build, target: Build.ResolvedTarget, optimize: std.builtin.Opti
return lib;
}

fn buildLuaJIT(b: *Build, target: Build.ResolvedTarget, optimize: std.builtin.OptimizeMode, upstream: *Build.Dependency, shared: bool) *Step.Compile {
// TODO: extract this to the main build function because it is shared between all specialized build functions
const lib_opts = .{
.name = "lua",
.target = target,
.optimize = optimize,
};
const lib: *Step.Compile = if (shared)
b.addSharedLibrary(lib_opts)
else
b.addStaticLibrary(lib_opts);

// Compile minilua interpreter used at build time to generate files
const minilua = b.addExecutable(.{
.name = "minilua",
.target = target, // TODO ensure this is the host
.optimize = .ReleaseSafe,
});
minilua.linkLibC();
minilua.root_module.sanitize_c = false;
minilua.addCSourceFile(.{.file = upstream.path("src/host/minilua.c")});

// Generate the buildvm_arch.h file using minilua
const dynasm_run = b.addRunArtifact(minilua);
dynasm_run.addFileArg(upstream.path("dynasm/dynasm.lua"));
dynasm_run.addArgs(&.{ "-D", "ENDIAN_LE", "-D", "P64", "-D", "JIT", "-D", "FFI", "-D", "DUALNUM", "-D", "FPU", "-D", "HFABI", "-D", "VER=80" });
dynasm_run.addArg("-o");
const buildvm_arch_h = dynasm_run.addOutputFileArg("buildvm_arch.h");
dynasm_run.addFileArg(upstream.path("src/vm_arm64.dasc"));

// Generate luajit.h using minilua
const genversion_run = b.addRunArtifact(minilua);
genversion_run.addFileArg(upstream.path("src/host/genversion.lua"));
genversion_run.addFileArg(upstream.path("src/luajit_rolling.h"));
genversion_run.addFileArg(upstream.path(".relver"));
const luajit_h = genversion_run.addOutputFileArg("luajit.h");

// Compile the buildvm executable used to generate other files
const buildvm = b.addExecutable(.{
.name = "buildvm",
.target = target, // TODO ensure this is the host
.optimize = .ReleaseSafe,
});
buildvm.linkLibC();
buildvm.root_module.sanitize_c = false;

// Needs to run after minilua generates the buildvm_arch.h file
buildvm.step.dependOn(&dynasm_run.step);
buildvm.step.dependOn(&genversion_run.step);

buildvm.addCSourceFiles(.{
.dependency = upstream,
.files = &.{ "src/host/buildvm_asm.c", "src/host/buildvm_fold.c", "src/host/buildvm_lib.c", "src/host/buildvm_peobj.c", "src/host/buildvm.c" },
});

buildvm.addIncludePath(upstream.path("src"));
buildvm.addIncludePath(upstream.path("src/host"));
buildvm.addIncludePath(buildvm_arch_h.dirname());
buildvm.addIncludePath(luajit_h.dirname());

// Use buildvm to generate files and headers used in the final vm
const buildvm_bcdef = b.addRunArtifact(buildvm);
buildvm_bcdef.addArgs(&.{ "-m", "bcdef", "-o" });
const bcdef_header = buildvm_bcdef.addOutputFileArg("lj_bcdef.h");
for (luajit_lib) |file| {
buildvm_bcdef.addFileArg(upstream.path(file));
}

const buildvm_ffdef = b.addRunArtifact(buildvm);
buildvm_ffdef.addArgs(&.{ "-m", "ffdef", "-o" });
const ffdef_header = buildvm_ffdef.addOutputFileArg("lj_ffdef.h");
for (luajit_lib) |file| {
buildvm_ffdef.addFileArg(upstream.path(file));
}

const buildvm_libdef = b.addRunArtifact(buildvm);
buildvm_libdef.addArgs(&.{ "-m", "libdef", "-o" });
const libdef_header = buildvm_libdef.addOutputFileArg("lj_libdef.h");
for (luajit_lib) |file| {
buildvm_libdef.addFileArg(upstream.path(file));
}

const buildvm_recdef = b.addRunArtifact(buildvm);
buildvm_recdef.addArgs(&.{ "-m", "recdef", "-o" });
const recdef_header = buildvm_recdef.addOutputFileArg("lj_recdef.h");
for (luajit_lib) |file| {
buildvm_recdef.addFileArg(upstream.path(file));
}

const buildvm_folddef = b.addRunArtifact(buildvm);
buildvm_folddef.addArgs(&.{ "-m", "folddef", "-o" });
const folddef_header = buildvm_folddef.addOutputFileArg("lj_folddef.h");
for (luajit_lib) |file| {
buildvm_folddef.addFileArg(upstream.path(file));
}

const buildvm_ljvm = b.addRunArtifact(buildvm);
buildvm_ljvm.addArgs(&.{ "-m", "machasm", "-o" });
const ljvm_asm_output = buildvm_ljvm.addOutputFileArg("lj_vm.S");

// Finally build LuaJIT after generating all the files
lib.step.dependOn(&genversion_run.step);
lib.step.dependOn(&buildvm_bcdef.step);
lib.step.dependOn(&buildvm_ffdef.step);
lib.step.dependOn(&buildvm_libdef.step);
lib.step.dependOn(&buildvm_recdef.step);
lib.step.dependOn(&buildvm_folddef.step);
lib.step.dependOn(&buildvm_ljvm.step);

lib.linkLibC();

lib.addIncludePath(upstream.path("src"));
lib.addIncludePath(luajit_h.dirname());
lib.addIncludePath(bcdef_header.dirname());
lib.addIncludePath(ffdef_header.dirname());
lib.addIncludePath(libdef_header.dirname());
lib.addIncludePath(recdef_header.dirname());
lib.addIncludePath(folddef_header.dirname());

lib.addCSourceFiles(.{
.dependency = upstream,
.files = &luajit_vm,
});
lib.addAssemblyFile(ljvm_asm_output);

lib.root_module.sanitize_c = false;

installHeader(lib, upstream.path("src/lua.h"), "lua.h");
installHeader(lib, upstream.path("src/lualib.h"), "lualib.h");
installHeader(lib, upstream.path("src/lauxlib.h"), "lauxlib.h");
installHeader(lib, upstream.path("src/luaconf.h"), "luaconf.h");
installHeader(lib, luajit_h, "luajit.h");

return lib;
}

const lua_base_source_files = [_][]const u8{
"src/lapi.c",
"src/lcode.c",
Expand Down Expand Up @@ -297,6 +438,81 @@ const lua_54_source_files = lua_base_source_files ++ [_][]const u8{
"src/lutf8lib.c",
};

const luajit_lib = [_][]const u8 {
"src/lib_base.c",
"src/lib_math.c",
"src/lib_bit.c",
"src/lib_string.c",
"src/lib_table.c",
"src/lib_io.c",
"src/lib_os.c",
"src/lib_package.c",
"src/lib_debug.c",
"src/lib_jit.c",
"src/lib_ffi.c",
"src/lib_buffer.c",
};

const luajit_vm = luajit_lib ++ [_][]const u8{
"src/lj_assert.c",
"src/lj_gc.c",
"src/lj_err.c",
"src/lj_char.c",
"src/lj_bc.c",
"src/lj_obj.c",
"src/lj_buf.c",
"src/lj_str.c",
"src/lj_tab.c",
"src/lj_func.c",
"src/lj_udata.c",
"src/lj_meta.c",
"src/lj_debug.c",
"src/lj_prng.c",
"src/lj_state.c",
"src/lj_dispatch.c",
"src/lj_vmevent.c",
"src/lj_vmmath.c",
"src/lj_strscan.c",
"src/lj_strfmt.c",
"src/lj_strfmt_num.c",
"src/lj_serialize.c",
"src/lj_api.c",
"src/lj_profile.c",
"src/lj_lex.c",
"src/lj_parse.c",
"src/lj_bcread.c",
"src/lj_bcwrite.c",
"src/lj_load.c",
"src/lj_ir.c",
"src/lj_opt_mem.c",
"src/lj_opt_fold.c",
"src/lj_opt_narrow.c",
"src/lj_opt_dce.c",
"src/lj_opt_loop.c",
"src/lj_opt_split.c",
"src/lj_opt_sink.c",
"src/lj_mcode.c",
"src/lj_snap.c",
"src/lj_record.c",
"src/lj_crecord.c",
"src/lj_ffrecord.c",
"src/lj_asm.c",
"src/lj_trace.c",
"src/lj_gdbjit.c",
"src/lj_ctype.c",
"src/lj_cdata.c",
"src/lj_cconv.c",
"src/lj_ccall.c",
"src/lj_ccallback.c",
"src/lj_carith.c",
"src/lj_clib.c",
"src/lj_cparse.c",
"src/lj_lib.c",
"src/lj_alloc.c",
"src/lib_aux.c",
"src/lib_init.c",
};

const luau_source_files = [_][]const u8{
"Compiler/src/BuiltinFolding.cpp",
"Compiler/src/Builtins.cpp",
Expand Down
5 changes: 5 additions & 0 deletions build.zig.zon
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,11 @@
.hash = "1220f93ada1fa077ab096bf88a5b159ad421dbf6a478edec78ddb186d0c21d3476d9",
},

.luajit = .{
.url = "https://github.com/LuaJIT/LuaJIT/archive/c525bcb9024510cad9e170e12b6209aedb330f83.tar.gz",
.hash = "1220ae2d84cfcc2a7aa670661491f21bbed102d335de18ce7d36866640fd9dfcc33a",
},

.luau = .{
.url = "https://github.com/luau-lang/luau/archive/refs/tags/0.607.tar.gz",
.hash = "122003818ff2aa912db37d4bbda314ff9ff70d03d9243af4b639490be98e2bfa7cb6",
Expand Down
2 changes: 2 additions & 0 deletions src/lib51.zig
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,8 @@ const c = @cImport({
@cInclude("lua.h");
@cInclude("lualib.h");
@cInclude("lauxlib.h");

if (lang == .luajit) @cInclude("luajit.h");
});

const config = @import("config");
Expand Down
Loading

0 comments on commit 809e41e

Please sign in to comment.