Home My Page Projects Code Snippets Project Openings SML/NJ
Summary Activity Forums Tracker Lists Tasks Docs Surveys News SCM Files

SCM Repository

[smlnj] Annotation of /sml/branches/SMLNJ/src/MLRISC/sparc/sparc.sml
ViewVC logotype

Annotation of /sml/branches/SMLNJ/src/MLRISC/sparc/sparc.sml

Parent Directory Parent Directory | Revision Log Revision Log


Revision 129 - (view) (download)
Original Path: sml/trunk/src/MLRISC/sparc/sparc.sml

1 : monnier 129 (*
2 :     * Machine code generator for SPARC.
3 :     *
4 :     * The SPARC architecture has 32 general purpose registers (%g0 is always 0)
5 :     * and 32 single precision floating point registers.
6 :     *
7 :     * Some Ugliness: double precision floating point registers are
8 :     * register pairs. There are no double precision moves, negation and absolute
9 :     * values. These require two single precision operations. I've created
10 :     * composite instructions FMOVd, FNEGd and FABSd to stand for these.
11 :     *
12 :     * All integer arithmetic instructions can optionally set the condition
13 :     * code register. We use this to simplify certain comparisons with zero.
14 :     *
15 :     * Integer multiplication, division and conversion from integer to floating
16 :     * go thru the pseudo instruction interface, since older sparcs do not
17 :     * implement these instructions in hardware.
18 :     *
19 :     * In addition, the trap instruction for detecting overflow is a parameter.
20 :     * This allows different trap vectors to be used.
21 :     *
22 :     * The virtual register 65 is used to represent the %psr register.
23 :     *
24 :     * -- Allen
25 :     *)
26 :    
27 :     functor Sparc
28 :     (structure Flowgen : FLOWGRAPH_GEN
29 :     structure SparcInstr : SPARCINSTR
30 :     structure SparcMLTree : MLTREE
31 :     structure PseudoInstrs : SPARC_PSEUDO_INSTR
32 :     sharing SparcInstr.Region = SparcMLTree.Region
33 :     sharing Flowgen.I=PseudoInstrs.I=SparcInstr
34 :     sharing Flowgen.T=SparcMLTree
35 :     sharing SparcMLTree.Constant = SparcInstr.Constant
36 :     sharing SparcMLTree.BNames = Flowgen.B
37 :     val overflowtrap : SparcInstr.instruction list
38 :     ) : MLTREECOMP =
39 :     struct
40 :     structure F = Flowgen
41 :     structure T = SparcMLTree
42 :     structure R = SparcMLTree.Region
43 :     structure I = SparcInstr
44 :     structure C = SparcInstr.C
45 :     structure LE = LabelExp
46 :     structure W = Word32
47 :     structure P = PseudoInstrs
48 :    
49 :     datatype trapping = TRAPS | SILENT
50 :     datatype commutative = COMMUTE | DONTCOMMUTE
51 :     datatype target =
52 :     CC (* condition code only *)
53 :     | REG (* register only *)
54 :     | CC_REG (* conditional code and register *)
55 :    
56 :     fun error msg = MLRiscErrorMsg.impossible ("Sparc." ^ msg)
57 :    
58 :     val emit = F.emitInstr
59 :     fun newReg () = C.newReg()
60 :     fun newFreg() = C.newFreg()
61 :    
62 :     (* load/store has 13 bits sign extended immediates *)
63 :     fun immed13 n = ~4096 <= n andalso n < 4096
64 :     fun immed13w w = let val x = W.~>>(w,0w12)
65 :     in W.orb(x,W.notb x) = 0w0 end
66 :    
67 :     (* split into 22 high bits/10 low bits *)
68 :    
69 :     fun splitw w =
70 :     {hi=W.toInt(W.>>(w,0w10)), lo=W.toInt(W.andb(w,0wx3ff))}
71 :    
72 :     fun split n = splitw(W.fromInt n)
73 :    
74 :     (* load immediate *)
75 :     fun loadImmed(n,d) =
76 :     if immed13 n then emit(I.ARITH{a=I.OR,r=0,i=I.IMMED n,cc=false,d=d})
77 :     else let
78 :     val t = newReg()
79 :     val {hi,lo} = split n
80 :     in
81 :     if lo = 0 then emit(I.SETHI{i=hi,d=d})
82 :     else
83 :     (emit(I.SETHI{i=hi,d=t});
84 :     emit(I.ARITH{a=I.OR,r=t,i=I.IMMED lo,cc=false,d=d}))
85 :     end
86 :    
87 :     (* load word constant *)
88 :     fun loadImmed32(w,d) =
89 :     if immed13w w then
90 :     emit(I.ARITH{a=I.OR,r=0,i=I.IMMED(W.toIntX w),cc=false,d=d})
91 :     else let
92 :     val t = newReg()
93 :     val {hi,lo} = splitw w
94 :     in
95 :     if lo = 0 then emit(I.SETHI{i=hi,d=d})
96 :     else
97 :     (emit(I.SETHI{i=hi,d=t});
98 :     emit(I.ARITH{a=I.OR,r=t,i=I.IMMED lo,cc=false,d=d}))
99 :     end
100 :    
101 :     (* load constant *)
102 :     fun loadConst(c,d) = emit(I.ARITH{a=I.OR,r=0,i=I.CONST c,cc=false,d=d})
103 :    
104 :     (* load label expression *)
105 :     fun loadLabel(lab,d) = emit(I.ARITH{a=I.OR,r=0,i=I.LAB lab,cc=false,d=d})
106 :    
107 :     (* emit parallel copies *)
108 :     fun copy(dst,src) =
109 :     emit(I.COPY{dst=dst, src=src, impl=ref NONE,
110 :     tmp=case dst
111 :     of [_] => NONE
112 :     | _ => SOME(I.Direct(newReg()))})
113 :    
114 :     fun fcopy(dst,src) =
115 :     emit(I.FCOPY{dst=dst, src=src, impl=ref NONE,
116 :     tmp=case dst
117 :     of [_] => NONE
118 :     | _ => SOME(I.FDirect(newReg()))})
119 :    
120 :     (* move register s to register d *)
121 :     fun move(s,d) =
122 :     if s = d orelse d = 0 then ()
123 :     else emit(I.COPY{dst=[d],src=[s],tmp=NONE, impl=ref NONE})
124 :    
125 :     (* move floating point register s to register d *)
126 :     fun fmove(s,d) =
127 :     if s = d then ()
128 :     else emit(I.FCOPY{dst=[d],src=[s],tmp=NONE,impl=ref NONE})
129 :    
130 :     (* order the generation of instructions *)
131 :     fun order(gen,e1,e2,T.LR) = (gen e1, gen e2)
132 :     | order(gen,e1,e2,T.RL) = let
133 :     val y = gen e2
134 :     in (gen e1, y)
135 :     end
136 :    
137 :     (* generate arithmetic *)
138 :     fun arith(opcode,e1,e2,ord,d,cc,commutative,checkOverflow) =
139 :     let val d = case cc of
140 :     CC => 0
141 :     | _ => d
142 :     val cc = case cc of
143 :     CC => true
144 :     | CC_REG => true
145 :     | REG => false
146 :     in case (order(genOperand,e1,e2,ord),commutative) of
147 :     ((i,I.REG r),COMMUTE) => emit(I.ARITH{a=opcode,r=r,i=i,d=d,cc=cc})
148 :     | ((I.REG r,i),_) => emit(I.ARITH{a=opcode,r=r,i=i,d=d,cc=cc})
149 :     | ((a,i),_) =>
150 :     let val r = newReg()
151 :     in emit(I.ARITH{a=I.OR,r=0,i=a,d=r,cc=false});
152 :     emit(I.ARITH{a=opcode,r=r,i=i,d=d,cc=cc})
153 :     end;
154 :     case checkOverflow of
155 :     TRAPS => app emit overflowtrap
156 :     | SILENT => ()
157 :     end
158 :    
159 :     (* generate shift *)
160 :     and shift(opcode,e1,e2,ord,d) =
161 :     case order(genOperand,e1,e2,ord) of
162 :     (I.REG r,i) => emit(I.SHIFT{s=opcode,r=r,i=i,d=d})
163 :     | (a,i) => let val r = newReg()
164 :     in emit(I.ARITH{a=I.OR,r=0,i=a,d=r,cc=false});
165 :     emit(I.SHIFT{s=opcode,r=r,i=i,d=d})
166 :     end
167 :    
168 :     (* generate external arithmetic operation *)
169 :     and externalarith(gen,e1,e2,ord,d,cc,commutative) =
170 :     let val instrs =
171 :     case (order(genOperand,e1,e2,ord),commutative) of
172 :     ((i,I.REG r),COMMUTE) => gen({r=r,i=i,d=d},reduceOperand)
173 :     | ((I.REG r,i),_) => gen({r=r,i=i,d=d},reduceOperand)
174 :     | ((a,i),_) => let val r = newReg()
175 :     in emit(I.ARITH{a=I.OR,r=0,i=a,d=r,cc=false});
176 :     gen({r=r,i=i,d=d},reduceOperand)
177 :     end
178 :     in app emit instrs;
179 :     genCmp0(cc,d)
180 :     end
181 :    
182 :     (* Convert an operand into a register *)
183 :     and reduceOperand(I.REG r) = r
184 :     | reduceOperand(I.IMMED 0) = 0 (* %g0 *)
185 :     | reduceOperand i = let val d = newReg()
186 :     in emit(I.ARITH{a=I.OR,r=0,i=i,d=d,cc=false}); d end
187 :    
188 :     (* floating point arithmetic *)
189 :     and funary(opcode,e,d) = emit(I.FPop1{a=opcode,r=genFexpr e,d=d})
190 :    
191 :     and farith(opcode,e1,e2,d,ord) =
192 :     let val (r1,r2) = order(genFexpr,e1,e2,ord)
193 :     in emit(I.FPop2{a=opcode,r1=r1,r2=r2,d=d})
194 :     end
195 :    
196 :     (* compute addressing mode
197 :     * Sparc has only two addressing modes: displacement and indexed.
198 :     *)
199 :     and addrMode(T.ADD(e,T.LI n)) =
200 :     if immed13 n then (genExpr e,I.IMMED n)
201 :     else let val t = newReg()
202 :     val _ = loadImmed(n,t)
203 :     in (t,genOperand e) end
204 :     | addrMode(T.ADD(e,T.CONST c)) = (genExpr e,I.CONST c)
205 :     | addrMode(T.ADD(e,T.LABEL l)) = (genExpr e,I.LAB l)
206 :     | addrMode(T.ADD(i as T.LI _,e)) = addrMode(T.ADD(e,i))
207 :     | addrMode(T.ADD(T.CONST c,e)) = (genExpr e,I.CONST c)
208 :     | addrMode(T.ADD(T.LABEL l,e)) = (genExpr e,I.LAB l)
209 :     | addrMode(T.ADD(e1,e2)) = (genExpr e1,I.REG(genExpr e2))
210 :     | addrMode(T.SUB(e,T.LI n,_)) = addrMode(T.ADD(e,T.LI(~n)))
211 :     | addrMode(T.LABEL l) = (0,I.LAB l)
212 :     | addrMode addr = (genExpr addr,I.IMMED 0)
213 :    
214 :     (* load integer values *)
215 :     and load(opcode,addr,mem,d) =
216 :     let val (r,i) = addrMode addr
217 :     in emit(I.LOAD{l=opcode,r=r,i=i,d=d,mem=mem}) end
218 :    
219 :     (* store integer values *)
220 :     and store(opcode,addr,data,mem) =
221 :     let val (r,i) = addrMode addr
222 :     in emit(I.STORE{s=opcode,d=data,r=r,i=i,mem=mem}) end
223 :    
224 :     (* load floating point value *)
225 :     and fload(opcode,addr,mem,d) =
226 :     let val (r,i) = addrMode addr
227 :     in emit(I.FLOAD{l=opcode,r=r,i=i,d=d,mem=mem}) end
228 :    
229 :     (* store floating point value *)
230 :     and fstore(opcode,addr,data,mem) =
231 :     let val (r,i) = addrMode addr
232 :     in emit(I.FSTORE{s=opcode,d=data,r=r,i=i,mem=mem}) end
233 :    
234 :     and jmp(addr,labs) =
235 :     let val (r,i) = addrMode addr
236 :     in emit(I.JMP{r=r,i=i,labs=labs,nop=true}) end
237 :    
238 :     and call(addr,defs,uses) =
239 :     let val (r,i) = addrMode addr
240 :     fun live([],acc) = acc
241 :     | live(T.GPR(T.REG r)::regs,acc) = live(regs, C.addReg(r,acc))
242 :     | live(T.CCR(T.CC 65)::regs,acc) = live(regs, acc)
243 :     | live(T.CCR(T.CC cc)::regs,acc) = live(regs, C.addReg(cc,acc))
244 :     | live(T.FPR(T.FREG f)::regs,acc) = live(regs, C.addFreg(f,acc))
245 :     | live(_::regs, acc) = live(regs, acc)
246 :     val defs=live(defs,C.empty)
247 :     val uses=live(uses,C.empty)
248 :     in case (r,i) of
249 :     (0,I.LAB(LE.LABEL l)) =>
250 :     emit(I.CALL{label=l,defs=C.addReg(C.linkReg,defs),uses=uses,
251 :     nop=true})
252 :     | _ => emit(I.JMPL{r=r,i=i,d=C.linkReg,defs=defs,uses=uses,nop=true})
253 :     end
254 :    
255 :     (* Generate code for a statement *)
256 :     and doStmt stmt =
257 :     case stmt of
258 :     T.MV(d,e) => doExpr(e,d,REG)
259 :     | T.FMV(d,e) => doFexpr(e,d)
260 :     | T.CCMV(d,e) => doCCexpr(e,d)
261 :     | T.COPY(dst,src) => copy(dst,src)
262 :     | T.FCOPY(dst,src) => fcopy(dst,src)
263 :     | T.JMP(T.LABEL(LE.LABEL l),_) =>
264 :     emit(I.Bicc{b=I.BA,a=true,label=l,nop=false})
265 :     | T.JMP(e,labs) => jmp(e,labs)
266 :     | T.CALL(e,def,use) => call(e,def,use)
267 :     | T.RET => emit(I.RET{leaf=false,nop=true})
268 :     | T.STORE8(addr,data,mem) => store(I.STB,addr,genExpr data,mem)
269 :     | T.STORE32(addr,data,mem) => store(I.ST,addr,genExpr data,mem)
270 :     | T.STORED(addr,data,mem) => fstore(I.STDF,addr,genFexpr data,mem)
271 :     | T.STORECC(addr,data,mem) => store(I.ST,addr,genCCexpr data,mem)
272 :     | T.BCC(cond,cc,lab) => branch(cond,cc,lab)
273 :     | T.FBCC(cond,cc,lab) => fbranch(cond,cc,lab)
274 :    
275 :     (*
276 :     * generate conditional branches
277 :     * Perform a subtract (with cc), then branch on cc.
278 :     * Note: when we are comparing with zero, do something smarter.
279 :     *)
280 :     and branch(_,T.CMP(cond,e1,e2,order),lab) =
281 :     let val (cond,e1,e2) =
282 :     case e1 of
283 :     (T.LI _ | T.LI32 _ | T.CONST _ | T.LABEL _) => (flip cond,e2,e1)
284 :     | _ => (cond,e1,e2)
285 :     in doExpr(T.SUB(e1,e2,order),newReg(),CC); br(cond,lab)
286 :     end
287 :     | branch(cond,T.CC 65,lab) = (* psr *)
288 :     br(cond,lab)
289 :     | branch(cond,T.CC r,lab) =
290 :     (genCmp0(CC,r); br(cond,lab))
291 :     | branch _ = error "branch"
292 :    
293 :     and cond T.LT = I.BL
294 :     | cond T.LTU = I.BCS
295 :     | cond T.LE = I.BLE
296 :     | cond T.LEU = I.BLEU
297 :     | cond T.EQ = I.BE
298 :     | cond T.NEQ = I.BNE
299 :     | cond T.GE = I.BGE
300 :     | cond T.GEU = I.BCC
301 :     | cond T.GT = I.BG
302 :     | cond T.GTU = I.BGU
303 :    
304 :     (* exchange the order of the arguments to a comparison *)
305 :     and flip T.LT = T.GT
306 :     | flip T.LTU = T.GTU
307 :     | flip T.LE = T.GE
308 :     | flip T.LEU = T.GEU
309 :     | flip T.EQ = T.EQ
310 :     | flip T.NEQ = T.NEQ
311 :     | flip T.GE = T.LE
312 :     | flip T.GEU = T.LEU
313 :     | flip T.GT = T.LT
314 :     | flip T.GTU = T.LTU
315 :    
316 :     and fcond T.== = I.FBE
317 :     | fcond T.?<> = I.FBNE
318 :     | fcond T.? = I.FBU
319 :     | fcond T.<=> = I.FBO
320 :     | fcond T.> = I.FBG
321 :     | fcond T.>= = I.FBGE
322 :     | fcond T.?> = I.FBUG
323 :     | fcond T.?>= = I.FBUGE
324 :     | fcond T.< = I.FBL
325 :     | fcond T.<= = I.FBLE
326 :     | fcond T.?< = I.FBUL
327 :     | fcond T.?<= = I.FBULE
328 :     | fcond T.<> = I.FBLG
329 :     | fcond T.?= = I.FBUE
330 :    
331 :     and br(c,lab) = emit(I.Bicc{b=cond c,a=true,label=lab,nop=true})
332 :    
333 :     and fbranch(_,T.FCMP(cond,e1,e2,ord),lab) =
334 :     let val (r1,r2) = order(genFexpr,e1,e2,ord)
335 :     in emit(I.FCMP{cmp=I.FCMPd,r1=r1,r2=r2});
336 :     emit(I.FBfcc{b=fcond cond,a=false,label=lab,nop=true})
337 :     end
338 :     | fbranch _ = error "fbranch"
339 :    
340 :     (* compute expr and write the result to register d,
341 :     * optionally set the condition code register.
342 :     *)
343 :     and doExpr(expr,d,cc) =
344 :     case expr of
345 :     T.REG r => (move(r,d); genCmp0(cc,r))
346 :     | T.LI n => (loadImmed(n,d); genCmp0(cc,d))
347 :     | T.LI32 w => (loadImmed32(w,d); genCmp0(cc,d))
348 :     | T.LABEL lab => (loadLabel(lab,d); genCmp0(cc,d))
349 :     | T.CONST c => (loadConst(c,d); genCmp0(cc,d))
350 :     | T.ADD(e1,e2) => arith(I.ADD,e1,e2,T.LR,d,cc,COMMUTE,SILENT)
351 :     | T.SUB(e1,T.LI 0,_) => doExpr(e1,d,cc)
352 :     | T.SUB(e1,T.LI32 0w0,_) => doExpr(e1,d,cc)
353 :     | T.SUB(e1,e2,ord) => arith(I.SUB,e1,e2,ord,d,cc,DONTCOMMUTE,SILENT)
354 :     | T.ADDT(e1,e2) => arith(I.ADD,e1,e2,T.LR,d,CC_REG,COMMUTE,TRAPS)
355 :     | T.SUBT(e1,e2,ord)=> arith(I.SUB,e1,e2,ord,d,CC_REG,DONTCOMMUTE,TRAPS)
356 :     | T.ANDB(e1,e2) => arith(I.AND,e1,e2,T.LR,d,cc,COMMUTE,SILENT)
357 :     | T.ORB(e1,e2) => arith(I.OR,e1,e2,T.LR,d,cc,COMMUTE,SILENT)
358 :     | T.XORB(e1,e2) => arith(I.XOR,e1,e2,T.LR,d,cc,COMMUTE,SILENT)
359 :     | T.SRA(e1,e2,ord) => (shift(I.SRA,e1,e2,ord,d); genCmp0(cc,d))
360 :     | T.SRL(e1,e2,ord) => (shift(I.SRL,e1,e2,ord,d); genCmp0(cc,d))
361 :     | T.SLL(e1,e2,ord) => (shift(I.SLL,e1,e2,ord,d); genCmp0(cc,d))
362 :     | T.LOAD8(addr,mem) => (load(I.LDUB,addr,mem,d); genCmp0(cc,d))
363 :     | T.LOAD32(addr,mem) => (load(I.LD,addr,mem,d); genCmp0(cc,d))
364 :     | T.SEQ(stmt,e) => (doStmt stmt; doExpr(e,d,cc))
365 :     | T.MULU(e1,e2) => externalarith(P.umul,e1,e2,T.LR,d,cc,COMMUTE)
366 :     | T.MULT(e1,e2) => externalarith(P.smul,e1,e2,T.LR,d,cc,COMMUTE)
367 :     | T.DIVU(e1,e2,ord)=> externalarith(P.udiv,e1,e2,ord,d,cc,DONTCOMMUTE)
368 :     | T.DIVT(e1,e2,ord)=> externalarith(P.sdiv,e1,e2,ord,d,cc,DONTCOMMUTE)
369 :    
370 :     (* Compare with zero if cc is set *)
371 :     and genCmp0(cc,d) =
372 :     case cc of
373 :     REG => ()
374 :     | _ => emit(I.ARITH{a=I.SUB,r=d,i=I.IMMED 0,d=0,cc=true})
375 :    
376 :     and doFexpr(expr,d) =
377 :     case expr of
378 :     T.FREG r => fmove(r,d)
379 :     | T.LOADD(addr,mem) => fload(I.LDDF,addr,mem,d)
380 :     | T.FADDD(e1,e2) => farith(I.FADDd,e1,e2,d,T.LR)
381 :     | T.FMULD(e1,e2) => farith(I.FMULd,e1,e2,d,T.LR)
382 :     | T.FSUBD(e1,e2,ord) => farith(I.FSUBd,e1,e2,d,ord)
383 :     | T.FDIVD(e1,e2,ord) => farith(I.FDIVd,e1,e2,d,ord)
384 :     | T.FABSD e => funary(I.FABSd,e,d)
385 :     | T.FNEGD e => funary(I.FNEGd,e,d)
386 :     | T.CVTI2D e => app emit
387 :     (P.cvti2d({i=genOperand e,d=d},reduceOperand))
388 :     | T.FSEQ(stmt,e) => (doStmt stmt; doFexpr(e,d))
389 :    
390 :     and doCCexpr(T.CMP(cond,e1,e2,ord),65) = (* psr *)
391 :     doExpr(T.SUB(e1,e2,ord),newReg(),CC)
392 :     | doCCexpr(_,65) = error "doCCexpr 65"
393 :     | doCCexpr(expr,d) =
394 :     case expr of
395 :     T.CC r => move(r,d)
396 :     | T.LOADCC(addr,mem) => load(I.LD,addr,mem,d)
397 :     | _ => error "doCCexpr"
398 :    
399 :     (*
400 :     * generate an expression and return the register that holds its value
401 :     *)
402 :     and genExpr(T.LI 0) = 0 (* register %g0 *)
403 :     | genExpr(T.LI32 0w0) = 0 (* register %g0 *)
404 :     | genExpr(T.REG r) = r
405 :     | genExpr expr = let val r = newReg() in doExpr(expr,r,REG); r end
406 :    
407 :     and genFexpr(T.FREG r) = r
408 :     | genFexpr expr = let val r = newFreg() in doFexpr(expr,r); r end
409 :    
410 :     and genCCexpr(T.CC 65) = error "genCCexpr"
411 :     | genCCexpr(T.CC r) = r
412 :     | genCCexpr expr = let val r = newReg() in doCCexpr(expr,r); r end
413 :    
414 :     (*
415 :     * generate an expression and returns it as an operand
416 :     *)
417 :     and genOperand(T.LI 0) = I.REG 0
418 :     | genOperand(T.LI32 0w0) = I.REG 0
419 :     | genOperand(e as T.LI n) =
420 :     if immed13 n then I.IMMED n else I.REG(genExpr e)
421 :     | genOperand(e as T.LI32 w) =
422 :     if immed13w w then I.IMMED(W.toIntX w) else I.REG(genExpr e)
423 :     | genOperand(T.CONST c) = I.CONST c
424 :     | genOperand(T.LABEL l) = I.LAB l
425 :     | genOperand(e) = I.REG(genExpr e)
426 :    
427 :     fun mltreeComp mltree =
428 :     let (* condition code registers are mapped onto general registers *)
429 :     fun cc (x as T.CCR(T.CC 65),l) = l
430 :     | cc (T.CCR(T.CC cc),l) = T.GPR(T.REG cc)::l
431 :     | cc (x,l) = x::l
432 :     fun comp(T.BEGINCLUSTER) = F.beginCluster()
433 :     | comp(T.PSEUDO_OP p) = F.pseudoOp p
434 :     | comp(T.DEFINELABEL lab) = F.defineLabel lab
435 :     | comp(T.ENTRYLABEL lab) = F.entryLabel lab
436 :     | comp(T.CODE stmts) = app doStmt stmts
437 :     | comp(T.BLOCK_NAME name) = F.blockName name
438 :     | comp(T.ORDERED mltrees) = F.ordered mltrees
439 :     | comp(T.ESCAPEBLOCK regs) = F.exitBlock(foldl cc [] regs)
440 :     | comp(T.ENDCLUSTER regmap) = F.endCluster regmap
441 :     in comp mltree
442 :     end
443 :    
444 :     val mlriscComp = doStmt
445 :    
446 :     end
447 :    
448 :     (*
449 :     * $Log$
450 :     *)

root@smlnj-gforge.cs.uchicago.edu
ViewVC Help
Powered by ViewVC 1.0.0