// compile.ce — compile a .cm module to native .dylib via QBE // // Usage: // cell --dev compile.ce // // Produces .dylib in the current directory. var fd = use('fd') var os = use('os') if (length(args) < 1) { print('usage: cell --dev compile.ce ') return } var file = args[0] var base = file if (ends_with(base, '.cm')) { base = text(base, 0, length(base) - 3) } var safe = 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 cwd = fd.getcwd() var rc = 0 // Step 1: emit QBE IL print('emit qbe...') rc = os.system('cd ' + cwd + ' && ./cell --dev qbe.ce ' + file + ' > ' + ssa_path) if (rc != 0) { print('failed to emit qbe il') return } // Step 2: append wrapper function — called as symbol(ctx) by os.dylib_symbol. // Delegates to cell_rt_module_entry which heap-allocates a frame // (so closures survive) and calls cell_main. var wrapper_cmd = `printf '\nexport function l $` + symbol + `(l %%ctx) {\n@entry\n %%result =l call $cell_rt_module_entry(l %%ctx)\n ret %%result\n}\n' >> ` + ssa_path rc = os.system(wrapper_cmd) if (rc != 0) { print('wrapper append failed') return } // 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') return } // Step 4: assemble print('assemble...') rc = os.system('cc -c ' + s_path + ' -o ' + o_path) if (rc != 0) { print('assembly failed') return } // Step 5: compile runtime stubs (cached — skip if already built) if (!fd.is_file(rt_o_path)) { print('compile runtime stubs...') rc = os.system('cc -c ' + cwd + '/qbe_rt.c -o ' + rt_o_path + ' -fPIC') if (rc != 0) { print('runtime stubs compilation failed') return } } // Step 6: link dylib print('link...') rc = os.system('cc -shared -fPIC -undefined dynamic_lookup ' + o_path + ' ' + rt_o_path + ' -o ' + cwd + '/' + dylib_path) if (rc != 0) { print('linking failed') return } print('built: ' + dylib_path)