summaryrefslogtreecommitdiff
path: root/bytecomp/emitcode.ml
diff options
context:
space:
mode:
Diffstat (limited to 'bytecomp/emitcode.ml')
-rw-r--r--bytecomp/emitcode.ml285
1 files changed, 0 insertions, 285 deletions
diff --git a/bytecomp/emitcode.ml b/bytecomp/emitcode.ml
deleted file mode 100644
index df97932a7d..0000000000
--- a/bytecomp/emitcode.ml
+++ /dev/null
@@ -1,285 +0,0 @@
-(* Generation of bytecode + relocation information *)
-
-open Config
-open Misc
-open Asttypes
-open Lambda
-open Instruct
-open Opcodes
-
-
-(* Relocation information *)
-
-type reloc_info =
- Reloc_literal of structured_constant (* structured constant *)
- | Reloc_getglobal of Ident.t (* reference to a global *)
- | Reloc_setglobal of Ident.t (* definition of a global *)
- | Reloc_primitive of string (* C primitive number *)
-
-(* Descriptor for compilation units *)
-
-type compilation_unit =
- { mutable cu_pos: int; (* Absolute position in file *)
- cu_codesize: int; (* Size of code block *)
- cu_reloc: (reloc_info * int) list; (* Relocation information *)
- cu_interfaces: (string * int) list } (* Names and CRC of intfs imported *)
-
-(* Format of a .cmo file:
- Obj.magic number (Config.cmo_magic_number)
- absolute offset of compilation unit descriptor
- block of relocatable bytecode
- compilation unit descriptor *)
-
-(* 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
-
-let out_int n =
- out_word n (n asr 8) (n asr 16) (n asr 24)
-
-(* 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;
- let new_table = Array.new !new_size (Label_undefined []) in
- Array.blit !label_table 0 new_table 0 (Array.length !label_table);
- label_table := new_table
-
-let backpatch (pos, orig) =
- let displ = (!out_position - orig) / 4 in
- !out_buffer.[pos] <- Char.unsafe_chr displ;
- !out_buffer.[pos+1] <- Char.unsafe_chr (displ lsr 8);
- !out_buffer.[pos+2] <- Char.unsafe_chr (displ lsr 16);
- !out_buffer.[pos+3] <- Char.unsafe_chr (displ lsr 24)
-
-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 ->
- out_int((def - orig) / 4)
- | 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
-
-(* Initialization *)
-
-let init () =
- out_position := 0;
- label_table := Array.new 16 (Label_undefined []);
- reloc_info := []
-
-(* Emission of one instruction *)
-
-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 ->
- if n < 4 then out(opENVACC0 + n) else (out opENVACC; out_int n)
- | 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
- | Kclosurerec(lbl, n) -> out opCLOSUREREC; out_int n; out_label lbl
- | Kgetglobal q -> out opGETGLOBAL; slot_for_getglobal q
- | Ksetglobal q -> out opSETGLOBAL; slot_for_setglobal q
- | Kconst sc ->
- begin match sc with
- Const_base(Const_int i) when i >= immed_min & i <= immed_max ->
- out opCONSTINT; out_int i
- | Const_base(Const_char c) ->
- out opCONSTINT; out_int (Char.code c)
- | Const_block(t, []) ->
- if t < 4 then out (opATOM0 + t) else (out opATOM; out_int t)
- | _ ->
- out opGETGLOBAL; slot_for_literal sc
- end
- | Kmakeblock(n, t) ->
- if n = 0 then
- if t < 4 then out (opATOM0 + t) else (out opATOM; out_int t)
- 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)
- | Ktagof -> out opTAGOF
- | Kdummy n -> out opDUMMY; out_int n
- | Kupdate -> out opUPDATE
- | 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
- | Kswitch lblv ->
- out opSWITCH; out_int (Array.length lblv);
- let org = !out_position in
- Array.iter (out_label_with_orig org) lblv
- | Ktranslate tbl ->
- out opTRANSLATE; out_int (Array.length tbl);
- Array.iter
- (fun (lo, hi, ofs) -> out_int (lo + (hi lsl 8) + (ofs lsl 16)))
- tbl
- | Kboolnot -> out opBOOLNOT
- | Kpushtrap lbl -> out opPUSHTRAP; out_label lbl
- | Kpoptrap -> out opPOPTRAP
- | Kraise -> out opRAISE
- | Kcheck_signals -> out opCHECK_SIGNALS
- | Kccall(name, n) ->
- if n <= 4
- 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
- | Kintcomp Ceq -> out opEQ | Kintcomp Cneq -> out opNEQ
- | Kintcomp Clt -> out opLTINT | Kintcomp Cle -> out opLEINT
- | Kintcomp Cgt -> out opGTINT | Kintcomp Cge -> out opGEINT
- | Koffsetint n -> out opOFFSETINT; out_int n
- | Koffsetref n -> out opOFFSETREF; out_int n
- | Kstop -> out opSTOP
-
-(* Emission of a list of instructions. Include some peephole optimization. *)
-
-let rec emit = function
- [] -> ()
- (* Peephole optimizations *)
- | Kpush :: Kacc n :: c ->
- if n < 8 then out(opPUSHACC0 + n) else (out opPUSHACC; out_int n);
- emit c
- | Kpush :: Kenvacc n :: c ->
- if n < 4 then out(opPUSHENVACC0 + n) else (out opPUSHENVACC; out_int n);
- emit c
- | Kpush :: Kgetglobal id :: Kgetfield n :: c ->
- out opPUSHGETGLOBALFIELD; slot_for_getglobal id; out n; emit c
- | Kpush :: Kgetglobal q :: c ->
- out opPUSHGETGLOBAL; slot_for_getglobal q; emit c
- | Kpush :: Kconst sc :: c ->
- begin match sc with
- Const_base(Const_int i) when i >= immed_min & i <= immed_max ->
- out opPUSHCONSTINT; out_int i
- | Const_base(Const_char c) ->
- out opPUSHCONSTINT; out_int(Char.code c)
- | Const_block(t, []) ->
- if t < 4 then out (opPUSHATOM0 + t) else (out opPUSHATOM; out_int t)
- | _ ->
- out opPUSHGETGLOBAL; slot_for_literal sc
- end;
- emit c
- | Kgetglobal id :: Kgetfield n :: c ->
- out opGETGLOBALFIELD; slot_for_getglobal id; out n; emit c
- (* Default case *)
- | instr :: c ->
- emit_instr instr; emit c
-
-(* Emission to a file *)
-
-let to_file outchan unit_name crc_interface code =
- 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;
- let compunit =
- { cu_pos = pos_code;
- cu_codesize = !out_position;
- cu_reloc = List.rev !reloc_info;
- cu_interfaces = (unit_name, crc_interface) :: Env.imported_units() } in
- init(); (* Free out_buffer and reloc_info *)
- 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)
-