53 lines
1.8 KiB
OCaml
53 lines
1.8 KiB
OCaml
(** Driver: typed IR → an executable, via LLVM IR text and clang.
|
|
|
|
The release path from plan.org, Compilation:
|
|
|
|
{v flan → typed IR → .ll → clang --target={native,wasm32} v}
|
|
|
|
Not the dev path — that one never invokes the clang driver, because the
|
|
driver *is* the cost (52ms of the measured 68), and goes llc + ld -shared +
|
|
dlopen instead for ~16ms. Nothing at milestone 2 needs it yet. *)
|
|
|
|
let clang = try Sys.getenv "FLAN_CLANG" with Not_found -> "clang"
|
|
|
|
let write path contents =
|
|
let ch = open_out path in
|
|
output_string ch contents;
|
|
close_out ch
|
|
|
|
(* One temporary directory per build, so the .ll is findable by name when
|
|
something is wrong with it. *)
|
|
let workdir () =
|
|
let d =
|
|
Filename.concat (Filename.get_temp_dir_name ())
|
|
(Printf.sprintf "flan-%d" (Unix.getpid ()))
|
|
in
|
|
(try Unix.mkdir d 0o700 with Unix.Unix_error (Unix.EEXIST, _, _) -> ());
|
|
d
|
|
|
|
type opts = {
|
|
target : string option; (* None is the host; "wasm32-wasi" is the other *)
|
|
opt : string;
|
|
keep : bool; (* leave the .ll behind *)
|
|
}
|
|
|
|
let default = { target = None; opt = "-O2"; keep = false }
|
|
|
|
let executable ?(opts = default) (p : Tast.program) ~out =
|
|
let dir = workdir () in
|
|
let ll = Filename.concat dir (Filename.basename out ^ ".ll") in
|
|
let rt = Filename.concat dir "flan_rt.c" in
|
|
write ll (Emit.program p);
|
|
write rt Runtime_src.source;
|
|
let cmd =
|
|
String.concat " "
|
|
([ Filename.quote clang; opts.opt; "-Wno-override-module" ]
|
|
@ (match opts.target with None -> [] | Some t -> [ "--target=" ^ t ])
|
|
@ [ Filename.quote ll; Filename.quote rt; "-o"; Filename.quote out ])
|
|
in
|
|
let code = Sys.command cmd in
|
|
if code <> 0 then
|
|
failwith (Printf.sprintf "%s failed (exit %d); the IR is at %s" clang code ll);
|
|
if not opts.keep then (try Sys.remove ll; Sys.remove rt with Sys_error _ -> ());
|
|
out
|