aboutsummaryrefslogtreecommitdiff
path: root/src/boot/driver
diff options
context:
space:
mode:
Diffstat (limited to 'src/boot/driver')
-rw-r--r--src/boot/driver/lib.ml232
-rw-r--r--src/boot/driver/llvm/glue.ml37
-rw-r--r--src/boot/driver/main.ml421
-rw-r--r--src/boot/driver/session.ml111
-rw-r--r--src/boot/driver/x86/glue.ml16
5 files changed, 817 insertions, 0 deletions
diff --git a/src/boot/driver/lib.ml b/src/boot/driver/lib.ml
new file mode 100644
index 00000000..e0391c65
--- /dev/null
+++ b/src/boot/driver/lib.ml
@@ -0,0 +1,232 @@
+open Common;;
+
+let log (sess:Session.sess) =
+ Session.log "lib"
+ sess.Session.sess_log_lib
+ sess.Session.sess_log_out
+;;
+
+let iflog (sess:Session.sess) (thunk:(unit -> unit)) : unit =
+ if sess.Session.sess_log_lib
+ then thunk ()
+ else ()
+;;
+
+(* FIXME: move these to sess. *)
+let ar_cache = Hashtbl.create 0 ;;
+let sects_cache = Hashtbl.create 0;;
+let meta_cache = Hashtbl.create 0;;
+let die_cache = Hashtbl.create 0;;
+
+let get_ar
+ (sess:Session.sess)
+ (filename:filename)
+ : Asm.asm_reader option =
+ htab_search_or_add ar_cache filename
+ begin
+ fun _ ->
+ let sniff =
+ match sess.Session.sess_targ with
+ Win32_x86_pe -> Pe.sniff
+ | MacOS_x86_macho -> Macho.sniff
+ | Linux_x86_elf -> Elf.sniff
+ in
+ sniff sess filename
+ end
+;;
+
+
+let get_sects
+ (sess:Session.sess)
+ (filename:filename) :
+ (Asm.asm_reader * ((string,(int*int)) Hashtbl.t)) option =
+ htab_search_or_add sects_cache filename
+ begin
+ fun _ ->
+ match get_ar sess filename with
+ None -> None
+ | Some ar ->
+ let get_sections =
+ match sess.Session.sess_targ with
+ Win32_x86_pe -> Pe.get_sections
+ | MacOS_x86_macho -> Macho.get_sections
+ | Linux_x86_elf -> Elf.get_sections
+ in
+ Some (ar, (get_sections sess ar))
+ end
+;;
+
+let get_meta
+ (sess:Session.sess)
+ (filename:filename)
+ : Ast.meta option =
+ htab_search_or_add meta_cache filename
+ begin
+ fun _ ->
+ match get_sects sess filename with
+ None -> None
+ | Some (ar, sects) ->
+ match htab_search sects ".note.rust" with
+ Some (off, _) ->
+ ar.Asm.asm_seek off;
+ Some (Asm.read_rust_note ar)
+ | None -> None
+ end
+;;
+
+let get_dies_opt
+ (sess:Session.sess)
+ (filename:filename)
+ : (Dwarf.rooted_dies option) =
+ htab_search_or_add die_cache filename
+ begin
+ fun _ ->
+ match get_sects sess filename with
+ None -> None
+ | Some (ar, sects) ->
+ let debug_abbrev = Hashtbl.find sects ".debug_abbrev" in
+ let debug_info = Hashtbl.find sects ".debug_info" in
+ let abbrevs = Dwarf.read_abbrevs sess ar debug_abbrev in
+ let dies = Dwarf.read_dies sess ar debug_info abbrevs in
+ ar.Asm.asm_close ();
+ Hashtbl.remove ar_cache filename;
+ Some dies
+ end
+;;
+
+let get_dies
+ (sess:Session.sess)
+ (filename:filename)
+ : Dwarf.rooted_dies =
+ match get_dies_opt sess filename with
+ None ->
+ Printf.fprintf stderr "Error: bad crate file: %s\n%!" filename;
+ exit 1
+ | Some dies -> dies
+;;
+
+let get_file_mod
+ (sess:Session.sess)
+ (abi:Abi.abi)
+ (filename:filename)
+ (nref:node_id ref)
+ (oref:opaque_id ref)
+ : Ast.mod_items =
+ let dies = get_dies sess filename in
+ let items = Hashtbl.create 0 in
+ Dwarf.extract_mod_items nref oref abi items dies;
+ items
+;;
+
+let get_mod
+ (sess:Session.sess)
+ (abi:Abi.abi)
+ (meta:Ast.meta_pat)
+ (use_id:node_id)
+ (nref:node_id ref)
+ (oref:opaque_id ref)
+ : (filename * Ast.mod_items) =
+ let found = Queue.create () in
+ let suffix =
+ match sess.Session.sess_targ with
+ Win32_x86_pe -> ".dll"
+ | MacOS_x86_macho -> ".dylib"
+ | Linux_x86_elf -> ".so"
+ in
+ let rec meta_matches i f_meta =
+ if i >= (Array.length meta)
+ then true
+ else
+ match meta.(i) with
+ (* FIXME: bind the wildcards. *)
+ (_, None) -> meta_matches (i+1) f_meta
+ | (k, Some v) ->
+ match atab_search f_meta k with
+ None -> false
+ | Some v' ->
+ if v = v'
+ then meta_matches (i+1) f_meta
+ else false
+ in
+ let file_matches file =
+ log sess "searching for metadata in %s" file;
+ match get_meta sess file with
+ None -> false
+ | Some f_meta ->
+ log sess "matching metadata in %s" file;
+ meta_matches 0 f_meta
+ in
+ iflog sess
+ begin
+ fun _ ->
+ log sess "searching for library matching:";
+ Array.iter
+ begin
+ fun (k,vo) ->
+ match vo with
+ None -> ()
+ | Some v ->
+ log sess "%s = %S" k v
+ end
+ meta;
+ end;
+ Queue.iter
+ begin
+ fun dir ->
+ let dh = Unix.opendir dir in
+ let rec scan _ =
+ try
+ let file = Unix.readdir dh in
+ log sess "considering file %s" file;
+ if (Filename.check_suffix file suffix) &&
+ (file_matches file)
+ then
+ begin
+ iflog sess
+ begin
+ fun _ ->
+ log sess "matched against library %s" file;
+ match get_meta sess file with
+ None -> ()
+ | Some meta ->
+ Array.iter
+ (fun (k,v) -> log sess "%s = %S" k v)
+ meta;
+ end;
+ Queue.add file found;
+ end;
+ scan()
+ with
+ End_of_file -> ()
+ in
+ scan ()
+ end
+ sess.Session.sess_lib_dirs;
+ match Queue.length found with
+ 0 -> Common.err (Some use_id) "unsatisfied 'use' clause"
+ | 1 ->
+ let filename = Queue.pop found in
+ let items = get_file_mod sess abi filename nref oref in
+ (filename, items)
+ | _ -> Common.err (Some use_id) "multiple crates match 'use' clause"
+;;
+
+let infer_lib_name
+ (sess:Session.sess)
+ (ident:filename)
+ : filename =
+ match sess.Session.sess_targ with
+ Win32_x86_pe -> ident ^ ".dll"
+ | MacOS_x86_macho -> "lib" ^ ident ^ ".dylib"
+ | Linux_x86_elf -> "lib" ^ ident ^ ".so"
+;;
+
+
+(*
+ * Local Variables:
+ * fill-column: 78;
+ * indent-tabs-mode: nil
+ * buffer-file-coding-system: utf-8-unix
+ * compile-command: "make -k -C ../.. 2>&1 | sed -e 's/\\/x\\//x:\\//g'";
+ * End:
+ *)
diff --git a/src/boot/driver/llvm/glue.ml b/src/boot/driver/llvm/glue.ml
new file mode 100644
index 00000000..ef5c1c86
--- /dev/null
+++ b/src/boot/driver/llvm/glue.ml
@@ -0,0 +1,37 @@
+(*
+ * Glue for the LLVM backend.
+ *)
+
+let alt_argspecs sess = [
+ ("-llvm", Arg.Unit (fun _ -> sess.Session.sess_alt_backend <- true),
+ "emit LLVM bitcode")
+];;
+
+let alt_pipeline sess sem_cx crate =
+ let process processor =
+ processor sem_cx crate;
+ if sess.Session.sess_failed then exit 1 else ()
+ in
+ Array.iter process
+ [|
+ Resolve.process_crate;
+ Type.process_crate;
+ Effect.process_crate;
+ Typestate.process_crate;
+ Loop.process_crate;
+ Alias.process_crate;
+ Dead.process_crate;
+ Layout.process_crate
+ |];
+ Llemit.trans_and_process_crate sess sem_cx crate
+;;
+
+(*
+ * Local Variables:
+ * fill-column: 78;
+ * indent-tabs-mode: nil
+ * buffer-file-coding-system: utf-8-unix
+ * compile-command: "make -k -C ../../.. 2>&1 | sed -e 's/\\/x\\//x:\\//g'";
+ * End:
+ *)
+
diff --git a/src/boot/driver/main.ml b/src/boot/driver/main.ml
new file mode 100644
index 00000000..c5199a82
--- /dev/null
+++ b/src/boot/driver/main.ml
@@ -0,0 +1,421 @@
+
+open Common;;
+
+let _ =
+ Gc.set { (Gc.get()) with
+ Gc.space_overhead = 400; }
+;;
+
+let (targ:Common.target) =
+ match Sys.os_type with
+ "Unix" ->
+ (* FIXME: this is an absurd heuristic. *)
+ if Sys.file_exists "/System/Library"
+ then MacOS_x86_macho
+ else Linux_x86_elf
+ | "Win32" -> Win32_x86_pe
+ | "Cygwin" -> Win32_x86_pe
+ | _ -> Linux_x86_elf
+;;
+
+let (abi:Abi.abi) = X86.abi;;
+
+let (sess:Session.sess) =
+ {
+ Session.sess_in = None;
+ Session.sess_out = None;
+ Session.sess_library_mode = false;
+ Session.sess_alt_backend = false;
+ (* FIXME: need something fancier here for unix sub-flavours. *)
+ Session.sess_targ = targ;
+ Session.sess_log_lex = false;
+ Session.sess_log_parse = false;
+ Session.sess_log_ast = false;
+ Session.sess_log_resolve = false;
+ Session.sess_log_type = false;
+ Session.sess_log_effect = false;
+ Session.sess_log_typestate = false;
+ Session.sess_log_loop = false;
+ Session.sess_log_alias = false;
+ Session.sess_log_dead = false;
+ Session.sess_log_layout = false;
+ Session.sess_log_itype = false;
+ Session.sess_log_trans = false;
+ Session.sess_log_dwarf = false;
+ Session.sess_log_ra = false;
+ Session.sess_log_insn = false;
+ Session.sess_log_asm = false;
+ Session.sess_log_obj = false;
+ Session.sess_log_lib = false;
+ Session.sess_log_out = stdout;
+ Session.sess_trace_block = false;
+ Session.sess_trace_drop = false;
+ Session.sess_trace_tag = false;
+ Session.sess_trace_gc = false;
+ Session.sess_failed = false;
+ Session.sess_spans = Hashtbl.create 0;
+ Session.sess_report_timing = false;
+ Session.sess_report_gc = false;
+ Session.sess_report_deps = false;
+ Session.sess_timings = Hashtbl.create 0;
+ Session.sess_lib_dirs = Queue.create ();
+ }
+;;
+
+let default_output_filename (sess:Session.sess) : filename option =
+ match sess.Session.sess_in with
+ None -> None
+ | Some fname ->
+ let base = Filename.chop_extension (Filename.basename fname) in
+ let out =
+ if sess.Session.sess_library_mode
+ then
+ Lib.infer_lib_name sess base
+ else
+ base ^ (match sess.Session.sess_targ with
+ Linux_x86_elf -> ""
+ | MacOS_x86_macho -> ""
+ | Win32_x86_pe -> ".exe")
+ in
+ Some out
+;;
+
+let set_default_output_filename (sess:Session.sess) : unit =
+ match sess.Session.sess_out with
+ None -> (sess.Session.sess_out <- default_output_filename sess)
+ | _ -> ()
+;;
+
+
+let dump_sig (filename:filename) : unit =
+ let items =
+ Lib.get_file_mod sess abi filename (ref (Node 0)) (ref (Opaque 0)) in
+ Printf.fprintf stdout "%s\n" (Ast.fmt_to_str Ast.fmt_mod_items items);
+ exit 0
+;;
+
+let dump_meta (filename:filename) : unit =
+ begin
+ match Lib.get_meta sess filename with
+ None -> Printf.fprintf stderr "Error: bad crate file: %s\n" filename
+ | Some meta ->
+ Array.iter
+ begin
+ fun (k,v) ->
+ Printf.fprintf stdout "%s = %S\n" k v;
+ end
+ meta
+ end;
+ exit 0
+;;
+
+let flag f opt desc =
+ (opt, Arg.Unit f, desc)
+;;
+
+let argspecs =
+ [
+ ("-t", Arg.Symbol (["linux-x86-elf"; "win32-x86-pe"; "macos-x86-macho"],
+ fun s -> (sess.Session.sess_targ <-
+ (match s with
+ "win32-x86-pe" -> Win32_x86_pe
+ | "macos-x86-macho" -> MacOS_x86_macho
+ | _ -> Linux_x86_elf))),
+ (" target (default: " ^ (match sess.Session.sess_targ with
+ Win32_x86_pe -> "win32-x86-pe"
+ | Linux_x86_elf -> "linux-x86-elf"
+ | MacOS_x86_macho -> "macos-x86-macho"
+ ) ^ ")"));
+ ("-o", Arg.String (fun s -> sess.Session.sess_out <- Some s),
+ "file to output (default: "
+ ^ (Session.filename_of sess.Session.sess_out) ^ ")");
+ ("-shared", Arg.Unit (fun _ -> sess.Session.sess_library_mode <- true),
+ "compile a shared-library crate");
+ ("-L", Arg.String (fun s -> Queue.add s sess.Session.sess_lib_dirs),
+ "dir to add to library path");
+ ("-litype", Arg.Unit (fun _ -> sess.Session.sess_log_itype <- true;
+ Il.log_iltypes := true), "log IL types");
+ (flag (fun _ -> sess.Session.sess_log_lex <- true)
+ "-llex" "log lexing");
+ (flag (fun _ -> sess.Session.sess_log_parse <- true)
+ "-lparse" "log parsing");
+ (flag (fun _ -> sess.Session.sess_log_ast <- true)
+ "-last" "log AST");
+ (flag (fun _ -> sess.Session.sess_log_resolve <- true)
+ "-lresolve" "log resolution");
+ (flag (fun _ -> sess.Session.sess_log_type <- true)
+ "-ltype" "log type checking");
+ (flag (fun _ -> sess.Session.sess_log_effect <- true)
+ "-leffect" "log effect checking");
+ (flag (fun _ -> sess.Session.sess_log_typestate <- true)
+ "-ltypestate" "log typestate pass");
+ (flag (fun _ -> sess.Session.sess_log_loop <- true)
+ "-lloop" "log loop analysis");
+ (flag (fun _ -> sess.Session.sess_log_alias <- true)
+ "-lalias" "log alias analysis");
+ (flag (fun _ -> sess.Session.sess_log_dead <- true)
+ "-ldead" "log dead analysis");
+ (flag (fun _ -> sess.Session.sess_log_layout <- true)
+ "-llayout" "log frame layout");
+ (flag (fun _ -> sess.Session.sess_log_trans <- true)
+ "-ltrans" "log IR translation");
+ (flag (fun _ -> sess.Session.sess_log_dwarf <- true)
+ "-ldwarf" "log DWARF generation");
+ (flag (fun _ -> sess.Session.sess_log_ra <- true)
+ "-lra" "log register allocation");
+ (flag (fun _ -> sess.Session.sess_log_insn <- true)
+ "-linsn" "log instruction selection");
+ (flag (fun _ -> sess.Session.sess_log_asm <- true)
+ "-lasm" "log assembly");
+ (flag (fun _ -> sess.Session.sess_log_obj <- true)
+ "-lobj" "log object-file generation");
+ (flag (fun _ -> sess.Session.sess_log_lib <- true)
+ "-llib" "log library search");
+
+ (flag (fun _ -> sess.Session.sess_trace_block <- true)
+ "-tblock" "emit block-boundary tracing code");
+ (flag (fun _ -> sess.Session.sess_trace_drop <- true)
+ "-tdrop" "emit slot-drop tracing code");
+ (flag (fun _ -> sess.Session.sess_trace_tag <- true)
+ "-ttag" "emit tag-construction tracing code");
+ (flag (fun _ -> sess.Session.sess_trace_gc <- true)
+ "-tgc" "emit GC tracing code");
+
+ ("-tall", Arg.Unit (fun _ ->
+ sess.Session.sess_trace_block <- true;
+ sess.Session.sess_trace_drop <- true;
+ sess.Session.sess_trace_tag <- true ),
+ "emit all tracing code");
+
+ (flag (fun _ -> sess.Session.sess_report_timing <- true)
+ "-rtime" "report timing of compiler phases");
+ (flag (fun _ -> sess.Session.sess_report_gc <- true)
+ "-rgc" "report gc behavior of compiler");
+ ("-rsig", Arg.String dump_sig,
+ "report type-signature from DWARF info in compiled file, then exit");
+ ("-rmeta", Arg.String dump_meta,
+ "report metadata from DWARF info in compiled file, then exit");
+ ("-rdeps", Arg.Unit (fun _ -> sess.Session.sess_report_deps <- true),
+ "report dependencies of input, then exit");
+ ] @ (Glue.alt_argspecs sess)
+;;
+
+let exit_if_failed _ =
+ if sess.Session.sess_failed
+ then exit 1
+ else ()
+;;
+
+Arg.parse
+ argspecs
+ (fun arg -> sess.Session.sess_in <- (Some arg))
+ ("usage: " ^ Sys.argv.(0) ^ " [options] (CRATE_FILE.rc|SOURCE_FILE.rs)\n")
+;;
+
+let _ = set_default_output_filename sess
+;;
+
+let _ =
+ if sess.Session.sess_out = None
+ then (Printf.fprintf stderr "Error: no output file specified\n"; exit 1)
+ else ()
+;;
+
+let _ =
+ if sess.Session.sess_in = None
+ then (Printf.fprintf stderr "Error: empty input filename\n"; exit 1)
+ else ()
+;;
+
+
+let (crate:Ast.crate) =
+ Session.time_inner "parse" sess
+ begin
+ fun _ ->
+ let infile = Session.filename_of sess.Session.sess_in in
+ let crate =
+ if Filename.check_suffix infile ".rc"
+ then
+ Cexp.parse_crate_file sess
+ (Lib.get_mod sess abi)
+ (Lib.infer_lib_name sess)
+ else
+ if Filename.check_suffix infile ".rs"
+ then
+ Cexp.parse_src_file sess
+ (Lib.get_mod sess abi)
+ (Lib.infer_lib_name sess)
+ else
+ begin
+ Printf.fprintf stderr
+ "Error: unrecognized input file type: %s\n"
+ infile;
+ exit 1
+ end
+ in
+ if sess.Session.sess_report_deps
+ then
+ let outfile = (Session.filename_of sess.Session.sess_out) in
+ let depfile =
+ match sess.Session.sess_targ with
+ Linux_x86_elf
+ | MacOS_x86_macho -> outfile ^ ".d"
+ | Win32_x86_pe -> (Filename.chop_extension outfile) ^ ".d"
+ in
+ begin
+ Array.iter
+ begin
+ fun out ->
+ Printf.fprintf stdout "%s: \\\n" out;
+ Hashtbl.iter
+ (fun _ file ->
+ Printf.fprintf stdout " %s \\\n" file)
+ crate.node.Ast.crate_files;
+ Printf.fprintf stdout "\n"
+ end
+ [| outfile; depfile|];
+ exit 0
+ end
+ else
+ crate
+ end
+;;
+
+exit_if_failed ()
+;;
+
+if sess.Session.sess_log_ast
+then
+ begin
+ Printf.fprintf stdout "Post-parse AST:\n";
+ Format.set_margin 80;
+ Printf.fprintf stdout "%s\n" (Ast.fmt_to_str Ast.fmt_crate crate)
+ end
+
+let list_to_seq ls = Asm.SEQ (Array.of_list ls);;
+let select_insns (quads:Il.quads) : Asm.frag =
+ Session.time_inner "insn" sess
+ (fun _ -> X86.select_insns sess quads)
+;;
+
+
+(* Semantic passes. *)
+let sem_cx = Semant.new_ctxt sess abi crate.node
+;;
+
+
+let main_pipeline _ =
+ let _ =
+ Array.iter
+ (fun proc ->
+ proc sem_cx crate;
+ exit_if_failed ())
+ [| Resolve.process_crate;
+ Type.process_crate;
+ Effect.process_crate;
+ Typestate.process_crate;
+ Loop.process_crate;
+ Alias.process_crate;
+ Dead.process_crate;
+ Layout.process_crate;
+ Trans.process_crate |]
+ in
+
+ (* Tying up various knots, allocating registers and selecting
+ * instructions.
+ *)
+ let process_code _ (code:Semant.code) : Asm.frag =
+ let frag =
+ match code.Semant.code_vregs_and_spill with
+ None -> select_insns code.Semant.code_quads
+ | Some (n_vregs, spill_fix) ->
+ let (quads', n_spills) =
+ (Session.time_inner "RA" sess
+ (fun _ ->
+ Ra.reg_alloc sess
+ code.Semant.code_quads
+ n_vregs abi))
+ in
+ let insns = select_insns quads' in
+ begin
+ spill_fix.fixup_mem_sz <-
+ Some (Int64.mul
+ (Int64.of_int n_spills)
+ abi.Abi.abi_word_sz);
+ insns
+ end
+ in
+ Asm.ALIGN_FILE (Abi.general_code_alignment,
+ Asm.DEF (code.Semant.code_fixup, frag))
+ in
+
+ let (file_frags:Asm.frag) =
+ let process_file file_id frag_code =
+ let file_fix = Hashtbl.find sem_cx.Semant.ctxt_file_fixups file_id in
+ Asm.DEF (file_fix,
+ list_to_seq (reduce_hash_to_list process_code frag_code))
+ in
+ list_to_seq (reduce_hash_to_list
+ process_file sem_cx.Semant.ctxt_file_code)
+ in
+
+ exit_if_failed ();
+ let (glue_frags:Asm.frag) =
+ list_to_seq (reduce_hash_to_list
+ process_code sem_cx.Semant.ctxt_glue_code)
+ in
+
+ exit_if_failed ();
+ let code = Asm.SEQ [| file_frags; glue_frags |] in
+ let data = list_to_seq (reduce_hash_to_list
+ (fun _ (_, i) -> i) sem_cx.Semant.ctxt_data)
+ in
+ (* Emitting Dwarf and PE/ELF/Macho. *)
+ let (dwarf:Dwarf.debug_records) =
+ Session.time_inner "dwarf" sess
+ (fun _ -> Dwarf.process_crate sem_cx crate)
+ in
+
+ exit_if_failed ();
+ let emitter =
+ match sess.Session.sess_targ with
+ Win32_x86_pe -> Pe.emit_file
+ | MacOS_x86_macho -> Macho.emit_file
+ | Linux_x86_elf -> Elf.emit_file
+ in
+ Session.time_inner "emit" sess
+ (fun _ -> emitter sess crate code data sem_cx dwarf);
+ exit_if_failed ()
+;;
+
+if sess.Session.sess_alt_backend
+then Glue.alt_pipeline sess sem_cx crate
+else main_pipeline ()
+;;
+
+if sess.Session.sess_report_timing
+then
+ begin
+ Printf.fprintf stdout "timing:\n\n";
+ Array.iter
+ begin
+ fun name ->
+ Printf.fprintf stdout "%20s: %f\n" name
+ (Hashtbl.find sess.Session.sess_timings name)
+ end
+ (sorted_htab_keys sess.Session.sess_timings)
+ end;
+;;
+
+if sess.Session.sess_report_gc
+then Gc.print_stat stdout;;
+
+
+(*
+ * Local Variables:
+ * fill-column: 78;
+ * indent-tabs-mode: nil
+ * buffer-file-coding-system: utf-8-unix
+ * compile-command: "make -k -C ../.. 2>&1 | sed -e 's/\\/x\\//x:\\//g'";
+ * End:
+ *)
diff --git a/src/boot/driver/session.ml b/src/boot/driver/session.ml
new file mode 100644
index 00000000..80253f44
--- /dev/null
+++ b/src/boot/driver/session.ml
@@ -0,0 +1,111 @@
+(*
+ * This module goes near the bottom of the dependency DAG, and holds option,
+ * and global-state machinery for a single run of the compiler.
+ *)
+
+open Common;;
+
+type sess =
+{
+ mutable sess_in: filename option;
+ mutable sess_out: filename option;
+ mutable sess_library_mode: bool;
+ mutable sess_alt_backend: bool;
+ mutable sess_targ: target;
+ mutable sess_log_lex: bool;
+ mutable sess_log_parse: bool;
+ mutable sess_log_ast: bool;
+ mutable sess_log_resolve: bool;
+ mutable sess_log_type: bool;
+ mutable sess_log_effect: bool;
+ mutable sess_log_typestate: bool;
+ mutable sess_log_dead: bool;
+ mutable sess_log_loop: bool;
+ mutable sess_log_alias: bool;
+ mutable sess_log_layout: bool;
+ mutable sess_log_trans: bool;
+ mutable sess_log_itype: bool;
+ mutable sess_log_dwarf: bool;
+ mutable sess_log_ra: bool;
+ mutable sess_log_insn: bool;
+ mutable sess_log_asm: bool;
+ mutable sess_log_obj: bool;
+ mutable sess_log_lib: bool;
+ mutable sess_log_out: out_channel;
+ mutable sess_trace_block: bool;
+ mutable sess_trace_drop: bool;
+ mutable sess_trace_tag: bool;
+ mutable sess_trace_gc: bool;
+ mutable sess_failed: bool;
+ mutable sess_report_timing: bool;
+ mutable sess_report_gc: bool;
+ mutable sess_report_deps: bool;
+ sess_timings: (string, float) Hashtbl.t;
+ sess_spans: (node_id,span) Hashtbl.t;
+ sess_lib_dirs: filename Queue.t;
+}
+;;
+
+let add_time sess name amt =
+ let existing =
+ if Hashtbl.mem sess.sess_timings name
+ then Hashtbl.find sess.sess_timings name
+ else 0.0
+ in
+ (Hashtbl.replace sess.sess_timings name (existing +. amt))
+;;
+
+let time_inner name sess thunk =
+ let t0 = Unix.gettimeofday() in
+ let x = thunk() in
+ let t1 = Unix.gettimeofday() in
+ add_time sess name (t1 -. t0);
+ x
+;;
+
+let get_span sess id =
+ if Hashtbl.mem sess.sess_spans id
+ then (Some (Hashtbl.find sess.sess_spans id))
+ else None
+;;
+
+let log name flag chan =
+ let k1 s =
+ Printf.fprintf chan "%s: %s\n%!" name s
+ in
+ let k2 _ = () in
+ Printf.ksprintf (if flag then k1 else k2)
+;;
+
+let fail sess =
+ sess.sess_failed <- true;
+ Printf.fprintf sess.sess_log_out
+;;
+
+
+let string_of_pos (p:pos) =
+ let (filename, line, col) = p in
+ Printf.sprintf "%s:%d:%d" filename line col
+;;
+
+
+let string_of_span (s:span) =
+ let (filename, line0, col0) = s.lo in
+ let (_, line1, col1) = s.hi in
+ Printf.sprintf "%s:%d:%d - %d:%d" filename line0 col0 line1 col1
+;;
+
+let filename_of (fo:filename option) : filename =
+ match fo with
+ None -> "<none>"
+ | Some f -> f
+;;
+
+(*
+ * Local Variables:
+ * fill-column: 78;
+ * indent-tabs-mode: nil
+ * buffer-file-coding-system: utf-8-unix
+ * compile-command: "make -k -C ../.. 2>&1 | sed -e 's/\\/x\\//x:\\//g'";
+ * End:
+ *)
diff --git a/src/boot/driver/x86/glue.ml b/src/boot/driver/x86/glue.ml
new file mode 100644
index 00000000..4fc74480
--- /dev/null
+++ b/src/boot/driver/x86/glue.ml
@@ -0,0 +1,16 @@
+(*
+ * Glue, or lack thereof, for the standard x86 backend.
+ *)
+
+let alt_argspecs _ = [];;
+let alt_pipeline _ _ _ = ();;
+
+(*
+ * Local Variables:
+ * fill-column: 78;
+ * indent-tabs-mode: nil
+ * buffer-file-coding-system: utf-8-unix
+ * compile-command: "make -k -C ../.. 2>&1 | sed -e 's/\\/x\\//x:\\//g'";
+ * End:
+ *)
+