File: code-obj.sml

package info (click to toggle)
smlnj 110.79-8
  • links: PTS, VCS
  • area: main
  • in suites: bookworm, sid
  • size: 82,564 kB
  • sloc: ansic: 32,532; asm: 6,314; sh: 2,296; makefile: 1,821; perl: 1,170; pascal: 295; yacc: 190; cs: 78; python: 77; lisp: 19
file content (87 lines) | stat: -rw-r--r-- 2,361 bytes parent folder | download | duplicates (4)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
(* code-obj.sml
 *
 * COPYRIGHT (c) 1998 Bell Labs, Lucent Technologies.
 *
 * An interface for manipulating code objects.
 *)

structure CodeObj :> CODE_OBJ =
  struct

    structure W8A = Word8Array
    structure W8V = Word8Vector
    type object = Unsafe.Object.object

    datatype code_object = C of {
	entrypoint : int ref,
	obj : Word8Array.array
      }

    type csegments = {
	c0 : code_object,
	cn : code_object list, 
	data : Word8Vector.vector
      }

    type executable = object -> object

  (* raised by input when there are insufficient bytes *)
    exception FormatError

    local
      structure CI = Unsafe.CInterface
    in
    val allocCode : int -> W8A.array =
	  CI.c_function "SMLNJ-RunT" "allocCode"
    val mkLiterals : W8V.vector -> object = CI.c_function "SMLNJ-RunT" "mkLiterals"
    val mkExec : W8A.array * int -> executable = CI.c_function "SMLNJ-RunT" "mkExec"
    end (* local *)

  (* Allocate an uninitialized code object.
   *)
    fun alloc n =
	(if (n <= 0) then raise Size else ();
	 C { entrypoint = ref 0, obj = allocCode n })

  (* Allocate a code object of the given size and initialize it
   * from the input stream.
   * NOTE: someday, we might read the data directly into the code
   * object, but this will require hacking around with the reader.
   *)
    fun input (inStrm, sz) = let
	  val (co as C{obj, ...}) = alloc sz
	  val data = BinIO.inputN (inStrm, sz)
	  in
	    if (W8V.length data < sz)
	      then (
		Control_Print.say(concat[
		    "Bin file format error: expected ", Int.toString sz,
		    " bytes, but only found ", Int.toString(W8V.length data)
		  ]);
		raise FormatError)
	      else ();
	    W8A.copyVec{src=data, dst=obj, di=0};
	    co
	  end

  (* Output a code object to the given output stream *)
    fun output (outStrm, C{obj, ...}) = (
	  BinIO.output(outStrm, Unsafe.cast obj);
	  BinIO.flushOut outStrm)

  (* View the code object as an updatable array of bytes. *)
    fun bytes (C{obj, ...}) = obj

  (* View the code object as an executable.  This has the side-effect
   * of flushing the instruction cache.
   *)
    fun exec (C{obj, entrypoint = ref ep }) = mkExec (obj, ep)

  (* return the size of the code object *)
    fun size (C{obj, ...}) = W8A.length obj

    fun entrypoint (C c) = !(#entrypoint c)

    fun set_entrypoint (C c, ep) = #entrypoint c := ep

  end;