[project @ 2004-08-13 10:45:16 by simonmar]
[ghc-hetmet.git] / ghc / compiler / absCSyn / AbsCUtils.lhs
index 9271ba2..fef7bf5 100644 (file)
@@ -12,7 +12,8 @@ module AbsCUtils (
        getAmodeRep,
        mixedTypeLocn, mixedPtrLocn,
        flattenAbsC,
-       mkAbsCStmtList
+       mkAbsCStmtList,
+       shimFCallArg
        -- printing/forcing stuff comes from PprAbsC
     ) where
 
@@ -20,9 +21,13 @@ module AbsCUtils (
 #include "../includes/config.h"
 
 import AbsCSyn
+import Type            ( tyConAppTyCon, repType )
+import TysPrim         ( foreignObjPrimTyCon, arrayPrimTyCon, 
+                         byteArrayPrimTyCon, mutableByteArrayPrimTyCon,
+                         mutableArrayPrimTyCon )
 import CLabel          ( mkMAP_FROZEN_infoLabel )
 import Digraph         ( stronglyConnComp, SCC(..) )
-import DataCon         ( fIRST_TAG, ConTag )
+import DataCon         ( fIRST_TAG, dataConTag )
 import Literal         ( literalPrimRep, mkMachWord, mkMachInt )
 import PrimRep         ( getPrimRepSize, PrimRep(..) )
 import PrimOp          ( PrimOp(..) )
@@ -31,15 +36,14 @@ import Unique               ( Unique{-instance Eq-} )
 import UniqSupply      ( uniqFromSupply, uniqsFromSupply, splitUniqSupply, 
                          UniqSupply )
 import CmdLineOpts      ( opt_EmitCExternDecls, opt_Unregisterised )
-import ForeignCall     ( ForeignCall(..), CCallSpec(..),
-                         isDynamicTarget, isCasmTarget )
-import StgSyn          ( StgOp(..) )
+import ForeignCall     ( ForeignCall(..), CCallSpec(..), isDynamicTarget )
+import StgSyn          ( StgOp(..), stgArgType )
+import CoreSyn         ( AltCon(..) )
 import SMRep           ( arrPtrsHdrSize, arrWordsHdrSize, fixedHdrSize )
 import Outputable
 import Panic           ( panic )
 import FastTypes
-
-import Maybe           ( isJust )
+import Constants       ( wORD_SIZE, wORD_SIZE_IN_BITS )
 
 infixr 9 `thenFlt`
 \end{code}
@@ -107,18 +111,14 @@ mkAbsCStmtList' other r = other : r
 \end{code}
 
 \begin{code}
-mkAlgAltsCSwitch :: CAddrMode -> [(ConTag, AbstractC)] -> AbstractC -> AbstractC
+mkAlgAltsCSwitch :: CAddrMode -> [(AltCon, AbstractC)] -> AbstractC
 
-mkAlgAltsCSwitch scrutinee tagged_alts deflt_absc
- | isJust (nonemptyAbsC deflt_absc) 
-       = CSwitch scrutinee (adjust tagged_alts) deflt_absc
- | otherwise 
-       = CSwitch scrutinee (adjust rest) first_alt
+mkAlgAltsCSwitch scrutinee ((_,first_alt) : rest_alts)
+ = CSwitch scrutinee (adjust rest_alts) first_alt
  where
-   -- it's ok to convert one of the alts into a default if we don't already have
-   -- one, because this is an algebraic case and we're guaranteed that the tag 
-   -- will match one of the branches.
-   ((_,first_alt):rest) = tagged_alts
+   -- We use the first alt as the default.  Either it *is* the DEFAULT,
+   -- (which is always first if present), or the case is exhaustive,
+   -- in which case we can use the first as the default anyway
 
    -- Adjust the tags in the switch to start at zero.
    -- This is the convention used by primitive ops which return algebraic
@@ -127,8 +127,8 @@ mkAlgAltsCSwitch scrutinee tagged_alts deflt_absc
 
    -- We also need to convert to Literals to keep the CSwitch happy
    adjust tagged_alts
-     = [ (mkMachWord (toInteger (tag - fIRST_TAG)), abs_c)
-       | (tag, abs_c) <- tagged_alts ]
+     = [ (mkMachWord (toInteger (dataConTag dc - fIRST_TAG)), abs_c)
+       | (DataAlt dc, abs_c) <- tagged_alts ]
 \end{code}
 
 %************************************************************************
@@ -144,13 +144,12 @@ magicIdPrimRep (FloatReg _)           = FloatRep
 magicIdPrimRep (DoubleReg _)       = DoubleRep
 magicIdPrimRep (LongReg kind _)            = kind
 magicIdPrimRep Sp                  = PtrRep
-magicIdPrimRep Su                  = PtrRep
 magicIdPrimRep SpLim               = PtrRep
 magicIdPrimRep Hp                  = PtrRep
 magicIdPrimRep HpLim               = PtrRep
 magicIdPrimRep CurCostCentre       = CostCentreRep
 magicIdPrimRep VoidReg             = VoidRep
-magicIdPrimRep CurrentTSO          = ThreadIdRep
+magicIdPrimRep CurrentTSO          = PtrRep
 magicIdPrimRep CurrentNursery      = PtrRep
 magicIdPrimRep HpAlloc              = WordRep
 \end{code}
@@ -320,11 +319,10 @@ flatAbsC (AbsCStmts s1 s2)
     returnFlt (mkAbsCStmts inline_s1 inline_s2,
               mkAbsCStmts top_s1    top_s2)
 
-flatAbsC (CClosureInfoAndCode cl_info slow maybe_fast descr)
-  = flatAbsC slow              `thenFlt` \ (slow_heres, slow_tops) ->
-    flat_maybe maybe_fast      `thenFlt` \ (fast_heres, fast_tops) ->
-    returnFlt (AbsCNop, mkAbstractCs [slow_tops, fast_tops,
-       CClosureInfoAndCode cl_info slow_heres fast_heres descr]
+flatAbsC (CClosureInfoAndCode cl_info entry)
+  = flatAbsC entry             `thenFlt` \ (entry_heres, entry_tops) ->
+    returnFlt (AbsCNop, mkAbstractCs [entry_tops, 
+       CClosureInfoAndCode cl_info entry_heres]
     )
 
 flatAbsC (CCodeBlock lbl abs_C)
@@ -349,8 +347,8 @@ flatAbsC (CSwitch discrim alts deflt)
        returnFlt ( (tag, alt_heres), alt_tops )
 
 flatAbsC stmt@(COpStmt results (StgFCallOp (CCall ccall@(CCallSpec target _ _)) uniq) args _)
-  |  is_dynamic                                 -- Emit a typedef if its a dynamic call
-     || (opt_EmitCExternDecls && not (isCasmTarget target)) -- or we want extern decls
+  |  is_dynamic                       -- Emit a typedef if its a dynamic call
+     || (opt_EmitCExternDecls) -- or we want extern decls
   = returnFlt (stmt, CCallTypedef is_dynamic ccall uniq results args)
   where
     is_dynamic = isDynamicTarget target
@@ -418,10 +416,11 @@ flatAbsC (CSequential abcs)
 
 -- Some statements only make sense at the top level, so we always float
 -- them.  This probably isn't necessary.
-flatAbsC stmt@(CStaticClosure _ _ _)           = returnFlt (AbsCNop, stmt)
+flatAbsC stmt@(CStaticClosure _ _ _ _)                 = returnFlt (AbsCNop, stmt)
 flatAbsC stmt@(CClosureTbl _)                  = returnFlt (AbsCNop, stmt)
 flatAbsC stmt@(CSRT _ _)                       = returnFlt (AbsCNop, stmt)
-flatAbsC stmt@(CBitmap _ _)                    = returnFlt (AbsCNop, stmt)
+flatAbsC stmt@(CSRTDesc _ _ _ _ _)             = returnFlt (AbsCNop, stmt)
+flatAbsC stmt@(CBitmap _)                      = returnFlt (AbsCNop, stmt)
 flatAbsC stmt@(CCostCentreDecl _ _)            = returnFlt (AbsCNop, stmt)
 flatAbsC stmt@(CCostCentreStackDecl _)         = returnFlt (AbsCNop, stmt)
 flatAbsC stmt@(CSplitMarker)                   = returnFlt (AbsCNop, stmt)
@@ -429,13 +428,6 @@ flatAbsC stmt@(CRetVector _ _ _ _)              = returnFlt (AbsCNop, stmt)
 flatAbsC stmt@(CModuleInitBlock _ _ _)          = returnFlt (AbsCNop, stmt)
 \end{code}
 
-\begin{code}
-flat_maybe :: Maybe AbstractC -> FlatM (Maybe AbstractC, AbstractC)
-flat_maybe Nothing      = returnFlt (Nothing, AbsCNop)
-flat_maybe (Just abs_c) = flatAbsC abs_c `thenFlt` \ (heres, tops) ->
-                         returnFlt (Just heres, tops)
-\end{code}
-
 %************************************************************************
 %*                                                                     *
 \subsection[flat-simultaneous]{Doing things simultaneously}
@@ -607,27 +599,24 @@ rrConflictsWithRR s1b s2b rr1 rr2 = rr rr1 rr2
 -- why it needs to take into account endianness.
 --
 mkHalfWord_HIADDR res arg
-   = mkTemp IntRep                     `thenFlt` \ t_hw_shift ->
-     mkTemp WordRep                    `thenFlt` \ t_hw_mask1 ->
+   = mkTemp WordRep                    `thenFlt` \ t_hw_mask1 ->
      mkTemp WordRep                    `thenFlt` \ t_hw_mask2 ->
-     let a_hw_shift 
-            = CMachOpStmt t_hw_shift
-                          MO_Nat_Shl [CBytesPerWord, CLit (mkMachInt 2)] Nothing
+     let 
+        hw_shift = mkIntCLit (wORD_SIZE_IN_BITS `quot` 2)
+
+#        if WORDS_BIGENDIAN
          a_hw_mask1
             = CMachOpStmt t_hw_mask1
-                          MO_Nat_Shl [CLit (mkMachWord 1), t_hw_shift] Nothing
+                          MO_Nat_Shl [CLit (mkMachWord 1), hw_shift] Nothing
          a_hw_mask2
             = CMachOpStmt t_hw_mask2
                           MO_Nat_Sub [t_hw_mask1, CLit (mkMachWord 1)] Nothing
          final
-#        if WORDS_BIGENDIAN
-            = CSequential [ a_hw_shift, a_hw_mask1, a_hw_mask2,
+            = CSequential [ a_hw_mask1, a_hw_mask2,
                  CMachOpStmt res MO_Nat_And [arg, t_hw_mask2] Nothing
               ]
 #        else
-            = CSequential [ a_hw_shift,
-                 CMachOpStmt res MO_Nat_Shr [arg, t_hw_shift] Nothing
-              ]
+         final = CMachOpStmt res MO_Nat_Shr [arg, hw_shift] Nothing
 #        endif
      in
          returnFlt final
@@ -672,7 +661,7 @@ mk_OSBI_ref offw rep base idx
 
 
 doIndexOffForeignObjOp maybe_post_read_cast rep res addr idx
-   = mkBasicIndexedRead fixedHdrSize maybe_post_read_cast rep res addr idx
+   = mkBasicIndexedRead 0 maybe_post_read_cast rep res (mkDerefOff WordRep addr fixedHdrSize) idx
 
 doIndexOffAddrOp maybe_post_read_cast rep res addr idx
    = mkBasicIndexedRead 0 maybe_post_read_cast rep res addr idx
@@ -728,19 +717,6 @@ translateOp_dyadic_cast1 mop res cast_arg1_to arg1 arg2 vols
            (if isDefinitelyInlineMachOp mop then Nothing else Just vols)
      ]
 
-getBitsPerWordMinus1 :: FlatM (AbstractC, CAddrMode)
-getBitsPerWordMinus1
-   = mkTemps [IntRep, IntRep]          `thenFlt` \ [t1,t2] ->
-     returnFlt (
-        CSequential [
-           CMachOpStmt t1 MO_Nat_Shl 
-                       [CBytesPerWord, CLit (mkMachInt 3)] Nothing,
-           CMachOpStmt t2 MO_Nat_Sub
-                       [t1, CLit (mkMachInt 1)] Nothing
-        ],
-        t2
-     )
-
 -- IA64 mangler doesn't place tables next to code
 tablesNextToCode :: Bool
 #ifdef ia64_TARGET_ARCH
@@ -792,15 +768,14 @@ dscCOpStmt [res_r,res_c] IntAddCOp [aa,bb] vols
    c  = t4 >>unsigned BITS_IN(I_)-1
 -}
    = mkTemps [IntRep,IntRep,IntRep,IntRep]     `thenFlt` \ [t1,t2,t3,t4] ->
-     getBitsPerWordMinus1                      `thenFlt` \ (bpw1_code,bpw1_t) ->
+     let bpw1 = mkIntCLit (wORD_SIZE_IN_BITS - 1) in
      (returnFlt . CSequential) [
         CMachOpStmt res_r MO_Nat_Add [aa,bb] Nothing,
         CMachOpStmt t1 MO_Nat_Xor [aa,bb] Nothing,
         CMachOpStmt t2 MO_Nat_Not [t1] Nothing,
         CMachOpStmt t3 MO_Nat_Xor [aa,res_r] Nothing,
         CMachOpStmt t4 MO_Nat_And [t2,t3] Nothing,
-        bpw1_code,
-        CMachOpStmt res_c MO_Nat_Shr [t4, bpw1_t] Nothing
+        CMachOpStmt res_c MO_Nat_Shr [t4, bpw1] Nothing
      ]
 
 
@@ -820,14 +795,13 @@ dscCOpStmt [res_r,res_c] IntSubCOp [aa,bb] vols
    c  = t3 >>unsigned BITS_IN(I_)-1
 -}
    = mkTemps [IntRep,IntRep,IntRep]            `thenFlt` \ [t1,t2,t3] ->
-     getBitsPerWordMinus1                      `thenFlt` \ (bpw1_code,bpw1_t) ->
+     let bpw1 = mkIntCLit (wORD_SIZE_IN_BITS - 1) in
      (returnFlt . CSequential) [
         CMachOpStmt res_r MO_Nat_Sub [aa,bb] Nothing,
         CMachOpStmt t1 MO_Nat_Xor [aa,bb] Nothing,
         CMachOpStmt t2 MO_Nat_Xor [aa,res_r] Nothing,
         CMachOpStmt t3 MO_Nat_And [t1,t2] Nothing,
-        bpw1_code,
-        CMachOpStmt res_c MO_Nat_Shr [t3, bpw1_t] Nothing
+        CMachOpStmt res_c MO_Nat_Shr [t3, bpw1] Nothing
      ]
 
 
@@ -866,7 +840,7 @@ dscCOpStmt [res] SizeofByteArrayOp [arg] vols
    = mkTemp WordRep                    `thenFlt` \ w ->
      (returnFlt . CSequential) [
         CAssign w (mkDerefOff WordRep arg fixedHdrSize),
-        CMachOpStmt w MO_NatU_Mul [w, CBytesPerWord] (Just vols),
+        CMachOpStmt w MO_NatU_Mul [w, mkIntCLit wORD_SIZE] (Just vols),
         CAssign res w
      ]
 
@@ -1120,7 +1094,7 @@ dscCOpStmt [] WriteOffAddrOp_Int        [a,i,x] vols = doWriteOffAddrOp Nothing
 dscCOpStmt [] WriteOffAddrOp_Word       [a,i,x] vols = doWriteOffAddrOp Nothing WordRep a i x
 dscCOpStmt [] WriteOffAddrOp_Addr       [a,i,x] vols = doWriteOffAddrOp Nothing AddrRep a i x
 dscCOpStmt [] WriteOffAddrOp_Float      [a,i,x] vols = doWriteOffAddrOp Nothing FloatRep a i x
-dscCOpStmt [] WriteOffAddrOp_ForeignObj [a,i,x] vols = doWriteOffAddrOp Nothing ForeignObjRep a i x
+dscCOpStmt [] WriteOffAddrOp_ForeignObj [a,i,x] vols = doWriteOffAddrOp Nothing PtrRep a i x
 dscCOpStmt [] WriteOffAddrOp_Double     [a,i,x] vols = doWriteOffAddrOp Nothing DoubleRep a i x
 dscCOpStmt [] WriteOffAddrOp_StablePtr  [a,i,x] vols = doWriteOffAddrOp Nothing StablePtrRep a i x
 
@@ -1323,5 +1297,19 @@ translateOp [r] EqForeignObj [a1,a2]  = Just (r, MO_Nat_Eq,    [a1,a2])
 translateOp [r] EqStablePtrOp [a1,a2]  = Just (r, MO_Nat_Eq,    [a1,a2])
 
 translateOp _ _ _ = Nothing
+\end{code}
+
 
+\begin{code}
+shimFCallArg arg amode
+  | tycon == foreignObjPrimTyCon
+       = CMacroExpr AddrRep ForeignObj_CLOSURE_DATA [amode]
+  | tycon == arrayPrimTyCon || tycon == mutableArrayPrimTyCon
+       = CMacroExpr PtrRep PTRS_ARR_CTS [amode]
+  | tycon == byteArrayPrimTyCon || tycon == mutableByteArrayPrimTyCon
+       = CMacroExpr AddrRep BYTE_ARR_CTS [amode]
+  | otherwise = amode
+  where        
+       -- should be a tycon app, since this is a foreign call
+       tycon = tyConAppTyCon (repType (stgArgType arg))
 \end{code}