[project @ 2004-08-13 13:04:50 by simonmar]
[ghc-hetmet.git] / ghc / compiler / nativeGen / AbsCStixGen.lhs
diff --git a/ghc/compiler/nativeGen/AbsCStixGen.lhs b/ghc/compiler/nativeGen/AbsCStixGen.lhs
deleted file mode 100644 (file)
index 4a53f14..0000000
+++ /dev/null
@@ -1,694 +0,0 @@
-%
-% (c) The AQUA Project, Glasgow University, 1993-1998
-%
-
-\begin{code}
-module AbsCStixGen ( genCodeAbstractC ) where
-
-#include "HsVersions.h"
-
-import Ratio   ( Rational )
-
-import AbsCSyn
-import Stix
-import MachMisc
-
-import AbsCUtils       ( getAmodeRep, mixedTypeLocn,
-                         nonemptyAbsC, mkAbsCStmts
-                       )
-import PprAbsC          ( dumpRealC )
-import SMRep           ( retItblSize )
-import CLabel           ( CLabel, mkReturnInfoLabel, mkReturnPtLabel,
-                          mkClosureTblLabel, mkClosureLabel,
-                         labelDynamic, mkSplitMarkerLabel )
-import ClosureInfo
-import Literal         ( Literal(..), word2IntLit )
-import StgSyn          ( StgOp(..) )
-import MachOp          ( MachOp(..), resultRepOfMachOp )
-import PrimRep         ( isFloatingRep, is64BitRep, 
-                         PrimRep(..), getPrimRepSizeInBytes )
-import StixMacro       ( macroCode, checkCode )
-import StixPrim                ( foreignCallCode, amodeToStix, amodeToStix' )
-import Outputable       ( pprPanic, ppr )
-import UniqSupply      ( returnUs, thenUs, mapUs, getUniqueUs, UniqSM )
-import Util            ( naturalMergeSortLe )
-import Panic           ( panic )
-import TyCon           ( tyConDataCons )
-import Name             ( NamedThing(..) )
-import CmdLineOpts     ( opt_EnsureSplittableC )
-import Outputable      ( assertPanic )
-
-import Char            ( ord )
-
--- DEBUGGING ONLY
---import TRACE         ( trace )
---import Outputable    ( showSDoc )
---import MachOp                ( pprMachOp )
-
-#include "nativeGen/NCG.h"
-\end{code}
-
-For each independent chunk of AbstractC code, we generate a list of
-@StixTree@s, where each tree corresponds to a single Stix instruction.
-We leave the chunks separated so that register allocation can be
-performed locally within the chunk.
-
-\begin{code}
-genCodeAbstractC :: AbstractC -> UniqSM [StixStmt]
-
-genCodeAbstractC absC
-  = gentopcode absC
- where
- a2stix      = amodeToStix
- a2stix'     = amodeToStix'
- volsaves    = volatileSaves
- volrestores = volatileRestores
- -- real code follows... ---------
-\end{code}
-
-Here we handle top-level things, like @CCodeBlock@s and
-@CClosureInfoTable@s.
-
-\begin{code}
- {-
- genCodeTopAbsC
-    :: AbstractC
-    -> UniqSM [StixTree]
- -}
-
- gentopcode (CCodeBlock lbl absC)
-  = gencode absC                               `thenUs` \ code ->
-    returnUs (StSegment TextSegment : StFunBegin lbl : code [StFunEnd lbl])
-
- gentopcode stmt@(CStaticClosure lbl closure_info _ _)
-  = genCodeStaticClosure stmt                  `thenUs` \ code ->
-    returnUs ( StSegment DataSegment 
-             : StLabel lbl : code []
-             )
-
- gentopcode stmt@(CRetVector lbl amodes srt liveness)
-  = returnUs ( StSegment TextSegment
-            : StData PtrRep table
-            : StLabel lbl
-            : []
-            )
-  where
-    table = map amodeToStix (mkVecInfoTable amodes srt liveness)
-
- gentopcode stmt@(CRetDirect uniq absC srt liveness)
-  = gencode absC                                      `thenUs` \ code ->
-    returnUs ( StSegment TextSegment
-            : StData PtrRep table
-            : StLabel info_lbl
-            : StLabel ret_lbl
-            : code [])
-  where 
-    info_lbl = mkReturnInfoLabel uniq
-    ret_lbl  = mkReturnPtLabel uniq
-    table    = map amodeToStix (mkRetInfoTable ret_lbl srt liveness)
-
- gentopcode stmt@(CClosureInfoAndCode cl_info entry)
-  = gencode entry                      `thenUs` \ slow_code ->
-    returnUs ( StSegment TextSegment
-            : StData PtrRep table
-            : StLabel info_lbl
-            : StFunBegin entry_lbl
-            : slow_code [StFunEnd entry_lbl])
-  where
-    entry_lbl = entryLabelFromCI cl_info
-    info_lbl = infoTableLabelFromCI cl_info
-    table    = map amodeToStix (mkInfoTable cl_info)
-
- gentopcode stmt@(CSRT lbl closures)
-  = returnUs [ StSegment TextSegment 
-            , StLabel lbl 
-            , StData DataPtrRep (map mk_StCLbl_for_SRT closures)
-            ]
-    where
-       mk_StCLbl_for_SRT :: CLabel -> StixExpr
-       mk_StCLbl_for_SRT label
-          | labelDynamic label
-          = StIndex Int8Rep (StCLbl label) (StInt 1)
-          | otherwise
-          = StCLbl label
-
- gentopcode stmt@(CBitmap l@(Liveness lbl size mask))
-  = returnUs 
-       [ StSegment TextSegment 
-       , StLabel lbl 
-       , StData WordRep (map StInt (toInteger size : map toInteger mask))
-       ]
-
- gentopcode stmt@(CSRTDesc lbl srt_lbl off len bitmap)
-  = returnUs 
-       [ StSegment TextSegment 
-       , StLabel lbl 
-       , StData WordRep (
-               StIndex PtrRep (StCLbl srt_lbl) (StInt (toInteger off)) :
-               map StInt (toInteger len : map toInteger bitmap)
-           )
-       ]
-
- gentopcode stmt@(CClosureTbl tycon)
-  = returnUs [ StSegment TextSegment
-             , StLabel (mkClosureTblLabel tycon)
-             , StData DataPtrRep (map (StCLbl . mkClosureLabel . getName) 
-                                      (tyConDataCons tycon) )
-             ]
-
- gentopcode stmt@(CModuleInitBlock plain_lbl lbl absC)
-  = gencode absC                       `thenUs` \ code ->
-    getUniqLabelNCG                    `thenUs` \ tmp_lbl ->
-    getUniqLabelNCG                    `thenUs` \ flag_lbl ->
-    returnUs ( StSegment DataSegment
-            : StLabel flag_lbl
-            : StData IntRep [StInt 0]
-            : StSegment TextSegment
-            : StLabel plain_lbl
-            : StJump NoDestInfo (StCLbl lbl)
-            : StLabel lbl
-            : StCondJump tmp_lbl (StMachOp MO_Nat_Ne
-                                    [StInd IntRep (StCLbl flag_lbl),
-                                     StInt 0])
-            : StAssignMem IntRep (StCLbl flag_lbl) (StInt 1)
-            : code 
-            [ StLabel tmp_lbl
-            , StAssignReg PtrRep stgSp
-                           (StIndex PtrRep (StReg stgSp) (StInt (-1)))
-            , StJump NoDestInfo (StInd WordRep (StReg stgSp))
-            ])
-
- gentopcode absC
-  = gencode absC                               `thenUs` \ code ->
-    returnUs (StSegment TextSegment : code [])
-\end{code}
-
-\begin{code}
- {-
- genCodeStaticClosure
-    :: AbstractC
-    -> UniqSM StixTreeList
- -}
- genCodeStaticClosure (CStaticClosure lbl cl_info cost_centre amodes)
-  = returnUs (\xs -> table ++ xs)
-  where
-    table = StData PtrRep [StCLbl (infoTableLabelFromCI cl_info)] : 
-           foldr do_one_amode [] amodes
-
-    do_one_amode amode rest
-       | rep == VoidRep = rest
-       | otherwise      = StData (promote_to_word rep) [a2stix amode] : rest
-       where 
-         rep = getAmodeRep amode
-
-    -- We need to promote any item smaller than a word to a word
-    promote_to_word pk 
-       | getPrimRepSizeInBytes pk >= getPrimRepSizeInBytes IntRep  = pk
-       | otherwise                                                 = IntRep
-\end{code}
-
-Now the individual AbstractC statements.
-
-\begin{code}
- {-
- gencode
-    :: AbstractC
-    -> UniqSM StixTreeList
- -}
-\end{code}
-
-@AbsCNop@s just disappear.
-
-\begin{code}
-
- gencode AbsCNop = returnUs id
-
-\end{code}
-
-Split markers just insert a __stg_split_marker, which is caught by the
-split-mangler later on and used to split the assembly into chunks.
-
-\begin{code}
-
- gencode CSplitMarker
-   | opt_EnsureSplittableC = returnUs (\xs -> StLabel mkSplitMarkerLabel : xs)
-   | otherwise             = returnUs id
-
-\end{code}
-
-AbstractC instruction sequences are handled individually, and the
-resulting StixTreeLists are joined together.
-
-\begin{code}
-
- gencode (AbsCStmts c1 c2)
-  = gencode c1                         `thenUs` \ b1 ->
-    gencode c2                         `thenUs` \ b2 ->
-    returnUs (b1 . b2)
-
- gencode (CSequential stuff)
-  = foo stuff
-    where
-       foo [] = returnUs id
-       foo (s:ss) = gencode s  `thenUs` \ stix ->
-                    foo ss     `thenUs` \ stixes ->
-                    returnUs (stix . stixes)
-
-\end{code}
-
-Initialising closure headers in the heap...a fairly complex ordeal if
-done properly. For now, we just set the info pointer, but we should
-really take a peek at the flags to determine whether or not there are
-other things to be done (setting cost centres, age headers, global
-addresses, etc.)
-
-\begin{code}
-
- gencode (CInitHdr cl_info reg_rel _ _)
-  = let
-       lhs = a2stix reg_rel
-       lbl = infoTableLabelFromCI cl_info
-    in
-       returnUs (\xs -> StAssignMem PtrRep lhs (StCLbl lbl) : xs)
-
-\end{code}
-
-Heap/Stack Checks.
-
-\begin{code}
-
- gencode (CCheck macro args assts)
-  = gencode assts `thenUs` \assts_stix ->
-    checkCode macro args assts_stix
-
-\end{code}
-
-Assignment, the curse of von Neumann, is the center of the code we
-produce.  In most cases, the type of the assignment is determined
-by the type of the destination.  However, when the destination can
-have mixed types, the type of the assignment is ``StgWord'' (we use
-PtrRep for lack of anything better).  Think:  do we also want a cast
-of the source?  Be careful about floats/doubles.
-
-\begin{code}
-
- gencode (CAssign lhs rhs)
-  | lhs_rep == VoidRep 
-  = returnUs id
-  | otherwise
-  = let -- This is a Hack.  Should be cleaned up.
-        -- JRS, 10 Dec 01
-        pk' | ncg_target_is_32bit && is64BitRep lhs_rep
-            = lhs_rep
-            | otherwise
-            = if   mixedTypeLocn lhs && not (isFloatingRep lhs_rep) 
-              then IntRep 
-              else lhs_rep
-       lhs' = a2stix lhs
-       rhs' = a2stix' rhs
-    in
-       returnUs (\xs -> mkStAssign pk' lhs' rhs' : xs)
-    where 
-       lhs_rep = getAmodeRep lhs
-
-\end{code}
-
-Unconditional jumps, including the special ``enter closure'' operation.
-Note that the new entry convention requires that we load the InfoPtr (R2)
-with the address of the info table before jumping to the entry code for Node.
-
-For a vectored return, we must subtract the size of the info table to
-get at the return vector.  This depends on the size of the info table,
-which varies depending on whether we're profiling etc.
-
-\begin{code}
-
- gencode (CJump dest)
-  = returnUs (\xs -> StJump NoDestInfo (a2stix dest) : xs)
-
- gencode (CFallThrough (CLbl lbl _))
-  = returnUs (\xs -> StFallThrough lbl : xs)
-
- gencode (CReturn dest DirectReturn)
-  = returnUs (\xs -> StJump NoDestInfo (a2stix dest) : xs)
-
- gencode (CReturn table (StaticVectoredReturn n))
-  = returnUs (\xs -> StJump NoDestInfo dest : xs)
-  where
-    dest = StInd PtrRep (StIndex PtrRep (a2stix table)
-                                 (StInt (toInteger (-n-retItblSize-1))))
-
- gencode (CReturn table (DynamicVectoredReturn am))
-  = returnUs (\xs -> StJump NoDestInfo dest : xs)
-  where
-    dest = StInd PtrRep (StIndex PtrRep (a2stix table) dyn_off)
-    dyn_off = StMachOp MO_Nat_Sub [StMachOp MO_NatS_Neg [a2stix am], 
-                                  StInt (toInteger (retItblSize+1))]
-
-\end{code}
-
-Now the PrimOps, some of which may need caller-saves register wrappers.
-
-\begin{code}
- gencode (COpStmt results (StgFCallOp fcall _) args vols)
-  = ASSERT( null vols )
-    foreignCallCode (nonVoid results) fcall (nonVoid args)
-
- gencode (COpStmt results (StgPrimOp op) args vols)
-  = panic "AbsCStixGen.gencode: un-translated PrimOp"
-
- gencode (CMachOpStmt res mop args vols)
-  = returnUs (\xs -> mkStAssign (resultRepOfMachOp mop) (a2stix res) 
-                                (StMachOp mop (map a2stix args))
-                     : xs
-             )
-\end{code}
-
-Now the dreaded conditional jump.
-
-Now the if statement.  Almost *all* flow of control are of this form.
-@
-       if (am==lit) { absC } else { absCdef }
-@
-       =>
-@
-       IF am = lit GOTO l1:
-       absC
-       jump l2:
-   l1:
-       absCdef
-   l2:
-@
-
-\begin{code}
-
- gencode (CSwitch discrim alts deflt)
-  = case alts of
-      [] -> gencode deflt
-
-      [(tag,alt_code)] -> case maybe_empty_deflt of
-                               Nothing -> gencode alt_code
-                               Just dc -> mkIfThenElse discrim tag alt_code dc
-
-      [(tag1@(MachInt i1), alt_code1),
-       (tag2@(MachInt i2), alt_code2)]
-       | deflt_is_empty && i1 == 0 && i2 == 1
-       -> mkIfThenElse discrim tag1 alt_code1 alt_code2
-       | deflt_is_empty && i1 == 1 && i2 == 0
-       -> mkIfThenElse discrim tag2 alt_code2 alt_code1
-
-       -- If the @discrim@ is simple, then this unfolding is safe.
-      other | simple_discrim -> mkSimpleSwitches discrim alts deflt
-
-       -- Otherwise, we need to do a bit of work.
-      other ->  getUniqueUs                      `thenUs` \ u ->
-               gencode (AbsCStmts
-               (CAssign (CTemp u pk) discrim)
-               (CSwitch (CTemp u pk) alts deflt))
-
-  where
-    maybe_empty_deflt = nonemptyAbsC deflt
-    deflt_is_empty = case maybe_empty_deflt of
-                       Nothing -> True
-                       Just _  -> False
-
-    pk = getAmodeRep discrim
-
-    simple_discrim = case discrim of
-                       CReg _    -> True
-                       CTemp _ _ -> True
-                       other     -> False
-\end{code}
-
-
-
-Finally, all of the disgusting AbstractC macros.
-
-\begin{code}
-
- gencode (CMacroStmt macro args) = macroCode macro (map amodeToStix args)
-
- gencode (CCallProfCtrMacro macro _)
-  = returnUs (\xs -> StComment macro : xs)
-
- gencode (CCallProfCCMacro macro _)
-  = returnUs (\xs -> StComment macro : xs)
-
- gencode CCallTypedef{} = returnUs id
-
- gencode other
-  = pprPanic "AbsCStixGen.gencode" (dumpRealC other)
-
- nonVoid = filter ((/= VoidRep) . getAmodeRep)
-\end{code}
-
-Here, we generate a jump table if there are more than four (integer)
-alternatives and the jump table occupancy is greater than 50%.
-Otherwise, we generate a binary comparison tree.  (Perhaps this could
-be tuned.)
-
-\begin{code}
-
- intTag :: Literal -> Integer
- intTag (MachChar c)  = toInteger (ord c)
- intTag (MachInt i)   = i
- intTag (MachWord w)  = intTag (word2IntLit (MachWord w))
- intTag _             = panic "intTag"
-
- fltTag :: Literal -> Rational
-
- fltTag (MachFloat f)  = f
- fltTag (MachDouble d) = d
- fltTag x              = pprPanic "fltTag" (ppr x)
-
- {-
- mkSimpleSwitches
-    :: CAddrMode -> [(Literal,AbstractC)] -> AbstractC
-    -> UniqSM StixTreeList
- -}
- mkSimpleSwitches am alts absC
-  = getUniqLabelNCG                                    `thenUs` \ udlbl ->
-    getUniqLabelNCG                                    `thenUs` \ ujlbl ->
-    let am' = a2stix am
-       joinedAlts = map (\ (tag,code) -> (tag, mkJoin code ujlbl)) alts
-       sortedAlts = naturalMergeSortLe leAlt joinedAlts
-                    -- naturalMergeSortLe, because we often get sorted alts to begin with
-
-       lowTag = intTag (fst (head sortedAlts))
-       highTag = intTag (fst (last sortedAlts))
-
-       -- lowest and highest possible values the discriminant could take
-       lowest = if floating then targetMinDouble else targetMinInt
-       highest = if floating then targetMaxDouble else targetMaxInt
-    in
-       (
-       if  not floating && choices > 4 
-            && highTag - lowTag < toInteger (2 * choices)
-        then
-           mkJumpTable am' sortedAlts lowTag highTag udlbl
-       else
-           mkBinaryTree am' floating sortedAlts choices lowest highest udlbl
-       )
-                                               `thenUs` \ alt_code ->
-       gencode absC                            `thenUs` \ dflt_code ->
-
-       returnUs (\xs -> alt_code (StLabel udlbl : dflt_code (StLabel ujlbl : xs)))
-
-    where
-       floating = isFloatingRep (getAmodeRep am)
-       choices = length alts
-
-       (x@(MachChar _),_)  `leAlt` (y,_) = intTag x <= intTag y
-       (x@(MachInt _), _)  `leAlt` (y,_) = intTag x <= intTag y
-       (x@(MachWord _), _) `leAlt` (y,_) = intTag x <= intTag y
-       (x,_)               `leAlt` (y,_) = fltTag x <= fltTag y
-
-\end{code}
-
-We use jump tables when doing an integer switch on a relatively dense
-list of alternatives.  We expect to be given a list of alternatives,
-sorted by tag, and a range of values for which we are to generate a
-table.  Of course, the tags of the alternatives should lie within the
-indicated range.  The alternatives need not cover the range; a default
-target is provided for the missing alternatives.
-
-If a join is necessary after the switch, the alternatives should
-already finish with a jump to the join point.
-
-\begin{code}
- {-
- mkJumpTable
-    :: StixTree                -- discriminant
-    -> [(Literal, AbstractC)]  -- alternatives
-    -> Integer                         -- low tag
-    -> Integer                         -- high tag
-    -> CLabel                  -- default label
-    -> UniqSM StixTreeList
- -}
-
- mkJumpTable am alts lowTag highTag dflt
-  = getUniqLabelNCG                                    `thenUs` \ utlbl ->
-    mapUs genLabel alts                                `thenUs` \ branches ->
-    let        cjmpLo = StCondJump dflt (StMachOp MO_NatS_Lt [am, StInt (toInteger lowTag)])
-       cjmpHi = StCondJump dflt (StMachOp MO_NatS_Gt [am, StInt (toInteger highTag)])
-
-       offset = StMachOp MO_Nat_Sub [am, StInt lowTag]
-        dsts   = DestInfo (dflt : map fst branches)
-
-       jump = StJump dsts (StInd PtrRep (StIndex PtrRep (StCLbl utlbl) offset))
-       tlbl = StLabel utlbl
-       table = StData PtrRep (mkTable branches [lowTag..highTag] [])
-    in
-       mapUs mkBranch branches                         `thenUs` \ alts ->
-
-       returnUs (\xs -> cjmpLo : cjmpHi : jump :
-                        StSegment DataSegment : tlbl : table :
-                        StSegment TextSegment : foldr1 (.) alts xs)
-
-    where
-       genLabel x = getUniqLabelNCG `thenUs` \ lbl -> returnUs (lbl, x)
-
-       mkBranch (lbl,(_,alt)) =
-           gencode alt                         `thenUs` \ alt_code ->
-           returnUs (\xs -> StLabel lbl : alt_code xs)
-
-       mkTable _  []     tbl = reverse tbl
-       mkTable [] (x:xs) tbl = mkTable [] xs (StCLbl dflt : tbl)
-       mkTable alts@((lbl,(tag,_)):rest) (x:xs) tbl
-         | intTag tag == x = mkTable rest xs (StCLbl lbl : tbl)
-         | otherwise = mkTable alts xs (StCLbl dflt : tbl)
-
-\end{code}
-
-We generate binary comparison trees when a jump table is inappropriate.
-We expect to be given a list of alternatives, sorted by tag, and for
-convenience, the length of the alternative list.  We recursively break
-the list in half and do a comparison on the first tag of the second half
-of the list.  (Odd lists are broken so that the second half of the list
-is longer.)  We can handle either integer or floating kind alternatives,
-so long as they are not mixed.  (We assume that the type of the discriminant
-determines the type of the alternatives.)
-
-As with the jump table approach, if a join is necessary after the switch, the
-alternatives should already finish with a jump to the join point.
-
-\begin{code}
- {-
- mkBinaryTree
-    :: StixTree                -- discriminant
-    -> Bool                    -- floating point?
-    -> [(Literal, AbstractC)]  -- alternatives
-    -> Int                     -- number of choices
-    -> Literal                 -- low tag
-    -> Literal                 -- high tag
-    -> CLabel                  -- default code label
-    -> UniqSM StixTreeList
- -}
-
- mkBinaryTree am floating [(tag,alt)] _ lowTag highTag udlbl
-  | rangeOfOne = gencode alt
-  | otherwise
-  = let        tag' = a2stix (CLit tag)
-       cmpOp = if floating then MO_Dbl_Ne else MO_Nat_Ne
-       test = StMachOp cmpOp [am, tag']
-       cjmp = StCondJump udlbl test
-    in
-       gencode alt                             `thenUs` \ alt_code ->
-       returnUs (\xs -> cjmp : alt_code xs)
-
-    where
-       rangeOfOne = not floating && intTag lowTag + 1 >= intTag highTag
-       -- When there is only one possible tag left in range, we skip the comparison
-
- mkBinaryTree am floating alts choices lowTag highTag udlbl
-  = getUniqLabelNCG                                    `thenUs` \ uhlbl ->
-    let tag' = a2stix (CLit splitTag)
-       cmpOp = if floating then MO_Dbl_Ge else MO_NatS_Ge
-       test = StMachOp cmpOp [am, tag']
-       cjmp = StCondJump uhlbl test
-    in
-       mkBinaryTree am floating alts_lo half lowTag splitTag udlbl
-                                                       `thenUs` \ lo_code ->
-       mkBinaryTree am floating alts_hi (choices - half) splitTag highTag udlbl
-                                                       `thenUs` \ hi_code ->
-
-       returnUs (\xs -> cjmp : lo_code (StLabel uhlbl : hi_code xs))
-
-    where
-       half = choices `div` 2
-       (alts_lo, alts_hi) = splitAt half alts
-       splitTag = fst (head alts_hi)
-
-\end{code}
-
-\begin{code}
- {-
- mkIfThenElse
-    :: CAddrMode           -- discriminant
-    -> Literal             -- tag
-    -> AbstractC           -- if-part
-    -> AbstractC           -- else-part
-    -> UniqSM StixTreeList
- -}
-
- mkIfThenElse discrim tag alt deflt
-  = getUniqLabelNCG                                    `thenUs` \ ujlbl ->
-    getUniqLabelNCG                                    `thenUs` \ utlbl ->
-    let discrim' = a2stix discrim
-       tag' = a2stix (CLit tag)
-       cmpOp = if (isFloatingRep (getAmodeRep discrim)) then MO_Dbl_Ne else MO_Nat_Ne
-       test = StMachOp cmpOp [discrim', tag']
-       cjmp = StCondJump utlbl test
-       dest = StLabel utlbl
-       join = StLabel ujlbl
-    in
-       gencode (mkJoin alt ujlbl)              `thenUs` \ alt_code ->
-       gencode deflt                           `thenUs` \ dflt_code ->
-       returnUs (\xs -> cjmp : alt_code (dest : dflt_code (join : xs)))
-
-
-mkJoin :: AbstractC -> CLabel -> AbstractC
-mkJoin code lbl
-  | mightFallThrough code = mkAbsCStmts code (CJump (CLbl lbl PtrRep))
-  | otherwise = code
-\end{code}
-
-%---------------------------------------------------------------------------
-
-This answers the question: Can the code fall through to the next
-line(s) of code?  This errs towards saying True if it can't choose,
-because it is used for eliminating needless jumps.  In other words, if
-you might possibly {\em not} jump, then say yes to falling through.
-
-\begin{code}
-mightFallThrough :: AbstractC -> Bool
-
-mightFallThrough absC = ft absC True
- where
-  ft AbsCNop      if_empty = if_empty
-
-  ft (CJump _)       if_empty = False
-  ft (CReturn _ _)   if_empty = False
-  ft (CSwitch _ alts deflt) if_empty
-       = ft deflt if_empty ||
-         or [ft alt if_empty | (_,alt) <- alts]
-
-  ft (AbsCStmts c1 c2) if_empty = ft c2 (ft c1 if_empty)
-  ft _ if_empty = if_empty
-
-{- Old algorithm, which called nonemptyAbsC for every subexpression! =========
-fallThroughAbsC (AbsCStmts c1 c2)
-  = case nonemptyAbsC c2 of
-       Nothing -> fallThroughAbsC c1
-       Just x -> fallThroughAbsC x
-fallThroughAbsC (CJump _)       = False
-fallThroughAbsC (CReturn _ _)   = False
-fallThroughAbsC (CSwitch _ choices deflt)
-  = (not (isEmptyAbsC deflt) && fallThroughAbsC deflt)
-    || or (map (fallThroughAbsC . snd) choices)
-fallThroughAbsC other           = True
-
-isEmptyAbsC :: AbstractC -> Bool
-isEmptyAbsC = not . maybeToBool . nonemptyAbsC
-================= End of old, quadratic, algorithm -}
-\end{code}