From d4e0a55c3761544989209a2180d6d0489470db3d Mon Sep 17 00:00:00 2001 From: simonpj <unknown> Date: Wed, 5 Apr 2000 16:25:54 +0000 Subject: [PATCH] [project @ 2000-04-05 16:25:51 by simonpj] * Add new flag -fddump-minimal-imports, which dumps a file M.imports that contains the (allegedly) minimal bunch of imports that make the system work. It's done by Rename.printMinimalImports * Extend foreign import/export to handle * Booleans * newtypes as requested by the FFI team * Tidy up DsCCall quite a bit Remove maybeBoxedPrimTy from TcHsSyn --- ghc/compiler/absCSyn/PprAbsC.lhs | 13 +- ghc/compiler/basicTypes/MkId.lhs | 2 +- ghc/compiler/basicTypes/Name.lhs | 8 +- ghc/compiler/codeGen/CgRetConv.lhs | 5 +- ghc/compiler/coreSyn/CoreLint.lhs | 1 - ghc/compiler/coreSyn/CoreUnfold.lhs | 2 +- ghc/compiler/coreSyn/CoreUtils.lhs | 7 +- ghc/compiler/deSugar/DsCCall.lhs | 313 +++++++++++++------------- ghc/compiler/deSugar/DsExpr.lhs | 32 +-- ghc/compiler/deSugar/DsForeign.lhs | 57 +---- ghc/compiler/main/CmdLineOpts.lhs | 2 + ghc/compiler/prelude/TysWiredIn.lhs | 160 ++++++------- ghc/compiler/rename/Rename.lhs | 72 +++++- ghc/compiler/rename/RnEnv.lhs | 34 +-- ghc/compiler/rename/RnMonad.lhs | 10 +- ghc/compiler/rename/RnNames.lhs | 12 +- ghc/compiler/simplCore/SimplCore.lhs | 2 +- ghc/compiler/stranal/WwLib.lhs | 2 +- ghc/compiler/typecheck/TcExpr.lhs | 5 +- ghc/compiler/typecheck/TcHsSyn.lhs | 25 +- ghc/compiler/typecheck/TcInstDcls.lhs | 60 +---- ghc/compiler/types/Type.lhs | 2 +- 22 files changed, 366 insertions(+), 460 deletions(-) diff --git a/ghc/compiler/absCSyn/PprAbsC.lhs b/ghc/compiler/absCSyn/PprAbsC.lhs index 3bcf9425a464..7c869bfb3a3b 100644 --- a/ghc/compiler/absCSyn/PprAbsC.lhs +++ b/ghc/compiler/absCSyn/PprAbsC.lhs @@ -45,7 +45,8 @@ import TyCon ( tyConDataCons ) import Name ( NamedThing(..) ) import DataCon ( DataCon{-instance NamedThing-}, dataConWrapId ) import Maybes ( maybeToBool, catMaybes ) -import PrimOp ( primOpNeedsWrapper, pprPrimOp, PrimOp(..), CCall(..), CCallTarget(..) ) +import PrimOp ( primOpNeedsWrapper, pprPrimOp, pprCCallOp, + PrimOp(..), CCall(..), CCallTarget(..) ) import PrimRep ( isFloatingRep, PrimRep(..), getPrimRepSize, showPrimRep ) import SMRep ( pprSMRep ) import Unique ( pprUnique, Unique{-instance NamedThing-} ) @@ -777,7 +778,7 @@ Amendment to the above: if we can GC, we have to: that the runtime check that PerformGC is being used sensibly will work. \begin{code} -pprCCall (CCall op_str is_asm may_gc cconv) args results vol_regs +pprCCall call@(CCall op_str is_asm may_gc cconv) args results vol_regs = vcat [ char '{', declare_local_vars, -- local var for *result* @@ -797,10 +798,10 @@ pprCCall (CCall op_str is_asm may_gc cconv) args results vol_regs | otherwise = ( pp_basic_saves $$ pp_saves, pp_basic_restores $$ pp_restores) - non_void_args = - let nvas = tail args - in ASSERT (all non_void nvas) nvas - -- the first argument will be the "I/O world" token (a VoidRep) + non_void_args = let nvas = take (length args - 1) args + in ASSERT2 ( all non_void nvas, pprCCallOp call <+> hsep (map pprAmode args) ) + nvas + -- the last argument will be the "I/O world" token (a VoidRep) -- all others should be non-void non_void_results = diff --git a/ghc/compiler/basicTypes/MkId.lhs b/ghc/compiler/basicTypes/MkId.lhs index c06c67c2e49b..bcae7ede8b9f 100644 --- a/ghc/compiler/basicTypes/MkId.lhs +++ b/ghc/compiler/basicTypes/MkId.lhs @@ -43,7 +43,7 @@ import Rules ( addRule ) import Type ( Type, ClassContext, mkDictTy, mkTyConApp, mkTyVarTys, mkFunTys, mkFunTy, mkSigmaTy, classesToPreds, isUnLiftedType, mkForAllTys, mkTyVarTy, tyVarsOfType, tyVarsOfTypes, - splitSigmaTy, splitFunTy_maybe, splitAlgTyConApp, + splitSigmaTy, splitFunTy_maybe, splitFunTys, splitForAllTys, unUsgTy, mkUsgTy, UsageAnn(..) ) diff --git a/ghc/compiler/basicTypes/Name.lhs b/ghc/compiler/basicTypes/Name.lhs index b5e120a1ec86..c8a382bfac00 100644 --- a/ghc/compiler/basicTypes/Name.lhs +++ b/ghc/compiler/basicTypes/Name.lhs @@ -23,8 +23,9 @@ module Name ( tidyTopName, nameOccName, nameModule, setNameOcc, nameRdrName, setNameModule, - isUserExportedName, isUserImportedName, isUserImportedExplicitlyName, nameSrcLoc, - isLocallyDefinedName, isDynName, + isUserExportedName, isUserImportedName, isUserImportedExplicitlyName, + maybeUserImportedFrom, + nameSrcLoc, isLocallyDefinedName, isDynName, isSystemName, isLocalName, isGlobalName, isExternallyVisibleName, @@ -431,6 +432,9 @@ isUserImportedExplicitlyName other = False isUserImportedName (Name { n_prov = NonLocalDef (UserImport _ _ _) _ }) = True isUserImportedName other = False +maybeUserImportedFrom (Name { n_prov = NonLocalDef (UserImport m _ _) _ }) = Just m +maybeUserImportedFrom other = Nothing + isDynName :: Name -> Bool -- Does this name come from a DLL? isDynName nm = not (isLocallyDefinedName nm) && diff --git a/ghc/compiler/codeGen/CgRetConv.lhs b/ghc/compiler/codeGen/CgRetConv.lhs index a68a35287b37..f02b4d6590a9 100644 --- a/ghc/compiler/codeGen/CgRetConv.lhs +++ b/ghc/compiler/codeGen/CgRetConv.lhs @@ -1,7 +1,7 @@ % % (c) The GRASP Project, Glasgow University, 1992-1998 % -% $Id: CgRetConv.lhs,v 1.20 2000/03/23 17:45:19 simonpj Exp $ +% $Id: CgRetConv.lhs,v 1.21 2000/04/05 16:25:51 simonpj Exp $ % \section[CgRetConv]{Return conventions for the code generator} @@ -31,8 +31,7 @@ import DataCon ( DataCon ) import PrimOp ( PrimOp{-instance Outputable-} ) import PrimRep ( isFloatingRep, PrimRep(..), is64BitRep ) import TyCon ( TyCon, tyConDataCons, tyConFamilySize ) -import Type ( Type, typePrimRep, isUnLiftedType, - splitAlgTyConApp_maybe ) +import Type ( Type, typePrimRep, isUnLiftedType ) import Util ( isn'tIn ) import Outputable diff --git a/ghc/compiler/coreSyn/CoreLint.lhs b/ghc/compiler/coreSyn/CoreLint.lhs index 02d6e8747518..b1602d3c8c28 100644 --- a/ghc/compiler/coreSyn/CoreLint.lhs +++ b/ghc/compiler/coreSyn/CoreLint.lhs @@ -36,7 +36,6 @@ import Type ( Type, Kind, tyVarsOfType, splitFunTy_maybe, mkPiType, mkTyVarTy, unUsgTy, splitForAllTy_maybe, splitTyConApp_maybe, isUnLiftedType, typeKind, - splitAlgTyConApp_maybe, isUnboxedTupleType, hasMoreBoxityInfo ) diff --git a/ghc/compiler/coreSyn/CoreUnfold.lhs b/ghc/compiler/coreSyn/CoreUnfold.lhs index 35491cd4b78e..4089f3472d9d 100644 --- a/ghc/compiler/coreSyn/CoreUnfold.lhs +++ b/ghc/compiler/coreSyn/CoreUnfold.lhs @@ -56,7 +56,7 @@ import Literal ( isLitLitLit ) import PrimOp ( PrimOp(..), primOpIsDupable, primOpOutOfLine, ccallIsCasm ) import IdInfo ( ArityInfo(..), InlinePragInfo(..), OccInfo(..), IdFlavour(..), CprInfo(..), insideLam, workerExists ) import TyCon ( tyConFamilySize ) -import Type ( splitAlgTyConApp_maybe, splitFunTy_maybe, isUnLiftedType ) +import Type ( splitFunTy_maybe, isUnLiftedType ) import Unique ( Unique, buildIdKey, augmentIdKey ) import Maybes ( maybeToBool ) import Bag diff --git a/ghc/compiler/coreSyn/CoreUtils.lhs b/ghc/compiler/coreSyn/CoreUtils.lhs index 131bd4706170..583c32aa5c99 100644 --- a/ghc/compiler/coreSyn/CoreUtils.lhs +++ b/ghc/compiler/coreSyn/CoreUtils.lhs @@ -159,9 +159,7 @@ mkInlineMe e | exprIsTrivial e = e \begin{code} -mkCoerce :: Type -> Type -> Expr b -> Expr b --- In (mkCoerce to_ty from_ty e), we require that from_ty = exprType e --- But exprType is defined in CoreUtils, so we don't check the assertion +mkCoerce :: Type -> Type -> CoreExpr -> CoreExpr mkCoerce to_ty from_ty (Note (Coerce to_ty2 from_ty2) expr) = ASSERT( from_ty == to_ty2 ) @@ -169,7 +167,8 @@ mkCoerce to_ty from_ty (Note (Coerce to_ty2 from_ty2) expr) mkCoerce to_ty from_ty expr | to_ty == from_ty = expr - | otherwise = Note (Coerce to_ty from_ty) expr + | otherwise = ASSERT( from_ty == exprType expr ) + Note (Coerce to_ty from_ty) expr \end{code} \begin{code} diff --git a/ghc/compiler/deSugar/DsCCall.lhs b/ghc/compiler/deSugar/DsCCall.lhs index f5fa47ffd870..ecab4763f665 100644 --- a/ghc/compiler/deSugar/DsCCall.lhs +++ b/ghc/compiler/deSugar/DsCCall.lhs @@ -9,9 +9,7 @@ module DsCCall , mkCCall , unboxArg , boxResult - , wrapUnboxedValue - , can'tSeeDataConsPanic - + , resultWrapper ) where #include "HsVersions.h" @@ -21,31 +19,31 @@ import CoreSyn import DsMonad import DsUtils -import TcHsSyn ( maybeBoxedPrimType ) -import CoreUtils ( exprType ) +import CoreUtils ( exprType, mkCoerce ) import Id ( Id, mkWildId ) -import MkId ( mkCCallOpId ) +import MkId ( mkCCallOpId, realWorldPrimId ) import Maybes ( maybeToBool ) import PrelInfo ( packStringForCId ) import PrimOp ( PrimOp(..), CCall(..), CCallTarget(..) ) -import DataCon ( DataCon, splitProductType_maybe ) +import DataCon ( DataCon, splitProductType_maybe, dataConSourceArity, dataConWrapId ) import CallConv import Type ( isUnLiftedType, splitAlgTyConApp_maybe, mkFunTys, - splitTyConApp_maybe, tyVarsOfType, mkForAllTys, Type + splitTyConApp_maybe, tyVarsOfType, mkForAllTys, + isNewType, repType, isUnLiftedType, mkFunTy, + Type ) import TysPrim ( byteArrayPrimTy, realWorldStatePrimTy, - byteArrayPrimTyCon, mutableByteArrayPrimTyCon, - intPrimTy + byteArrayPrimTyCon, mutableByteArrayPrimTyCon, intPrimTy ) -import TysWiredIn ( unitDataConId, stringTy, boolTy, - falseDataCon, falseDataConId, - trueDataCon, trueDataConId, +import TysWiredIn ( unitDataConId, stringTy, unboxedPairDataCon, - mkUnboxedTupleTy, unboxedTupleCon + mkUnboxedTupleTy, unboxedTupleCon, + boolTy, trueDataCon, falseDataCon, trueDataConId, falseDataConId, + unitTy ) import Literal ( mkMachInt ) import CStrings ( CLabelString ) -import Unique ( Unique ) +import Unique ( Unique, Uniquable(..), ioTyConKey ) import VarSet ( varSetElems ) import Outputable \end{code} @@ -90,22 +88,18 @@ dsCCall :: CLabelString -- C routine to invoke -> [CoreExpr] -- Arguments (desugared) -> Bool -- True <=> might cause Haskell GC -> Bool -- True <=> really a "_casm_" - -> Type -- Type of the result (a boxed-prim IO type) + -> Type -- Type of the result: IO t -> DsM CoreExpr dsCCall lbl args may_gc is_asm result_ty - = newSysLocalDs realWorldStatePrimTy `thenDs` \ old_s -> - - mapAndUnzipDs unboxArg args `thenDs` \ (unboxed_args, arg_wrappers) -> - boxResult result_ty `thenDs` \ (final_result_ty, res_wrapper) -> + = mapAndUnzipDs unboxArg args `thenDs` \ (unboxed_args, arg_wrappers) -> + boxResult result_ty `thenDs` \ (ccall_result_ty, res_wrapper) -> getUniqueDs `thenDs` \ uniq -> let - val_args = Var old_s : unboxed_args the_ccall = CCall (StaticTarget lbl) is_asm may_gc cCallConv - the_prim_app = mkCCall uniq the_ccall val_args final_result_ty - the_body = foldr ($) (res_wrapper the_prim_app) arg_wrappers + the_prim_app = mkCCall uniq the_ccall unboxed_args ccall_result_ty in - returnDs (Lam old_s the_body) + returnDs (foldr ($) (res_wrapper the_prim_app) arg_wrappers) mkCCall :: Unique -> CCall -> [CoreExpr] -- Args @@ -135,32 +129,42 @@ unboxArg :: CoreExpr -- The supplied argument -> DsM (CoreExpr, -- To pass as the actual argument CoreExpr -> CoreExpr -- Wrapper to unbox the arg ) -unboxArg arg +-- Example: if the arg is e::Int, unboxArg will return +-- (x#::Int#, \W. case x of I# x# -> W) +-- where W is a CoreExpr that probably mentions x# - -- Primitive types - -- ADR Question: can this ever be used? None of the PrimTypes are - -- instances of the CCallable class. - -- - -- SOF response: - -- Oh yes they are, I've just added them :-) Having _ccall_ and _casm_ - -- that accept unboxed arguments is a Good Thing if you have a stub generator - -- which generates the boiler-plate box-unbox code for you, i.e., it may help - -- us nuke this very module :-) - -- +unboxArg arg + -- Unlifted types: nothing to unbox | isUnLiftedType arg_ty = returnDs (arg, \body -> body) - -- Strings - | arg_ty == stringTy - -- ToDo (ADR): - allow synonyms of Strings too? - = newSysLocalDs byteArrayPrimTy `thenDs` \ prim_arg -> + -- Newtypes + | isNewType arg_ty + = unboxArg (mkCoerce (repType arg_ty) arg_ty arg) + + -- Booleans + | arg_ty == boolTy + = newSysLocalDs intPrimTy `thenDs` \ prim_arg -> returnDs (Var prim_arg, - \body -> Case (App (Var packStringForCId) arg) - prim_arg [(DEFAULT,[],body)]) + \ body -> Case (Case arg (mkWildId arg_ty) + [(DataAlt falseDataCon,[],mkIntLit 0), + (DataAlt trueDataCon, [],mkIntLit 1)]) + prim_arg + [(DEFAULT,[],body)]) + + -- Data types with a single constructor, which has a single, primitive-typed arg + -- This deals with Int, Float etc + | is_product_type && data_con_arity == 1 + = ASSERT(isUnLiftedType data_con_arg_ty1 ) -- Typechecker ensures this + newSysLocalDs arg_ty `thenDs` \ case_bndr -> + newSysLocalDs data_con_arg_ty1 `thenDs` \ prim_arg -> + returnDs (Var prim_arg, + \ body -> Case arg case_bndr [(DataAlt data_con,[prim_arg],body)] + ) -- Byte-arrays, both mutable and otherwise; hack warning | is_product_type && - length data_con_arg_tys == 3 && + data_con_arity == 3 && maybeToBool maybe_arg3_tycon && (arg3_tycon == byteArrayPrimTyCon || arg3_tycon == mutableByteArrayPrimTyCon) @@ -171,141 +175,134 @@ unboxArg arg \ body -> Case arg case_bndr [(DataAlt data_con,vars,body)] ) - -- Data types with a single constructor, which has a single, primitive-typed arg - | maybeToBool maybe_boxed_prim_arg_ty - = newSysLocalDs arg_ty `thenDs` \ case_bndr -> - newSysLocalDs the_prim_arg_ty `thenDs` \ prim_arg -> - returnDs (Var prim_arg, - \ body -> Case arg case_bndr [(DataAlt box_data_con,[prim_arg],body)] - ) - - -- Booleans - | arg_ty == boolTy - = newSysLocalDs intPrimTy `thenDs` \ prim_arg -> - returnDs (Var prim_arg, - \ body -> Case (Case arg (mkWildId arg_ty) [ - (DataAlt falseDataCon,[],mkIntLit 0), - (DataAlt trueDataCon, [],mkIntLit 1)]) - prim_arg [(DEFAULT,[],body)] - ) - | otherwise = getSrcLocDs `thenDs` \ l -> pprPanic "unboxArg: " (ppr l <+> ppr arg_ty) where - arg_ty = exprType arg - - maybe_boxed_prim_arg_ty = maybeBoxedPrimType arg_ty - (Just (box_data_con, the_prim_arg_ty)) = maybe_boxed_prim_arg_ty + arg_ty = exprType arg + arg_rep_ty = repType arg_ty maybe_product_type = splitProductType_maybe arg_ty is_product_type = maybeToBool maybe_product_type Just (tycon, _, data_con, data_con_arg_tys) = maybe_product_type - (data_con_arg_ty1 : data_con_arg_ty2 : data_con_arg_ty3 :_) - = data_con_arg_tys - - maybe_arg3_tycon = splitTyConApp_maybe data_con_arg_ty3 - Just (arg3_tycon,_) = maybe_arg3_tycon + data_con_arity = dataConSourceArity data_con + (data_con_arg_ty1 : _) = data_con_arg_tys -can'tSeeDataConsPanic thing ty - = pprPanic - "ERROR: Can't see the data constructor(s) for _ccall_/_casm_/foreign declaration" - (hcat [ text thing, text "; type: ", ppr ty - , text "(try compiling with -fno-prune-tydecls ..)\n"]) + (_ : _ : data_con_arg_ty3 : _) = data_con_arg_tys + maybe_arg3_tycon = splitTyConApp_maybe data_con_arg_ty3 + Just (arg3_tycon,_) = maybe_arg3_tycon \end{code} \begin{code} -boxResult :: Type -- Type of desired result - -> DsM (Type, -- Type of the result of the ccall itself - CoreExpr -> CoreExpr) -- Wrapper for the ccall - -- to box the result -boxResult result_ty - -- Data types with a single nullary constructor - | (maybeToBool maybe_product_type) && -- Data type - (null data_con_arg_tys) - = - newSysLocalDs realWorldStatePrimTy `thenDs` \ prim_state_id -> -{- - wrapUnboxedValue result_ty `thenDs` \ (state_and_prim_datacon, - state_and_prim_ty, prim_result_id, the_result) -> - mkConDs ioOkDataCon - [TyArg result_ty, VarArg (Var prim_state_id), VarArg the_result] - `thenDs` \ the_pair -> --} - let - the_pair = mkConApp unboxedPairDataCon - [Type realWorldStatePrimTy, Type result_ty, - Var prim_state_id, - Var unitDataConId] - the_alt = (DataAlt (unboxedTupleCon 1), [prim_state_id], the_pair) - scrut_ty = mkUnboxedTupleTy 1 [realWorldStatePrimTy] - in - returnDs (scrut_ty, \prim_app -> Case prim_app (mkWildId scrut_ty) [the_alt] - ) +boxResult :: Type -> DsM (Type, CoreExpr -> CoreExpr) + +-- Takes the result of the user-level ccall: +-- either (IO t), +-- or maybe just t for an side-effect-free call +-- Returns a wrapper for the primitive ccall itself, along with the +-- type of the result of the primitive ccall. This result type +-- will be of the form +-- State# RealWorld -> (# State# RealWorld, t' #) +-- where t' is the unwrapped form of t. If t is simply (), then +-- the result type will be +-- State# RealWorld -> (# State# RealWorld #) - -- Data types with a single constructor, which has a single, primitive-typed arg - | (maybeToBool maybe_product_type) && -- Data type - not (null data_con_arg_tys) && null other_args_tys && -- Just one arg - isUnLiftedType the_prim_result_ty -- of primitive type - = - newSysLocalDs realWorldStatePrimTy `thenDs` \ prim_state_id -> - newSysLocalDs the_prim_result_ty `thenDs` \ prim_result_id -> - newSysLocalDs ccall_res_type `thenDs` \ case_bndr -> - - let - the_result = mkConApp data_con (map Type tycon_arg_tys ++ [Var prim_result_id]) - the_pair = mkConApp unboxedPairDataCon - [Type realWorldStatePrimTy, Type result_ty, - Var prim_state_id, the_result] - the_alt = (DataAlt unboxedPairDataCon, [prim_state_id, prim_result_id], the_pair) - in - returnDs (ccall_res_type, \prim_app -> Case prim_app case_bndr [the_alt] - ) +boxResult result_ty + = case splitAlgTyConApp_maybe result_ty of + + -- The result is IO t, so wrap the result in an IO constructor + Just (io_tycon, [io_res_ty], [io_data_con]) | getUnique io_tycon == ioTyConKey + -> mk_alt return_result + (resultWrapper io_res_ty) `thenDs` \ (ccall_res_ty, the_alt) -> + newSysLocalDs realWorldStatePrimTy `thenDs` \ state_id -> + let + wrap = \ the_call -> mkApps (Var (dataConWrapId io_data_con)) + [Type io_res_ty, Lam state_id $ + Case (App the_call (Var state_id)) + (mkWildId ccall_res_ty) + [the_alt]] + in + returnDs (realWorldStatePrimTy `mkFunTy` ccall_res_ty, wrap) + where + return_result state ans = mkConApp unboxedPairDataCon + [Type realWorldStatePrimTy, Type io_res_ty, + state, ans] + + -- It isn't, so do unsafePerformIO + -- It's not conveniently available, so we inline it + other -> mk_alt return_result + (resultWrapper result_ty) `thenDs` \ (ccall_res_ty, the_alt) -> + let + wrap = \ the_call -> Case (App the_call (Var realWorldPrimId)) + (mkWildId ccall_res_ty) + [the_alt] + in + returnDs (realWorldStatePrimTy `mkFunTy` ccall_res_ty, wrap) + where + return_result state ans = ans + where + mk_alt return_result (Nothing, wrap_result) + = -- The ccall returns () + newSysLocalDs realWorldStatePrimTy `thenDs` \ state_id -> + let + the_rhs = return_result (Var state_id) (wrap_result (panic "boxResult")) + ccall_res_ty = mkUnboxedTupleTy 1 [realWorldStatePrimTy] + the_alt = (DataAlt (unboxedTupleCon 1), [state_id], the_rhs) + in + returnDs (ccall_res_ty, the_alt) + + mk_alt return_result (Just prim_res_ty, wrap_result) + = -- The ccall returns a non-() value + newSysLocalDs realWorldStatePrimTy `thenDs` \ state_id -> + newSysLocalDs prim_res_ty `thenDs` \ result_id -> + let + the_rhs = return_result (Var state_id) (wrap_result (Var result_id)) + ccall_res_ty = mkUnboxedTupleTy 2 [realWorldStatePrimTy, prim_res_ty] + the_alt = (DataAlt unboxedPairDataCon, [state_id, result_id], the_rhs) + in + returnDs (ccall_res_ty, the_alt) + + +resultWrapper :: Type + -> (Maybe Type, -- Type of the expected result, if any + CoreExpr -> CoreExpr) -- Wrapper for the result +resultWrapper result_ty + -- Base case 1: primitive types + | isUnLiftedType result_ty + = (Just result_ty, \e -> e) + + -- Base case 1: the unit type () + | result_ty == unitTy + = (Nothing, \e -> Var unitDataConId) - -- Booleans | result_ty == boolTy - = returnDs (mkUnboxedTupleTy 2 [realWorldStatePrimTy, intPrimTy], - \ prim_app -> Case prim_app (mkWildId intPrimTy) [ - (LitAlt (mkMachInt 0),[],Var falseDataConId), - (DEFAULT ,[],Var trueDataConId )]) + = (Just intPrimTy, \e -> Case e (mkWildId intPrimTy) + [(LitAlt (mkMachInt 0),[],Var falseDataConId), + (DEFAULT ,[],Var trueDataConId )]) + + -- Data types with a single constructor, which has a single arg + | is_product_type && data_con_arity == 1 + = let + (maybe_ty, wrapper) = resultWrapper unwrapped_res_ty + (unwrapped_res_ty : _) = data_con_arg_tys + in + (maybe_ty, \e -> mkApps (Var (dataConWrapId data_con)) + (map Type tycon_arg_tys ++ [wrapper e])) + + -- newtypes + | isNewType result_ty + = let + rep_ty = repType result_ty + (maybe_ty, wrapper) = resultWrapper rep_ty + in + (maybe_ty, \e -> mkCoerce result_ty rep_ty (wrapper e)) | otherwise - = pprPanic "boxResult: " (ppr result_ty) + = pprPanic "resultWrapper" (ppr result_ty) where maybe_product_type = splitProductType_maybe result_ty + is_product_type = maybeToBool maybe_product_type Just (tycon, tycon_arg_tys, data_con, data_con_arg_tys) = maybe_product_type - (the_prim_result_ty : other_args_tys) = data_con_arg_tys - - ccall_res_type = mkUnboxedTupleTy 2 [realWorldStatePrimTy, the_prim_result_ty] - --- wrap up an unboxed value. -wrapUnboxedValue :: Type -> DsM (Type, Id, CoreExpr) -wrapUnboxedValue ty - | (maybeToBool maybe_product_type) && -- Data type - not (null data_con_arg_tys) && null other_args_tys && -- Just one arg - isUnLiftedType the_prim_result_ty -- of primitive type - = - newSysLocalDs the_prim_result_ty `thenDs` \ prim_result_id -> - let - the_result = mkConApp data_con (map Type tycon_arg_tys ++ [Var prim_result_id]) - in - returnDs (ccall_res_type, prim_result_id, the_result) - - -- Data types with a single nullary constructor - | (maybeToBool maybe_product_type) && -- Data type - (null data_con_arg_tys) - = - let - scrut_ty = mkUnboxedTupleTy 1 [realWorldStatePrimTy] - in - returnDs (scrut_ty, unitDataConId, Var unitDataConId) - - | otherwise - = pprPanic "boxResult: " (ppr ty) - where - maybe_product_type = splitProductType_maybe ty - Just (tycon, tycon_arg_tys, data_con, data_con_arg_tys) = maybe_product_type - (the_prim_result_ty : other_args_tys) = data_con_arg_tys - ccall_res_type = mkUnboxedTupleTy 2 [realWorldStatePrimTy, the_prim_result_ty] + data_con_arity = dataConSourceArity data_con \end{code} diff --git a/ghc/compiler/deSugar/DsExpr.lhs b/ghc/compiler/deSugar/DsExpr.lhs index c812165ed032..8ab7d4dde204 100644 --- a/ghc/compiler/deSugar/DsExpr.lhs +++ b/ghc/compiler/deSugar/DsExpr.lhs @@ -15,9 +15,7 @@ import HsSyn ( failureFreePat, mkSimpleMatch ) import TcHsSyn ( TypecheckedHsExpr, TypecheckedHsBinds, - TypecheckedStmt, - maybeBoxedPrimType - + TypecheckedStmt ) import CoreSyn import CoreUtils ( exprType, mkIfThenElse, bindNonRec ) @@ -25,7 +23,7 @@ import CoreUtils ( exprType, mkIfThenElse, bindNonRec ) import DsMonad import DsBinds ( dsMonoBinds, AutoScc(..) ) import DsGRHSs ( dsGuarded ) -import DsCCall ( dsCCall ) +import DsCCall ( dsCCall, resultWrapper ) import DsListComp ( dsListComp ) import DsUtils ( mkErrorAppDs, mkDsLets, mkConsExpr, mkNilExpr ) import Match ( matchWrapper, matchSimply ) @@ -164,29 +162,11 @@ dsExpr (HsLitOut (HsString str) _) = returnDs (mkStringLitFS str) dsExpr (HsLitOut (HsLitLit str) ty) - | isUnLiftedType ty - = returnDs (mkLit (MachLitLit str ty)) - | otherwise - = case (maybeBoxedPrimType ty) of - Just (boxing_data_con, prim_ty) -> - returnDs ( mkConApp boxing_data_con [mkLit (MachLitLit str prim_ty)] ) - _ -> - pprError "ERROR:" - (vcat - [ hcat [ text "Cannot see data constructor of ``literal-literal''s type: " - , text "value:", quotes (quotes (ptext str)) - , text "; type: ", ppr ty - ] - , text "Try compiling with -fno-prune-tydecls." - ]) - + = ASSERT( maybeToBool maybe_ty ) + returnDs (wrap_fn (mkLit (MachLitLit str rep_ty))) where - (data_con, prim_ty) - = case (maybeBoxedPrimType ty) of - Just (boxing_data_con, prim_ty) -> (boxing_data_con, prim_ty) - Nothing - -> pprPanic "ERROR: ``literal-literal'' not a single-constructor type: " - (hcat [ptext str, text "; type: ", ppr ty]) + (maybe_ty, wrap_fn) = resultWrapper ty + Just rep_ty = maybe_ty dsExpr (HsLitOut (HsInt i) ty) = returnDs (mkIntegerLit i) diff --git a/ghc/compiler/deSugar/DsForeign.lhs b/ghc/compiler/deSugar/DsForeign.lhs index 8e4d0b71119a..c1fb6fe5a790 100644 --- a/ghc/compiler/deSugar/DsForeign.lhs +++ b/ghc/compiler/deSugar/DsForeign.lhs @@ -12,7 +12,7 @@ module DsForeign ( dsForeigns ) where import CoreSyn -import DsCCall ( dsCCall, mkCCall, boxResult, unboxArg, wrapUnboxedValue ) +import DsCCall ( dsCCall, mkCCall, boxResult, unboxArg ) import DsMonad import DsUtils @@ -23,15 +23,15 @@ import TcHsSyn ( TypecheckedForeignDecl ) import CoreUtils ( exprType, mkInlineMe, bindNonRec ) import DataCon ( DataCon, dataConWrapId ) import Id ( Id, idType, idName, mkWildId, mkVanillaId ) -import MkId ( mkCCallOpId, mkWorkerId ) +import MkId ( mkWorkerId ) import Literal ( Literal(..) ) import Module ( Module, moduleUserString ) import Name ( mkGlobalName, nameModule, nameOccName, getOccString, mkForeignExportOcc, isLocalName, NamedThing(..), Provenance(..), ExportFlag(..) ) -import PrelInfo ( deRefStablePtr_NAME, bindIO_NAME, makeStablePtr_NAME, realWorldPrimId ) -import Type ( splitAlgTyConApp_maybe, unUsgTy, +import PrelInfo ( deRefStablePtr_NAME, bindIO_NAME, makeStablePtr_NAME ) +import Type ( unUsgTy, splitTyConApp_maybe, splitFunTys, splitForAllTys, Type, mkFunTys, mkForAllTys, mkTyConApp, mkTyVarTy, mkFunTy, splitAppTy @@ -45,10 +45,6 @@ import TysWiredIn ( unitTyCon, addrTy, stablePtrTyCon, import Unique import Maybes ( maybeToBool ) import Outputable - -#if __GLASGOW_HASKELL__ >= 404 -import GlaExts ( fromInt ) -#endif \end{code} Desugaring of @foreign@ declarations is naturally split up into @@ -133,21 +129,12 @@ dsFImport :: Id -> DsM [CoreBind] dsFImport fn_id ty may_not_gc ext_name cconv = let - (tvs, arg_tys, mbIoDataCon, io_res_ty) = splitForeignTyDs ty - is_io_action = maybeToBool mbIoDataCon + (tvs, fun_ty) = splitForAllTys ty + (arg_tys, io_res_ty) = splitFunTys fun_ty in newSysLocalsDs arg_tys `thenDs` \ args -> - newSysLocalDs realWorldStatePrimTy `thenDs` \ old_s -> - mapAndUnzipDs unboxArg (map Var args) `thenDs` \ (unboxed_args, arg_wrappers) -> - - (if not is_io_action then - newSysLocalDs realWorldStatePrimTy `thenDs` \ state_tok -> - wrapUnboxedValue io_res_ty `thenDs` \ (ccall_result_ty, v, res_v) -> - returnDs ( ccall_result_ty - , \ prim_app -> Case prim_app (mkWildId ccall_result_ty) - [(DataAlt (unboxedTupleCon 2), [state_tok, v], res_v)]) - else - boxResult io_res_ty) `thenDs` \ (ccall_result_ty, res_wrapper) -> + mapAndUnzipDs unboxArg (map Var args) `thenDs` \ (val_args, arg_wrappers) -> + boxResult io_res_ty `thenDs` \ (ccall_result_ty, res_wrapper) -> (case ext_name of Dynamic -> getUniqueDs `thenDs` \ u -> @@ -157,11 +144,7 @@ dsFImport fn_id ty may_not_gc ext_name cconv getUniqueDs `thenDs` \ ccall_uniq -> getUniqueDs `thenDs` \ work_uniq -> let - the_state_arg | is_io_action = old_s - | otherwise = realWorldPrimId - -- Build the worker - val_args = Var the_state_arg : unboxed_args work_arg_ids = [v | Var v <- val_args] -- All guaranteed to be vars worker_ty = mkForAllTys tvs (mkFunTys (map idType work_arg_ids) ccall_result_ty) the_ccall = CCall lbl False (not may_not_gc) cconv @@ -172,32 +155,12 @@ dsFImport fn_id ty may_not_gc ext_name cconv -- Build the wrapper work_app = mkApps (mkVarApps (Var work_id) tvs) val_args wrapper_body = foldr ($) (res_wrapper work_app) arg_wrappers - io_app = case mbIoDataCon of - Nothing -> wrapper_body - Just ioDataCon -> mkApps (Var (dataConWrapId ioDataCon)) - [Type io_res_ty, Lam old_s wrapper_body] - wrap_rhs = mkInlineMe (mkLams (tvs ++ args) io_app) + wrap_rhs = mkInlineMe (mkLams (tvs ++ args) wrapper_body) in returnDs [NonRec fn_id wrap_rhs, NonRec work_id work_rhs] \end{code} -Given the type of a foreign import declaration, split it up into -its constituent parts. - -\begin{code} -splitForeignTyDs :: Type -> ([TyVar], [Type], Maybe DataCon, Type) -splitForeignTyDs ty - = case splitAlgTyConApp_maybe res_ty of - Just (_,(io_res_ty:_),(ioCon:_)) -> -- .... -> IO t - (tvs, arg_tys, Just ioCon, io_res_ty) - _ -> -- .... -> t - (tvs, arg_tys, Nothing, res_ty) - where - (arg_tys, res_ty) = splitFunTys sans_foralls - (tvs, sans_foralls) = splitForAllTys ty -\end{code} - -foreign labels +Foreign labels \begin{code} dsFLabel :: Id -> ExtName -> DsM CoreBind diff --git a/ghc/compiler/main/CmdLineOpts.lhs b/ghc/compiler/main/CmdLineOpts.lhs index 77cc791290bf..3d2bf138ed6e 100644 --- a/ghc/compiler/main/CmdLineOpts.lhs +++ b/ghc/compiler/main/CmdLineOpts.lhs @@ -44,6 +44,7 @@ module CmdLineOpts ( opt_D_dump_rn_trace, opt_D_dump_rn_stats, opt_D_dump_stix, + opt_D_dump_minimal_imports, opt_D_source_stats, opt_D_verbose_core2core, opt_D_verbose_stg2stg, @@ -334,6 +335,7 @@ opt_D_dump_simpl_stats = opt_D_dump_most || lookUp SLIT("-ddump-simpl-stats") opt_D_source_stats = opt_D_dump_most || lookUp SLIT("-dsource-stats") opt_D_verbose_core2core = opt_D_dump_all || lookUp SLIT("-dverbose-simpl") opt_D_verbose_stg2stg = opt_D_dump_all || lookUp SLIT("-dverbose-stg") +opt_D_dump_minimal_imports = lookUp SLIT("-ddump-minimal-imports") opt_DoCoreLinting = lookUp SLIT("-dcore-lint") opt_DoStgLinting = lookUp SLIT("-dstg-lint") diff --git a/ghc/compiler/prelude/TysWiredIn.lhs b/ghc/compiler/prelude/TysWiredIn.lhs index 565f66ea3d27..7a76a1acc108 100644 --- a/ghc/compiler/prelude/TysWiredIn.lhs +++ b/ghc/compiler/prelude/TysWiredIn.lhs @@ -86,12 +86,14 @@ import Module ( Module, mkPrelModule ) import Name ( mkWiredInTyConName, mkWiredInIdName, mkSrcOccFS, mkWorkerOcc, dataName ) import DataCon ( DataCon, StrictnessMark(..), mkDataCon, dataConId ) import Var ( TyVar, tyVarKind ) -import TyCon ( TyCon, AlgTyConFlavour(..), ArgVrcs, mkAlgTyCon, mkSynTyCon, mkTupleTyCon ) +import TyCon ( TyCon, AlgTyConFlavour(..), ArgVrcs, tyConDataCons, + mkAlgTyCon, mkSynTyCon, mkTupleTyCon, isUnLiftedTyCon + ) import BasicTypes ( Arity, NewOrData(..), RecFlag(..) ) import Type ( Type, mkTyConTy, mkTyConApp, mkSigmaTy, mkTyVarTys, mkArrowKinds, boxedTypeKind, unboxedTypeKind, - mkFunTy, mkFunTys, isUnLiftedType, - splitTyConApp_maybe, splitAlgTyConApp_maybe, + mkFunTy, mkFunTys, + splitTyConApp_maybe, repType, TauType, ClassContext ) import PrimRep ( PrimRep(..) ) import Unique @@ -198,10 +200,10 @@ mk_tuple arity = (tycon, tuple_con) dc_uniq = mkTupleDataConUnique arity mod = mkPrelModule mod_name -unitTyCon = tupleTyCon 0 -pairTyCon = tupleTyCon 2 +unitTyCon = tupleTyCon 0 +unitDataConId = dataConId (head (tyConDataCons unitTyCon)) -unitDataConId = dataConId (tupleCon 0) +pairTyCon = tupleTyCon 2 \end{code} %************************************************************************ @@ -285,10 +287,7 @@ intTyCon = pcNonRecDataTyCon intTyConKey pREL_BASE SLIT("Int") [] [] [intDataCon intDataCon = pcDataCon intDataConKey pREL_BASE SLIT("I#") [] [] [intPrimTy] intTyCon isIntTy :: Type -> Bool -isIntTy ty - = case (splitAlgTyConApp_maybe ty) of - Just (tycon, [], _) -> getUnique tycon == intTyConKey - _ -> False +isIntTy = isTyCon intTyConKey \end{code} \begin{code} @@ -306,11 +305,7 @@ addrTyCon = pcNonRecDataTyCon addrTyConKey pREL_ADDR SLIT("Addr") [] [] [addrD addrDataCon = pcDataCon addrDataConKey pREL_ADDR SLIT("A#") [] [] [addrPrimTy] addrTyCon isAddrTy :: Type -> Bool -isAddrTy ty - = case (splitAlgTyConApp_maybe ty) of - Just (tycon, [], _) -> getUnique tycon == addrTyConKey - _ -> False - +isAddrTy = isTyCon addrTyConKey \end{code} \begin{code} @@ -320,21 +315,14 @@ floatTyCon = pcNonRecDataTyCon floatTyConKey pREL_FLOAT SLIT("Float") [] [] [flo floatDataCon = pcDataCon floatDataConKey pREL_FLOAT SLIT("F#") [] [] [floatPrimTy] floatTyCon isFloatTy :: Type -> Bool -isFloatTy ty - = case (splitAlgTyConApp_maybe ty) of - Just (tycon, [], _) -> getUnique tycon == floatTyConKey - _ -> False - +isFloatTy = isTyCon floatTyConKey \end{code} \begin{code} doubleTy = mkTyConTy doubleTyCon isDoubleTy :: Type -> Bool -isDoubleTy ty - = case (splitAlgTyConApp_maybe ty) of - Just (tycon, [], _) -> getUnique tycon == doubleTyConKey - _ -> False +isDoubleTy = isTyCon doubleTyConKey doubleTyCon = pcNonRecDataTyCon doubleTyConKey pREL_FLOAT SLIT("Double") [] [] [doubleDataCon] doubleDataCon = pcDataCon doubleDataConKey pREL_FLOAT SLIT("D#") [] [] [doublePrimTy] doubleTyCon @@ -358,6 +346,9 @@ foreignObjTyCon foreignObjDataCon = pcDataCon foreignObjDataConKey pREL_IO_BASE SLIT("ForeignObj") [] [] [foreignObjPrimTy] foreignObjTyCon + +isForeignObjTy :: Type -> Bool +isForeignObjTy = isTyCon foreignObjTyConKey \end{code} %************************************************************************ @@ -381,10 +372,7 @@ largeIntegerDataCon = pcDataCon largeIntegerDataConKey pREL_NUM SLIT("J#") isIntegerTy :: Type -> Bool -isIntegerTy ty - = case (splitAlgTyConApp_maybe ty) of - Just (tycon, [], _) -> getUnique tycon == integerTyConKey - _ -> False +isIntegerTy = isTyCon integerTyConKey \end{code} @@ -400,75 +388,67 @@ being the ) \begin{code} isFFIArgumentTy :: Bool -> Type -> Bool -isFFIArgumentTy forASafeCall ty = - (opt_GlasgowExts && isUnLiftedType ty) || - case (splitAlgTyConApp_maybe ty) of - Just (tycon, _, _) -> - let - u = getUnique tycon - in - u `elem` primArgTyConKeys && -- it has a suitable prim type, and - (not forASafeCall || not ( u `elem` notSafeExternalTyCons)) -- it is safe to pass out. - _ -> False - --- types that can be passed as arguments to "foreign" functions -primArgTyConKeys - = [ intTyConKey, int8TyConKey, int16TyConKey, int32TyConKey, int64TyConKey - , wordTyConKey, word8TyConKey, word16TyConKey, word32TyConKey, word64TyConKey - , floatTyConKey, doubleTyConKey - , addrTyConKey, charTyConKey, foreignObjTyConKey - , stablePtrTyConKey - , byteArrayTyConKey, mutableByteArrayTyConKey - ] - --- types that can be passed from the outside world into Haskell. --- excludes (mutable) byteArrays. -isFFIExternalTy :: Type -> Bool -isFFIExternalTy ty = - (opt_GlasgowExts && isUnLiftedType ty) || --leave out for now: maybeToBool (maybeBoxedPrimType ty))) || - case (splitAlgTyConApp_maybe ty) of - Just (tycon, _, _) -> - let - u_tycon = getUnique tycon - in - (u_tycon `elem` primArgTyConKeys) && - not (u_tycon `elem` notLegalExternalTyCons) - _ -> False +-- Checks for valid argument type for a 'foreign import' +isFFIArgumentTy is_safe ty = checkTyCon (legalOutgoingTyCon is_safe) ty +isFFIExternalTy :: Type -> Bool +-- Types that are allowed as arguments of a 'foreign export' +isFFIExternalTy ty = checkTyCon legalIncomingTyCon ty isFFIResultTy :: Type -> Bool -isFFIResultTy ty = - not (isUnLiftedType ty) && - case (splitAlgTyConApp_maybe ty) of - Just (tycon, _, _) -> - let - u_tycon = getUnique tycon - in - (u_tycon == getUnique unitTyCon) || - ((u_tycon `elem` primArgTyConKeys) && - not (u_tycon `elem` notLegalExternalTyCons)) - _ -> False - --- it's illegal to return foreign objects and (mutable) --- bytearrays from a _ccall_ / foreign declaration --- (or be passed them as arguments in foreign exported functions). -notLegalExternalTyCons = - [ foreignObjTyConKey, byteArrayTyConKey, mutableByteArrayTyConKey ] - --- it's really unsafe to pass out references to objects in the heap, --- so for safe call-outs we simply disallow it. -notSafeExternalTyCons = - [ byteArrayTyConKey, mutableByteArrayTyConKey ] +-- Types that are allowed as a result of a 'foreign import' or of a 'foreign export' +-- Maybe we should distinguish between import and export, but +-- here we just choose the more restrictive 'incoming' predicate +-- But we allow () as well +isFFIResultTy ty = checkTyCon (\tc -> tc == unitTyCon || legalIncomingTyCon tc) ty + +checkTyCon :: (TyCon -> Bool) -> Type -> Bool +checkTyCon check_tc ty = case splitTyConApp_maybe (repType ty) of + Just (tycon, _) -> check_tc tycon + Nothing -> False + +isTyCon :: Unique -> Type -> Bool +isTyCon uniq ty = checkTyCon (\tc -> uniq == getUnique tc) ty +\end{code} +---------------------------------------------- +These chaps do the work; they are not exported +---------------------------------------------- -isForeignObjTy :: Type -> Bool -isForeignObjTy ty = - case (splitAlgTyConApp_maybe ty) of - Just (tycon, _, _) -> (getUnique tycon) == foreignObjTyConKey - _ -> False - +\begin{code} +legalIncomingTyCon :: TyCon -> Bool +-- It's illegal to return foreign objects and (mutable) +-- bytearrays from a _ccall_ / foreign declaration +-- (or be passed them as arguments in foreign exported functions). +legalIncomingTyCon tc + | getUnique tc `elem` [ foreignObjTyConKey, byteArrayTyConKey, mutableByteArrayTyConKey ] + = False + | otherwise + = marshalableTyCon tc + +legalOutgoingTyCon :: Bool -> TyCon -> Bool +-- Checks validity of types going from Haskell -> external world +-- The boolean is true for a 'safe' call (when we don't want to +-- pass Haskell pointers to the world) +legalOutgoingTyCon be_safe tc + | be_safe && getUnique tc `elem` [byteArrayTyConKey, mutableByteArrayTyConKey] + = False + | otherwise + = marshalableTyCon tc + +marshalableTyCon tc + = (opt_GlasgowExts && isUnLiftedTyCon tc) + || getUnique tc `elem` [ intTyConKey, int8TyConKey, int16TyConKey, int32TyConKey, int64TyConKey + , wordTyConKey, word8TyConKey, word16TyConKey, word32TyConKey, word64TyConKey + , floatTyConKey, doubleTyConKey + , addrTyConKey, charTyConKey, foreignObjTyConKey + , stablePtrTyConKey + , byteArrayTyConKey, mutableByteArrayTyConKey + , boolTyConKey + ] \end{code} + %************************************************************************ %* * \subsection[TysWiredIn-Bool]{The @Bool@ type} diff --git a/ghc/compiler/rename/Rename.lhs b/ghc/compiler/rename/Rename.lhs index 359f28413362..5a563a0703dc 100644 --- a/ghc/compiler/rename/Rename.lhs +++ b/ghc/compiler/rename/Rename.lhs @@ -14,22 +14,24 @@ import RnHsSyn ( RenamedHsModule, RenamedHsDecl, extractHsTyNames, extractHsCtxtTyNames ) -import CmdLineOpts ( opt_HiMap, opt_D_dump_rn_trace, +import CmdLineOpts ( opt_HiMap, opt_D_dump_rn_trace, opt_D_dump_minimal_imports, opt_D_dump_rn, opt_D_dump_rn_stats, opt_WarnDeprecations ) import RnMonad import RnNames ( getGlobalNames ) import RnSource ( rnSourceDecls, rnDecl ) -import RnIfaces ( getImportedInstDecls, importDecl, getImportVersions, +import RnIfaces ( getImportedInstDecls, importDecl, getImportVersions, getInterfaceExports, getImportedRules, loadHomeInterface, getSlurped, removeContext ) -import RnEnv ( availName, availsToNameSet, - warnUnusedImports, warnUnusedLocalBinds, lookupImplicitOccRn, +import RnEnv ( availName, availsToNameSet, unitAvailEnv, availEnvElts, plusAvailEnv, + warnUnusedImports, warnUnusedLocalBinds, lookupImplicitOccRn, pprAvail, FreeVars, plusFVs, plusFV, unitFV, emptyFVs, isEmptyFVs ) -import Module ( Module, ModuleName, mkSearchPath, mkThisModule ) +import Module ( Module, ModuleName, WhereFrom(..), + moduleNameUserString, mkSearchPath, moduleName, mkThisModule + ) import Name ( Name, isLocallyDefined, NamedThing(..), getSrcLoc, - nameOccName, nameUnique, + nameOccName, nameUnique, nameModule, maybeUserImportedFrom, isUserImportedExplicitlyName, isUserImportedName, maybeWiredInTyConName, maybeWiredInIdName, isWiredInName ) @@ -37,18 +39,19 @@ import OccName ( occNameFlavour, isValOcc ) import Id ( idType ) import TyCon ( isSynTyCon, getSynTyConDefn ) import NameSet -import PrelMods ( mAIN_Name, pREL_MAIN_Name ) +import PrelMods ( mAIN_Name, pREL_MAIN_Name, pRELUDE_Name ) import TysWiredIn ( unitTyCon, intTyCon, doubleTyCon, boolTyCon ) import PrelInfo ( ioTyCon_NAME, thinAirIdNames, fractionalClassKeys, derivingOccurrences ) import Type ( namesOfType, funTyCon ) import ErrUtils ( printErrorsAndWarnings, dumpIfSet, ghcExit ) import BasicTypes ( NewOrData(..) ) import Bag ( isEmptyBag, bagToList ) -import FiniteMap ( eltsFM ) +import FiniteMap ( FiniteMap, eltsFM, fmToList, emptyFM, addToFM_C ) import UniqSupply ( UniqSupply ) import UniqFM ( lookupUFM ) import Maybes ( maybeToBool ) import Outputable +import IO ( openFile, IOMode(..) ) \end{code} @@ -144,7 +147,7 @@ rename this_mod@(HsModule mod_name vers _ imports local_decls mod_deprec loc) getNameSupplyRn `thenRn` \ name_supply -> -- REPORT UNUSED NAMES - reportUnusedNames gbl_env global_avail_env + reportUnusedNames mod_name gbl_env global_avail_env export_env source_fvs `thenRn_` @@ -525,8 +528,8 @@ getInstDeclGates other = emptyFVs %********************************************************* \begin{code} -reportUnusedNames :: GlobalRdrEnv -> NameEnv AvailInfo -> ExportEnv -> NameSet -> RnM d () -reportUnusedNames gbl_env avail_env (ExportEnv export_avails _ _) mentioned_names +reportUnusedNames :: ModuleName -> GlobalRdrEnv -> AvailEnv -> ExportEnv -> NameSet -> RnMG () +reportUnusedNames mod_name gbl_env avail_env (ExportEnv export_avails _ _) mentioned_names = let used_names = mentioned_names `unionNameSets` availsToNameSet export_avails @@ -569,14 +572,61 @@ reportUnusedNames gbl_env avail_env (ExportEnv export_avails _ _) mentioned_name | n <- nameSetToList mentioned_names, not (isLocallyDefined n), Just txt <- [lookupNameEnv deprec_env n] ] + + minimal_imports :: FiniteMap Module AvailEnv + minimal_imports = foldNameSet add emptyFM really_used_names + add n acc = case maybeUserImportedFrom n of + Nothing -> acc + Just m -> addToFM_C plusAvailEnv acc m + (unitAvailEnv (mk_avail n)) + mk_avail n = case lookupNameEnv avail_env n of + Just (AvailTC m _) | n==m -> AvailTC n [n] + | otherwise -> AvailTC m [n,m] + Just avail -> Avail n + Nothing -> pprPanic "mk_avail" (ppr n) in warnUnusedLocalBinds bad_locals `thenRn_` warnUnusedImports bad_imps `thenRn_` + printMinimalImports mod_name minimal_imports `thenRn_` getIfacesRn `thenRn` \ ifaces -> (if opt_WarnDeprecations then mapRn_ warnDeprec (deprec_used (iDeprecs ifaces)) else returnRn ()) +-- ToDo: deal with original imports with 'qualified' and 'as M' clauses +printMinimalImports mod_name imps + | not opt_D_dump_minimal_imports + = returnRn () + | otherwise + = mapRn to_ies (fmToList imps) `thenRn` \ mod_ies -> + ioToRnM (do { h <- openFile filename WriteMode ; + printForUser h (vcat (map ppr_mod_ie mod_ies)) + }) `thenRn_` + returnRn () + where + filename = moduleNameUserString mod_name ++ ".imports" + ppr_mod_ie (mod_name, ies) + | mod_name == pRELUDE_Name + = empty + | otherwise + = ptext SLIT("import") <+> ppr mod_name <> + parens (fsep (punctuate comma (map ppr ies))) + + to_ies (mod, avail_env) = mapRn to_ie (availEnvElts avail_env) `thenRn` \ ies -> + returnRn (moduleName mod, ies) + + to_ie :: AvailInfo -> RnMG (IE Name) + to_ie (Avail n) = returnRn (IEVar n) + to_ie (AvailTC n [m]) = ASSERT( n==m ) + returnRn (IEThingAbs n) + to_ie (AvailTC n ns) = getInterfaceExports (moduleName (nameModule n)) + ImportBySystem `thenRn` \ (_, avails) -> + case [ms | AvailTC m ms <- avails, m == n] of + [ms] | all (`elem` ns) ms -> returnRn (IEThingAll n) + | otherwise -> returnRn (IEThingWith n (filter (/= n) ns)) + other -> pprTrace "to_ie" (ppr n <+> ppr (nameModule n) <+> ppr other) $ + returnRn (IEVar n) + warnDeprec :: (Name, DeprecTxt) -> RnM d () warnDeprec (name, txt) = pushSrcLocRn (getSrcLoc name) $ diff --git a/ghc/compiler/rename/RnEnv.lhs b/ghc/compiler/rename/RnEnv.lhs index adc5a063db95..4bd6122757e4 100644 --- a/ghc/compiler/rename/RnEnv.lhs +++ b/ghc/compiler/rename/RnEnv.lhs @@ -590,7 +590,7 @@ mkExportAvails mod_name unqual_imp name_env avails plusExportAvails :: ExportAvails -> ExportAvails -> ExportAvails plusExportAvails (m1, e1) (m2, e2) - = (plusFM_C (++) m1 m2, plusUFM_C plusAvail e1 e2) + = (plusFM_C (++) m1 m2, plusAvailEnv e1 e2) -- ToDo: wasteful: we do this once for each constructor! \end{code} @@ -599,12 +599,24 @@ plusExportAvails (m1, e1) (m2, e2) \begin{code} plusAvail (Avail n1) (Avail n2) = Avail n1 -plusAvail (AvailTC n1 ns1) (AvailTC n2 ns2) = AvailTC n1 (nub (ns1 ++ ns2)) +plusAvail (AvailTC n1 ns1) (AvailTC n2 ns2) = AvailTC n2 (nub (ns1 ++ ns2)) -- Added SOF 4/97 #ifdef DEBUG plusAvail a1 a2 = pprPanic "RnEnv.plusAvail" (hsep [pprAvail a1,pprAvail a2]) #endif +addAvail :: AvailEnv -> AvailInfo -> AvailEnv +addAvail avails avail = addToNameEnv_C plusAvail avails (availName avail) avail + +emptyAvailEnv = emptyNameEnv +unitAvailEnv :: AvailInfo -> AvailEnv +unitAvailEnv a = unitNameEnv (availName a) a + +plusAvailEnv :: AvailEnv -> AvailEnv -> AvailEnv +plusAvailEnv = plusNameEnv_C plusAvail + +availEnvElts = nameEnvElts + addAvailToNameSet :: NameSet -> AvailInfo -> NameSet addAvailToNameSet names avail = addListToNameSet names (availNames avail) @@ -658,20 +670,12 @@ filterAvail (IEThingAll _) avail@(AvailTC _ _) = Just avail filterAvail ie avail = Nothing +pprAvail :: AvailInfo -> SDoc +pprAvail (AvailTC n ns) = ppr n <> case filter (/= n) ns of + [] -> empty + ns' -> parens (hsep (punctuate comma (map ppr ns'))) --- In interfaces, pprAvail gets given the OccName of the "host" thing -pprAvail avail = getPprStyle $ \ sty -> - if ifaceStyle sty then - ppr_avail (pprOccName . nameOccName) avail - else - ppr_avail ppr avail - -ppr_avail pp_name (AvailTC n ns) = hsep [ - pp_name n, - parens $ hsep $ punctuate comma $ - map pp_name ns - ] -ppr_avail pp_name (Avail n) = pp_name n +pprAvail (Avail n) = ppr n \end{code} diff --git a/ghc/compiler/rename/RnMonad.lhs b/ghc/compiler/rename/RnMonad.lhs index ac646e945f93..95a248edadf1 100644 --- a/ghc/compiler/rename/RnMonad.lhs +++ b/ghc/compiler/rename/RnMonad.lhs @@ -173,20 +173,24 @@ nameEnvElts :: NameEnv a -> [a] addToNameEnv_C :: (a->a->a) -> NameEnv a -> Name -> a -> NameEnv a addToNameEnv :: NameEnv a -> Name -> a -> NameEnv a plusNameEnv :: NameEnv a -> NameEnv a -> NameEnv a +plusNameEnv_C :: (a->a->a) -> NameEnv a -> NameEnv a -> NameEnv a extendNameEnv :: NameEnv a -> [(Name,a)] -> NameEnv a lookupNameEnv :: NameEnv a -> Name -> Maybe a delFromNameEnv :: NameEnv a -> Name -> NameEnv a elemNameEnv :: Name -> NameEnv a -> Bool +unitNameEnv :: Name -> a -> NameEnv a emptyNameEnv = emptyUFM nameEnvElts = eltsUFM addToNameEnv_C = addToUFM_C addToNameEnv = addToUFM plusNameEnv = plusUFM +plusNameEnv_C = plusUFM_C extendNameEnv = addListToUFM lookupNameEnv = lookupUFM delFromNameEnv = delFromUFM elemNameEnv = elemUFM +unitNameEnv = unitUFM -------------------------------- type FixityEnv = NameEnv RenamedFixitySig @@ -236,9 +240,8 @@ type ExportAvails = (FiniteMap ModuleName Avails, -- Includes avails only from *unqualified* imports -- (see 1.4 Report Section 5.1.1) - NameEnv AvailInfo) -- Used to figure out all other export specifiers. - -- Maps a Name to the AvailInfo that contains it - + AvailEnv) -- Used to figure out all other export specifiers. + data GenAvailInfo name = Avail name -- An ordinary identifier | AvailTC name -- The name of the type or class @@ -247,6 +250,7 @@ data GenAvailInfo name = Avail name -- An ordinary identifier -- to be in scope, it must be in this list. -- Thus, typically: AvailTC Eq [Eq, ==, /=] +type AvailEnv = NameEnv AvailInfo -- Maps a Name to the AvailInfo that contains it type AvailInfo = GenAvailInfo Name type RdrAvailInfo = GenAvailInfo OccName \end{code} diff --git a/ghc/compiler/rename/RnNames.lhs b/ghc/compiler/rename/RnNames.lhs index 4ef7c0a5db7a..788440b22545 100644 --- a/ghc/compiler/rename/RnNames.lhs +++ b/ghc/compiler/rename/RnNames.lhs @@ -64,7 +64,7 @@ getGlobalNames :: RdrNameHsModule -> RnMG (Maybe (ExportEnv, GlobalRdrEnv, FixityEnv, -- Fixities for local decls only - NameEnv AvailInfo -- Maps a name to its parent AvailInfo + AvailEnv -- Maps a name to its parent AvailInfo -- Just for in-scope things only )) -- Nothing => no need to recompile @@ -547,7 +547,7 @@ type ExportAccum -- The type of the accumulating parameter of -- the main worker function in exportsFromAvail = ([ModuleName], -- 'module M's seen so far ExportOccMap, -- Tracks exported occurrence names - NameEnv AvailInfo) -- The accumulated exported stuff, kept in an env + AvailEnv) -- The accumulated exported stuff, kept in an env -- so we can common-up related AvailInfos type ExportOccMap = FiniteMap OccName (Name, RdrNameIE) @@ -578,7 +578,7 @@ exportsFromAvail this_mod (Just export_items) (mod_avail_env, entity_avail_env) global_name_env = foldlRn exports_from_item - ([], emptyFM, emptyNameEnv) export_items `thenRn` \ (_, _, export_avail_map) -> + ([], emptyFM, emptyAvailEnv) export_items `thenRn` \ (_, _, export_avail_map) -> let export_avails :: [AvailInfo] export_avails = nameEnvElts export_avail_map @@ -600,7 +600,7 @@ exportsFromAvail this_mod (Just export_items) Just mod_avails -> foldlRn (check_occs ie) occs mod_avails `thenRn` \ occs' -> let - avails' = foldl add_avail avails mod_avails + avails' = foldl addAvail avails mod_avails in returnRn (mod:mods, occs', avails') @@ -628,7 +628,7 @@ exportsFromAvail this_mod (Just export_items) = warnCheckRn (ok_item ie avail) (dodgyExportWarn ie) `thenRn_` check_occs ie occs export_avail `thenRn` \ occs' -> - returnRn (mods, occs', add_avail avails export_avail) + returnRn (mods, occs', addAvail avails export_avail) where rdr_name = ieName ie @@ -646,8 +646,6 @@ exportsFromAvail this_mod (Just export_items) -- in the AvailTC is the type or class itself ok_item _ _ = True -add_avail avails avail = addToNameEnv_C plusAvail avails (availName avail) avail - check_occs :: RdrNameIE -> ExportOccMap -> AvailInfo -> RnMG ExportOccMap check_occs ie occs avail = foldlRn check occs (availNames avail) diff --git a/ghc/compiler/simplCore/SimplCore.lhs b/ghc/compiler/simplCore/SimplCore.lhs index 5e11d8180b1a..f3a5d145b8c1 100644 --- a/ghc/compiler/simplCore/SimplCore.lhs +++ b/ghc/compiler/simplCore/SimplCore.lhs @@ -45,7 +45,7 @@ import Name ( mkLocalName, tidyOccName, tidyTopName, import TyCon ( TyCon, isDataTyCon ) import PrelInfo ( unpackCStringId, unpackCString2Id, addr2IntegerId ) import PrelRules ( builtinRules ) -import Type ( Type, splitAlgTyConApp_maybe, +import Type ( Type, isUnLiftedType, tidyType, tidyTypes, tidyTopType, tidyTyVar, tidyTyVars, Type diff --git a/ghc/compiler/stranal/WwLib.lhs b/ghc/compiler/stranal/WwLib.lhs index 1215078bfd4b..5fcb8d7db9be 100644 --- a/ghc/compiler/stranal/WwLib.lhs +++ b/ghc/compiler/stranal/WwLib.lhs @@ -25,7 +25,7 @@ import TysPrim ( realWorldStatePrimTy ) import TysWiredIn ( unboxedTupleCon, unboxedTupleTyCon ) import Type ( isUnLiftedType, splitForAllTys, splitFunTys, isAlgType, - splitAlgTyConApp_maybe, splitNewType_maybe, + splitNewType_maybe, mkTyConApp, mkFunTys, Type ) diff --git a/ghc/compiler/typecheck/TcExpr.lhs b/ghc/compiler/typecheck/TcExpr.lhs index 77161009275f..806396117119 100644 --- a/ghc/compiler/typecheck/TcExpr.lhs +++ b/ghc/compiler/typecheck/TcExpr.lhs @@ -14,7 +14,7 @@ import HsSyn ( HsExpr(..), HsLit(..), ArithSeqInfo(..), ) import RnHsSyn ( RenamedHsExpr, RenamedRecordBinds ) import TcHsSyn ( TcExpr, TcRecordBinds, mkHsConApp, - mkHsTyApp, mkHsLet, maybeBoxedPrimType + mkHsTyApp, mkHsLet ) import TcMonad @@ -390,8 +390,7 @@ tcMonoExpr (HsCCall lbl args may_gc is_asm ignored_fake_result_ty) res_ty -- constraints on the argument and result types. mapNF_Tc new_arg_dict (zipEqual "tcMonoExpr:CCall" args arg_tys) `thenNF_Tc` \ ccarg_dicts_s -> newClassDicts result_origin [(cReturnableClass, [result_ty])] `thenNF_Tc` \ (ccres_dict, _) -> - returnTc (mkHsConApp ioDataCon [result_ty] [HsCCall lbl args' may_gc is_asm result_ty], - -- do the wrapping in the newtype constructor here + returnTc (HsCCall lbl args' may_gc is_asm io_result_ty, foldr plusLIE ccres_dict ccarg_dicts_s `plusLIE` args_lie) \end{code} diff --git a/ghc/compiler/typecheck/TcHsSyn.lhs b/ghc/compiler/typecheck/TcHsSyn.lhs index 37b7036f137f..e99c01daf55f 100644 --- a/ghc/compiler/typecheck/TcHsSyn.lhs +++ b/ghc/compiler/typecheck/TcHsSyn.lhs @@ -29,8 +29,6 @@ module TcHsSyn ( -- re-exported from TcEnv TcId, tcInstId, - maybeBoxedPrimType, - zonkTopBinds, zonkId, zonkIdOcc, zonkForeignExports, zonkRules ) where @@ -51,7 +49,7 @@ import TcMonad import TcType ( TcType, TcTyVar, zonkTcTypeToType, zonkTcTyVarToTyVar, zonkTcTyVarBndr, zonkTcType ) -import Type ( mkTyVarTy, splitAlgTyConApp_maybe, isUnLiftedType, Type ) +import Type ( mkTyVarTy, isUnLiftedType, Type ) import Name ( isLocallyDefined ) import Var ( TyVar ) import VarEnv ( TyVarEnv, emptyVarEnv, extendVarEnvList ) @@ -140,27 +138,6 @@ idsToMonoBinds ids %* * %************************************************************************ -Some gruesome hackery for desugaring ccalls. It's here because if we put it -in Type.lhs we get irritating loops, and it's only used by TcInstDcls.lhs and -DsCCall.lhs. - -\begin{code} -maybeBoxedPrimType :: Type -> Maybe (DataCon, Type) -maybeBoxedPrimType ty - = case splitProductType_maybe ty of -- Product data type - Just (tycon, tys_applied, data_con, [data_con_arg_ty]) -- constr has one arg - | isUnLiftedType data_con_arg_ty -- which is primitive - -> Just (data_con, data_con_arg_ty) - - other_cases -> Nothing -\end{code} - -%************************************************************************ -%* * -\subsection[BackSubst-HsBinds]{Running a substitution over @HsBinds@} -%* * -%************************************************************************ - This zonking pass runs over the bindings a) to convert TcTyVars to TyVars etc, dereferencing any bindings etc diff --git a/ghc/compiler/typecheck/TcInstDcls.lhs b/ghc/compiler/typecheck/TcInstDcls.lhs index 0d9ffac08169..b50818d02674 100644 --- a/ghc/compiler/typecheck/TcInstDcls.lhs +++ b/ghc/compiler/typecheck/TcInstDcls.lhs @@ -14,9 +14,7 @@ import HsSyn ( HsDecl(..), InstDecl(..), andMonoBindList ) import RnHsSyn ( RenamedHsBinds, RenamedInstDecl, RenamedHsDecl ) -import TcHsSyn ( TcMonoBinds, mkHsConApp, - maybeBoxedPrimType - ) +import TcHsSyn ( TcMonoBinds, mkHsConApp ) import TcBinds ( tcSpecSigs ) import TcClassDcl ( tcMethodBind, checkFromThisClass ) @@ -60,7 +58,7 @@ import Type ( Type, isUnLiftedType, mkTyVarTys, import Subst ( mkTopTyVarSubst, substClasses ) import VarSet ( mkVarSet, varSetElems ) import TysPrim ( byteArrayPrimTyCon, mutableByteArrayPrimTyCon ) -import TysWiredIn ( stringTy ) +import TysWiredIn ( stringTy, isFFIArgumentTy, isFFIResultTy ) import Unique ( Unique, cCallableClassKey, cReturnableClassKey, Uniquable(..) ) import Outputable \end{code} @@ -491,18 +489,7 @@ scrutiniseInstanceConstraint (clas, tys) | otherwise = addErrTc (instConstraintErr clas tys) scrutiniseInstanceHead clas inst_taus - | -- CCALL CHECK (a).... urgh! - -- To verify that a user declaration of a CCallable/CReturnable - -- instance is OK, we must be able to see the constructor(s) - -- of the instance type (see next guard.) - -- - -- We flag this separately to give a more precise error msg. - -- - (getUnique clas == cCallableClassKey || getUnique clas == cReturnableClassKey) - && is_alg_tycon_app && not constructors_visible - = addErrTc (invisibleDataConPrimCCallErr clas first_inst_tau) - - | -- CCALL CHECK (b) + | -- CCALL CHECK -- A user declaration of a CCallable/CReturnable instance -- must be for a "boxed primitive" type. (getUnique clas == cCallableClassKey && not (ccallable_type first_inst_tau)) || @@ -558,32 +545,8 @@ scrutiniseInstanceHead clas inst_taus constructors_visible = not (null data_cons) - --- These conditions come directly from what the DsCCall is capable of. --- Totally grotesque. Green card should solve this. - -ccallable_type ty = isUnLiftedType ty || -- Allow CCallable Int# etc - maybeToBool (maybeBoxedPrimType ty) || -- Ditto Int etc - ty == stringTy || - byte_arr_thing - where - byte_arr_thing = case splitProductType_maybe ty of - Just (tycon, ty_args, data_con, [data_con_arg_ty1, data_con_arg_ty2, data_con_arg_ty3]) -> - maybeToBool maybe_arg3_tycon && - (arg3_tycon == byteArrayPrimTyCon || - arg3_tycon == mutableByteArrayPrimTyCon) - where - maybe_arg3_tycon = splitTyConApp_maybe data_con_arg_ty3 - Just (arg3_tycon,_) = maybe_arg3_tycon - - other -> False - -creturnable_type ty = maybeToBool (maybeBoxedPrimType ty) || - -- Or, a data type with a single nullary constructor - case (splitAlgTyConApp_maybe ty) of - Just (tycon, tys_applied, [data_con]) - -> isNullaryDataCon data_con - other -> False +ccallable_type ty = isFFIArgumentTy False {- Not safe call -} ty +creturnable_type ty = isFFIResultTy ty \end{code} \begin{code} @@ -609,19 +572,6 @@ nonBoxedPrimCCallErr clas inst_ty 4 (hsep [ ptext SLIT("class"), ppr clas, ptext SLIT("type"), ppr inst_ty]) -{- - Declaring CCallable & CReturnable instances in a module different - from where the type was defined. Caused by importing data type - abstractly (either programmatically or by the renamer being over-eager - in its pruning.) --} -invisibleDataConPrimCCallErr clas inst_ty - = hang (hsep [ptext SLIT("Constructors for"), quotes (ppr inst_ty), - ptext SLIT("not visible when checking"), - quotes (ppr clas), ptext SLIT("instance")]) - 4 (hsep [text "(Try either importing", ppr inst_ty, - text "non-abstractly or compile using -fno-prune-tydecls ..)"]) - methodCtxt = ptext SLIT("When checking the methods of an instance declaration") superClassCtxt = ptext SLIT("When checking the superclasses of an instance declaration") \end{code} diff --git a/ghc/compiler/types/Type.lhs b/ghc/compiler/types/Type.lhs index 4fdb337d2c09..1aaf17a8e885 100644 --- a/ghc/compiler/types/Type.lhs +++ b/ghc/compiler/types/Type.lhs @@ -316,7 +316,7 @@ splitTyConApp_maybe other = Nothing splitAlgTyConApp_maybe :: Type -> Maybe (TyCon, [Type], [DataCon]) splitAlgTyConApp_maybe (TyConApp tc tys) - | isAlgTyCon tc && + | isAlgTyCon tc && tyConArity tc == length tys = Just (tc, tys, tyConDataCons tc) splitAlgTyConApp_maybe (NoteTy _ ty) = splitAlgTyConApp_maybe ty splitAlgTyConApp_maybe other = Nothing -- GitLab