getAmodeRep,
mixedTypeLocn, mixedPtrLocn,
flattenAbsC,
- mkAbsCStmtList
+ mkAbsCStmtList,
+ shimFCallArg
-- printing/forcing stuff comes from PprAbsC
) where
#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(..) )
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}
\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
-- 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}
%************************************************************************
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
flatAbsC stmt@(CStaticClosure _ _ _ _) = returnFlt (AbsCNop, stmt)
flatAbsC stmt@(CClosureTbl _) = returnFlt (AbsCNop, stmt)
flatAbsC stmt@(CSRT _ _) = 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@(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}
-- 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
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
(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
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
]
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
]
= 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
]
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}