1995-08-09 08:06:35 -07:00
|
|
|
(***********************************************************************)
|
|
|
|
(* *)
|
2011-07-27 07:17:02 -07:00
|
|
|
(* OCaml *)
|
1995-08-09 08:06:35 -07:00
|
|
|
(* *)
|
|
|
|
(* Xavier Leroy, projet Cristal, INRIA Rocquencourt *)
|
|
|
|
(* *)
|
1996-04-30 07:53:58 -07:00
|
|
|
(* Copyright 1996 Institut National de Recherche en Informatique et *)
|
1999-11-17 10:59:06 -08:00
|
|
|
(* en Automatique. All rights reserved. This file is distributed *)
|
|
|
|
(* under the terms of the Q Public License version 1.0. *)
|
1995-08-09 08:06:35 -07:00
|
|
|
(* *)
|
|
|
|
(***********************************************************************)
|
|
|
|
|
|
|
|
(* $Id$ *)
|
|
|
|
|
1995-05-04 03:15:53 -07:00
|
|
|
(* Generation of bytecode + relocation information *)
|
|
|
|
|
|
|
|
open Config
|
|
|
|
open Misc
|
|
|
|
open Asttypes
|
|
|
|
open Lambda
|
|
|
|
open Instruct
|
|
|
|
open Opcodes
|
2006-05-11 08:50:53 -07:00
|
|
|
open Cmo_format
|
1995-05-04 03:15:53 -07:00
|
|
|
|
|
|
|
(* Buffering of bytecode *)
|
|
|
|
|
|
|
|
let out_buffer = ref(String.create 1024)
|
|
|
|
and out_position = ref 0
|
|
|
|
|
|
|
|
let out_word b1 b2 b3 b4 =
|
|
|
|
let p = !out_position in
|
|
|
|
if p >= String.length !out_buffer then begin
|
|
|
|
let len = String.length !out_buffer in
|
|
|
|
let new_buffer = String.create (2 * len) in
|
|
|
|
String.blit !out_buffer 0 new_buffer 0 len;
|
|
|
|
out_buffer := new_buffer
|
|
|
|
end;
|
|
|
|
String.unsafe_set !out_buffer p (Char.unsafe_chr b1);
|
|
|
|
String.unsafe_set !out_buffer (p+1) (Char.unsafe_chr b2);
|
|
|
|
String.unsafe_set !out_buffer (p+2) (Char.unsafe_chr b3);
|
|
|
|
String.unsafe_set !out_buffer (p+3) (Char.unsafe_chr b4);
|
|
|
|
out_position := p + 4
|
|
|
|
|
|
|
|
let out opcode =
|
|
|
|
out_word opcode 0 0 0
|
|
|
|
|
2000-10-02 07:18:05 -07:00
|
|
|
|
|
|
|
exception AsInt
|
|
|
|
|
|
|
|
let const_as_int = function
|
|
|
|
| Const_base(Const_int i) -> i
|
|
|
|
| Const_base(Const_char c) -> Char.code c
|
|
|
|
| Const_pointer i -> i
|
|
|
|
| _ -> raise AsInt
|
|
|
|
|
|
|
|
let is_immed i = immed_min <= i && i <= immed_max
|
|
|
|
let is_immed_const k =
|
|
|
|
try
|
|
|
|
is_immed (const_as_int k)
|
|
|
|
with
|
|
|
|
| AsInt -> false
|
|
|
|
|
|
|
|
|
1995-05-04 03:15:53 -07:00
|
|
|
let out_int n =
|
|
|
|
out_word n (n asr 8) (n asr 16) (n asr 24)
|
|
|
|
|
2000-10-02 07:18:05 -07:00
|
|
|
let out_const c =
|
|
|
|
try
|
|
|
|
out_int (const_as_int c)
|
|
|
|
with
|
|
|
|
| AsInt -> Misc.fatal_error "Emitcode.const_as_int"
|
2010-01-22 04:48:24 -08:00
|
|
|
|
2000-10-02 07:18:05 -07:00
|
|
|
|
1995-05-04 03:15:53 -07:00
|
|
|
(* Handling of local labels and backpatching *)
|
|
|
|
|
|
|
|
type label_definition =
|
|
|
|
Label_defined of int
|
|
|
|
| Label_undefined of (int * int) list
|
|
|
|
|
|
|
|
let label_table = ref ([| |] : label_definition array)
|
|
|
|
|
|
|
|
let extend_label_table needed =
|
|
|
|
let new_size = ref(Array.length !label_table) in
|
|
|
|
while needed >= !new_size do new_size := 2 * !new_size done;
|
1996-04-22 04:15:41 -07:00
|
|
|
let new_table = Array.create !new_size (Label_undefined []) in
|
1995-05-04 03:15:53 -07:00
|
|
|
Array.blit !label_table 0 new_table 0 (Array.length !label_table);
|
|
|
|
label_table := new_table
|
|
|
|
|
|
|
|
let backpatch (pos, orig) =
|
1997-03-13 10:21:01 -08:00
|
|
|
let displ = (!out_position - orig) asr 2 in
|
1995-05-04 03:15:53 -07:00
|
|
|
!out_buffer.[pos] <- Char.unsafe_chr displ;
|
1997-03-13 10:21:01 -08:00
|
|
|
!out_buffer.[pos+1] <- Char.unsafe_chr (displ asr 8);
|
|
|
|
!out_buffer.[pos+2] <- Char.unsafe_chr (displ asr 16);
|
|
|
|
!out_buffer.[pos+3] <- Char.unsafe_chr (displ asr 24)
|
1995-05-04 03:15:53 -07:00
|
|
|
|
|
|
|
let define_label lbl =
|
|
|
|
if lbl >= Array.length !label_table then extend_label_table lbl;
|
|
|
|
match (!label_table).(lbl) with
|
|
|
|
Label_defined _ ->
|
|
|
|
fatal_error "Emitcode.define_label"
|
|
|
|
| Label_undefined patchlist ->
|
|
|
|
List.iter backpatch patchlist;
|
|
|
|
(!label_table).(lbl) <- Label_defined !out_position
|
|
|
|
|
|
|
|
let out_label_with_orig orig lbl =
|
|
|
|
if lbl >= Array.length !label_table then extend_label_table lbl;
|
|
|
|
match (!label_table).(lbl) with
|
|
|
|
Label_defined def ->
|
1997-03-13 10:21:01 -08:00
|
|
|
out_int((def - orig) asr 2)
|
1995-05-04 03:15:53 -07:00
|
|
|
| Label_undefined patchlist ->
|
|
|
|
(!label_table).(lbl) <-
|
|
|
|
Label_undefined((!out_position, orig) :: patchlist);
|
|
|
|
out_int 0
|
|
|
|
|
|
|
|
let out_label l = out_label_with_orig !out_position l
|
|
|
|
|
|
|
|
(* Relocation information *)
|
|
|
|
|
|
|
|
let reloc_info = ref ([] : (reloc_info * int) list)
|
|
|
|
|
|
|
|
let enter info =
|
|
|
|
reloc_info := (info, !out_position) :: !reloc_info
|
|
|
|
|
|
|
|
let slot_for_literal sc =
|
|
|
|
enter (Reloc_literal sc);
|
|
|
|
out_int 0
|
|
|
|
and slot_for_getglobal id =
|
|
|
|
enter (Reloc_getglobal id);
|
|
|
|
out_int 0
|
|
|
|
and slot_for_setglobal id =
|
|
|
|
enter (Reloc_setglobal id);
|
|
|
|
out_int 0
|
|
|
|
and slot_for_c_prim name =
|
|
|
|
enter (Reloc_primitive name);
|
|
|
|
out_int 0
|
|
|
|
|
1996-11-29 10:36:42 -08:00
|
|
|
(* Debugging events *)
|
|
|
|
|
|
|
|
let events = ref ([] : debug_event list)
|
|
|
|
|
|
|
|
let record_event ev =
|
|
|
|
ev.ev_pos <- !out_position;
|
|
|
|
events := ev :: !events
|
|
|
|
|
1995-05-04 03:15:53 -07:00
|
|
|
(* Initialization *)
|
|
|
|
|
|
|
|
let init () =
|
|
|
|
out_position := 0;
|
1996-04-22 04:15:41 -07:00
|
|
|
label_table := Array.create 16 (Label_undefined []);
|
1996-11-29 10:36:42 -08:00
|
|
|
reloc_info := [];
|
|
|
|
events := []
|
1995-05-04 03:15:53 -07:00
|
|
|
|
|
|
|
(* Emission of one instruction *)
|
|
|
|
|
2000-10-02 07:18:05 -07:00
|
|
|
let emit_comp = function
|
|
|
|
| Ceq -> out opEQ | Cneq -> out opNEQ
|
|
|
|
| Clt -> out opLTINT | Cle -> out opLEINT
|
|
|
|
| Cgt -> out opGTINT | Cge -> out opGEINT
|
|
|
|
|
|
|
|
and emit_branch_comp = function
|
|
|
|
| Ceq -> out opBEQ | Cneq -> out opBNEQ
|
|
|
|
| Clt -> out opBLTINT | Cle -> out opBLEINT
|
|
|
|
| Cgt -> out opBGTINT | Cge -> out opBGEINT
|
|
|
|
|
1995-05-04 03:15:53 -07:00
|
|
|
let emit_instr = function
|
|
|
|
Klabel lbl -> define_label lbl
|
|
|
|
| Kacc n ->
|
|
|
|
if n < 8 then out(opACC0 + n) else (out opACC; out_int n)
|
|
|
|
| Kenvacc n ->
|
1999-11-08 07:27:26 -08:00
|
|
|
if n >= 1 && n <= 4
|
1998-04-06 02:15:55 -07:00
|
|
|
then out(opENVACC1 + n - 1)
|
|
|
|
else (out opENVACC; out_int n)
|
1995-05-04 03:15:53 -07:00
|
|
|
| Kpush ->
|
|
|
|
out opPUSH
|
|
|
|
| Kpop n ->
|
|
|
|
out opPOP; out_int n
|
|
|
|
| Kassign n ->
|
|
|
|
out opASSIGN; out_int n
|
|
|
|
| Kpush_retaddr lbl -> out opPUSH_RETADDR; out_label lbl
|
|
|
|
| Kapply n ->
|
|
|
|
if n < 4 then out(opAPPLY1 + n - 1) else (out opAPPLY; out_int n)
|
|
|
|
| Kappterm(n, sz) ->
|
|
|
|
if n < 4 then (out(opAPPTERM1 + n - 1); out_int sz)
|
|
|
|
else (out opAPPTERM; out_int n; out_int sz)
|
|
|
|
| Kreturn n -> out opRETURN; out_int n
|
|
|
|
| Krestart -> out opRESTART
|
|
|
|
| Kgrab n -> out opGRAB; out_int n
|
|
|
|
| Kclosure(lbl, n) -> out opCLOSURE; out_int n; out_label lbl
|
1998-04-06 02:15:55 -07:00
|
|
|
| Kclosurerec(lbls, n) ->
|
|
|
|
out opCLOSUREREC; out_int (List.length lbls); out_int n;
|
|
|
|
let org = !out_position in
|
|
|
|
List.iter (out_label_with_orig org) lbls
|
|
|
|
| Koffsetclosure ofs ->
|
|
|
|
if ofs = -2 || ofs = 0 || ofs = 2
|
|
|
|
then out (opOFFSETCLOSURE0 + ofs / 2)
|
|
|
|
else (out opOFFSETCLOSURE; out_int ofs)
|
1995-05-04 03:15:53 -07:00
|
|
|
| Kgetglobal q -> out opGETGLOBAL; slot_for_getglobal q
|
|
|
|
| Ksetglobal q -> out opSETGLOBAL; slot_for_setglobal q
|
|
|
|
| Kconst sc ->
|
|
|
|
begin match sc with
|
2000-10-02 07:18:05 -07:00
|
|
|
Const_base(Const_int i) when is_immed i ->
|
2000-12-28 05:07:42 -08:00
|
|
|
if i >= 0 && i <= 3
|
1995-06-18 07:44:56 -07:00
|
|
|
then out (opCONST0 + i)
|
|
|
|
else (out opCONSTINT; out_int i)
|
1995-05-04 03:15:53 -07:00
|
|
|
| Const_base(Const_char c) ->
|
|
|
|
out opCONSTINT; out_int (Char.code c)
|
1995-07-02 09:45:21 -07:00
|
|
|
| Const_pointer i ->
|
2000-12-28 05:07:42 -08:00
|
|
|
if i >= 0 && i <= 3
|
1995-07-02 09:45:21 -07:00
|
|
|
then out (opCONST0 + i)
|
|
|
|
else (out opCONSTINT; out_int i)
|
1995-05-04 03:15:53 -07:00
|
|
|
| Const_block(t, []) ->
|
1995-06-18 07:44:56 -07:00
|
|
|
if t = 0 then out opATOM0 else (out opATOM; out_int t)
|
1995-05-04 03:15:53 -07:00
|
|
|
| _ ->
|
|
|
|
out opGETGLOBAL; slot_for_literal sc
|
|
|
|
end
|
|
|
|
| Kmakeblock(n, t) ->
|
|
|
|
if n = 0 then
|
1999-11-08 07:27:26 -08:00
|
|
|
if t = 0 then out opATOM0 else (out opATOM; out_int t)
|
1995-05-04 03:15:53 -07:00
|
|
|
else if n < 4 then (out(opMAKEBLOCK1 + n - 1); out_int t)
|
|
|
|
else (out opMAKEBLOCK; out_int n; out_int t)
|
|
|
|
| Kgetfield n ->
|
|
|
|
if n < 4 then out(opGETFIELD0 + n) else (out opGETFIELD; out_int n)
|
|
|
|
| Ksetfield n ->
|
|
|
|
if n < 4 then out(opSETFIELD0 + n) else (out opSETFIELD; out_int n)
|
1998-04-06 02:15:55 -07:00
|
|
|
| Kmakefloatblock(n) ->
|
|
|
|
if n = 0 then out opATOM0 else (out opMAKEFLOATBLOCK; out_int n)
|
|
|
|
| Kgetfloatfield n -> out opGETFLOATFIELD; out_int n
|
|
|
|
| Ksetfloatfield n -> out opSETFLOATFIELD; out_int n
|
1995-05-04 03:15:53 -07:00
|
|
|
| Kvectlength -> out opVECTLENGTH
|
|
|
|
| Kgetvectitem -> out opGETVECTITEM
|
|
|
|
| Ksetvectitem -> out opSETVECTITEM
|
|
|
|
| Kgetstringchar -> out opGETSTRINGCHAR
|
|
|
|
| Ksetstringchar -> out opSETSTRINGCHAR
|
|
|
|
| Kbranch lbl -> out opBRANCH; out_label lbl
|
|
|
|
| Kbranchif lbl -> out opBRANCHIF; out_label lbl
|
|
|
|
| Kbranchifnot lbl -> out opBRANCHIFNOT; out_label lbl
|
|
|
|
| Kstrictbranchif lbl -> out opBRANCHIF; out_label lbl
|
|
|
|
| Kstrictbranchifnot lbl -> out opBRANCHIFNOT; out_label lbl
|
1995-06-18 07:44:56 -07:00
|
|
|
| Kswitch(tbl_const, tbl_block) ->
|
|
|
|
out opSWITCH;
|
|
|
|
out_int (Array.length tbl_const + (Array.length tbl_block lsl 16));
|
1995-05-04 03:15:53 -07:00
|
|
|
let org = !out_position in
|
1995-06-18 07:44:56 -07:00
|
|
|
Array.iter (out_label_with_orig org) tbl_const;
|
|
|
|
Array.iter (out_label_with_orig org) tbl_block
|
1995-05-04 03:15:53 -07:00
|
|
|
| Kboolnot -> out opBOOLNOT
|
|
|
|
| Kpushtrap lbl -> out opPUSHTRAP; out_label lbl
|
|
|
|
| Kpoptrap -> out opPOPTRAP
|
|
|
|
| Kraise -> out opRAISE
|
|
|
|
| Kcheck_signals -> out opCHECK_SIGNALS
|
|
|
|
| Kccall(name, n) ->
|
1995-07-11 11:05:47 -07:00
|
|
|
if n <= 5
|
1995-05-04 03:15:53 -07:00
|
|
|
then (out (opC_CALL1 + n - 1); slot_for_c_prim name)
|
|
|
|
else (out opC_CALLN; out_int n; slot_for_c_prim name)
|
|
|
|
| Knegint -> out opNEGINT | Kaddint -> out opADDINT
|
|
|
|
| Ksubint -> out opSUBINT | Kmulint -> out opMULINT
|
|
|
|
| Kdivint -> out opDIVINT | Kmodint -> out opMODINT
|
|
|
|
| Kandint -> out opANDINT | Korint -> out opORINT
|
|
|
|
| Kxorint -> out opXORINT | Klslint -> out opLSLINT
|
|
|
|
| Klsrint -> out opLSRINT | Kasrint -> out opASRINT
|
2000-10-02 07:18:05 -07:00
|
|
|
| Kintcomp c -> emit_comp c
|
1995-05-04 03:15:53 -07:00
|
|
|
| Koffsetint n -> out opOFFSETINT; out_int n
|
|
|
|
| Koffsetref n -> out opOFFSETREF; out_int n
|
1999-12-06 08:59:24 -08:00
|
|
|
| Kisint -> out opISINT
|
2000-10-02 07:18:05 -07:00
|
|
|
| Kisout -> out opULTINT
|
1996-04-22 04:15:41 -07:00
|
|
|
| Kgetmethod -> out opGETMETHOD
|
2004-05-26 04:10:52 -07:00
|
|
|
| Kgetpubmet tag -> out opGETPUBMET; out_int tag; out_int 0
|
|
|
|
| Kgetdynmet -> out opGETDYNMET
|
1996-11-29 10:36:42 -08:00
|
|
|
| Kevent ev -> record_event ev
|
1995-05-04 03:15:53 -07:00
|
|
|
| Kstop -> out opSTOP
|
|
|
|
|
|
|
|
(* Emission of a list of instructions. Include some peephole optimization. *)
|
|
|
|
|
|
|
|
let rec emit = function
|
|
|
|
[] -> ()
|
|
|
|
(* Peephole optimizations *)
|
2000-10-02 07:18:05 -07:00
|
|
|
(* optimization of integer tests *)
|
|
|
|
| Kpush::Kconst k::Kintcomp c::Kbranchif lbl::rem
|
|
|
|
when is_immed_const k ->
|
|
|
|
emit_branch_comp c ;
|
|
|
|
out_const k ;
|
|
|
|
out_label lbl ;
|
|
|
|
emit rem
|
|
|
|
| Kpush::Kconst k::Kintcomp c::Kbranchifnot lbl::rem
|
|
|
|
when is_immed_const k ->
|
|
|
|
emit_branch_comp (negate_comparison c) ;
|
|
|
|
out_const k ;
|
|
|
|
out_label lbl ;
|
|
|
|
emit rem
|
|
|
|
(* same for range tests *)
|
|
|
|
| Kpush::Kconst k::Kisout::Kbranchif lbl::rem
|
|
|
|
when is_immed_const k ->
|
|
|
|
out opBULTINT ;
|
|
|
|
out_const k ;
|
|
|
|
out_label lbl ;
|
|
|
|
emit rem
|
|
|
|
| Kpush::Kconst k::Kisout::Kbranchifnot lbl::rem
|
|
|
|
when is_immed_const k ->
|
|
|
|
out opBUGEINT ;
|
|
|
|
out_const k ;
|
|
|
|
out_label lbl ;
|
|
|
|
emit rem
|
2001-03-30 05:35:15 -08:00
|
|
|
(* Some special case of push ; i ; ret generated by the match compiler *)
|
|
|
|
| Kpush :: Kacc 0 :: Kreturn m :: c ->
|
|
|
|
emit (Kreturn (m-1) :: c)
|
|
|
|
(* General push then access scheme *)
|
1995-05-04 03:15:53 -07:00
|
|
|
| Kpush :: Kacc n :: c ->
|
|
|
|
if n < 8 then out(opPUSHACC0 + n) else (out opPUSHACC; out_int n);
|
|
|
|
emit c
|
|
|
|
| Kpush :: Kenvacc n :: c ->
|
1998-04-06 02:15:55 -07:00
|
|
|
if n >= 1 && n < 4
|
|
|
|
then out(opPUSHENVACC1 + n - 1)
|
|
|
|
else (out opPUSHENVACC; out_int n);
|
|
|
|
emit c
|
|
|
|
| Kpush :: Koffsetclosure ofs :: c ->
|
|
|
|
if ofs = -2 || ofs = 0 || ofs = 2
|
|
|
|
then out(opPUSHOFFSETCLOSURE0 + ofs / 2)
|
|
|
|
else (out opPUSHOFFSETCLOSURE; out_int ofs);
|
1995-05-04 03:15:53 -07:00
|
|
|
emit c
|
|
|
|
| Kpush :: Kgetglobal id :: Kgetfield n :: c ->
|
1996-05-27 07:19:02 -07:00
|
|
|
out opPUSHGETGLOBALFIELD; slot_for_getglobal id; out_int n; emit c
|
1997-02-19 08:08:05 -08:00
|
|
|
| Kpush :: Kgetglobal id :: c ->
|
|
|
|
out opPUSHGETGLOBAL; slot_for_getglobal id; emit c
|
1995-05-04 03:15:53 -07:00
|
|
|
| Kpush :: Kconst sc :: c ->
|
|
|
|
begin match sc with
|
2000-10-02 07:18:05 -07:00
|
|
|
Const_base(Const_int i) when is_immed i ->
|
2000-12-28 05:07:42 -08:00
|
|
|
if i >= 0 && i <= 3
|
1995-06-18 07:44:56 -07:00
|
|
|
then out (opPUSHCONST0 + i)
|
|
|
|
else (out opPUSHCONSTINT; out_int i)
|
1995-05-04 03:15:53 -07:00
|
|
|
| Const_base(Const_char c) ->
|
|
|
|
out opPUSHCONSTINT; out_int(Char.code c)
|
1997-02-19 08:08:05 -08:00
|
|
|
| Const_pointer i ->
|
2000-12-28 05:07:42 -08:00
|
|
|
if i >= 0 && i <= 3
|
1997-02-19 08:08:05 -08:00
|
|
|
then out (opPUSHCONST0 + i)
|
|
|
|
else (out opPUSHCONSTINT; out_int i)
|
1995-05-04 03:15:53 -07:00
|
|
|
| Const_block(t, []) ->
|
1995-06-18 07:44:56 -07:00
|
|
|
if t = 0 then out opPUSHATOM0 else (out opPUSHATOM; out_int t)
|
1995-05-04 03:15:53 -07:00
|
|
|
| _ ->
|
|
|
|
out opPUSHGETGLOBAL; slot_for_literal sc
|
|
|
|
end;
|
|
|
|
emit c
|
1997-02-19 08:08:05 -08:00
|
|
|
| Kpush :: (Kevent {ev_kind = Event_before} as ev) ::
|
|
|
|
(Kgetglobal _ as instr1) :: (Kgetfield _ as instr2) :: c ->
|
|
|
|
emit (Kpush :: instr1 :: instr2 :: ev :: c)
|
|
|
|
| Kpush :: (Kevent {ev_kind = Event_before} as ev) ::
|
1998-04-06 02:15:55 -07:00
|
|
|
(Kacc _ | Kenvacc _ | Koffsetclosure _ | Kgetglobal _ | Kconst _ as instr) :: c ->
|
1997-02-19 08:08:05 -08:00
|
|
|
emit (Kpush :: instr :: ev :: c)
|
1995-05-04 03:15:53 -07:00
|
|
|
| Kgetglobal id :: Kgetfield n :: c ->
|
1996-05-27 07:19:02 -07:00
|
|
|
out opGETGLOBALFIELD; slot_for_getglobal id; out_int n; emit c
|
1995-05-04 03:15:53 -07:00
|
|
|
(* Default case *)
|
|
|
|
| instr :: c ->
|
|
|
|
emit_instr instr; emit c
|
|
|
|
|
|
|
|
(* Emission to a file *)
|
|
|
|
|
1997-05-15 06:25:14 -07:00
|
|
|
let to_file outchan unit_name code =
|
1995-05-04 03:15:53 -07:00
|
|
|
init();
|
|
|
|
output_string outchan cmo_magic_number;
|
|
|
|
let pos_depl = pos_out outchan in
|
|
|
|
output_binary_int outchan 0;
|
|
|
|
let pos_code = pos_out outchan in
|
|
|
|
emit code;
|
|
|
|
output outchan !out_buffer 0 !out_position;
|
1997-02-19 08:08:05 -08:00
|
|
|
let (pos_debug, size_debug) =
|
|
|
|
if !Clflags.debug then begin
|
|
|
|
let p = pos_out outchan in
|
|
|
|
output_value outchan !events;
|
|
|
|
(p, pos_out outchan - p)
|
|
|
|
end else
|
|
|
|
(0, 0) in
|
1995-05-04 03:15:53 -07:00
|
|
|
let compunit =
|
1995-10-09 06:37:11 -07:00
|
|
|
{ cu_name = unit_name;
|
|
|
|
cu_pos = pos_code;
|
1995-05-04 03:15:53 -07:00
|
|
|
cu_codesize = !out_position;
|
|
|
|
cu_reloc = List.rev !reloc_info;
|
1995-10-09 06:37:11 -07:00
|
|
|
cu_imports = Env.imported_units();
|
2008-07-23 22:35:22 -07:00
|
|
|
cu_primitives = List.map Primitive.byte_name !Translmod.primitive_declarations;
|
1996-11-29 10:36:42 -08:00
|
|
|
cu_force_link = false;
|
1997-02-19 08:08:05 -08:00
|
|
|
cu_debug = pos_debug;
|
|
|
|
cu_debugsize = size_debug } in
|
1995-05-04 03:15:53 -07:00
|
|
|
init(); (* Free out_buffer and reloc_info *)
|
1997-03-24 12:12:51 -08:00
|
|
|
Btype.cleanup_abbrev (); (* Remove any cached abbreviation
|
1997-01-21 09:43:53 -08:00
|
|
|
expansion before saving *)
|
1995-05-04 03:15:53 -07:00
|
|
|
let pos_compunit = pos_out outchan in
|
|
|
|
output_value outchan compunit;
|
|
|
|
seek_out outchan pos_depl;
|
|
|
|
output_binary_int outchan pos_compunit
|
|
|
|
|
|
|
|
(* Emission to a memory block *)
|
|
|
|
|
|
|
|
let to_memory init_code fun_code =
|
|
|
|
init();
|
|
|
|
emit init_code;
|
|
|
|
emit fun_code;
|
|
|
|
let code = Meta.static_alloc !out_position in
|
|
|
|
String.unsafe_blit !out_buffer 0 code 0 !out_position;
|
|
|
|
let reloc = List.rev !reloc_info
|
|
|
|
and code_size = !out_position in
|
|
|
|
init();
|
|
|
|
(code, code_size, reloc)
|
2003-03-06 07:59:55 -08:00
|
|
|
|
|
|
|
(* Emission to a file for a packed library *)
|
|
|
|
|
|
|
|
let to_packed_file outchan code =
|
|
|
|
init();
|
|
|
|
emit code;
|
|
|
|
output outchan !out_buffer 0 !out_position;
|
|
|
|
let reloc = !reloc_info in
|
|
|
|
init();
|
|
|
|
reloc
|