[project @ 2000-03-23 17:45:17 by simonpj]
[ghc-hetmet.git] / ghc / compiler / nativeGen / AbsCStixGen.lhs
1 %
2 % (c) The AQUA Project, Glasgow University, 1993-1998
3 %
4
5 \begin{code}
6 module AbsCStixGen ( genCodeAbstractC ) where
7
8 #include "HsVersions.h"
9
10 import Ratio    ( Rational )
11
12 import AbsCSyn
13 import Stix
14 import MachMisc
15
16 import AbsCUtils        ( getAmodeRep, mixedTypeLocn,
17                           nonemptyAbsC, mkAbsCStmts, mkAbsCStmtList
18                         )
19 import PprAbsC          ( dumpRealC )
20 import SMRep            ( fixedItblSize, 
21                           rET_SMALL, rET_BIG, 
22                           rET_VEC_SMALL, rET_VEC_BIG 
23                         )
24 import Constants        ( mIN_UPD_SIZE )
25 import CLabel           ( CLabel, mkReturnInfoLabel, mkReturnPtLabel,
26                           mkClosureTblLabel, mkClosureLabel
27                           moduleRegdLabel )
28 import ClosureInfo      ( infoTableLabelFromCI, entryLabelFromCI,
29                           fastLabelFromCI, closureUpdReqd,
30                           staticClosureNeedsLink
31                         )
32 import Literal          ( Literal(..) )
33 import Maybes           ( maybeToBool )
34 import PrimOp           ( primOpNeedsWrapper, PrimOp(..) )
35 import PrimRep          ( isFloatingRep, PrimRep(..) )
36 import StixInfo         ( genCodeInfoTable, genBitmapInfoTable )
37 import StixMacro        ( macroCode, checkCode )
38 import StixPrim         ( primCode, amodeToStix, amodeToStix' )
39 import Outputable       ( pprPanic )
40 import UniqSupply       ( returnUs, thenUs, mapUs, getUniqueUs, UniqSM )
41 import Util             ( naturalMergeSortLe )
42 import Panic            ( panic )
43 import TyCon            ( tyConDataCons )
44 import DataCon          ( dataConWrapId )
45 import BitSet           ( intBS )
46 import Name             ( NamedThing(..) )
47
48 #ifdef REALLY_HASKELL_1_3
49 ord = fromEnum :: Char -> Int
50 #endif
51 \end{code}
52
53 For each independent chunk of AbstractC code, we generate a list of
54 @StixTree@s, where each tree corresponds to a single Stix instruction.
55 We leave the chunks separated so that register allocation can be
56 performed locally within the chunk.
57
58 \begin{code}
59 genCodeAbstractC :: AbstractC -> UniqSM [[StixTree]]
60
61 genCodeAbstractC absC
62   = mapUs gentopcode (mkAbsCStmtList absC) `thenUs` \ trees ->
63     returnUs ([StComment SLIT("Native Code")] : trees)
64  where
65  a2stix      = amodeToStix
66  a2stix'     = amodeToStix'
67  volsaves    = volatileSaves
68  volrestores = volatileRestores
69  p2stix      = primCode
70  macro_code  = macroCode
71  -- real code follows... ---------
72 \end{code}
73
74 Here we handle top-level things, like @CCodeBlock@s and
75 @CClosureInfoTable@s.
76
77 \begin{code}
78  {-
79  genCodeTopAbsC
80     :: AbstractC
81     -> UniqSM [StixTree]
82  -}
83
84  gentopcode (CCodeBlock lbl absC)
85   = gencode absC                                `thenUs` \ code ->
86     returnUs (StSegment TextSegment : StFunBegin lbl : code [StFunEnd lbl])
87
88  gentopcode stmt@(CStaticClosure lbl _ _ _)
89   = genCodeStaticClosure stmt                   `thenUs` \ code ->
90     returnUs (StSegment DataSegment : StLabel lbl : code [])
91
92  gentopcode stmt@(CRetVector lbl _ _ _)
93   = genCodeVecTbl stmt                          `thenUs` \ code ->
94     returnUs (StSegment TextSegment : code [StLabel lbl])
95
96  gentopcode stmt@(CRetDirect uniq absC srt liveness)
97   = gencode absC                                       `thenUs` \ code ->
98     genBitmapInfoTable liveness srt closure_type False `thenUs` \ itbl ->
99     returnUs (StSegment TextSegment : 
100               itbl (StLabel lbl_info : StLabel lbl_ret : code []))
101   where 
102         lbl_info = mkReturnInfoLabel uniq
103         lbl_ret  = mkReturnPtLabel uniq
104         closure_type = case liveness of
105                          LvSmall _ -> rET_SMALL
106                          LvLarge _ -> rET_BIG
107
108  gentopcode stmt@(CClosureInfoAndCode cl_info slow Nothing _)
109
110   | slow_is_empty
111   = genCodeInfoTable stmt               `thenUs` \ itbl ->
112     returnUs (StSegment TextSegment : itbl [])
113
114   | otherwise
115   = genCodeInfoTable stmt               `thenUs` \ itbl ->
116     gencode slow                        `thenUs` \ slow_code ->
117     returnUs (StSegment TextSegment : itbl (StFunBegin slow_lbl :
118               slow_code [StFunEnd slow_lbl]))
119   where
120     slow_is_empty = not (maybeToBool (nonemptyAbsC slow))
121     slow_lbl = entryLabelFromCI cl_info
122
123  gentopcode stmt@(CClosureInfoAndCode cl_info slow (Just fast) _) =
124  -- ToDo: what if this is empty? ------------------------^^^^
125     genCodeInfoTable stmt               `thenUs` \ itbl ->
126     gencode slow                        `thenUs` \ slow_code ->
127     gencode fast                        `thenUs` \ fast_code ->
128     returnUs (StSegment TextSegment : itbl (StFunBegin slow_lbl :
129               slow_code (StFunEnd slow_lbl : StFunBegin fast_lbl :
130               fast_code [StFunEnd fast_lbl])))
131   where
132     slow_lbl = entryLabelFromCI cl_info
133     fast_lbl = fastLabelFromCI cl_info
134
135  gentopcode stmt@(CSRT lbl closures)
136   = returnUs [ StSegment TextSegment 
137              , StLabel lbl 
138              , StData DataPtrRep (map StCLbl closures)
139              ]
140
141  gentopcode stmt@(CBitmap lbl mask)
142   = returnUs [ StSegment TextSegment 
143              , StLabel lbl 
144              , StData WordRep (StInt (toInteger (length mask)) : 
145                                 map  (StInt . toInteger . intBS) mask)
146              ]
147
148  gentopcode stmt@(CClosureTbl tycon)
149   = returnUs [ StSegment TextSegment
150              , StLabel (mkClosureTblLabel tycon)
151              , StData DataPtrRep (map (StCLbl . mkClosureLabel . getName . dataConWrapId) 
152                                       (tyConDataCons tycon) )
153              ]
154
155  gentopcode stmt@(CModuleInitBlock lbl absC)
156   = gencode absC                        `thenUs` \ code ->
157     getUniqLabelNCG                     `thenUs` \ tmp_lbl ->
158     returnUs ( StSegment DataSegment
159              : StLabel moduleRegdLabel
160              : StData IntRep [StInt 0]
161              : StSegment TextSegment
162              : StLabel lbl
163              : StCondJump tmp_lbl (StPrim IntNeOp [StCLbl moduleRegdLabel, 
164                                                    StInt 0])
165              : StAssign IntRep (StInd IntRep (StCLbl moduleRegdLabel)) (StInt 1)
166              : code 
167              [ StLabel tmp_lbl
168              , StAssign PtrRep stgSp (StPrim IntSubOp [stgSp, StInt 4])
169              , StJump (StInd WordRep stgSp)
170              ])
171
172  gentopcode absC
173   = gencode absC                                `thenUs` \ code ->
174     returnUs (StSegment TextSegment : code [])
175 \end{code}
176
177 \begin{code}
178  {-
179  genCodeVecTbl
180     :: AbstractC
181     -> UniqSM StixTreeList
182  -}
183  genCodeVecTbl (CRetVector lbl amodes srt liveness)
184   = genBitmapInfoTable liveness srt closure_type True `thenUs` \itbl ->
185     returnUs (\xs -> vectbl : itbl xs)
186   where
187     vectbl = StData PtrRep (reverse (map a2stix amodes))
188     closure_type = case liveness of
189                     LvSmall _ -> rET_VEC_SMALL
190                     LvLarge _ -> rET_VEC_BIG
191
192 \end{code}
193
194 \begin{code}
195  {-
196  genCodeStaticClosure
197     :: AbstractC
198     -> UniqSM StixTreeList
199  -}
200  genCodeStaticClosure (CStaticClosure _ cl_info cost_centre amodes)
201   = returnUs (\xs -> table ++ xs)
202   where
203     table = StData PtrRep [StCLbl (infoTableLabelFromCI cl_info)] : 
204             map (\amode -> StData (getAmodeRep amode) [a2stix amode]) amodes ++
205             [StData PtrRep (padding_wds ++ static_link)]
206
207     -- always at least one padding word: this is the static link field
208     -- for the garbage collector.
209     padding_wds = if closureUpdReqd cl_info then
210                         take (max 0 (mIN_UPD_SIZE - length amodes)) zeros
211                   else
212                         []
213
214     static_link | staticClosureNeedsLink cl_info = [StInt 0]
215                 | otherwise                      = []
216
217     zeros = StInt 0 : zeros
218
219     {- needed??? --SDM
220         -- Watch out for VoidKinds...cf. PprAbsC
221     amodeZeroVoid item
222       | getAmodeRep item == VoidRep = StInt 0
223       | otherwise = a2stix item
224     -}
225
226 \end{code}
227
228 Now the individual AbstractC statements.
229
230 \begin{code}
231  {-
232  gencode
233     :: AbstractC
234     -> UniqSM StixTreeList
235  -}
236 \end{code}
237
238 @AbsCNop@s just disappear.
239
240 \begin{code}
241
242  gencode AbsCNop = returnUs id
243
244 \end{code}
245
246 Split markers are a NOP in this land.
247
248 \begin{code}
249
250  gencode CSplitMarker = returnUs id
251
252 \end{code}
253
254 AbstractC instruction sequences are handled individually, and the
255 resulting StixTreeLists are joined together.
256
257 \begin{code}
258
259  gencode (AbsCStmts c1 c2)
260   = gencode c1                          `thenUs` \ b1 ->
261     gencode c2                          `thenUs` \ b2 ->
262     returnUs (b1 . b2)
263
264 \end{code}
265
266 Initialising closure headers in the heap...a fairly complex ordeal if
267 done properly.  For now, we just set the info pointer, but we should
268 really take a peek at the flags to determine whether or not there are
269 other things to be done (setting cost centres, age headers, global
270 addresses, etc.)
271
272 \begin{code}
273
274  gencode (CInitHdr cl_info reg_rel _)
275   = let
276         lhs = a2stix reg_rel
277         lbl = infoTableLabelFromCI cl_info
278     in
279         returnUs (\xs -> StAssign PtrRep (StInd PtrRep lhs) (StCLbl lbl) : xs)
280
281 \end{code}
282
283 Heap/Stack Checks.
284
285 \begin{code}
286
287  gencode (CCheck macro args assts)
288   = gencode assts `thenUs` \assts_stix ->
289     checkCode macro args assts_stix
290
291 \end{code}
292
293 Assignment, the curse of von Neumann, is the center of the code we
294 produce.  In most cases, the type of the assignment is determined
295 by the type of the destination.  However, when the destination can
296 have mixed types, the type of the assignment is ``StgWord'' (we use
297 PtrRep for lack of anything better).  Think:  do we also want a cast
298 of the source?  Be careful about floats/doubles.
299
300 \begin{code}
301
302  gencode (CAssign lhs rhs)
303   | getAmodeRep lhs == VoidRep = returnUs id
304   | otherwise
305   = let pk = getAmodeRep lhs
306         pk' = if mixedTypeLocn lhs && not (isFloatingRep pk) then IntRep else pk
307         lhs' = a2stix lhs
308         rhs' = a2stix' rhs
309     in
310         returnUs (\xs -> StAssign pk' lhs' rhs' : xs)
311
312 \end{code}
313
314 Unconditional jumps, including the special ``enter closure'' operation.
315 Note that the new entry convention requires that we load the InfoPtr (R2)
316 with the address of the info table before jumping to the entry code for Node.
317
318 For a vectored return, we must subtract the size of the info table to
319 get at the return vector.  This depends on the size of the info table,
320 which varies depending on whether we're profiling etc.
321
322 \begin{code}
323
324  gencode (CJump dest)
325   = returnUs (\xs -> StJump (a2stix dest) : xs)
326
327  gencode (CFallThrough (CLbl lbl _))
328   = returnUs (\xs -> StFallThrough lbl : xs)
329
330  gencode (CReturn dest DirectReturn)
331   = returnUs (\xs -> StJump (a2stix dest) : xs)
332
333  gencode (CReturn table (StaticVectoredReturn n))
334   = returnUs (\xs -> StJump dest : xs)
335   where
336     dest = StInd PtrRep (StIndex PtrRep (a2stix table)
337                                   (StInt (toInteger (-n-fixedItblSize-1))))
338
339  gencode (CReturn table (DynamicVectoredReturn am))
340   = returnUs (\xs -> StJump dest : xs)
341   where
342     dest = StInd PtrRep (StIndex PtrRep (a2stix table) dyn_off)
343     dyn_off = StPrim IntSubOp [StPrim IntNegOp [a2stix am], 
344                                StInt (toInteger (fixedItblSize+1))]
345
346 \end{code}
347
348 Now the PrimOps, some of which may need caller-saves register wrappers.
349
350 \begin{code}
351
352  gencode (COpStmt results op args vols)
353   -- ToDo (ADR?): use that liveness mask
354   | primOpNeedsWrapper op
355   = let
356         saves = volsaves vols
357         restores = volrestores vols
358     in
359         p2stix (nonVoid results) op (nonVoid args)
360                                                         `thenUs` \ code ->
361         returnUs (\xs -> saves ++ code (restores ++ xs))
362
363   | otherwise = p2stix (nonVoid results) op (nonVoid args)
364     where
365         nonVoid = filter ((/= VoidRep) . getAmodeRep)
366
367 \end{code}
368
369 Now the dreaded conditional jump.
370
371 Now the if statement.  Almost *all* flow of control are of this form.
372 @
373         if (am==lit) { absC } else { absCdef }
374 @
375         =>
376 @
377         IF am = lit GOTO l1:
378         absC
379         jump l2:
380    l1:
381         absCdef
382    l2:
383 @
384
385 \begin{code}
386
387  gencode (CSwitch discrim alts deflt)
388   = case alts of
389       [] -> gencode deflt
390
391       [(tag,alt_code)] -> case maybe_empty_deflt of
392                                 Nothing -> gencode alt_code
393                                 Just dc -> mkIfThenElse discrim tag alt_code dc
394
395       [(tag1@(MachInt i1), alt_code1),
396        (tag2@(MachInt i2), alt_code2)]
397         | deflt_is_empty && i1 == 0 && i2 == 1
398         -> mkIfThenElse discrim tag1 alt_code1 alt_code2
399         | deflt_is_empty && i1 == 1 && i2 == 0
400         -> mkIfThenElse discrim tag2 alt_code2 alt_code1
401
402         -- If the @discrim@ is simple, then this unfolding is safe.
403       other | simple_discrim -> mkSimpleSwitches discrim alts deflt
404
405         -- Otherwise, we need to do a bit of work.
406       other ->  getUniqueUs                       `thenUs` \ u ->
407                 gencode (AbsCStmts
408                 (CAssign (CTemp u pk) discrim)
409                 (CSwitch (CTemp u pk) alts deflt))
410
411   where
412     maybe_empty_deflt = nonemptyAbsC deflt
413     deflt_is_empty = case maybe_empty_deflt of
414                         Nothing -> True
415                         Just _  -> False
416
417     pk = getAmodeRep discrim
418
419     simple_discrim = case discrim of
420                         CReg _    -> True
421                         CTemp _ _ -> True
422                         other     -> False
423 \end{code}
424
425
426
427 Finally, all of the disgusting AbstractC macros.
428
429 \begin{code}
430
431  gencode (CMacroStmt macro args) = macro_code macro args
432
433  gencode (CCallProfCtrMacro macro _)
434   = returnUs (\xs -> StComment macro : xs)
435
436  gencode (CCallProfCCMacro macro _)
437   = returnUs (\xs -> StComment macro : xs)
438
439  gencode other
440   = pprPanic "AbsCStixGen.gencode" (dumpRealC other)
441 \end{code}
442
443 Here, we generate a jump table if there are more than four (integer)
444 alternatives and the jump table occupancy is greater than 50%.
445 Otherwise, we generate a binary comparison tree.  (Perhaps this could
446 be tuned.)
447
448 \begin{code}
449
450  intTag :: Literal -> Integer
451  intTag (MachChar c)  = toInteger (ord c)
452  intTag (MachInt i) = i
453  intTag _ = panic "intTag"
454
455  fltTag :: Literal -> Rational
456
457  fltTag (MachFloat f) = f
458  fltTag (MachDouble d) = d
459  fltTag _ = panic "fltTag"
460
461  {-
462  mkSimpleSwitches
463     :: CAddrMode -> [(Literal,AbstractC)] -> AbstractC
464     -> UniqSM StixTreeList
465  -}
466  mkSimpleSwitches am alts absC
467   = getUniqLabelNCG                                     `thenUs` \ udlbl ->
468     getUniqLabelNCG                                     `thenUs` \ ujlbl ->
469     let am' = a2stix am
470         joinedAlts = map (\ (tag,code) -> (tag, mkJoin code ujlbl)) alts
471         sortedAlts = naturalMergeSortLe leAlt joinedAlts
472                      -- naturalMergeSortLe, because we often get sorted alts to begin with
473
474         lowTag = intTag (fst (head sortedAlts))
475         highTag = intTag (fst (last sortedAlts))
476
477         -- lowest and highest possible values the discriminant could take
478         lowest = if floating then targetMinDouble else targetMinInt
479         highest = if floating then targetMaxDouble else targetMaxInt
480     in
481         (
482         if not floating && choices > 4 && highTag - lowTag < toInteger (2 * choices) then
483             mkJumpTable am' sortedAlts lowTag highTag udlbl
484         else
485             mkBinaryTree am' floating sortedAlts choices lowest highest udlbl
486         )
487                                                         `thenUs` \ alt_code ->
488         gencode absC                            `thenUs` \ dflt_code ->
489
490         returnUs (\xs -> alt_code (StLabel udlbl : dflt_code (StLabel ujlbl : xs)))
491
492     where
493         floating = isFloatingRep (getAmodeRep am)
494         choices = length alts
495
496         (x@(MachChar _),_) `leAlt` (y,_) = intTag x <= intTag y
497         (x@(MachInt _), _) `leAlt` (y,_) = intTag x <= intTag y
498         (x,_)              `leAlt` (y,_) = fltTag x <= fltTag y
499
500 \end{code}
501
502 We use jump tables when doing an integer switch on a relatively dense
503 list of alternatives.  We expect to be given a list of alternatives,
504 sorted by tag, and a range of values for which we are to generate a
505 table.  Of course, the tags of the alternatives should lie within the
506 indicated range.  The alternatives need not cover the range; a default
507 target is provided for the missing alternatives.
508
509 If a join is necessary after the switch, the alternatives should
510 already finish with a jump to the join point.
511
512 \begin{code}
513  {-
514  mkJumpTable
515     :: StixTree                 -- discriminant
516     -> [(Literal, AbstractC)]   -- alternatives
517     -> Integer                  -- low tag
518     -> Integer                  -- high tag
519     -> CLabel                   -- default label
520     -> UniqSM StixTreeList
521  -}
522
523  mkJumpTable am alts lowTag highTag dflt
524   = getUniqLabelNCG                                     `thenUs` \ utlbl ->
525     mapUs genLabel alts                                 `thenUs` \ branches ->
526     let cjmpLo = StCondJump dflt (StPrim IntLtOp [am, StInt (toInteger lowTag)])
527         cjmpHi = StCondJump dflt (StPrim IntGtOp [am, StInt (toInteger highTag)])
528
529         offset = StPrim IntSubOp [am, StInt lowTag]
530
531         jump = StJump (StInd PtrRep (StIndex PtrRep (StCLbl utlbl) offset))
532         tlbl = StLabel utlbl
533         table = StData PtrRep (mkTable branches [lowTag..highTag] [])
534     in
535         mapUs mkBranch branches                         `thenUs` \ alts ->
536
537         returnUs (\xs -> cjmpLo : cjmpHi : jump :
538                          StSegment DataSegment : tlbl : table :
539                          StSegment TextSegment : foldr1 (.) alts xs)
540
541     where
542         genLabel x = getUniqLabelNCG `thenUs` \ lbl -> returnUs (lbl, x)
543
544         mkBranch (lbl,(_,alt)) =
545             gencode alt                         `thenUs` \ alt_code ->
546             returnUs (\xs -> StLabel lbl : alt_code xs)
547
548         mkTable _  []     tbl = reverse tbl
549         mkTable [] (x:xs) tbl = mkTable [] xs (StCLbl dflt : tbl)
550         mkTable alts@((lbl,(tag,_)):rest) (x:xs) tbl
551           | intTag tag == x = mkTable rest xs (StCLbl lbl : tbl)
552           | otherwise = mkTable alts xs (StCLbl dflt : tbl)
553
554 \end{code}
555
556 We generate binary comparison trees when a jump table is inappropriate.
557 We expect to be given a list of alternatives, sorted by tag, and for
558 convenience, the length of the alternative list.  We recursively break
559 the list in half and do a comparison on the first tag of the second half
560 of the list.  (Odd lists are broken so that the second half of the list
561 is longer.)  We can handle either integer or floating kind alternatives,
562 so long as they are not mixed.  (We assume that the type of the discriminant
563 determines the type of the alternatives.)
564
565 As with the jump table approach, if a join is necessary after the switch, the
566 alternatives should already finish with a jump to the join point.
567
568 \begin{code}
569  {-
570  mkBinaryTree
571     :: StixTree                 -- discriminant
572     -> Bool                     -- floating point?
573     -> [(Literal, AbstractC)]   -- alternatives
574     -> Int                      -- number of choices
575     -> Literal                  -- low tag
576     -> Literal                  -- high tag
577     -> CLabel                   -- default code label
578     -> UniqSM StixTreeList
579  -}
580
581  mkBinaryTree am floating [(tag,alt)] _ lowTag highTag udlbl
582   | rangeOfOne = gencode alt
583   | otherwise
584   = let tag' = a2stix (CLit tag)
585         cmpOp = if floating then DoubleNeOp else IntNeOp
586         test = StPrim cmpOp [am, tag']
587         cjmp = StCondJump udlbl test
588     in
589         gencode alt                             `thenUs` \ alt_code ->
590         returnUs (\xs -> cjmp : alt_code xs)
591
592     where
593         rangeOfOne = not floating && intTag lowTag + 1 >= intTag highTag
594         -- When there is only one possible tag left in range, we skip the comparison
595
596  mkBinaryTree am floating alts choices lowTag highTag udlbl
597   = getUniqLabelNCG                                     `thenUs` \ uhlbl ->
598     let tag' = a2stix (CLit splitTag)
599         cmpOp = if floating then DoubleGeOp else IntGeOp
600         test = StPrim cmpOp [am, tag']
601         cjmp = StCondJump uhlbl test
602     in
603         mkBinaryTree am floating alts_lo half lowTag splitTag udlbl
604                                                         `thenUs` \ lo_code ->
605         mkBinaryTree am floating alts_hi (choices - half) splitTag highTag udlbl
606                                                         `thenUs` \ hi_code ->
607
608         returnUs (\xs -> cjmp : lo_code (StLabel uhlbl : hi_code xs))
609
610     where
611         half = choices `div` 2
612         (alts_lo, alts_hi) = splitAt half alts
613         splitTag = fst (head alts_hi)
614
615 \end{code}
616
617 \begin{code}
618  {-
619  mkIfThenElse
620     :: CAddrMode            -- discriminant
621     -> Literal              -- tag
622     -> AbstractC            -- if-part
623     -> AbstractC            -- else-part
624     -> UniqSM StixTreeList
625  -}
626
627  mkIfThenElse discrim tag alt deflt
628   = getUniqLabelNCG                                     `thenUs` \ ujlbl ->
629     getUniqLabelNCG                                     `thenUs` \ utlbl ->
630     let discrim' = a2stix discrim
631         tag' = a2stix (CLit tag)
632         cmpOp = if (isFloatingRep (getAmodeRep discrim)) then DoubleNeOp else IntNeOp
633         test = StPrim cmpOp [discrim', tag']
634         cjmp = StCondJump utlbl test
635         dest = StLabel utlbl
636         join = StLabel ujlbl
637     in
638         gencode (mkJoin alt ujlbl)              `thenUs` \ alt_code ->
639         gencode deflt                           `thenUs` \ dflt_code ->
640         returnUs (\xs -> cjmp : alt_code (dest : dflt_code (join : xs)))
641
642 mkJoin :: AbstractC -> CLabel -> AbstractC
643
644 mkJoin code lbl
645   | mightFallThrough code = mkAbsCStmts code (CJump (CLbl lbl PtrRep))
646   | otherwise = code
647 \end{code}
648
649 %---------------------------------------------------------------------------
650
651 This answers the question: Can the code fall through to the next
652 line(s) of code?  This errs towards saying True if it can't choose,
653 because it is used for eliminating needless jumps.  In other words, if
654 you might possibly {\em not} jump, then say yes to falling through.
655
656 \begin{code}
657 mightFallThrough :: AbstractC -> Bool
658
659 mightFallThrough absC = ft absC True
660  where
661   ft AbsCNop       if_empty = if_empty
662
663   ft (CJump _)       if_empty = False
664   ft (CReturn _ _)   if_empty = False
665   ft (CSwitch _ alts deflt) if_empty
666         = ft deflt if_empty ||
667           or [ft alt if_empty | (_,alt) <- alts]
668
669   ft (AbsCStmts c1 c2) if_empty = ft c2 (ft c1 if_empty)
670   ft _ if_empty = if_empty
671
672 {- Old algorithm, which called nonemptyAbsC for every subexpression! =========
673 fallThroughAbsC (AbsCStmts c1 c2)
674   = case nonemptyAbsC c2 of
675         Nothing -> fallThroughAbsC c1
676         Just x -> fallThroughAbsC x
677 fallThroughAbsC (CJump _)        = False
678 fallThroughAbsC (CReturn _ _)    = False
679 fallThroughAbsC (CSwitch _ choices deflt)
680   = (not (isEmptyAbsC deflt) && fallThroughAbsC deflt)
681     || or (map (fallThroughAbsC . snd) choices)
682 fallThroughAbsC other            = True
683
684 isEmptyAbsC :: AbstractC -> Bool
685 isEmptyAbsC = not . maybeToBool . nonemptyAbsC
686 ================= End of old, quadratic, algorithm -}
687 \end{code}