-
Notifications
You must be signed in to change notification settings - Fork 1
/
rewrite.sml
90 lines (78 loc) · 2.52 KB
/
rewrite.sml
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
88
89
90
(* rewrite.sml
*
* Instruction rewriting (to account for spills produced by the
* register allocator).
*
* Copyright (c) 2005 by Matthias Blume (blume@tti-c.org)
*)
structure Rewrite : sig
val rewrite : Frame.frame * LVar.lvar list ->
Asm.instr * Asm.instr list -> Asm.instr list
end = struct
structure M = LVar.Map
structure A = Asm
(* Given the frame data structure for the current cluster and
* a list of spilled lvars, construct function that
* maps an instruction to an equivalent list of instructions
* that implement spilling. The constructed function
* also takes the "remaining" instructions as an argument
* so that it can be used in a "fold": *)
fun rewrite (frame, spills) = let
(* figure out stack offsets for the spills: *)
val offsetmap =
foldl (fn (t, m) => M.insert (m, t, Frame.allocSpill frame))
M.empty spills
fun offset t = Option.map (Frame.spillOff frame) (M.find (offsetmap, t))
(* storing into the stack frame *)
fun store (tmp, off) =
A.OPER { asm = concat ["\tstw `s0,", off, "(`s1)"],
src = [tmp, Frame.sp], dst = [], jmp = A.NOJUMP }
(* loading from the stack frame *)
fun load (tmp, off) =
A.OPER { asm = concat ["\tlwz `d0,", off, "(`s0)"],
src = [Frame.sp], dst = [tmp], jmp = A.NOJUMP }
(* utility functions for dealing with spilled destinations
* and sources: *)
fun spillDst dst =
case offset dst of
NONE => (dst, [])
| SOME off =>
let val t = LVar.clone dst
in (t, [store (t, off)])
end
fun spillDst' (dst, (rl, il)) =
let val (dst', il') = spillDst dst
in (dst' :: rl, il' @ il)
end
fun spillSrc src =
case offset src of
NONE => (src, [])
| SOME off =>
let val t = LVar.clone src
in (t, [load (t, off)])
end
fun spillSrc' (src, (rl, il)) =
let val (src', il') = spillSrc src
in
(src' :: rl, il' @ il)
end
(* do it for one instruction: *)
fun rw (i as (A.LABEL _ |
A.REGSAVE |
A.REGRESTORE |
A.NOSTACK), il) = i :: il
| rw (A.MOVE { src, dst, asm }, il) =
let val (src', il1) = spillSrc src
val (dst', il2) = spillDst dst
in il1 @ A.MOVE { src = src', dst = dst', asm = asm } ::
il2 @ il
end
| rw (i as A.OPER { src, dst, asm = a, jmp = j }, il) =
let val (src', il1) = foldr spillSrc' ([], []) src
val (dst', il2) = foldr spillDst' ([], []) dst
in il1 @ A.OPER { asm = a, src = src', dst = dst', jmp = j } ::
il2 @ il
end
in rw
end
end