diff --git a/ghc/compiler/absCSyn/AbsCSyn.lhs b/ghc/compiler/absCSyn/AbsCSyn.lhs index dfaf400f06882af11f06f91d294c82b2519e2bf9..a8445bb4ac5e46fc8c3a595515cb588ba370a2fd 100644 --- a/ghc/compiler/absCSyn/AbsCSyn.lhs +++ b/ghc/compiler/absCSyn/AbsCSyn.lhs @@ -1,7 +1,7 @@ % % (c) The GRASP/AQUA Project, Glasgow University, 1992-1998 % -% $Id: AbsCSyn.lhs,v 1.21 1999/03/11 11:32:22 simonm Exp $ +% $Id: AbsCSyn.lhs,v 1.22 1999/04/26 16:06:27 simonm Exp $ % \section[AbstractC]{Abstract C: the last stop before machine code} @@ -52,6 +52,7 @@ import PrimRep ( PrimRep(..) ) import PrimOp ( PrimOp ) import Unique ( Unique ) import StgSyn ( SRT(..) ) +import TyCon ( TyCon ) import BitSet -- for liveness masks \end{code} @@ -196,6 +197,9 @@ stored in a mixed type location.) (CLabel,SRT) -- SRT info Liveness -- stack liveness at the return point + | CClosureTbl -- table of constructors for enumerated types + TyCon -- which TyCon this table is for + | CCostCentreDecl -- A cost centre *declaration* Bool -- True <=> local => full declaration -- False <=> extern; just say so diff --git a/ghc/compiler/absCSyn/AbsCUtils.lhs b/ghc/compiler/absCSyn/AbsCUtils.lhs index e90719c3c886f7fe508b2332ed47a1b0d3bf4da0..072be07db7e121cbc8f7a301a9a4ee32c3f3e0d4 100644 --- a/ghc/compiler/absCSyn/AbsCUtils.lhs +++ b/ghc/compiler/absCSyn/AbsCUtils.lhs @@ -362,6 +362,7 @@ flatAbsC stmt@(COpStmt results op args vol_regs)= returnFlt (stmt, AbsCNop) -- Some statements only make sense at the top level, so we always float -- them. This probably isn't necessary. flatAbsC stmt@(CStaticClosure _ _ _ _) = returnFlt (AbsCNop, stmt) +flatAbsC stmt@(CClosureTbl _) = returnFlt (AbsCNop, stmt) flatAbsC stmt@(CSRT _ _) = returnFlt (AbsCNop, stmt) flatAbsC stmt@(CBitmap _ _) = returnFlt (AbsCNop, stmt) flatAbsC stmt@(CCostCentreDecl _ _) = returnFlt (AbsCNop, stmt) diff --git a/ghc/compiler/absCSyn/PprAbsC.lhs b/ghc/compiler/absCSyn/PprAbsC.lhs index 67b22b551fb0293085c676c3b75acc274a709162..721a1215ed69eb38ae4aa476afc8cc12092995c2 100644 --- a/ghc/compiler/absCSyn/PprAbsC.lhs +++ b/ghc/compiler/absCSyn/PprAbsC.lhs @@ -29,7 +29,8 @@ import Constants ( mIN_UPD_SIZE ) import CallConv ( CallConv, callConvAttribute, cCallConv ) import CLabel ( externallyVisibleCLabel, mkErrorStdEntryLabel, isReadOnly, needsCDecl, pprCLabel, - mkReturnInfoLabel, mkReturnPtLabel, + mkReturnInfoLabel, mkReturnPtLabel, mkClosureTblLabel, + mkStaticClosureLabel, CLabel, CLabelType(..), labelType, labelDynamic ) @@ -40,6 +41,9 @@ import Costs ( costs, addrModeCosts, CostRes(..), Side(..) ) import CStrings ( stringToC ) import FiniteMap ( addToFM, emptyFM, lookupFM, FiniteMap ) import Const ( Literal(..) ) +import TyCon ( tyConDataCons ) +import Name ( NamedThing(..) ) +import DataCon ( DataCon{-instance NamedThing-} ) import Maybes ( maybeToBool, catMaybes ) import PrimOp ( primOpNeedsWrapper, pprPrimOp, PrimOp(..) ) import PrimRep ( isFloatingRep, PrimRep(..), getPrimRepSize, showPrimRep ) @@ -251,10 +255,6 @@ pprAbsC stmt@(CSRT lbl closures) c $$ nest 2 (hcat (punctuate comma (map pp_closure_lbl closures))) <> ptext SLIT("};") } - where - pp_closure_lbl lbl - | labelDynamic lbl = text "DLL_SRT_ENTRY" <> parens (pprCLabel lbl) - | otherwise = char '&' <> pprCLabel lbl pprAbsC stmt@(CBitmap lbl mask) c = vcat [ @@ -461,6 +461,15 @@ pprAbsC stmt@(CClosureInfoAndCode cl_info slow maybe_fast cl_descr) _ pp_descr = hcat [char '"', text (stringToC cl_descr), char '"'] pp_type = hcat [char '"', text (stringToC (closureTypeDescr cl_info)), char '"'] +pprAbsC stmt@(CClosureTbl tycon) _ + = vcat ( + ptext SLIT("CLOSURE_TBL") <> + lparen <> pprCLabel (mkClosureTblLabel tycon) <> rparen : + punctuate comma ( + map (pp_closure_lbl . mkStaticClosureLabel . getName) (tyConDataCons tycon) + ) + ) $$ ptext SLIT("};") + pprAbsC stmt@(CRetDirect uniq code srt liveness) _ = vcat [ hcat [ @@ -627,6 +636,12 @@ pp_srt_info srt = int len, comma ] \end{code} +\begin{code} +pp_closure_lbl lbl + | labelDynamic lbl = text "DLL_SRT_ENTRY" <> parens (pprCLabel lbl) + | otherwise = char '&' <> pprCLabel lbl +\end{code} + \begin{code} if_profiling pretty = if opt_SccProfilingOn diff --git a/ghc/compiler/basicTypes/Unique.lhs b/ghc/compiler/basicTypes/Unique.lhs index 396c20bdc2a87e5655f0ac454d8b57ad5467cc5e..81e137ded156fd7dc1d5802d998bd4e034bee051 100644 --- a/ghc/compiler/basicTypes/Unique.lhs +++ b/ghc/compiler/basicTypes/Unique.lhs @@ -95,6 +95,7 @@ module Unique ( funTyConKey, functorClassKey, geClassOpKey, + getTagIdKey, intDataConKey, intPrimTyConKey, intTyConKey, @@ -606,6 +607,7 @@ zipIdKey = mkPreludeMiscIdUnique 35 bindIOIdKey = mkPreludeMiscIdUnique 36 deRefStablePtrIdKey = mkPreludeMiscIdUnique 37 makeStablePtrIdKey = mkPreludeMiscIdUnique 38 +getTagIdKey = mkPreludeMiscIdUnique 39 \end{code} Certain class operations from Prelude classes. They get their own diff --git a/ghc/compiler/codeGen/CgConTbls.lhs b/ghc/compiler/codeGen/CgConTbls.lhs index 12c50649ffb4d6366daf854729d0522b310393f9..99d286ea7c22a46e76fa704661351f6fbd905524 100644 --- a/ghc/compiler/codeGen/CgConTbls.lhs +++ b/ghc/compiler/codeGen/CgConTbls.lhs @@ -12,7 +12,7 @@ import AbsCSyn import CgMonad import StgSyn ( SRT(..) ) -import AbsCUtils ( mkAbstractCs ) +import AbsCUtils ( mkAbstractCs, mkAbsCStmts ) import CgTailCall ( performReturn, mkStaticAlgReturnCode ) import CLabel ( mkConEntryLabel, mkStaticClosureLabel ) import ClosureInfo ( layOutStaticClosure, layOutDynCon, @@ -24,7 +24,7 @@ import DataCon ( DataCon, dataConName, dataConRawArgTys ) import Const ( Con(..) ) import Name ( getOccString ) import PrimRep ( getPrimRepSize, PrimRep(..) ) -import TyCon ( tyConDataCons, TyCon ) +import TyCon ( tyConDataCons, isEnumerationTyCon, TyCon ) import Type ( typePrimRep, Type ) import BasicTypes ( TopLevelFlag(..) ) import Outputable @@ -96,7 +96,13 @@ genStaticConBits comp_info gen_tycons tycon_specs where gen_for_tycon :: TyCon -> AbstractC gen_for_tycon tycon - = mkAbstractCs (map (genConInfo comp_info tycon) (tyConDataCons tycon)) + = mkAbstractCs (map (genConInfo comp_info tycon) (tyConDataCons tycon)) + `mkAbsCStmts` ( + -- after the con decls, so we don't need to declare the constructor labels + if (isEnumerationTyCon tycon) + then CClosureTbl tycon + else AbsCNop + ) \end{code} %************************************************************************ diff --git a/ghc/compiler/prelude/PrelInfo.lhs b/ghc/compiler/prelude/PrelInfo.lhs index de18e05b966176b97e9059d12cd64089fa42d7c3..33022296a4377c646d5ed28819bd7a67ce829d89 100644 --- a/ghc/compiler/prelude/PrelInfo.lhs +++ b/ghc/compiler/prelude/PrelInfo.lhs @@ -51,7 +51,7 @@ module PrelInfo ( ltH_Float_RDR, eqH_Double_RDR, ltH_Double_RDR, eqH_Int_RDR, ltH_Int_RDR, geH_RDR, leH_RDR, minusH_RDR, false_RDR, true_RDR, and_RDR, not_RDR, append_RDR, map_RDR, compose_RDR, mkInt_RDR, - error_RDR, assertErr_RDR, dataToTagH_RDR, + error_RDR, assertErr_RDR, getTag_RDR, showString_RDR, showParen_RDR, readParen_RDR, lex_RDR, showSpace_RDR, showList___RDR, readList___RDR, negate_RDR, @@ -221,9 +221,10 @@ wired_in_ids , rEC_CON_ERROR_ID , rEC_UPD_ERROR_ID - -- These two can't be defined in Haskell + -- These three can't be defined in Haskell , realWorldPrimId , unsafeCoerceId + , getTagId ] \end{code} @@ -566,7 +567,8 @@ ltH_Int_RDR = prelude_primop IntLtOp geH_RDR = prelude_primop IntGeOp leH_RDR = prelude_primop IntLeOp minusH_RDR = prelude_primop IntSubOp -dataToTagH_RDR = prelude_primop DataToTagOp + +getTag_RDR = varQual pREL_GHC SLIT("getTag#") \end{code} \begin{code} diff --git a/ghc/compiler/prelude/PrelVals.lhs b/ghc/compiler/prelude/PrelVals.lhs index f183292f10ca077a47213301d3e37554700a54a1..16f6d9d4731e830d5eb2e3b6285b22daa276e75f 100644 --- a/ghc/compiler/prelude/PrelVals.lhs +++ b/ghc/compiler/prelude/PrelVals.lhs @@ -20,6 +20,8 @@ import TysWiredIn -- others: import CoreSyn -- quite a bit import IdInfo -- quite a bit +import PrimOp ( PrimOp(..) ) +import Const ( Con(..) ) import Module ( Module ) import Name ( mkWiredInIdName, mkSrcVarOcc ) import Type @@ -61,6 +63,21 @@ unsafeCoerceId Note (Coerce betaTy alphaTy) (Var x) \end{code} +@getTag#@ is another function which can't be defined in Haskell. It needs to +evaluate its argument and call the dataToTag# primitive. + +\begin{code} +getTagId + = pcMiscPrelId getTagIdKey pREL_GHC SLIT("getTag#") ty + (mk_inline_unfolding template) + where + ty = mkForAllTys [alphaTyVar] (mkFunTy alphaTy intPrimTy) + [x,y] = mkTemplateLocals [alphaTy,alphaTy] + template = mkLams [alphaTyVar,x] $ + Case (Var x) y [ (DEFAULT, [], + Con (PrimOp DataToTagOp) [Type alphaTy, Var y]) ] +\end{code} + @realWorld#@ used to be a magic literal, \tr{void#}. If things get nasty as-is, change it back to a literal (@Literal@). diff --git a/ghc/compiler/simplCore/ConFold.lhs b/ghc/compiler/simplCore/ConFold.lhs index 1af5fbf652ea65b151bed39d96f7a6654a0555d3..1dfaf8242ac2763086fe97be3deb6bd45472fb96 100644 --- a/ghc/compiler/simplCore/ConFold.lhs +++ b/ghc/compiler/simplCore/ConFold.lhs @@ -20,6 +20,8 @@ import SimplMonad import TysWiredIn ( trueDataCon, falseDataCon ) import TyCon ( tyConDataCons, isEnumerationTyCon ) import DataCon ( dataConTag, fIRST_TAG ) +import Const ( conOkForAlt ) +import CoreUnfold ( Unfolding(..) ) import Type ( splitTyConApp_maybe ) import Char ( ord, chr ) @@ -104,14 +106,24 @@ tryPrimOp TagToEnumOp [Type ty, Con (Literal (MachInt i _)) _] constrs = tyConDataCons tycon (dc:_) = [ dc | dc <- constrs, tag == dataConTag dc ] (Just (tycon,_)) = splitTyConApp_maybe ty +\end{code} + +For dataToTag#, we can reduce if either + + (a) the argument is a constructor + (b) the argument is a variable whose unfolding is a known constructor +\begin{code} tryPrimOp DataToTagOp [Type ty, Con (DataCon dc) _] = Just (Con (Literal (mkMachInt (toInteger (dataConTag dc - fIRST_TAG)))) []) tryPrimOp DataToTagOp [Type ty, Var x] - | unfolding_is_constr + | has_unfolding && unfolding_is_constr = Just (Con (Literal (mkMachInt (toInteger (dataConTag dc - fIRST_TAG)))) []) where - unfolding = getIdUnfolding var + has_unfolding = case unfolding of + CoreUnfolding _ _ _ -> True + other -> False + unfolding = getIdUnfolding x CoreUnfolding form guidance unf_template = unfolding unfolding_is_constr = case unf_template of Con con@(DataCon _) _ -> conOkForAlt con diff --git a/ghc/compiler/simplCore/SimplCore.lhs b/ghc/compiler/simplCore/SimplCore.lhs index 62d67a836436b7b5083c283c71e0f1eda9f3cd06..a763a7c4a7473f5833e22a5ad5760e4feb9fb1c1 100644 --- a/ghc/compiler/simplCore/SimplCore.lhs +++ b/ghc/compiler/simplCore/SimplCore.lhs @@ -35,8 +35,9 @@ import Id ( Id, mkSysLocal, mkUserId, isBottomingId, ) import IdInfo ( InlinePragInfo(..), specInfo, setSpecInfo, inlinePragInfo, setInlinePragInfo, - setUnfoldingInfo + setUnfoldingInfo, setDemandInfo ) +import Demand ( wwLazy ) import VarEnv import VarSet import Module ( Module ) @@ -370,7 +371,7 @@ tidyIdInfo env info ICanSafelyBeINLINEd _ _ -> NoInlinePragInfo `setInlinePragInfo` info1 other -> info1 - info3 = noUnfolding `setUnfoldingInfo` info2 + info3 = noUnfolding `setUnfoldingInfo` (wwLazy `setDemandInfo` info2) tidy_item (tyvars, tys, rhs) = (tyvars', tidyTypes env' tys, tidyExpr env' rhs) diff --git a/ghc/compiler/stgSyn/CoreToStg.lhs b/ghc/compiler/stgSyn/CoreToStg.lhs index f97ea1b6aa36465a5a24dfba9e42149b7102f3a5..c5de5edc4dcd2acc13265c0342623e3b84567aa0 100644 --- a/ghc/compiler/stgSyn/CoreToStg.lhs +++ b/ghc/compiler/stgSyn/CoreToStg.lhs @@ -437,16 +437,6 @@ coreExprToStgFloat env expr@(Con (PrimOp (CCallOp (Right _) a b c)) args) let con' = PrimOp (CCallOp (Right u) a b c) in returnUs (binds, StgCon con' stg_atoms (coreExprType expr)) --- for dataToTag#, we need to make sure the argument is evaluated first. -coreExprToStgFloat env expr@(Con op@(PrimOp DataToTagOp) [Type ty, a]) - = newStgVar ty `thenUs` \ v -> - coreArgToStg env a `thenUs` \ (binds, arg) -> - let e = case arg of - StgVarArg v -> StgApp v [] - StgConArg c -> StgCon c [] (coreExprType a) - in - returnUs (binds ++ [CaseBind v e], StgCon op [StgVarArg v] (coreExprType expr)) - coreExprToStgFloat env expr@(Con con args) = coreArgsToStg env args `thenUs` \ (binds, stg_atoms) -> returnUs (binds, StgCon con stg_atoms (coreExprType expr)) diff --git a/ghc/compiler/typecheck/TcGenDeriv.lhs b/ghc/compiler/typecheck/TcGenDeriv.lhs index 884817e258dbf1343df61ec8a37667264a276ae2..77f3c4276b9ede60bae43080c0935a7ab288d095 100644 --- a/ghc/compiler/typecheck/TcGenDeriv.lhs +++ b/ghc/compiler/typecheck/TcGenDeriv.lhs @@ -1066,7 +1066,7 @@ gen_tag_n_con_monobind gen_tag_n_con_monobind (rdr_name, tycon, GenCon2Tag) | lots_of_constructors = mk_FunMonoBind (getSrcLoc tycon) rdr_name - [([VarPatIn a_RDR], HsApp dataToTag_Expr a_Expr)] + [([VarPatIn a_RDR], HsApp getTag_Expr a_Expr)] | otherwise = mk_FunMonoBind (getSrcLoc tycon) rdr_name (map mk_stuff (tyConDataCons tycon)) @@ -1361,7 +1361,7 @@ gtTag_Expr = HsVar gtTag_RDR false_Expr = HsVar false_RDR true_Expr = HsVar true_RDR -dataToTag_Expr = HsVar dataToTagH_RDR +getTag_Expr = HsVar getTag_RDR con2tag_Expr tycon = HsVar (con2tag_RDR tycon) a_Pat = VarPatIn a_RDR