File: mlrisc-cluster2cfg.sml

package info (click to toggle)
mlton 20210117%2Bdfsg-3
  • links: PTS, VCS
  • area: main
  • in suites: sid
  • size: 58,464 kB
  • sloc: ansic: 27,682; sh: 4,455; asm: 3,569; lisp: 2,879; makefile: 2,347; perl: 1,169; python: 191; pascal: 68; javascript: 7
file content (185 lines) | stat: -rw-r--r-- 6,724 bytes parent folder | download | duplicates (5)
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
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
(*
 *  Convert the old cluster format into the new control flow graph format
 *
 * -- Allen
 *)

signature CLUSTER2CFG =
sig
   structure CFG : CONTROL_FLOW_GRAPH
   structure F   : FLOWGRAPH
      sharing CFG.I = F.I
      sharing CFG.P = F.P

   val cluster2cfg : F.cluster -> CFG.cfg

end 

functor Cluster2CFG
   (structure CFG       : CONTROL_FLOW_GRAPH 
    structure Util      : CFG_UTIL
    structure Flowgraph : FLOWGRAPH
    structure InsnProps : INSN_PROPERTIES
       sharing Util.CFG = CFG
       sharing CFG.I = Flowgraph.I = InsnProps.I
       sharing CFG.P = Flowgraph.P
   ) : CLUSTER2CFG =
struct

    structure CFG  = CFG
    structure I    = CFG.I
    structure F    = Flowgraph
    structure G    = Graph
    structure W    = CFG.W

    fun error msg = MLRiscErrorMsg.error("Cluster2CFG",msg)

    fun cluster2cfg
         (F.CLUSTER{blocks, entry, exit, blkCounter, annotations,...})=
    let fun id(F.BBLOCK{blknum, ...}) = blknum
          | id(F.ENTRY {blknum, ...}) = blknum
          | id(F.EXIT {blknum, ...})  = blknum
          | id _                      = error "id"

        fun idfreq(blk,freq) = (id blk,freq)

        fun first_block (F.BBLOCK{blknum,...}::_) = blknum
          | first_block (_::bs)                   = first_block bs
          | first_block []                        = error "first_block"

        val reorder = ref false
        val info = CFG.INFO { firstBlock   = ref(first_block blocks),
                              reorder      = reorder,
                              annotations  = annotations
                             }

        val CFG as G.GRAPH cfg = CFG.cfg(info)

        val F.ENTRY{ blknum = ENTRY, ... } = entry
        val F.EXIT{ blknum = EXIT, ... }   = exit

            (* Add a list of blocks into the CFG *) 
        fun add(F.ENTRY e::rest,Ps,Ls)     = add_entry(e,Ps,Ls,rest)
          | add(F.EXIT e::rest,Ps,Ls)      = add_exit(e,Ps,Ls,rest)
          | add(F.BBLOCK b::rest,Ps,Ls)    = add_block(b,rev Ps,Ls,rest)
          | add((F.PSEUDO p)::rest,Ps,Ls)  = 
              add(rest,CFG.PSEUDO p::map CFG.LABEL Ls@Ps,[])
          | add((F.LABEL l)::rest,Ps,Ls)   = add(rest,Ps,l::Ls)
          | add([],Ps,Ls)                  = finish(Ps,Ls)

            (* Insert an entry node *)
        and add_entry({blknum, succ, freq}, [], [], rest) =
              ( #add_node cfg (blknum,CFG.newStart(blknum,freq));
                #set_entries cfg [blknum];
                app (fn (blk,w) => add_edge(blknum, id blk, CFG.JUMP, w)) 
                     (!succ);
                add(rest, [], [])
              )
          | add_entry _ = error "add_entry"

            (* Insert an exit node *)
        and add_exit({blknum, pred, freq}, [], [], rest) = 
              ( #add_node cfg (blknum, CFG.newStop(blknum,freq));
                #set_exits cfg [blknum];
                add(rest, [], [])
              )
  
            (* Insert an normal basic block *)
       and add_block({blknum,annotations,
                      freq,liveIn,liveOut,succ,pred,insns},
                     Ps,Ls,rest) =
           let val an = !annotations
               val an = 
                   case !succ of
                     ([(F.EXIT _,_)] | []) => #create CFG.LIVEOUT(!liveOut)::an
                   | _ => an
               val bb = CFG.BLOCK{id    = blknum,
                                  kind  = CFG.NORMAL,
                                  labels= ref Ls,
                                  freq  = freq,
                                  data  = ref Ps,
                                  insns = insns,
                                  annotations=ref an
                                 }
           in  #add_node cfg (blknum,bb);
               add_edges(blknum, !succ, !insns);
               (*
               add_call_edges(blknum, !callSucc);
               add_return_edge(blknum, !returnSucc);
                *)
               add(rest, [], [])
           end

            (* Finished insertion *)
       and finish([],[]) = ()
         | finish(Ps,[]) = 
               let val CFG.BLOCK{data,labels,...} = #node_info cfg EXIT
               in  data := Ps @ !data
               end
         | finish _ = error "finish"

            (* Insert one edge into the flowgraph *)
       and add_edge(i,j,k,w) =
           let val k = if ENTRY = i then CFG.ENTRY
                       else if EXIT = j then CFG.EXIT
                       else k
           in  #add_edge cfg (i,j,CFG.EDGE{k=k,w=w,a=ref []})
           end

            (* Add edges into the flowgraph *)
       and add_edges (i, succs, insns) = 
           let fun is_fallsthru (j,yes,no) =
                   if j = i + 1 then
                      (case insns of
                         jmp::_ => (case InsnProps.instrKind jmp of
                                      InsnProps.IK_JUMP => no
                                    | _                 => yes
                                   )
                      |  _ => yes)
                   else no
               fun add_branch(i,(j,jw),(k,kw)) =
               let val j = id j and k = id k
               in  if j = i + 1 then
                     ( add_edge(i,j,CFG.BRANCH false,jw);
                       add_edge(i,k,CFG.BRANCH true,kw))
                   else if k = i + 1 then
                     ( add_edge(i,k,CFG.BRANCH false,kw);
                       add_edge(i,j,CFG.BRANCH true,jw))
                   else error "add_branch"
               end
               fun add_switch(i,_,[]) = ()
                 | add_switch(i,k,(j,jw)::js) =
                   (add_edge(i,id j,CFG.SWITCH k,jw); add_switch(i,k+1,js))
           in  case succs of
                 []      => ()
               | [(j,w)] => 
                   let val j = id j
                   in  add_edge(i,j,is_fallsthru(j,CFG.FALLSTHRU,CFG.JUMP),w)
                   end
               | [j,k] => add_branch(i,j,k)
               | js    => add_switch(i,0,js)
           end

           fun check_for_bad_entries() =
               app (fn (i,j,e) =>
                     if j = EXIT then ()
                     else
                     case #in_edges cfg j of 
                        [_] => () (* only edge from ENTRY, okay *)
                     |  _ => 
                        error("entry "^Int.toString j^" has internal edges") 
                   ) (#out_edges cfg ENTRY)

           (* add edge from entry to exit *)
           fun insert_entry_to_exit () = 
               if #has_edge cfg (ENTRY,EXIT) then ()
               else add_edge (ENTRY,EXIT,CFG.JUMP,ref 0)
    in 
        add(entry::exit::blocks,[],[]);
        check_for_bad_entries();
        insert_entry_to_exit(); 
        CFG
    end

end