99 lines
2.5 KiB
Plaintext
99 lines
2.5 KiB
Plaintext
// compile_seed.ce — compile a .cm module to native .dylib via QBE (seed mode)
|
|
// Usage: ./cell --dev --seed compile_seed <file.cm>
|
|
|
|
var fd = use("fd")
|
|
var os = use("os")
|
|
var tokenize = use("tokenize")
|
|
var parse = use("parse")
|
|
var fold = use("fold")
|
|
var mcode = use("mcode")
|
|
var streamline = use("streamline")
|
|
var qbe_macros = use("qbe")
|
|
var qbe_emit = use("qbe_emit")
|
|
|
|
if (length(args) < 1) {
|
|
print("usage: cell --dev --seed compile_seed <file.cm>")
|
|
disrupt
|
|
}
|
|
|
|
var file = args[0]
|
|
var base = file
|
|
if (ends_with(base, ".cm")) {
|
|
base = text(base, 0, length(base) - 3)
|
|
} else if (ends_with(base, ".ce")) {
|
|
base = text(base, 0, length(base) - 3)
|
|
}
|
|
|
|
var safe = replace(replace(replace(base, "/", "_"), "-", "_"), ".", "_")
|
|
var symbol = "js_" + safe + "_use"
|
|
var tmp = "/tmp/qbe_" + safe
|
|
var ssa_path = tmp + ".ssa"
|
|
var s_path = tmp + ".s"
|
|
var o_path = tmp + ".o"
|
|
var rt_o_path = "/tmp/qbe_rt.o"
|
|
var dylib_path = file + ".dylib"
|
|
var rc = 0
|
|
|
|
// Step 1: compile to QBE IL
|
|
print("compiling " + file + " to QBE IL...")
|
|
var src = text(fd.slurp(file))
|
|
var result = tokenize(src, file)
|
|
var ast = parse(result.tokens, src, file, tokenize)
|
|
var folded = fold(ast)
|
|
var compiled = mcode(folded)
|
|
var optimized = streamline(compiled)
|
|
var il = qbe_emit(optimized, qbe_macros)
|
|
|
|
// Step 2: append wrapper function
|
|
var wrapper = `
|
|
export function l $${symbol}(l %ctx) {
|
|
@entry
|
|
%result =l call $cell_rt_module_entry(l %ctx)
|
|
ret %result
|
|
}
|
|
`
|
|
il = il + wrapper
|
|
|
|
// Write IL to file — remove old file first to avoid leftover content
|
|
if (fd.is_file(ssa_path)) fd.unlink(ssa_path)
|
|
var out_fd = fd.open(ssa_path, 1537, 420)
|
|
fd.write(out_fd, il)
|
|
fd.close(out_fd)
|
|
print("wrote " + ssa_path + " (" + text(length(il)) + " bytes)")
|
|
|
|
// Step 3: compile QBE IL to assembly
|
|
print("qbe compile...")
|
|
rc = os.system("qbe -o " + s_path + " " + ssa_path)
|
|
if (rc != 0) {
|
|
print("qbe compilation failed")
|
|
disrupt
|
|
}
|
|
|
|
// Step 4: assemble
|
|
print("assemble...")
|
|
rc = os.system("cc -c " + s_path + " -o " + o_path)
|
|
if (rc != 0) {
|
|
print("assembly failed")
|
|
disrupt
|
|
}
|
|
|
|
// Step 5: compile runtime stubs
|
|
if (!fd.is_file(rt_o_path)) {
|
|
print("compile runtime stubs...")
|
|
rc = os.system("cc -c source/qbe_helpers.c -o " + rt_o_path + " -fPIC -Isource")
|
|
if (rc != 0) {
|
|
print("runtime stubs compilation failed")
|
|
disrupt
|
|
}
|
|
}
|
|
|
|
// Step 6: link dylib
|
|
print("link...")
|
|
rc = os.system("cc -shared -fPIC -undefined dynamic_lookup " + o_path + " " + rt_o_path + " -o " + dylib_path)
|
|
if (rc != 0) {
|
|
print("linking failed")
|
|
disrupt
|
|
}
|
|
|
|
print("built: " + dylib_path)
|