|
|
1.1 root 1: (* Copyright 1989 by AT&T Bell Laboratories *)
2: signature BACKPATCH =
3: sig
4: eqtype Label
5: val newlabel : unit -> Label
6: type JumpKind
7: val emitstring : string -> unit
8: val align : unit -> unit
9: val define : Label -> unit
10: val jump : JumpKind*Label -> unit
11: val mark : unit -> unit
12: val finish : unit -> string
13: end
14:
15: signature JUMPS =
16: sig
17: type JumpKind
18: val sizejump : JumpKind*int*int*int -> int
19: val emitjump : JumpKind*int*int*int -> string
20: val emitlong : int -> string
21: end
22:
23: functor Backpatch(Kind: JUMPS) : BACKPATCH =
24: struct
25: open Kind System.Tags
26: type Label = int ref
27: fun newlabel() = ref 0
28:
29: datatype Desc
30: = BYTES of string * Desc | JUMP of JumpKind * Label * int ref * Desc
31: | LABEL of Label * Desc | ALIGN of Desc | MARK of Desc | NIL
32:
33: fun compress(len, sl as [s], r0 as BYTES(t,r)) =
34: let val lent = size t
35: in if len+len > lent andalso lent < 500 andalso len<500
36: then compress(len+lent, t::sl, r)
37: else BYTES(s, r0)
38: end
39: | compress(len, sl, r0 as BYTES(t,r)) =
40: let val lent = size t
41: in if len+len > lent andalso lent < 500
42: then compress(len+lent, t::sl, r)
43: else BYTES(implode sl, r0)
44: end
45: | compress(len, sl, r0) = BYTES(implode sl, r0)
46:
47: val refs = ref NIL
48: fun emitstring s = refs := compress(size s, [s],!refs)
49: fun align() = refs := ALIGN(!refs)
50: fun mark() = refs := MARK(!refs)
51: fun define lab = refs := LABEL(lab, !refs)
52: fun jump(k,lab) = refs := JUMP(k,lab,ref 0, !refs)
53:
54: fun reverse(r,NIL) = r
55: | reverse(r,BYTES(s,q)) = reverse(BYTES(s,r),q)
56: | reverse(r,ALIGN q) = reverse(ALIGN r, q)
57: | reverse(r,MARK q) = reverse(MARK r, q)
58: | reverse(r,LABEL(lab,q)) = reverse(LABEL(lab,r), q)
59: | reverse(r,JUMP(k,lab,x,q)) = reverse(JUMP(k,lab,x,r),q)
60:
61: fun finish() =
62: let val changed = ref true
63:
64: fun labels (pos, BYTES(s,rest)) = labels(pos+size s,rest)
65: | labels (pos, JUMP(k,l,ref size, rest)) = labels(pos+size, rest)
66: | labels (pos, LABEL(l,rest)) = (l := pos; labels(pos,rest))
67: | labels (pos, lab as ALIGN rest) = labels(((pos+3)div 4)*4, rest)
68: | labels (pos, MARK rest) = labels(pos+4, rest)
69: | labels (pos, NIL) = ()
70:
71: fun adjust (pos, BYTES(s,rest)) = adjust(pos+size s,rest)
72: | adjust (pos, JUMP(k, l, r as ref size, rest)) =
73: let val s = sizejump(k, size, pos, !l)
74: in if s > size then (r := s; changed := true) else ();
75: adjust(pos+size, rest)
76: end
77: | adjust (pos, LABEL(l,rest)) = adjust(pos,rest)
78: | adjust (pos, ALIGN rest) = adjust(((pos+3)div 4)*4, rest)
79: | adjust (pos, MARK rest) = adjust(pos+4, rest)
80: | adjust (pos, NIL) = ()
81:
82: fun chunk(pos, BYTES(s,r)) = s :: chunk(pos+size s,r)
83: | chunk(pos, JUMP(k,l,ref size, r)) =
84: emitjump(k,size,pos,!l) :: chunk(pos+size,r)
85: | chunk(pos, LABEL(l, rest)) = chunk(pos,rest)
86: | chunk(pos, ALIGN rest) =
87: (case pos mod 4
88: of 0 => chunk(pos,rest)
89: | 1 => "\000\000\000" :: chunk(pos+3,rest)
90: | 2 => "\000\000" :: chunk(pos+2,rest)
91: | 3 => "\000" :: chunk(pos+1,rest))
92: | chunk(pos, MARK r) =
93: emitlong(((pos+4)div 4)*power_tags+tag_backptr)
94: :: chunk(pos+4, r)
95: | chunk(pos, NIL) = nil
96:
97: val reflist = reverse (ALIGN NIL, !refs) before refs := NIL
98: in ErrorMsg.debugmsg "relocating...";
99: while !changed
100: do (changed := false; labels(0, reflist); adjust(0, reflist));
101: ErrorMsg.debugmsg "about to output";
102: implode(chunk(0, reflist))
103: end
104: end (* functor BackPatch *)
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.