(* Step 2: reach enough of the compiler that the linker cannot drop it, and do real compiler work in-process so the measurement is of a working compiler rather than of dead code that happened to link. The work is the driver's own path, the one bin/main.ml takes: read -> Parse.program -> Load.program -> Check.program -> Emit.program. That is the whole front end and the whole back end short of [llc]. Check.program prepends the prelude itself, so the prelude is in the measurement without being fed in twice. *) let compile file = let l = Flan.Load.program ~file (Flan.Parse.program (Flan.Reader.read_file file)) in let p = Flan.Check.program l.Flan.Load.decls in let ir = Flan.Emit.program ~dev:true p in (List.length l.Flan.Load.decls, String.length ir) (* Touched only so the linker keeps the modules a merged dev build would carry. Nothing here is called for its effect. *) let footprint () = String.concat "," [ Flan.Build.clang; string_of_int (String.length Flan.Shim.header); string_of_int (String.length Flan.Runtime_src.source); string_of_int (String.length Flan.Runtime_src.dev_source); string_of_int (List.length Flan.Session.externs); string_of_int (Flan.Render.max_span); string_of_int (String.length (Flan.Wire.ints [ 1; 2 ])) ] let () = Callback.register "spike_compile" (fun (file : string) -> match compile file with | d, n -> Printf.sprintf "%s: %d decls, %d bytes of LLVM IR" file d n | exception e -> Printf.sprintf "FAILED: %s" (Printexc.to_string e)); Callback.register "spike_footprint" footprint; (* Dev.start and Cimport are never run here, but naming them keeps the socket server and the C importer in the link -- a dev build pays for them. *) Callback.register "spike_unused" (fun () -> ignore (Flan.Dev.start : ?debug:bool -> file:string -> sock:string -> unit -> unit); ignore (Flan.Cimport.decl_source : Flan.Ast.decl -> string); "ok")