validate fix: eliminate a warning on non-Windows
[ghc-hetmet.git] / compiler / ghci / ByteCodeGen.lhs
index 72586ab..14b5ba4 100644 (file)
@@ -11,9 +11,9 @@ module ByteCodeGen ( UnlinkedBCO, byteCodeGen, coreExprToBCOs ) where
 
 import ByteCodeInstr
 import ByteCodeItbls
-import ByteCodeFFI
 import ByteCodeAsm
 import ByteCodeLink
+import LibFFI
 
 import Outputable
 import Name
@@ -30,7 +30,6 @@ import CoreFVs
 import Type
 import DataCon
 import TyCon
-import Class
 import Type
 import Util
 import DataCon
@@ -47,16 +46,21 @@ import Bitmap
 import OrdList
 import Constants
 
-import Data.List       ( intersperse, sortBy, zip4, zip6, partition )
-import Foreign         ( Ptr, castPtr, mallocBytes, pokeByteOff, Word8,
-                         withForeignPtr, castFunPtrToPtr )
+import Data.List
+import Foreign
 import Foreign.C
 import Control.Exception       ( throwDyn )
 
 import GHC.Exts                ( Int(..), ByteArray# )
 
 import Control.Monad   ( when )
-import Data.Char       ( ord, chr )
+import Data.Char
+
+import UniqSupply
+import BreakArray
+import Data.Maybe
+import Module 
+import IdInfo 
 
 -- -----------------------------------------------------------------------------
 -- Generating byte code for a complete module 
@@ -64,15 +68,17 @@ import Data.Char    ( ord, chr )
 byteCodeGen :: DynFlags
             -> [CoreBind]
            -> [TyCon]
+            -> ModBreaks 
             -> IO CompiledByteCode
-byteCodeGen dflags binds tycs
+byteCodeGen dflags binds tycs modBreaks 
    = do showPass dflags "ByteCodeGen"
 
         let flatBinds = [ (bndr, freeVars rhs) 
                        | (bndr, rhs) <- flattenBinds binds]
 
-        (BcM_State final_ctr mallocd, proto_bcos)
-           <- runBc (mapM schemeTopBind flatBinds)
+        us <- mkSplitUniqSupply 'y'  
+        (BcM_State _us _final_ctr mallocd _, proto_bcos) 
+           <- runBc us modBreaks (mapM schemeTopBind flatBinds)  
 
         when (notNull mallocd)
              (panic "ByteCodeGen.byteCodeGen: missing final emitBc?")
@@ -95,11 +101,14 @@ coreExprToBCOs dflags expr
 
       -- create a totally bogus name for the top-level BCO; this
       -- should be harmless, since it's never used for anything
-      let invented_name  = mkSystemVarName (mkPseudoUniqueE 0) FSLIT("ExprTopLevel")
+      let invented_name  = mkSystemVarName (mkPseudoUniqueE 0) (fsLit "ExprTopLevel")
           invented_id    = Id.mkLocalId invented_name (panic "invented_id's type")
          
-      (BcM_State final_ctr mallocd, proto_bco) 
-         <- runBc (schemeTopBind (invented_id, freeVars expr))
+      -- the uniques are needed to generate fresh variables when we introduce new
+      -- let bindings for ticked expressions
+      us <- mkSplitUniqSupply 'y'
+      (BcM_State _us _final_ctr mallocd _ , proto_bco)  
+         <- runBc us emptyModBreaks (schemeTopBind (invented_id, freeVars expr))
 
       when (notNull mallocd)
            (panic "ByteCodeGen.coreExprToBCOs: missing final emitBc?")
@@ -120,6 +129,7 @@ type Sequel = Int   -- back off to this depth before ENTER
 -- to mess with it after each push/pop.
 type BCEnv = FiniteMap Id Int  -- To find vars on the stack
 
+{-
 ppBCEnv :: BCEnv -> SDoc
 ppBCEnv p
    = text "begin-env"
@@ -128,6 +138,7 @@ ppBCEnv p
      where
         pp_one (var, offset) = int offset <> colon <+> ppr var <+> ppr (idCgRep var)
         cmp_snd x y = compare (snd x) (snd y)
+-}
 
 -- Create a BCO and do a spot of peephole optimisation on the insns
 -- at the same time.
@@ -141,8 +152,7 @@ mkProtoBCO
    -> Bool     -- True <=> is a return point, rather than a function
    -> [BcPtr]
    -> ProtoBCO name
-mkProtoBCO nm instrs_ordlist origin arity bitmap_size bitmap
-  is_ret mallocd_blocks
+mkProtoBCO nm instrs_ordlist origin arity bitmap_size bitmap is_ret mallocd_blocks 
    = ProtoBCO {
        protoBCOName = nm,
        protoBCOInstrs = maybe_with_stack_check,
@@ -161,17 +171,19 @@ mkProtoBCO nm instrs_ordlist origin arity bitmap_size bitmap
         -- (hopefully rare) cases when the (overestimated) stack use
         -- exceeds iNTERP_STACK_CHECK_THRESH.
         maybe_with_stack_check
-          | is_ret = peep_d
-               -- don't do stack checks at return points;
+          | is_ret && stack_usage < aP_STACK_SPLIM = peep_d
+               -- don't do stack checks at return points,
                -- everything is aggregated up to the top BCO
-               -- (which must be a function)
-           | stack_overest >= iNTERP_STACK_CHECK_THRESH
-           = STKCHECK stack_overest : peep_d
+               -- (which must be a function).
+                -- That is, unless the stack usage is >= AP_STACK_SPLIM,
+                -- see bug #1466.
+           | stack_usage >= iNTERP_STACK_CHECK_THRESH
+           = STKCHECK stack_usage : peep_d
            | otherwise
            = peep_d    -- the supposedly common case
              
         -- We assume that this sum doesn't wrap
-        stack_overest = sum (map bciStackUse peep_d)
+        stack_usage = sum (map bciStackUse peep_d)
 
         -- Merge local pushes
         peep_d = peep (fromOL instrs_ordlist)
@@ -199,22 +211,24 @@ argBits (rep : args)
 schemeTopBind :: (Id, AnnExpr Id VarSet) -> BcM (ProtoBCO Name)
 
 
-schemeTopBind (id, rhs)
+schemeTopBind (id, rhs) 
   | Just data_con <- isDataConWorkId_maybe id,
-    isNullaryRepDataCon data_con
-  =    -- Special case for the worker of a nullary data con.
+    isNullaryRepDataCon data_con = do
+       -- Special case for the worker of a nullary data con.
        -- It'll look like this:        Nil = /\a -> Nil a
        -- If we feed it into schemeR, we'll get 
        --      Nil = Nil
        -- because mkConAppCode treats nullary constructor applications
        -- by just re-using the single top-level definition.  So
        -- for the worker itself, we must allocate it directly.
+    -- ioToBc (putStrLn $ "top level BCO")
     emitBc (mkProtoBCO (getName id) (toOL [PACK data_con 0, ENTER])
-                       (Right rhs) 0 0 [{-no bitmap-}] False{-not alts-})
+                       (Right rhs) 0 0 [{-no bitmap-}] False{-not alts-}) 
 
   | otherwise
   = schemeR [{- No free variables -}] (id, rhs)
 
+
 -- -----------------------------------------------------------------------------
 -- schemeR
 
@@ -232,7 +246,7 @@ schemeR :: [Id]             -- Free vars of the RHS, ordered as they
                                -- top-level things, which have no free vars.
        -> (Id, AnnExpr Id VarSet)
        -> BcM (ProtoBCO Name)
-schemeR fvs (nm, rhs) 
+schemeR fvs (nm, rhs)
 {-
    | trace (showSDoc (
               (char ' '
@@ -245,11 +259,13 @@ schemeR fvs (nm, rhs)
 -}
    = schemeR_wrk fvs nm rhs (collect [] rhs)
 
-collect xs (_, AnnNote note e) = collect xs e
-collect xs (_, AnnCast e _)    = collect xs e
-collect xs (_, AnnLam x e)     = collect (if isTyVar x then xs else (x:xs)) e
-collect xs (_, not_lambda)     = (reverse xs, not_lambda)
+collect :: [Var] -> AnnExpr Id VarSet -> ([Var], AnnExpr' Id VarSet)
+collect xs (_, AnnNote _ e) = collect xs e
+collect xs (_, AnnCast e _) = collect xs e
+collect xs (_, AnnLam x e)  = collect (if isTyVar x then xs else (x:xs)) e
+collect xs (_, not_lambda)  = (reverse xs, not_lambda)
 
+schemeR_wrk :: [Id] -> Id -> AnnExpr Id VarSet -> ([Var], AnnExpr' Var VarSet) -> BcM (ProtoBCO Name) 
 schemeR_wrk fvs nm original_body (args, body)
    = let 
         all_args  = reverse args ++ fvs
@@ -267,10 +283,37 @@ schemeR_wrk fvs nm original_body (args, body)
         bitmap_size = length bits
         bitmap = mkBitmap bits
      in do
-     body_code <- schemeE szw_args 0 p_init body
+     body_code <- schemeER_wrk szw_args p_init body   
      emitBc (mkProtoBCO (getName nm) body_code (Right original_body)
                arity bitmap_size bitmap False{-not alts-})
 
+-- introduce break instructions for ticked expressions
+schemeER_wrk :: Int -> BCEnv -> AnnExpr' Id VarSet -> BcM BCInstrList
+schemeER_wrk d p rhs
+   | Just (tickInfo, (_annot, newRhs)) <- isTickedExp' rhs = do 
+        code <- schemeE d 0 p newRhs 
+        arr <- getBreakArray 
+        let idOffSets = getVarOffSets d p tickInfo 
+        let tickNumber = tickInfo_number tickInfo
+        let breakInfo = BreakInfo 
+                        { breakInfo_module = tickInfo_module tickInfo
+                        , breakInfo_number = tickNumber 
+                        , breakInfo_vars = idOffSets
+                        , breakInfo_resty = exprType (deAnnotate' newRhs)
+                        }
+        let breakInstr = case arr of (BA arr#) -> BRK_FUN arr# tickNumber breakInfo 
+        return $ breakInstr `consOL` code
+   | otherwise = schemeE d 0 p rhs 
+
+getVarOffSets :: Int -> BCEnv -> TickInfo -> [(Id, Int)]
+getVarOffSets d p = catMaybes . map (getOffSet d p) . tickInfo_locals 
+
+getOffSet :: Int -> BCEnv -> Id -> Maybe (Id, Int)
+getOffSet d env id 
+   = case lookupBCEnv_maybe env id of
+        Nothing     -> Nothing 
+        Just offset -> Just (id, d - offset)
 
 fvsToEnv :: BCEnv -> VarSet -> [Id]
 -- Takes the free variables of a right-hand side, and
@@ -288,12 +331,24 @@ fvsToEnv p fvs = [v | v <- varSetElems fvs,
 -- -----------------------------------------------------------------------------
 -- schemeE
 
+data TickInfo 
+   = TickInfo   
+     { tickInfo_number :: Int     -- the (module) unique number of the tick
+     , tickInfo_module :: Module  -- the origin of the ticked expression 
+     , tickInfo_locals :: [Id]    -- the local vars in scope at the ticked expression
+     } 
+
+instance Outputable TickInfo where
+   ppr info = text "TickInfo" <+> 
+              parens (int (tickInfo_number info) <+> ppr (tickInfo_module info) <+>
+                      ppr (tickInfo_locals info))
+
 -- Compile code to apply the given expression to the remaining args
 -- on the stack, returning a HNF.
 schemeE :: Int -> Sequel -> BCEnv -> AnnExpr' Id VarSet -> BcM BCInstrList
 
 -- Delegate tail-calls to schemeT.
-schemeE d s p e@(AnnApp f a) 
+schemeE d s p e@(AnnApp _ _) 
    = schemeT d s p e
 
 schemeE d s p e@(AnnVar v)
@@ -354,7 +409,7 @@ schemeE d s p (AnnLet binds (_,body))
          zipE  = zipEqual "schemeE"
 
          -- ToDo: don't build thunks for things with no free variables
-         build_thunk dd [] size bco off arity
+         build_thunk _ [] size bco off arity
             = return (PUSH_BCO bco `consOL` unitOL (mkap (off+size) size))
           where 
                mkap | arity == 0 = MKAP
@@ -365,9 +420,15 @@ schemeE d s p (AnnLet binds (_,body))
               return (push_code `appOL` more_push_code)
 
          alloc_code = toOL (zipWith mkAlloc sizes arities)
-          where mkAlloc sz 0     = ALLOC_AP sz
+          where mkAlloc sz 0
+                    | is_tick     = ALLOC_AP_NOUPD sz
+                    | otherwise   = ALLOC_AP sz
                 mkAlloc sz arity = ALLOC_PAP arity sz
 
+         is_tick = case binds of 
+                     AnnNonRec id _ -> occNameFS (getOccName id) == tickFS
+                     _other -> False
+
         compile_bind d' fvs x rhs size arity off = do
                bco <- schemeR fvs (x,rhs)
                build_thunk d' fvs size bco off arity
@@ -382,9 +443,26 @@ schemeE d s p (AnnLet binds (_,body))
      thunk_codes <- sequence compile_binds
      return (alloc_code `appOL` concatOL thunk_codes `appOL` body_code)
 
-
-
-schemeE d s p (AnnCase scrut bndr _ [(DataAlt dc, [bind1, bind2], rhs)])
+-- introduce a let binding for a ticked case expression. This rule
+-- *should* only fire when the expression was not already let-bound
+-- (the code gen for let bindings should take care of that).  Todo: we
+-- call exprFreeVars on a deAnnotated expression, this may not be the
+-- best way to calculate the free vars but it seemed like the least
+-- intrusive thing to do
+schemeE d s p exp@(AnnCase {})
+   | Just (_tickInfo, rhs) <- isTickedExp' exp
+   = if isUnLiftedType ty
+        then schemeE d s p (snd rhs)
+        else do
+          id <- newId ty
+          -- Todo: is emptyVarSet correct on the next line?
+          let letExp = AnnLet (AnnNonRec id (fvs, exp)) (emptyVarSet, AnnVar id)
+          schemeE d s p letExp
+   where exp' = deAnnotate' exp
+         fvs  = exprFreeVars exp'
+         ty   = exprType exp'
+
+schemeE d s p (AnnCase scrut _ _ [(DataAlt dc, [bind1, bind2], rhs)])
    | isUnboxedTupleCon dc, VoidArg <- typeCgRep (idType bind1)
        -- Convert 
        --      case .... of x { (# VoidArg'd-thing, a #) -> ... }
@@ -396,34 +474,81 @@ schemeE d s p (AnnCase scrut bndr _ [(DataAlt dc, [bind1, bind2], rhs)])
        -- envt (it won't be bound now) because we never look such things up.
 
    = --trace "automagic mashing of case alts (# VoidArg, a #)" $
-     doCase d s p scrut bind2 [(DEFAULT, [], rhs)] True{-unboxed tuple-}
+     doCase d s p scrut bind2 [(DEFAULT, [], rhs)] True{-unboxed tuple-} 
 
    | isUnboxedTupleCon dc, VoidArg <- typeCgRep (idType bind2)
    = --trace "automagic mashing of case alts (# a, VoidArg #)" $
-     doCase d s p scrut bind1 [(DEFAULT, [], rhs)] True{-unboxed tuple-}
+     doCase d s p scrut bind1 [(DEFAULT, [], rhs)] True{-unboxed tuple-} 
 
-schemeE d s p (AnnCase scrut bndr _ [(DataAlt dc, [bind1], rhs)])
+schemeE d s p (AnnCase scrut _ _ [(DataAlt dc, [bind1], rhs)])
    | isUnboxedTupleCon dc
        -- Similarly, convert
        --      case .... of x { (# a #) -> ... }
        -- to
        --      case .... of a { DEFAULT -> ... }
    = --trace "automagic mashing of case alts (# a #)"  $
-     doCase d s p scrut bind1 [(DEFAULT, [], rhs)] True{-unboxed tuple-}
+     doCase d s p scrut bind1 [(DEFAULT, [], rhs)] True{-unboxed tuple-} 
 
 schemeE d s p (AnnCase scrut bndr _ alts)
-   = doCase d s p scrut bndr alts False{-not an unboxed tuple-}
+   = doCase d s p scrut bndr alts False{-not an unboxed tuple-} 
 
-schemeE d s p (AnnNote note (_, body))
+schemeE d s p (AnnNote _ (_, body))
    = schemeE d s p body
 
 schemeE d s p (AnnCast (_, body) _)
    = schemeE d s p body
 
-schemeE d s p other
+schemeE _ _ _ expr
    = pprPanic "ByteCodeGen.schemeE: unhandled case" 
-               (pprCoreExpr (deAnnotate' other))
+               (pprCoreExpr (deAnnotate' expr))
 
+{- 
+   Ticked Expressions
+   ------------------
+  
+   A ticked expression looks like this:
+
+      case tick<n> var1 ... varN of DEFAULT -> e
+
+   (*) <n> is the number of the tick, which is unique within a module
+   (*) var1 ... varN are the local variables in scope at the tick site
+
+   If we find a ticked expression we return:
+
+      Just ((n, [var1 ... varN]), e)
+
+  otherwise we return Nothing.
+
+  The idea is that the "case tick<n> ..." is really just an annotation on 
+  the code. When we find such a thing, we pull out the useful information,
+  and then compile the code as if it was just the expression "e".
+
+-}
+
+isTickedExp' :: AnnExpr' Id a -> Maybe (TickInfo, AnnExpr Id a)
+isTickedExp' (AnnCase scrut _bndr _type alts)
+   | Just tickInfo <- isTickedScrut scrut,
+     [(DEFAULT, _bndr, rhs)] <- alts 
+     = Just (tickInfo, rhs)
+   where
+   isTickedScrut :: (AnnExpr Id a) -> Maybe TickInfo 
+   isTickedScrut expr
+      | Var id <- f,
+        Just (TickBox modName tickNumber) <- isTickBoxOp_maybe id
+           = Just $ TickInfo { tickInfo_number = tickNumber
+                             , tickInfo_module = modName
+                             , tickInfo_locals = idsOfArgs args
+                             }
+      | otherwise = Nothing
+      where
+      (f, args) = collectArgs $ deAnnotate expr
+      idsOfArgs :: [Expr Id] -> [Id]
+      idsOfArgs = catMaybes . map exprId 
+      exprId :: Expr Id -> Maybe Id
+      exprId (Var id) = Just id
+      exprId _        = Nothing
+
+isTickedExp' _ = Nothing
 
 -- Compile code to do a tail call.  Specifically, push the fn,
 -- slide the on-stack app back down to the sequel depth,
@@ -511,8 +636,8 @@ schemeT d s p app
               (AnnApp (_, AnnApp (_, AnnVar v) (_, AnnType t)) arg)
                  -> case isPrimOpId_maybe v of
                        Just TagToEnumOp -> Just (snd arg, extract_constr_Names t)
-                      other            -> Nothing
-              other -> Nothing
+                      _                -> Nothing
+              _ -> Nothing
 
        -- Extract the args (R->L) and fn
        -- The function will necessarily be a variable, 
@@ -536,13 +661,13 @@ mkConAppCode :: Int -> Sequel -> BCEnv
             -> [AnnExpr' Id VarSet]    -- Args, in *reverse* order
             -> BcM BCInstrList
 
-mkConAppCode orig_d s p con [] -- Nullary constructor
+mkConAppCode _ _ _ con []      -- Nullary constructor
   = ASSERT( isNullaryRepDataCon con )
     return (unitOL (PUSH_G (getName (dataConWorkId con))))
        -- Instead of doing a PACK, which would allocate a fresh
        -- copy of this constructor, use the single shared version.
 
-mkConAppCode orig_d s p con args_r_to_l 
+mkConAppCode orig_d _ p con args_r_to_l 
   = ASSERT( dataConRepArity con == length args_r_to_l )
     do_pushery orig_d (non_ptr_args ++ ptr_args)
  where
@@ -608,6 +733,7 @@ doTailCall init_d s p fn args
     return (final_d, push_code `appOL` more_push_code)
 
 -- v. similar to CgStackery.findMatch, ToDo: merge
+findPushSeq :: [CgRep] -> (BCInstr, Int, [CgRep])
 findPushSeq (PtrArg: PtrArg: PtrArg: PtrArg: PtrArg: PtrArg: rest)
   = (PUSH_APPLY_PPPPPP, 6, rest)
 findPushSeq (PtrArg: PtrArg: PtrArg: PtrArg: PtrArg: rest)
@@ -640,8 +766,7 @@ doCase  :: Int -> Sequel -> BCEnv
        -> AnnExpr Id VarSet -> Id -> [AnnAlt Id VarSet]
        -> Bool  -- True <=> is an unboxed tuple case, don't enter the result
        -> BcM BCInstrList
-doCase d s p (_,scrut)
- bndr alts is_unboxed_tuple
+doCase d s p (_,scrut) bndr alts is_unboxed_tuple 
   = let
         -- Top of stack is the return itbl, as usual.
         -- underneath it is the pointer to the alt_code BCO.
@@ -670,16 +795,17 @@ doCase d s p (_,scrut)
         isAlgCase = not (isUnLiftedType bndr_ty) && not is_unboxed_tuple
 
         -- given an alt, return a discr and code for it.
-       codeALt alt@(DEFAULT, _, (_,rhs))
+       codeAlt (DEFAULT, _, (_,rhs))
           = do rhs_code <- schemeE d_alts s p_alts rhs
                return (NoDiscr, rhs_code)
-        codeAlt alt@(discr, bndrs, (_,rhs))
+
+        codeAlt alt@(_, bndrs, (_,rhs))
           -- primitive or nullary constructor alt: no need to UNPACK
           | null real_bndrs = do
                rhs_code <- schemeE d_alts s p_alts rhs
                 return (my_discr alt, rhs_code)
           -- algebraic alt with some binders
-           | ASSERT(isAlgCase) otherwise =
+           | otherwise =
              let
                 (ptrs,nptrs) = partition (isFollowableArg.idCgRep) real_bndrs
                 ptr_sizes    = map idSizeW ptrs
@@ -691,19 +817,19 @@ doCase d s p (_,scrut)
                        (zip (reverse (ptrs ++ nptrs))
                          (mkStackOffsets d_alts (reverse bind_sizes)))
             in do
+             MASSERT(isAlgCase)
             rhs_code <- schemeE (d_alts+size) s p' rhs
              return (my_discr alt, unitOL (UNPACK size) `appOL` rhs_code)
           where
             real_bndrs = filter (not.isTyVar) bndrs
 
-
-        my_discr (DEFAULT, binds, rhs) = NoDiscr {-shouldn't really happen-}
-        my_discr (DataAlt dc, binds, rhs) 
+        my_discr (DEFAULT, _, _) = NoDiscr {-shouldn't really happen-}
+        my_discr (DataAlt dc, _, _) 
            | isUnboxedTupleCon dc
            = unboxedTupleException
            | otherwise
            = DiscrP (dataConTag dc - fIRST_TAG)
-        my_discr (LitAlt l, binds, rhs)
+        my_discr (LitAlt l, _, _)
            = case l of MachInt i     -> DiscrI (fromInteger i)
                        MachFloat r   -> DiscrF (fromRational r)
                        MachDouble r  -> DiscrD (fromRational r)
@@ -745,6 +871,7 @@ doCase d s p (_,scrut)
      in do
      alt_stuff <- mapM codeAlt alts
      alt_final <- mkMultiBranch maybe_ncons alt_stuff
+
      let 
          alt_bco_name = getName bndr
          alt_bco = mkProtoBCO alt_bco_name alt_final (Left alts)
@@ -776,7 +903,7 @@ generateCCall :: Int -> Sequel              -- stack and sequel depths
               -> [AnnExpr' Id VarSet]  -- args (atoms)
               -> BcM BCInstrList
 
-generateCCall d0 s p ccall_spec@(CCallSpec target cconv safety) fn args_r_to_l
+generateCCall d0 s p (CCallSpec target cconv _) fn args_r_to_l
    = let 
          -- useful constants
          addr_sizeW = cgRepSizeW NonPtrArg
@@ -786,7 +913,7 @@ generateCCall d0 s p ccall_spec@(CCallSpec target cconv safety) fn args_r_to_l
          -- depth to the first word of the bits for that arg, and the
          -- CgRep of what was actually pushed.
 
-         pargs d [] = return []
+         pargs _ [] = return []
          pargs d (a:az) 
             = let arg_ty = repType (exprType (deAnnotate' a))
 
@@ -797,18 +924,18 @@ generateCCall d0 s p ccall_spec@(CCallSpec target cconv safety) fn args_r_to_l
                     | t == arrayPrimTyCon || t == mutableArrayPrimTyCon
                        -> do rest <- pargs (d + addr_sizeW) az
                              code <- parg_ArrayishRep arrPtrsHdrSize d p a
-                             return ((code,NonPtrArg):rest)
+                             return ((code,AddrRep):rest)
 
                     | t == byteArrayPrimTyCon || t == mutableByteArrayPrimTyCon
                        -> do rest <- pargs (d + addr_sizeW) az
                              code <- parg_ArrayishRep arrWordsHdrSize d p a
-                             return ((code,NonPtrArg):rest)
+                             return ((code,AddrRep):rest)
 
                     -- Default case: push taggedly, but otherwise intact.
-                    other
+                    _
                        -> do (code_a, sz_a) <- pushAtom d p a
                              rest <- pargs (d+sz_a) az
-                             return ((code_a, atomRep a) : rest)
+                             return ((code_a, atomPrimRep a) : rest)
 
          -- Do magic for Ptr/Byte arrays.  Push a ptr to the array on
          -- the stack but then advance it over the headers, so as to
@@ -823,11 +950,12 @@ generateCCall d0 s p ccall_spec@(CCallSpec target cconv safety) fn args_r_to_l
      code_n_reps <- pargs d0 args_r_to_l
      let
          (pushs_arg, a_reps_pushed_r_to_l) = unzip code_n_reps
+         a_reps_sizeW = sum (map primRepSizeW a_reps_pushed_r_to_l)
 
          push_args    = concatOL pushs_arg
-         d_after_args = d0 + sum (map cgRepSizeW a_reps_pushed_r_to_l)
+         d_after_args = d0 + a_reps_sizeW
          a_reps_pushed_RAW
-            | null a_reps_pushed_r_to_l || head a_reps_pushed_r_to_l /= VoidArg
+            | null a_reps_pushed_r_to_l || head a_reps_pushed_r_to_l /= VoidRep
             = panic "ByteCodeGen.generateCCall: missing or invalid World token?"
             | otherwise
             = reverse (tail a_reps_pushed_r_to_l)
@@ -839,7 +967,7 @@ generateCCall d0 s p ccall_spec@(CCallSpec target cconv safety) fn args_r_to_l
          -- Get the result rep.
          (returns_void, r_rep)
             = case maybe_getCCallReturnRep (idType fn) of
-                 Nothing -> (True,  VoidArg)
+                 Nothing -> (True,  VoidRep)
                  Just rr -> (False, rr) 
          {-
          Because the Haskell stack grows down, the a_reps refer to 
@@ -882,8 +1010,18 @@ generateCCall d0 s p ccall_spec@(CCallSpec target cconv safety) fn args_r_to_l
                  DynamicTarget
                     -> return (False, panic "ByteCodeGen.generateCCall(dyn)")
                  StaticTarget target
-                    -> do res <- ioToBc (lookupStaticPtr target)
+                    -> do res <- ioToBc (lookupStaticPtr stdcall_adj_target)
                           return (True, res)
+                   where
+                      stdcall_adj_target
+#ifdef mingw32_TARGET_OS
+                          | StdCallConv <- cconv
+                          = let size = a_reps_sizeW * wORD_SIZE in
+                            mkFastString (unpackFS target ++ '@':show size)
+#endif
+                          | otherwise
+                          = target
+
      -- in
      (is_static, static_target_addr) <- get_target_info
      let
@@ -905,7 +1043,7 @@ generateCCall d0 s p ccall_spec@(CCallSpec target cconv safety) fn args_r_to_l
 
          -- Push the return placeholder.  For a call returning nothing,
          -- this is a VoidArg (tag).
-         r_sizeW   = cgRepSizeW r_rep
+         r_sizeW   = primRepSizeW r_rep
          d_after_r = d_after_Addr + r_sizeW
          r_lit     = mkDummyLiteral r_rep
          push_r    = (if   returns_void 
@@ -913,28 +1051,27 @@ generateCCall d0 s p ccall_spec@(CCallSpec target cconv safety) fn args_r_to_l
                       else unitOL (PUSH_UBX (Left r_lit) r_sizeW))
 
          -- generate the marshalling code we're going to call
-         r_offW       = 0 
-         addr_offW    = r_sizeW
-         arg1_offW    = r_sizeW + addr_sizeW
-         args_offW    = map (arg1_offW +) 
-                            (init (scanl (+) 0 (map cgRepSizeW a_reps)))
-     -- in
-     addr_of_marshaller <- ioToBc (mkMarshalCode cconv
-                                (r_offW, r_rep) addr_offW
-                                (zip args_offW a_reps))
-     recordItblMallocBc (ItblPtr (castFunPtrToPtr addr_of_marshaller))
-     let
+
         -- Offset of the next stack frame down the stack.  The CCALL
         -- instruction needs to describe the chunk of stack containing
         -- the ccall args to the GC, so it needs to know how large it
         -- is.  See comment in Interpreter.c with the CCALL instruction.
         stk_offset   = d_after_r - s
 
+     -- in
+     -- the only difference in libffi mode is that we prepare a cif
+     -- describing the call type by calling libffi, and we attach the
+     -- address of this to the CCALL instruction.
+     token <- ioToBc $ prepForeignCall cconv a_reps r_rep
+     let addr_of_marshaller = castPtrToFunPtr token
+
+     recordItblMallocBc (ItblPtr (castFunPtrToPtr addr_of_marshaller))
+     let
          -- do the call
          do_call      = unitOL (CCALL stk_offset (castFunPtrToPtr addr_of_marshaller))
          -- slide and return
          wrapup       = mkSLIDE r_sizeW (d_after_r - r_sizeW - s)
-                        `snocOL` RETURN_UBX r_rep
+                        `snocOL` RETURN_UBX (primRepToCgRep r_rep)
      --in
          --trace (show (arg1_offW, args_offW  ,  (map cgRepSizeW a_reps) )) $
      return (
@@ -942,17 +1079,19 @@ generateCCall d0 s p ccall_spec@(CCallSpec target cconv safety) fn args_r_to_l
          push_Addr `appOL` push_r `appOL` do_call `appOL` wrapup
          )
 
-
 -- Make a dummy literal, to be used as a placeholder for FFI return
 -- values on the stack.
-mkDummyLiteral :: CgRep -> Literal
+mkDummyLiteral :: PrimRep -> Literal
 mkDummyLiteral pr
    = case pr of
-        NonPtrArg -> MachWord 0
-        DoubleArg -> MachDouble 0
-        FloatArg  -> MachFloat 0
-        LongArg   -> MachWord64 0
-        _         -> moan64 "mkDummyLiteral" (ppr pr)
+        IntRep    -> MachInt 0
+        WordRep   -> MachWord 0
+        AddrRep   -> MachNullAddr
+        DoubleRep -> MachDouble 0
+        FloatRep  -> MachFloat 0
+        Int64Rep  -> MachInt64 0
+        Word64Rep -> MachWord64 0
+        _         -> panic "mkDummyLiteral"
 
 
 -- Convert (eg) 
@@ -969,21 +1108,21 @@ mkDummyLiteral pr
 --
 -- to  Nothing
 
-maybe_getCCallReturnRep :: Type -> Maybe CgRep
+maybe_getCCallReturnRep :: Type -> Maybe PrimRep
 maybe_getCCallReturnRep fn_ty
-   = let (a_tys, r_ty) = splitFunTys (dropForAlls fn_ty)
+   = let (_a_tys, r_ty) = splitFunTys (dropForAlls fn_ty)
          maybe_r_rep_to_go  
             = if isSingleton r_reps then Nothing else Just (r_reps !! 1)
          (r_tycon, r_reps) 
             = case splitTyConApp_maybe (repType r_ty) of
-                      (Just (tyc, tys)) -> (tyc, map typeCgRep tys)
+                      (Just (tyc, tys)) -> (tyc, map typePrimRep tys)
                       Nothing -> blargh
-         ok = ( ( r_reps `lengthIs` 2 && VoidArg == head r_reps)
-                || r_reps == [VoidArg] )
+         ok = ( ( r_reps `lengthIs` 2 && VoidRep == head r_reps)
+                || r_reps == [VoidRep] )
               && isUnboxedTupleTyCon r_tycon
               && case maybe_r_rep_to_go of
                     Nothing    -> True
-                    Just r_rep -> r_rep /= PtrArg
+                    Just r_rep -> r_rep /= PtrRep
                                   -- if it was, it would be impossible 
                                   -- to create a valid return value 
                                   -- placeholder on the stack
@@ -1034,7 +1173,7 @@ pushAtom :: Int -> BCEnv -> AnnExpr' Id VarSet -> BcM (BCInstrList, Int)
 pushAtom d p (AnnApp f (_, AnnType _))
    = pushAtom d p (snd f)
 
-pushAtom d p (AnnNote note e)
+pushAtom d p (AnnNote _ e)
    = pushAtom d p (snd e)
 
 pushAtom d p (AnnLam x e) 
@@ -1073,15 +1212,16 @@ pushAtom d p (AnnVar v)
          sz = idSizeW v
 
 
-pushAtom d p (AnnLit lit)
+pushAtom _ _ (AnnLit lit)
    = case lit of
-        MachLabel fs _ -> code NonPtrArg
-        MachWord w     -> code NonPtrArg
-        MachInt i      -> code PtrArg
-        MachFloat r    -> code FloatArg
-        MachDouble r   -> code DoubleArg
-        MachChar c     -> code NonPtrArg
-        MachStr s      -> pushStr s
+        MachLabel _ _ -> code NonPtrArg
+        MachWord _    -> code NonPtrArg
+        MachInt _     -> code PtrArg
+        MachFloat _   -> code FloatArg
+        MachDouble _  -> code DoubleArg
+        MachChar _    -> code NonPtrArg
+        MachStr s     -> pushStr s
+        l             -> pprPanic "pushAtom" (ppr l)
      where
         code rep
            = let size_host_words = cgRepSizeW rep
@@ -1114,9 +1254,9 @@ pushAtom d p (AnnLit lit)
 pushAtom d p (AnnCast e _)
    = pushAtom d p (snd e)
 
-pushAtom d p other
+pushAtom _ _ expr
    = pprPanic "ByteCodeGen.pushAtom" 
-              (pprCoreExpr (deAnnotate (undefined, other)))
+              (pprCoreExpr (deAnnotate (undefined, expr)))
 
 foreign import ccall unsafe "memcpy"
  memcpy :: Ptr a -> Ptr b -> CSize -> IO ()
@@ -1139,7 +1279,7 @@ mkMultiBranch maybe_ncons raw_ways
                         (filter (not.isNoDiscr.fst) raw_ways)
 
          mkTree :: [(Discr, BCInstrList)] -> Discr -> Discr -> BcM BCInstrList
-         mkTree [] range_lo range_hi = return the_default
+         mkTree [] _range_lo _range_hi = return the_default
 
          mkTree [val] range_lo range_hi
             | range_lo `eqAlt` range_hi 
@@ -1168,6 +1308,7 @@ mkMultiBranch maybe_ncons raw_ways
          the_default 
             = case d_way of [] -> unitOL CASEFAIL
                             [(_, def)] -> def
+                            _ -> panic "mkMultiBranch/the_default"
 
          -- None of these will be needed if there are no non-default alts
          (mkTestLT, mkTestEQ, init_lo, init_hi)
@@ -1190,7 +1331,8 @@ mkMultiBranch maybe_ncons raw_ways
               DiscrP _ -> ( \(DiscrP i) fail_label -> TESTLT_P i fail_label,
                             \(DiscrP i) fail_label -> TESTEQ_P i fail_label,
                             DiscrP algMinBound,
-                            DiscrP algMaxBound )
+                            DiscrP algMaxBound );
+              NoDiscr -> panic "mkMultiBranch NoDiscr"
               }
 
          (algMinBound, algMaxBound)
@@ -1256,17 +1398,18 @@ lookupBCEnv_maybe = lookupFM
 idSizeW :: Id -> Int
 idSizeW id = cgRepSizeW (typeCgRep (idType id))
 
+-- See bug #1257
 unboxedTupleException :: a
 unboxedTupleException 
    = throwDyn 
-        (Panic 
-           ("Bytecode generator can't handle unboxed tuples.  Possibly due\n" ++
-            "\tto foreign import/export decls in source.  Workaround:\n" ++
-            "\tcompile this module to a .o file, then restart session."))
+        (ProgramError 
+           ("Error: bytecode compiler can't handle unboxed tuples.\n"++
+            "  Possibly due to foreign import/export decls in source.\n"++
+            "  Workaround: use -fobject-code, or compile this module to .o separately."))
 
 
+mkSLIDE :: Int -> Int -> OrdList BCInstr
 mkSLIDE n d = if d == 0 then nilOL else unitOL (SLIDE n d)
-bind x f    = f x
 
 splitApp :: AnnExpr' id ann -> (AnnExpr' id ann, [AnnExpr' id ann])
        -- The arguments are returned in *right-to-left* order
@@ -1274,7 +1417,7 @@ splitApp (AnnApp (_,f) (_,a))
               | isTypeAtom a = splitApp f
               | otherwise    = case splitApp f of 
                                     (f', as) -> (f', a:as)
-splitApp (AnnNote n (_,e))    = splitApp e
+splitApp (AnnNote _ (_,e))    = splitApp e
 splitApp (AnnCast (_,e) _)    = splitApp e
 splitApp e                   = (e, [])
 
@@ -1284,19 +1427,22 @@ isTypeAtom (AnnType _) = True
 isTypeAtom _           = False
 
 isVoidArgAtom :: AnnExpr' id ann -> Bool
-isVoidArgAtom (AnnVar v)        = typeCgRep (idType v) == VoidArg
-isVoidArgAtom (AnnNote n (_,e)) = isVoidArgAtom e
+isVoidArgAtom (AnnVar v)        = typePrimRep (idType v) == VoidRep
+isVoidArgAtom (AnnNote _ (_,e)) = isVoidArgAtom e
 isVoidArgAtom (AnnCast (_,e) _) = isVoidArgAtom e
 isVoidArgAtom _                = False
 
+atomPrimRep :: AnnExpr' Id ann -> PrimRep
+atomPrimRep (AnnVar v)    = typePrimRep (idType v)
+atomPrimRep (AnnLit l)    = typePrimRep (literalType l)
+atomPrimRep (AnnNote _ b) = atomPrimRep (snd b)
+atomPrimRep (AnnApp f (_, AnnType _)) = atomPrimRep (snd f)
+atomPrimRep (AnnLam x e) | isTyVar x = atomPrimRep (snd e)
+atomPrimRep (AnnCast b _) = atomPrimRep (snd b)
+atomPrimRep other = pprPanic "atomPrimRep" (ppr (deAnnotate (undefined,other)))
+
 atomRep :: AnnExpr' Id ann -> CgRep
-atomRep (AnnVar v)    = typeCgRep (idType v)
-atomRep (AnnLit l)    = typeCgRep (literalType l)
-atomRep (AnnNote n b) = atomRep (snd b)
-atomRep (AnnApp f (_, AnnType _)) = atomRep (snd f)
-atomRep (AnnLam x e) | isTyVar x = atomRep (snd e)
-atomRep (AnnCast b _) = atomRep (snd b)
-atomRep other = pprPanic "atomRep" (ppr (deAnnotate (undefined,other)))
+atomRep e = primRepToCgRep (atomPrimRep e)
 
 isPtrAtom :: AnnExpr' Id ann -> Bool
 isPtrAtom e = atomRep e == PtrArg
@@ -1315,9 +1461,12 @@ type BcPtr = Either ItblPtr (Ptr ())
 
 data BcM_State 
    = BcM_State { 
+        uniqSupply :: UniqSupply,       -- for generating fresh variable names
        nextlabel :: Int,               -- for generating local labels
-       malloced  :: [BcPtr] }          -- thunks malloced for current BCO
+       malloced  :: [BcPtr],           -- thunks malloced for current BCO
                                        -- Should be free()d when it is GCd
+        breakArray :: BreakArray        -- array of breakpoint flags 
+        }
 
 newtype BcM r = BcM (BcM_State -> IO (BcM_State, r))
 
@@ -1326,8 +1475,11 @@ ioToBc io = BcM $ \st -> do
   x <- io 
   return (st, x)
 
-runBc :: BcM r -> IO (BcM_State, r)
-runBc (BcM m) = m (BcM_State 0 []) 
+runBc :: UniqSupply -> ModBreaks -> BcM r -> IO (BcM_State, r)
+runBc us modBreaks (BcM m) 
+   = m (BcM_State us 0 [] breakArray)   
+   where
+   breakArray = modBreaks_flags modBreaks
 
 thenBc :: BcM a -> (a -> BcM b) -> BcM b
 thenBc (BcM expr) cont = BcM $ \st0 -> do
@@ -1338,7 +1490,7 @@ thenBc (BcM expr) cont = BcM $ \st0 -> do
 
 thenBc_ :: BcM a -> BcM b -> BcM b
 thenBc_ (BcM expr) (BcM cont) = BcM $ \st0 -> do
-  (st1, q) <- expr st0
+  (st1, _) <- expr st0
   (st2, r) <- cont st1
   return (st2, r)
 
@@ -1370,4 +1522,21 @@ getLabelsBc :: Int -> BcM [Int]
 getLabelsBc n
   = BcM $ \st -> let ctr = nextlabel st 
                 in return (st{nextlabel = ctr+n}, [ctr .. ctr+n-1])
+
+getBreakArray :: BcM BreakArray 
+getBreakArray = BcM $ \st -> return (st, breakArray st)
+
+newUnique :: BcM Unique
+newUnique = BcM $
+   \st -> case splitUniqSupply (uniqSupply st) of
+             (us1, us2) -> let newState = st { uniqSupply = us2 } 
+                           in  return (newState, uniqFromSupply us1) 
+
+newId :: Type -> BcM Id
+newId ty = do 
+    uniq <- newUnique
+    return $ mkSysLocal tickFS uniq ty
+
+tickFS :: FastString
+tickFS = fsLit "ticked"
 \end{code}