packages feed

ghc-lib 0.20190402 → 0.20190423

raw patch · 57 files changed

+1130/−1349 lines, 57 filesdep ~ghc-lib-parserPVP ok

version bump matches the API change (PVP)

Dependency ranges changed: ghc-lib-parser

API changes (from Hackage documentation)

- AsmCodeGen: [ncg_x86fp_kludge] :: NcgImpl statics instr jumpDest -> [NatCmmDecl statics instr] -> [NatCmmDecl statics instr]
- Format: FF80 :: Format
- GhcPlugins: type Alignment = Int
- NCGMonad: [ncg_x86fp_kludge] :: NcgImpl statics instr jumpDest -> [NatCmmDecl statics instr] -> [NatCmmDecl statics instr]
- Reg: VirtualRegSSE :: {-# UNPACK #-} !Unique -> VirtualReg
- RegClass: RcDoubleSSE :: RegClass
- X86.Instr: GABS :: Format -> Reg -> Reg -> Instr
- X86.Instr: GADD :: Format -> Reg -> Reg -> Reg -> Instr
- X86.Instr: GCMP :: Cond -> Reg -> Reg -> Instr
- X86.Instr: GCOS :: Format -> CLabel -> CLabel -> Reg -> Reg -> Instr
- X86.Instr: GDIV :: Format -> Reg -> Reg -> Reg -> Instr
- X86.Instr: GDTOF :: Reg -> Reg -> Instr
- X86.Instr: GDTOI :: Reg -> Reg -> Instr
- X86.Instr: GFREE :: Instr
- X86.Instr: GFTOI :: Reg -> Reg -> Instr
- X86.Instr: GITOD :: Reg -> Reg -> Instr
- X86.Instr: GITOF :: Reg -> Reg -> Instr
- X86.Instr: GLD :: Format -> AddrMode -> Reg -> Instr
- X86.Instr: GLD1 :: Reg -> Instr
- X86.Instr: GLDZ :: Reg -> Instr
- X86.Instr: GMOV :: Reg -> Reg -> Instr
- X86.Instr: GMUL :: Format -> Reg -> Reg -> Reg -> Instr
- X86.Instr: GNEG :: Format -> Reg -> Reg -> Instr
- X86.Instr: GSIN :: Format -> CLabel -> CLabel -> Reg -> Reg -> Instr
- X86.Instr: GSQRT :: Format -> Reg -> Reg -> Instr
- X86.Instr: GST :: Format -> Reg -> AddrMode -> Instr
- X86.Instr: GSUB :: Format -> Reg -> Reg -> Reg -> Instr
- X86.Instr: GTAN :: Format -> CLabel -> CLabel -> Reg -> Reg -> Instr
- X86.Instr: i386_insert_ffrees :: [GenBasicBlock Instr] -> [GenBasicBlock Instr]
- X86.Regs: fake0 :: Reg
- X86.Regs: fake1 :: Reg
- X86.Regs: fake2 :: Reg
- X86.Regs: fake3 :: Reg
- X86.Regs: fake4 :: Reg
- X86.Regs: fake5 :: Reg
- X86.Regs: firstfake :: RegNo
+ CLabel: mayRedirectTo :: CLabel -> CLabel -> Bool
+ Check: instance Outputable.Outputable Check.PmResult
+ Check: instance Outputable.Outputable Check.UncoveredCandidates
+ CmmExpr: cmmExprAlignment :: CmmExpr -> Alignment
+ GhcPlugins: alignmentOf :: Int -> Alignment
+ GhcPlugins: data Alignment
+ GhcPlugins: mkAlignment :: Int -> Alignment
+ LlvmCodeGen.Base: llvmDefLabel :: LMString -> LMString
+ THNames: liftTypedIdKey :: Unique
+ THNames: liftTypedName :: Name
+ THNames: liftTyped_RDR :: RdrName
+ X86.Instr: X87Store :: Format -> AddrMode -> Instr
- AsmCodeGen: NcgImpl :: (RawCmmDecl -> NatM [NatCmmDecl statics instr]) -> (instr -> Maybe (NatCmmDecl statics instr)) -> (jumpDest -> Maybe BlockId) -> (instr -> Maybe jumpDest) -> ((BlockId -> Maybe jumpDest) -> statics -> statics) -> ((BlockId -> Maybe jumpDest) -> instr -> instr) -> (NatCmmDecl statics instr -> SDoc) -> Int -> [RealReg] -> ([NatCmmDecl statics instr] -> [NatCmmDecl statics instr]) -> ([NatCmmDecl statics instr] -> [NatCmmDecl statics instr]) -> (Int -> NatCmmDecl statics instr -> UniqSM (NatCmmDecl statics instr, [(BlockId, BlockId)])) -> (LabelMap CmmStatics -> [NatBasicBlock instr] -> [NatBasicBlock instr]) -> ([instr] -> [UnwindPoint]) -> (CFG -> LabelMap CmmStatics -> [NatBasicBlock instr] -> [NatBasicBlock instr]) -> NcgImpl statics instr jumpDest
+ AsmCodeGen: NcgImpl :: (RawCmmDecl -> NatM [NatCmmDecl statics instr]) -> (instr -> Maybe (NatCmmDecl statics instr)) -> (jumpDest -> Maybe BlockId) -> (instr -> Maybe jumpDest) -> ((BlockId -> Maybe jumpDest) -> statics -> statics) -> ((BlockId -> Maybe jumpDest) -> instr -> instr) -> (NatCmmDecl statics instr -> SDoc) -> Int -> [RealReg] -> ([NatCmmDecl statics instr] -> [NatCmmDecl statics instr]) -> (Int -> NatCmmDecl statics instr -> UniqSM (NatCmmDecl statics instr, [(BlockId, BlockId)])) -> (LabelMap CmmStatics -> [NatBasicBlock instr] -> [NatBasicBlock instr]) -> ([instr] -> [UnwindPoint]) -> (CFG -> LabelMap CmmStatics -> [NatBasicBlock instr] -> [NatBasicBlock instr]) -> NcgImpl statics instr jumpDest
- Inst: newMethodFromName :: CtOrigin -> Name -> TcRhoType -> TcM (HsExpr GhcTcId)
+ Inst: newMethodFromName :: CtOrigin -> Name -> [TcRhoType] -> TcM (HsExpr GhcTcId)
- NCGMonad: NcgImpl :: (RawCmmDecl -> NatM [NatCmmDecl statics instr]) -> (instr -> Maybe (NatCmmDecl statics instr)) -> (jumpDest -> Maybe BlockId) -> (instr -> Maybe jumpDest) -> ((BlockId -> Maybe jumpDest) -> statics -> statics) -> ((BlockId -> Maybe jumpDest) -> instr -> instr) -> (NatCmmDecl statics instr -> SDoc) -> Int -> [RealReg] -> ([NatCmmDecl statics instr] -> [NatCmmDecl statics instr]) -> ([NatCmmDecl statics instr] -> [NatCmmDecl statics instr]) -> (Int -> NatCmmDecl statics instr -> UniqSM (NatCmmDecl statics instr, [(BlockId, BlockId)])) -> (LabelMap CmmStatics -> [NatBasicBlock instr] -> [NatBasicBlock instr]) -> ([instr] -> [UnwindPoint]) -> (CFG -> LabelMap CmmStatics -> [NatBasicBlock instr] -> [NatBasicBlock instr]) -> NcgImpl statics instr jumpDest
+ NCGMonad: NcgImpl :: (RawCmmDecl -> NatM [NatCmmDecl statics instr]) -> (instr -> Maybe (NatCmmDecl statics instr)) -> (jumpDest -> Maybe BlockId) -> (instr -> Maybe jumpDest) -> ((BlockId -> Maybe jumpDest) -> statics -> statics) -> ((BlockId -> Maybe jumpDest) -> instr -> instr) -> (NatCmmDecl statics instr -> SDoc) -> Int -> [RealReg] -> ([NatCmmDecl statics instr] -> [NatCmmDecl statics instr]) -> (Int -> NatCmmDecl statics instr -> UniqSM (NatCmmDecl statics instr, [(BlockId, BlockId)])) -> (LabelMap CmmStatics -> [NatBasicBlock instr] -> [NatBasicBlock instr]) -> ([instr] -> [UnwindPoint]) -> (CFG -> LabelMap CmmStatics -> [NatBasicBlock instr] -> [NatBasicBlock instr]) -> NcgImpl statics instr jumpDest
- SysTools.Tasks: runCc :: DynFlags -> [Option] -> IO ()
+ SysTools.Tasks: runCc :: Maybe ForeignSrcLang -> DynFlags -> [Option] -> IO ()

Files

compiler/cmm/CLabel.hs view
@@ -98,7 +98,7 @@         needsCDecl, maybeLocalBlockLabel, externallyVisibleCLabel,         isMathFun,         isCFunctionLabel, isGcPtrLabel, labelDynamic,-        isLocalCLabel,+        isLocalCLabel, mayRedirectTo,          -- * Conversions         toClosureLbl, toSlowEntryLbl, toEntryLbl, toInfoLbl, hasHaskellName,@@ -1432,3 +1432,139 @@           SymbolPtr       -> text ".LC_" <> ppr lbl           GotSymbolPtr    -> ppr lbl <> text "@got"           GotSymbolOffset -> ppr lbl <> text "@gotoff"++-- Figure out whether `symbol` may serve as an alias+-- to `target` within one compilation unit.+--+-- This is true if any of these holds:+-- * `target` is a module-internal haskell name.+-- * `target` is an exported name, but comes from the same+--   module as `symbol`+--+-- These are sufficient conditions for establishing e.g. a+-- GNU assembly alias ('.equiv' directive). Sadly, there is+-- no such thing as an alias to an imported symbol (conf.+-- http://blog.omega-prime.co.uk/2011/07/06/the-sad-state-of-symbol-aliases/)+-- See note [emit-time elimination of static indirections].+--+-- Precondition is that both labels represent the+-- same semantic value.++mayRedirectTo :: CLabel -> CLabel -> Bool+mayRedirectTo symbol target+ | Just nam <- haskellName+ , staticClosureLabel+ , isExternalName nam+ , Just mod <- nameModule_maybe nam+ , Just anam <- hasHaskellName symbol+ , Just amod <- nameModule_maybe anam+ = amod == mod++ | Just nam <- haskellName+ , staticClosureLabel+ , isInternalName nam+ = True++ | otherwise = False+   where staticClosureLabel = isStaticClosureLabel target+         haskellName = hasHaskellName target+++{-+Note [emit-time elimination of static indirections]+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~+As described in #15155, certain static values are repesentationally+equivalent, e.g. 'cast'ed values (when created by 'newtype' wrappers).++             newtype A = A Int+             {-# NOINLINE a #-}+             a = A 42++a1_rYB :: Int+[GblId, Caf=NoCafRefs, Unf=OtherCon []]+a1_rYB = GHC.Types.I# 42#++a [InlPrag=NOINLINE] :: A+[GblId, Unf=OtherCon []]+a = a1_rYB `cast` (Sym (T15155.N:A[0]) :: Int ~R# A)++Formerly we created static indirections for these (IND_STATIC), which+consist of a statically allocated forwarding closure that contains+the (possibly tagged) indirectee. (See CMM/assembly below.)+This approach is suboptimal for two reasons:+  (a) they occupy extra space,+  (b) they need to be entered in order to obtain the indirectee,+      thus they cannot be tagged.++Fortunately there is a common case where static indirections can be+eliminated while emitting assembly (native or LLVM), viz. when the+indirectee is in the same module (object file) as the symbol that+points to it. In this case an assembly-level identification can+be created ('.equiv' directive), and as such the same object will+be assigned two names in the symbol table. Any of the identified+symbols can be referenced by a tagged pointer.++Currently the 'mayRedirectTo' predicate will+give a clue whether a label can be equated with another, already+emitted, label (which can in turn be an alias). The general mechanics+is that we identify data (IND_STATIC closures) that are amenable+to aliasing while pretty-printing of assembly output, and emit the+'.equiv' directive instead of static data in such a case.++Here is a sketch how the output is massaged:++                     Consider+newtype A = A Int+{-# NOINLINE a #-}+a = A 42                                -- I# 42# is the indirectee+                                        -- 'a' is exported++                 results in STG++a1_rXq :: GHC.Types.Int+[GblId, Caf=NoCafRefs, Unf=OtherCon []] =+    CCS_DONT_CARE GHC.Types.I#! [42#];++T15155.a [InlPrag=NOINLINE] :: T15155.A+[GblId, Unf=OtherCon []] =+    CAF_ccs  \ u  []  a1_rXq;++                 and CMM++[section ""data" . a1_rXq_closure" {+     a1_rXq_closure:+         const GHC.Types.I#_con_info;+         const 42;+ }]++[section ""data" . T15155.a_closure" {+     T15155.a_closure:+         const stg_IND_STATIC_info;+         const a1_rXq_closure+1;+         const 0;+         const 0;+ }]++The emitted assembly is++#### INDIRECTEE+a1_rXq_closure:                         -- module local haskell value+        .quad   GHC.Types.I#_con_info   -- an Int+        .quad   42++#### BEFORE+.globl T15155.a_closure                 -- exported newtype wrapped value+T15155.a_closure:+        .quad   stg_IND_STATIC_info     -- the closure info+        .quad   a1_rXq_closure+1        -- indirectee ('+1' being the tag)+        .quad   0+        .quad   0++#### AFTER+.globl T15155.a_closure                 -- exported newtype wrapped value+.equiv a1_rXq_closure,T15155.a_closure  -- both are shared++The transformation is performed because+     T15155.a_closure `mayRedirectTo` a1_rXq_closure+1+returns True.+-}
compiler/cmm/CmmCallConv.hs view
@@ -81,7 +81,6 @@                             | passFloatInXmm          -> k (RegisterParam (DoubleReg s), (vs, fs, ds, ls, ss))                         (W64, (vs, fs, d:ds, ls, ss))                             | not passFloatInXmm      -> k (RegisterParam d, (vs, fs, ds, ls, ss))-                        (W80, _) -> panic "F80 unsupported register type"                         _ -> (assts, (r:rs))               int = case (w, regs) of                       (W128, _) -> panic "W128 unsupported register type"@@ -100,6 +99,7 @@ passFloatArgsInXmm :: DynFlags -> Bool passFloatArgsInXmm dflags = case platformArch (targetPlatform dflags) of                               ArchX86_64 -> True+                              ArchX86    -> False                               _          -> False  -- We used to spill vector registers to the stack since the LLVM backend didn't
compiler/cmm/CmmExpr.hs view
@@ -5,7 +5,7 @@ {-# LANGUAGE UndecidableInstances #-}  module CmmExpr-    ( CmmExpr(..), cmmExprType, cmmExprWidth, maybeInvertCmmExpr+    ( CmmExpr(..), cmmExprType, cmmExprWidth, cmmExprAlignment, maybeInvertCmmExpr     , CmmReg(..), cmmRegType, cmmRegWidth     , CmmLit(..), cmmLitType     , LocalReg(..), localRegType@@ -43,6 +43,8 @@ import Data.Set (Set) import qualified Data.Set as Set +import BasicTypes (Alignment, mkAlignment, alignmentOf)+ ----------------------------------------------------------------------------- --              CmmExpr -- An expression.  Expressions have no side effects.@@ -239,6 +241,13 @@ cmmExprWidth :: DynFlags -> CmmExpr -> Width cmmExprWidth dflags e = typeWidth (cmmExprType dflags e) +-- | Returns an alignment in bytes of a CmmExpr when it's a statically+-- known integer constant, otherwise returns an alignment of 1 byte.+-- The caller is responsible for using with a sensible CmmExpr+-- argument.+cmmExprAlignment :: CmmExpr -> Alignment+cmmExprAlignment (CmmLit (CmmInt intOff _)) = alignmentOf (fromInteger intOff)+cmmExprAlignment _                          = mkAlignment 1 -------- --- Negation for conditional branches @@ -474,6 +483,9 @@    FloatReg i == FloatReg j = i==j    DoubleReg i == DoubleReg j = i==j    LongReg i == LongReg j = i==j+   -- NOTE: XMM, YMM, ZMM registers actually are the same registers+   -- at least with respect to store at YMM i and then read from XMM i+   -- and similarly for ZMM etc.    XmmReg i == XmmReg j = i==j    YmmReg i == YmmReg j = i==j    ZmmReg i == ZmmReg j = i==j@@ -584,6 +596,9 @@ globalRegType _      (FloatReg _)      = cmmFloat W32 globalRegType _      (DoubleReg _)     = cmmFloat W64 globalRegType _      (LongReg _)       = cmmBits W64+-- TODO: improve the internal model of SIMD/vectorized registers+-- the right design SHOULd improve handling of float and double code too.+-- see remarks in "NOTE [SIMD Design for the future]"" in StgCmmPrim globalRegType _      (XmmReg _)        = cmmVec 4 (cmmBits W32) globalRegType _      (YmmReg _)        = cmmVec 8 (cmmBits W32) globalRegType _      (ZmmReg _)        = cmmVec 16 (cmmBits W32)
compiler/codeGen/StgCmmBind.hs view
@@ -78,7 +78,9 @@   -- closure pointing directly to the indirectee.  This is exactly   -- what the CAF will eventually evaluate to anyway, we're just   -- shortcutting the whole process, and generating a lot less code-  -- (#7308)+  -- (#7308). Eventually the IND_STATIC closure will be eliminated+  -- by assembly '.equiv' directives, where possible (#15155).+  -- See note [emit-time elimination of static indirections] in CLabel.   --   -- Note: we omit the optimisation when this binding is part of a   -- recursive group, because the optimisation would inhibit the black
compiler/codeGen/StgCmmPrim.hs view
@@ -1727,8 +1727,38 @@ vecElemProjectCast _      WordVec  W64 =  Nothing vecElemProjectCast _      _        _   =  Nothing ++-- NOTE [SIMD Design for the future] -- Check to make sure that we can generate code for the specified vector type -- given the current set of dynamic flags.+-- Currently these checks are specific to x86 and x86_64 architecture.+-- This should be fixed!+-- In particular,+-- 1) Add better support for other architectures! (this may require a redesign)+-- 2) Decouple design choices from LLVM's pseudo SIMD model!+--   The high level LLVM naive rep makes per CPU family SIMD generation is own+--   optimization problem, and hides important differences in eg ARM vs x86_64 simd+-- 3) Depending on the architecture, the SIMD registers may also support general+--    computations on Float/Double/Word/Int scalars, but currently on+--    for example x86_64, we always put Word/Int (or sized) in GPR+--    (general purpose) registers. Would relaxing that allow for+--    useful optimization opportunities?+--      Phrased differently, it is worth experimenting with supporting+--    different register mapping strategies than we currently have, especially if+--    someday we want SIMD to be a first class denizen in GHC along with scalar+--    values!+--      The current design with respect to register mapping of scalars could+--    very well be the best,but exploring the  design space and doing careful+--    measurments is the only only way to validate that.+--      In some next generation CPU ISAs, notably RISC V, the SIMD extension+--    includes  support for a sort of run time CPU dependent vectorization parameter,+--    where a loop may act upon a single scalar each iteration OR some 2,4,8 ...+--    element chunk! Time will tell if that direction sees wide adoption,+--    but it is from that context that unifying our handling of simd and scalars+--    may benefit. It is not likely to benefit current architectures, though+--    it may very well be a design perspective that helps guide improving the NCG.++ checkVecCompatibility :: DynFlags -> PrimOpVecCat -> Length -> Width -> FCode () checkVecCompatibility dflags vcat l w = do     when (hscTarget dflags /= HscLlvm) $ do@@ -2005,8 +2035,8 @@   where     -- Copy data (we assume the arrays aren't overlapping since     -- they're of different types)-    copy _src _dst dst_p src_p bytes =-        emitMemcpyCall dst_p src_p bytes 1+    copy _src _dst dst_p src_p bytes align =+        emitMemcpyCall dst_p src_p bytes align  -- | Takes a source 'MutableByteArray#', an offset in the source -- array, a destination 'MutableByteArray#', an offset into the@@ -2020,22 +2050,26 @@     -- The only time the memory might overlap is when the two arrays     -- we were provided are the same array!     -- TODO: Optimize branch for common case of no aliasing.-    copy src dst dst_p src_p bytes = do+    copy src dst dst_p src_p bytes align = do         dflags <- getDynFlags         (moveCall, cpyCall) <- forkAltPair-            (getCode $ emitMemmoveCall dst_p src_p bytes 1)-            (getCode $ emitMemcpyCall  dst_p src_p bytes 1)+            (getCode $ emitMemmoveCall dst_p src_p bytes align)+            (getCode $ emitMemcpyCall  dst_p src_p bytes align)         emit =<< mkCmmIfThenElse (cmmEqWord dflags src dst) moveCall cpyCall  emitCopyByteArray :: (CmmExpr -> CmmExpr -> CmmExpr -> CmmExpr -> CmmExpr-                      -> FCode ())+                      -> Alignment -> FCode ())                   -> CmmExpr -> CmmExpr -> CmmExpr -> CmmExpr -> CmmExpr                   -> FCode () emitCopyByteArray copy src src_off dst dst_off n = do     dflags <- getDynFlags+    let byteArrayAlignment = wordAlignment dflags+        srcOffAlignment = cmmExprAlignment src_off+        dstOffAlignment = cmmExprAlignment dst_off+        align = minimum [byteArrayAlignment, srcOffAlignment, dstOffAlignment]     dst_p <- assignTempE $ cmmOffsetExpr dflags (cmmOffsetB dflags dst (arrWordsHdrSize dflags)) dst_off     src_p <- assignTempE $ cmmOffsetExpr dflags (cmmOffsetB dflags src (arrWordsHdrSize dflags)) src_off-    copy src dst dst_p src_p n+    copy src dst dst_p src_p n align  -- | Takes a source 'ByteArray#', an offset in the source array, a -- destination 'Addr#', and the number of bytes to copy.  Copies the given@@ -2045,7 +2079,7 @@     -- Use memcpy (we are allowed to assume the arrays aren't overlapping)     dflags <- getDynFlags     src_p <- assignTempE $ cmmOffsetExpr dflags (cmmOffsetB dflags src (arrWordsHdrSize dflags)) src_off-    emitMemcpyCall dst_p src_p bytes 1+    emitMemcpyCall dst_p src_p bytes (mkAlignment 1)  -- | Takes a source 'MutableByteArray#', an offset in the source array, a -- destination 'Addr#', and the number of bytes to copy.  Copies the given@@ -2062,7 +2096,7 @@     -- Use memcpy (we are allowed to assume the arrays aren't overlapping)     dflags <- getDynFlags     dst_p <- assignTempE $ cmmOffsetExpr dflags (cmmOffsetB dflags dst (arrWordsHdrSize dflags)) dst_off-    emitMemcpyCall dst_p src_p bytes 1+    emitMemcpyCall dst_p src_p bytes (mkAlignment 1)   -- ----------------------------------------------------------------------------@@ -2073,11 +2107,16 @@ -- character. doSetByteArrayOp :: CmmExpr -> CmmExpr -> CmmExpr -> CmmExpr                  -> FCode ()-doSetByteArrayOp ba off len c-    = do dflags <- getDynFlags-         p <- assignTempE $ cmmOffsetExpr dflags (cmmOffsetB dflags ba (arrWordsHdrSize dflags)) off-         emitMemsetCall p c len 1+doSetByteArrayOp ba off len c = do+    dflags <- getDynFlags +    let byteArrayAlignment = wordAlignment dflags -- known since BA is allocated on heap+        offsetAlignment = cmmExprAlignment off+        align = min byteArrayAlignment offsetAlignment++    p <- assignTempE $ cmmOffsetExpr dflags (cmmOffsetB dflags ba (arrWordsHdrSize dflags)) off+    emitMemsetCall p c len align+ -- ---------------------------------------------------------------------------- -- Allocating arrays @@ -2104,18 +2143,9 @@     emit $ mkAssign arr base      -- Initialise all elements of the array-    p <- assignTemp $ cmmOffsetB dflags (CmmReg arr) (hdrSize dflags rep)-    for <- newBlockId-    emitLabel for-    let loopBody =-            [ mkStore (CmmReg (CmmLocal p)) init-            , mkAssign (CmmLocal p) (cmmOffsetW dflags (CmmReg (CmmLocal p)) 1)-            , mkBranch for ]-    emit =<< mkCmmIfThen-        (cmmULtWord dflags (CmmReg (CmmLocal p))-         (cmmOffsetW dflags (CmmReg arr)-          (hdrSizeW dflags rep + n)))-        (catAGraphs loopBody)+    let mkOff off = cmmOffsetW dflags (CmmReg arr) (hdrSizeW dflags rep + off)+        initialization = [ mkStore (mkOff off) init | off <- [0.. n - 1] ]+    emit (catAGraphs initialization)      emit $ mkAssign (CmmLocal res_r) (CmmReg arr) @@ -2149,7 +2179,7 @@     copy _src _dst dst_p src_p bytes =         do dflags <- getDynFlags            emitMemcpyCall dst_p src_p (mkIntExpr dflags bytes)-               (wORD_SIZE dflags)+               (wordAlignment dflags)   -- | Takes a source 'MutableArray#', an offset in the source array, a@@ -2167,9 +2197,9 @@         dflags <- getDynFlags         (moveCall, cpyCall) <- forkAltPair             (getCode $ emitMemmoveCall dst_p src_p (mkIntExpr dflags bytes)-             (wORD_SIZE dflags))+             (wordAlignment dflags))             (getCode $ emitMemcpyCall  dst_p src_p (mkIntExpr dflags bytes)-             (wORD_SIZE dflags))+             (wordAlignment dflags))         emit =<< mkCmmIfThenElse (cmmEqWord dflags src dst) moveCall cpyCall  emitCopyArray :: (CmmExpr -> CmmExpr -> CmmExpr -> CmmExpr -> ByteOff@@ -2216,7 +2246,7 @@     copy _src _dst dst_p src_p bytes =         do dflags <- getDynFlags            emitMemcpyCall dst_p src_p (mkIntExpr dflags bytes)-               (wORD_SIZE dflags)+               (wordAlignment dflags)   doCopySmallMutableArrayOp :: CmmExpr -> CmmExpr -> CmmExpr -> CmmExpr -> WordOff@@ -2230,9 +2260,9 @@         dflags <- getDynFlags         (moveCall, cpyCall) <- forkAltPair             (getCode $ emitMemmoveCall dst_p src_p (mkIntExpr dflags bytes)-             (wORD_SIZE dflags))+             (wordAlignment dflags))             (getCode $ emitMemcpyCall  dst_p src_p (mkIntExpr dflags bytes)-             (wORD_SIZE dflags))+             (wordAlignment dflags))         emit =<< mkCmmIfThenElse (cmmEqWord dflags src dst) moveCall cpyCall  emitCopySmallArray :: (CmmExpr -> CmmExpr -> CmmExpr -> CmmExpr -> ByteOff@@ -2297,7 +2327,7 @@               (mkIntExpr dflags (arrPtrsHdrSizeW dflags)) src_off)      emitMemcpyCall dst_p src_p (mkIntExpr dflags (wordsToBytes dflags n))-        (wORD_SIZE dflags)+        (wordAlignment dflags)      emit $ mkAssign (CmmLocal res_r) (CmmReg arr) @@ -2334,7 +2364,7 @@               (mkIntExpr dflags (smallArrPtrsHdrSizeW dflags)) src_off)      emitMemcpyCall dst_p src_p (mkIntExpr dflags (wordsToBytes dflags n))-        (wORD_SIZE dflags)+        (wordAlignment dflags)      emit $ mkAssign (CmmLocal res_r) (CmmReg arr) @@ -2353,7 +2383,7 @@     emitMemsetCall (cmmAddWord dflags dst_cards_start start_card)         (mkIntExpr dflags 1)         (cmmAddWord dflags (cmmSubWord dflags end_card start_card) (mkIntExpr dflags 1))-        1 -- no alignment (1 byte)+        (mkAlignment 1) -- no alignment (1 byte)  -- Convert an element index to a card index cardCmm :: DynFlags -> CmmExpr -> CmmExpr@@ -2462,28 +2492,28 @@ -- Helpers for emitting function calls  -- | Emit a call to @memcpy@.-emitMemcpyCall :: CmmExpr -> CmmExpr -> CmmExpr -> Int -> FCode ()+emitMemcpyCall :: CmmExpr -> CmmExpr -> CmmExpr -> Alignment -> FCode () emitMemcpyCall dst src n align = do     emitPrimCall         [ {-no results-} ]-        (MO_Memcpy align)+        (MO_Memcpy (alignmentBytes align))         [ dst, src, n ]  -- | Emit a call to @memmove@.-emitMemmoveCall :: CmmExpr -> CmmExpr -> CmmExpr -> Int -> FCode ()+emitMemmoveCall :: CmmExpr -> CmmExpr -> CmmExpr -> Alignment -> FCode () emitMemmoveCall dst src n align = do     emitPrimCall         [ {- no results -} ]-        (MO_Memmove align)+        (MO_Memmove (alignmentBytes align))         [ dst, src, n ]  -- | Emit a call to @memset@.  The second argument must fit inside an -- unsigned char.-emitMemsetCall :: CmmExpr -> CmmExpr -> CmmExpr -> Int -> FCode ()+emitMemsetCall :: CmmExpr -> CmmExpr -> CmmExpr -> Alignment -> FCode () emitMemsetCall dst c n align = do     emitPrimCall         [ {- no results -} ]-        (MO_Memset align)+        (MO_Memset (alignmentBytes align))         [ dst, c, n ]  emitMemcmpCall :: LocalReg -> CmmExpr -> CmmExpr -> CmmExpr -> Int -> FCode ()
compiler/coreSyn/CoreLint.hs view
@@ -2080,7 +2080,7 @@ newtype LintM a =    LintM { unLintM ::             LintEnv ->-            WarnsAndErrs ->           -- Error and warning messages so far+            WarnsAndErrs ->           -- Warning and error messages so far             (Maybe a, WarnsAndErrs) } -- Result and messages (if any)  type WarnsAndErrs = (Bag MsgDoc, Bag MsgDoc)@@ -2189,10 +2189,13 @@   | InCo   Coercion     -- Inside a coercion  initL :: DynFlags -> LintFlags -> InScopeSet-       -> LintM a -> WarnsAndErrs    -- Errors and warnings+       -> LintM a -> WarnsAndErrs    -- Warnings and errors initL dflags flags in_scope m   = case unLintM m env (emptyBag, emptyBag) of-      (_, errs) -> errs+      (Just _, errs) -> errs+      (Nothing, errs@(_, e)) | not (isEmptyBag e) -> errs+                             | otherwise -> pprPanic ("Bug in Lint: a failure occurred " +++                                                      "without reporting an error message") empty   where     env = LE { le_flags = flags              , le_subst = mkEmptyTCvSubst in_scope
compiler/deSugar/Check.hs view
@@ -4,9 +4,13 @@ Pattern Matching Coverage Checking. -} -{-# LANGUAGE CPP, GADTs, DataKinds, KindSignatures #-}-{-# LANGUAGE TupleSections #-}-{-# LANGUAGE ViewPatterns  #-}+{-# LANGUAGE CPP            #-}+{-# LANGUAGE GADTs          #-}+{-# LANGUAGE DataKinds      #-}+{-# LANGUAGE KindSignatures #-}+{-# LANGUAGE TupleSections  #-}+{-# LANGUAGE ViewPatterns   #-}+{-# LANGUAGE MultiWayIf     #-}  module Check (         -- Checking and printing@@ -55,7 +59,7 @@  import Data.List     (find) import Data.Maybe    (catMaybes, isJust, fromMaybe)-import Control.Monad (forM, when, forM_, zipWithM)+import Control.Monad (forM, when, forM_, zipWithM, filterM) import Coercion import TcEvidence import TcSimplify    (tcNormalise)@@ -153,7 +157,9 @@   PmNLit :: { pm_lit_id   :: Id             , pm_lit_not  :: [PmLit] } -> PmPat 'VA   PmGrd  :: { pm_grd_pv   :: PatVec-            , pm_grd_expr :: PmExpr  } -> PmPat 'PAT+            , pm_grd_expr :: PmExpr } -> PmPat 'PAT+  -- | A fake guard pattern (True <- _) used to represent cases we cannot handle.+  PmFake :: PmPat 'PAT  instance Outputable (PmPat a) where   ppr = pprPmPatDebug@@ -289,6 +295,14 @@     , pmresultUncovered    :: UncoveredCandidates     , pmresultInaccessible :: [Located [LPat GhcTc]] } +instance Outputable PmResult where+  ppr pmr = hang (text "PmResult") 2 $ vcat+    [ text "pmresultProvenance" <+> ppr (pmresultProvenance pmr)+    , text "pmresultRedundant" <+> ppr (pmresultRedundant pmr)+    , text "pmresultUncovered" <+> ppr (pmresultUncovered pmr)+    , text "pmresultInaccessible" <+> ppr (pmresultInaccessible pmr)+    ]+ -- | Either a list of patterns that are not covered, or their type, in case we -- have no patterns at hand. Not having patterns at hand can arise when -- handling EmptyCase expressions, in two cases:@@ -303,6 +317,10 @@ data UncoveredCandidates = UncoveredPatterns Uncovered                          | TypeOfUncovered Type +instance Outputable UncoveredCandidates where+  ppr (UncoveredPatterns uc) = text "UnPat" <+> ppr uc+  ppr (TypeOfUncovered ty)   = text "UnTy" <+> ppr ty+ -- | The empty pattern check result emptyPmResult :: PmResult emptyPmResult = PmResult FromBuiltin [] (UncoveredPatterns []) []@@ -912,24 +930,11 @@ truePattern = nullaryConPattern (RealDataCon trueDataCon) {-# INLINE truePattern #-} --- | A fake guard pattern (True <- _) used to represent cases we cannot handle-fake_pat :: Pattern-fake_pat = PmGrd { pm_grd_pv   = [truePattern]-                 , pm_grd_expr = PmExprOther (EWildPat noExt) }-{-# INLINE fake_pat #-}---- | Check whether a guard pattern is generated by the checker (unhandled)-isFakeGuard :: [Pattern] -> PmExpr -> Bool-isFakeGuard [PmCon { pm_con_con = RealDataCon c }] (PmExprOther (EWildPat _))-  | c == trueDataCon = True-  | otherwise        = False-isFakeGuard _pats _e = False- -- | Generate a `canFail` pattern vector of a specific type mkCanFailPmPat :: Type -> DsM PatVec mkCanFailPmPat ty = do   var <- mkPmVar ty-  return [var, fake_pat]+  return [var, PmFake]  vanillaConPattern :: ConLike -> [Type] -> PatVec -> Pattern -- ADT constructor pattern => no existentials, no local constraints@@ -987,7 +992,7 @@     | otherwise -> do         ps      <- translatePat fam_insts p         (xp,xe) <- mkPmId2Forms ty-        let g = mkGuard ps (mkHsWrap wrapper (unLoc xe))+        g <- mkGuard ps (mkHsWrap wrapper (unLoc xe))         return [xp,g]    -- (n + k)  ===>   x (True <- x >= k) (n <- x-k)@@ -997,10 +1002,11 @@   ViewPat arg_ty lexpr lpat -> do     ps <- translatePat fam_insts (unLoc lpat)     -- See Note [Guards and Approximation]-    case all cantFailPattern ps of+    res <- allM cantFailPattern ps+    case res of       True  -> do         (xp,xe) <- mkPmId2Forms arg_ty-        let g = mkGuard ps (HsApp noExt lexpr xe)+        g <- mkGuard ps (HsApp noExt lexpr xe)         return [xp,g]       False -> mkCanFailPmPat arg_ty @@ -1255,41 +1261,38 @@ translateGuards :: FamInstEnvs -> [GuardStmt GhcTc] -> DsM PatVec translateGuards fam_insts guards = do   all_guards <- concat <$> mapM (translateGuard fam_insts) guards-  return (replace_unhandled all_guards)-  -- It should have been (return all_guards) but it is too expressive.+  let+    shouldKeep :: Pattern -> DsM Bool+    shouldKeep p+      | PmVar {} <- p = pure True+      | PmCon {} <- p = (&&)+                          <$> singleMatchConstructor (pm_con_con p) (pm_con_arg_tys p)+                          <*> allM shouldKeep (pm_con_args p)+    shouldKeep (PmGrd pv e)+      | isNotPmExprOther e = pure True  -- expensive but we want it+      | otherwise          = allM shouldKeep pv+    shouldKeep _other_pat  = pure False -- let the rest..++  all_handled <- allM shouldKeep all_guards+  -- It should have been @pure all_guards@ but it is too expressive.   -- Since the term oracle does not handle all constraints we generate,   -- we (hackily) replace all constraints the oracle cannot handle with a-  -- single one (we need to know if there is a possibility of falure).+  -- single one (we need to know if there is a possibility of failure).   -- See Note [Guards and Approximation] for all guard-related approximations   -- we implement.-  where-    replace_unhandled :: PatVec -> PatVec-    replace_unhandled gv-      | any_unhandled gv = fake_pat : [ p | p <- gv, shouldKeep p ]-      | otherwise        = gv--    any_unhandled :: PatVec -> Bool-    any_unhandled gv = any (not . shouldKeep) gv--    shouldKeep :: Pattern -> Bool-    shouldKeep p-      | PmVar {} <- p      = True-      | PmCon {} <- p      = singleConstructor (pm_con_con p)-                             && all shouldKeep (pm_con_args p)-    shouldKeep (PmGrd pv e)-      | all shouldKeep pv  = True-      | isNotPmExprOther e = True  -- expensive but we want it-    shouldKeep _other_pat  = False -- let the rest..+  if all_handled+    then pure all_guards+    else do+      kept <- filterM shouldKeep all_guards+      pure (PmFake : kept)  -- | Check whether a pattern can fail to match-cantFailPattern :: Pattern -> Bool-cantFailPattern p-  | PmVar {} <- p = True-  | PmCon {} <- p = singleConstructor (pm_con_con p)-                    && all cantFailPattern (pm_con_args p)-cantFailPattern (PmGrd pv _e)-                  = all cantFailPattern pv-cantFailPattern _ = False+cantFailPattern :: Pattern -> DsM Bool+cantFailPattern PmVar {}      = pure True+cantFailPattern PmCon { pm_con_con = c, pm_con_arg_tys = tys, pm_con_args = ps}+  = (&&) <$> singleMatchConstructor c tys <*> allM cantFailPattern ps+cantFailPattern (PmGrd pv _e) = allM cantFailPattern pv+cantFailPattern _             = pure False  -- | Translate a guard statement to Pattern translateGuard :: FamInstEnvs -> GuardStmt GhcTc -> DsM PatVec@@ -1312,7 +1315,8 @@ translateBind :: FamInstEnvs -> LPat GhcTc -> LHsExpr GhcTc -> DsM PatVec translateBind fam_insts (dL->L _ p) e = do   ps <- translatePat fam_insts p-  return [mkGuard ps (unLoc e)]+  g <- mkGuard ps (unLoc e)+  return [g]  -- | Translate a boolean guard translateBoolGuard :: LHsExpr GhcTc -> DsM PatVec@@ -1321,7 +1325,7 @@     -- The formal thing to do would be to generate (True <- True)     -- but it is trivial to solve so instead we give back an empty     -- PatVec for efficiency-  | otherwise = return [mkGuard [truePattern] (unLoc e)]+  | otherwise = (:[]) <$> mkGuard [truePattern] (unLoc e)  {- Note [Guards and Approximation] ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~@@ -1362,7 +1366,7 @@           expressivity in our warnings.       Hence, in this case, we replace the guard @([a,b] <- f x)@ with a *dummy*-     @fake_pat@: @True <- _@. That is, we record that there is a possibility+     @PmFake@: @True <- _@. That is, we record that there is a possibility      of failure but we minimize it to a True/False. This generates a single      warning and much smaller uncovered sets. @@ -1406,7 +1410,7 @@  Additionally, top-level guard translation (performed by @translateGuards@) replaces guards that cannot be reasoned about (like the ones we described in-1-4) with a single @fake_pat@ to record the possibility of failure to match.+1-4) with a single @PmFake@ to record the possibility of failure to match.  Note [Translate CoPats] ~~~~~~~~~~~~~~~~~~~~~~~@@ -1442,6 +1446,7 @@ pmPatType (PmGrd  { pm_grd_pv  = pv })   = ASSERT(patVecArity pv == 1) (pmPatType p)   where Just p = find ((==1) . patternArity) pv+pmPatType PmFake = pmPatType truePattern  -- | Information about a conlike that is relevant to coverage checking. -- It is called an \"inhabitation candidate\" since it is a value which may@@ -1658,13 +1663,14 @@ -- * More smart constructors and fresh variable generation  -- | Create a guard pattern-mkGuard :: PatVec -> HsExpr GhcTc -> Pattern-mkGuard pv e-  | all cantFailPattern pv = PmGrd pv expr-  | PmExprOther {} <- expr = fake_pat-  | otherwise              = PmGrd pv expr-  where-    expr = hsExprToPmExpr e+mkGuard :: PatVec -> HsExpr GhcTc -> DsM Pattern+mkGuard pv e = do+  res <- allM cantFailPattern pv+  let expr = hsExprToPmExpr e+  tracePmD "mkGuard" (vcat [ppr pv, ppr e, ppr res, ppr expr])+  if | res                    -> pure (PmGrd pv expr)+     | PmExprOther {} <- expr -> pure PmFake+     | otherwise              -> pure (PmGrd pv expr)  -- | Create a term equality of the form: `(False ~ (x ~ lit))` mkNegEq :: Id -> PmLit -> ComplexEq@@ -1737,16 +1743,40 @@            , pm_con_tvs  = tvs, pm_con_dicts = dicts            , pm_con_args = coercePatVec args }] coercePmPat (PmGrd {}) = [] -- drop the guards+coercePmPat PmFake     = [] -- drop the guards --- | Check whether a data constructor is the only way to construct--- a data type.-singleConstructor :: ConLike -> Bool-singleConstructor (RealDataCon dc) =-  case tyConDataCons (dataConTyCon dc) of-    [_] -> True-    _   -> False-singleConstructor _ = False+-- | Check whether a 'ConLike' has the /single match/ property, i.e. whether+-- it is the only possible match in the given context. See also+-- 'allCompleteMatches' and Note [Single match constructors].+singleMatchConstructor :: ConLike -> [Type] -> DsM Bool+singleMatchConstructor cl tys =+  any (isSingleton . snd) <$> allCompleteMatches cl tys +{-+Note [Single match constructors]+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~+When translating pattern guards for consumption by the checker, we desugar+every pattern guard that might fail ('cantFailPattern') to 'PmFake'+(True <- _). Which patterns can't fail? Exactly those that only match on+'singleMatchConstructor's.++Here are a few examples:+  * @f a | (a, b) <- foo a = 42@: Product constructors are generally+    single match. This extends to single constructors of GADTs like 'Refl'.+  * If @f | Id <- id () = 42@, where @pattern Id = ()@ and 'Id' is part of a+    singleton `COMPLETE` set, then 'Id' has the single match property.++In effect, we can just enumerate 'allCompleteMatches' and check if the conlike+occurs as a singleton set.+There's the chance that 'Id' is part of multiple `COMPLETE` sets. That's+irrelevant; If the user specified a singleton set, it is single-match.++Note that this doesn't really take into account incoming type constraints;+It might be obvious from type context that a particular GADT constructor has+the single-match property. We currently don't (can't) check this in the+translation step. See #15753 for why this yields surprising results.+-}+ -- | For a given conlike, finds all the sets of patterns which could -- be relevant to that conlike by consulting the result type. --@@ -1984,13 +2014,15 @@   | otherwise   = pmcheckGuardsI guards vva  -- Guard-pmcheck (p@(PmGrd pv e) : ps) guards vva@(ValVec vas delta)-    -- short-circuit if the guard pattern is useless.-    -- we just have two possible outcomes: fail here or match and recurse-    -- none of the two contains any useful information about the failure-    -- though. So just have these two cases but do not do all the boilerplate-  | isFakeGuard pv e = forces . mkCons vva <$> pmcheckI ps guards vva-  | otherwise = do+pmcheck (PmFake : ps) guards vva =+  -- short-circuit if the guard pattern is useless.+  -- we just have two possible outcomes: fail here or match and recurse+  -- none of the two contains any useful information about the failure+  -- though. So just have these two cases but do not do all the boilerplate+  forces . mkCons vva <$> pmcheckI ps guards vva+pmcheck (p : ps) guards (ValVec vas delta)+  | PmGrd { pm_grd_pv = pv, pm_grd_expr = e } <- p+  = do       y <- liftD $ mkPmId (pmPatType p)       let tm_state = extendSubst y e (delta_tm_cs delta)           delta'   = delta { delta_tm_cs = tm_state }@@ -2118,15 +2150,22 @@ -- no information is lost  -- LitCon-pmcheckHd (PmLit l) ps guards (va@(PmCon {})) (ValVec vva delta)+pmcheckHd p@PmLit{} ps guards va@PmCon{} (ValVec vva delta)   = do y <- liftD $ mkPmId (pmPatType va)-       let tm_state = extendSubst y (PmExprLit l) (delta_tm_cs delta)+       -- Analogous to the ConVar case, we have to case split the value+       -- abstraction on possible literals. We do so by introducing a fresh+       -- variable that is equated to the constructor. LitVar will then take+       -- care of the case split by resorting to NLit.+       let tm_state = extendSubst y (vaToPmExpr va) (delta_tm_cs delta)            delta'   = delta { delta_tm_cs = tm_state }-       pmcheckHdI (PmVar y) ps guards va (ValVec vva delta')+       pmcheckHdI p ps guards (PmVar y) (ValVec vva delta')  -- ConLit-pmcheckHd (p@(PmCon {})) ps guards (PmLit l) (ValVec vva delta)+pmcheckHd p@PmCon{} ps guards (PmLit l) (ValVec vva delta)   = do y <- liftD $ mkPmId (pmPatType p)+       -- This desugars to the ConVar case by introducing a fresh variable that+       -- is equated to the literal via a constraint. ConVar will then properly+       -- case split on all possible constructors.        let tm_state = extendSubst y (PmExprLit l) (delta_tm_cs delta)            delta'   = delta { delta_tm_cs = tm_state }        pmcheckHdI p ps guards (PmVar y) (ValVec vva delta')@@ -2136,6 +2175,7 @@   = pmcheckHdI p ps guards (PmVar x) vva  -- Impossible: handled by pmcheck+pmcheckHd PmFake     _ _ _ _ = panic "pmcheckHd: Fake" pmcheckHd (PmGrd {}) _ _ _ _ = panic "pmcheckHd: Guard"  {-@@ -2696,6 +2736,7 @@ pprPmPatDebug (PmNLit i nl) = text "PmNLit" <+> ppr i <+> ppr nl pprPmPatDebug (PmGrd pv ge) = text "PmGrd" <+> hsep (map pprPmPatDebug pv)                                            <+> ppr ge+pprPmPatDebug PmFake = text "PmFake"  pprPatVec :: PatVec -> SDoc pprPatVec ps = hang (text "Pattern:") 2
compiler/deSugar/TmOracle.hs view
@@ -33,6 +33,7 @@ import TcHsSyn import MonadUtils import Util+import Outputable  import NameEnv @@ -134,7 +135,8 @@    (PmExprEq _ _, PmExprEq _ _) -> Just (eq:standby, (unhandled, env)) -  _ -> Just (standby, (True, env)) -- I HATE CATCH-ALLS+  _ -> WARN( True, text "solveComplexEq: Catch all" <+> ppr eq )+       Just (standby, (True, env)) -- I HATE CATCH-ALLS  -- | Extend the substitution and solve the (possibly updated) constraints. extendSubstAndSolve :: Name -> PmExpr -> TmState -> Maybe TmState
compiler/ghci/ByteCodeLink.hs view
@@ -154,8 +154,8 @@                 , "the missing library using the -L/path/to/object/dir and -lmissinglibname"                 , "flags, or simply by naming the relevant files on the GHCi command line."                 , "Alternatively, this link failure might indicate a bug in GHCi."-                , "If you suspect the latter, please send a bug report to:"-                , "  glasgow-haskell-bugs@haskell.org"+                , "If you suspect the latter, please report this as a GHC bug:"+                , "  https://www.haskell.org/ghc/reportabug"                 ])  
compiler/llvmGen/Llvm/Types.hs view
@@ -185,6 +185,7 @@ pprSpecialStatic (LMBitc v t) =     ppr (pLower t) <> text ", bitcast (" <> ppr v <> text " to " <> ppr t         <> char ')'+pprSpecialStatic v@(LMStaticPointer x) = ppr (pLower $ getVarType x) <> comma <+> ppr v pprSpecialStatic stat = ppr stat  
compiler/llvmGen/LlvmCodeGen/Base.hs view
@@ -31,7 +31,7 @@         strCLabel_llvm, strDisplayName_llvm, strProcedureName_llvm,         getGlobalPtr, generateExternDecls, -        aliasify,+        aliasify, llvmDefLabel     ) where  #include "HsVersions.h"@@ -57,6 +57,7 @@ import ErrUtils import qualified Stream +import Data.Maybe (fromJust) import Control.Monad (ap)  -- ----------------------------------------------------------------------------@@ -97,7 +98,6 @@ widthToLlvmFloat :: Width -> LlvmType widthToLlvmFloat W32  = LMFloat widthToLlvmFloat W64  = LMDouble-widthToLlvmFloat W80  = LMFloat80 widthToLlvmFloat W128 = LMFloat128 widthToLlvmFloat w    = panic $ "widthToLlvmFloat: Bad float size: " ++ show w @@ -377,7 +377,7 @@     mk "newSpark" (llvmWord dflags) [i8Ptr, i8Ptr]   where     mk n ret args = do-      let n' = fsLit n `appendFS` fsLit "$def"+      let n' = llvmDefLabel $ fsLit n           decl = LlvmFunctionDecl n' ExternallyVisible CC_Ccc ret                                  FixedArgs (tysToParams args) Nothing       renderLlvm $ ppLlvmFunctionDecl decl@@ -437,12 +437,17 @@   let mkGlbVar lbl ty = LMGlobalVar lbl (LMPointer ty) Private Nothing Nothing   case m_ty of     -- Directly reference if we have seen it already-    Just ty -> return $ mkGlbVar (llvmLbl `appendFS` fsLit "$def") ty Global+    Just ty -> return $ mkGlbVar (llvmDefLabel llvmLbl) ty Global     -- Otherwise use a forward alias of it     Nothing -> do       saveAlias llvmLbl       return $ mkGlbVar llvmLbl i8 Alias +-- | Derive the definition label. It has an identified+-- structure type.+llvmDefLabel :: LMString -> LMString+llvmDefLabel = (`appendFS` fsLit "$def")+ -- | Generate definitions for aliases forward-referenced by @getGlobalPtr@. -- -- Must be called at a point where we are sure that no new global definitions@@ -473,10 +478,28 @@ -- | Here we take a global variable definition, rename it with a -- @$def@ suffix, and generate the appropriate alias. aliasify :: LMGlobal -> LlvmM [LMGlobal]+-- See note [emit-time elimination of static indirections] in CLabel.+-- Here we obtain the indirectee's precise type and introduce+-- fresh aliases to both the precise typed label (lbl$def) and the i8*+-- typed (regular) label of it with the matching new names.+aliasify (LMGlobal (LMGlobalVar lbl ty@LMAlias{} link sect align Alias)+                   (Just orig)) = do+    let defLbl = llvmDefLabel lbl+        LMStaticPointer (LMGlobalVar origLbl _ oLnk Nothing Nothing Alias) = orig+        defOrigLbl = llvmDefLabel origLbl+        orig' = LMStaticPointer (LMGlobalVar origLbl i8Ptr oLnk Nothing Nothing Alias)+    origType <- funLookup origLbl+    let defOrig = LMBitc (LMStaticPointer (LMGlobalVar defOrigLbl+                                           (pLift $ fromJust origType) oLnk+                                           Nothing Nothing Alias))+                         (pLift ty)+    pure [ LMGlobal (LMGlobalVar defLbl ty link sect align Alias) (Just defOrig)+         , LMGlobal (LMGlobalVar lbl i8Ptr link sect align Alias) (Just orig')+         ] aliasify (LMGlobal var val) = do     let LMGlobalVar lbl ty link sect align const = var -        defLbl = lbl `appendFS` fsLit "$def"+        defLbl = llvmDefLabel lbl         defVar = LMGlobalVar defLbl ty Internal sect align const          defPtrVar = LMGlobalVar defLbl (LMPointer ty) link Nothing Nothing const
compiler/llvmGen/LlvmCodeGen/Data.hs view
@@ -32,12 +32,41 @@ structStr :: LMString structStr = fsLit "_struct" +-- | The LLVM visibility of the label+linkage :: CLabel -> LlvmLinkageType+linkage lbl = if externallyVisibleCLabel lbl+              then ExternallyVisible else Internal+ -- ---------------------------------------------------------------------------- -- * Top level --  -- | Pass a CmmStatic section to an equivalent Llvm code. genLlvmData :: (Section, CmmStatics) -> LlvmM LlvmData+-- See note [emit-time elimination of static indirections] in CLabel.+genLlvmData (_, Statics alias [CmmStaticLit (CmmLabel lbl), CmmStaticLit ind, _, _])+  | lbl == mkIndStaticInfoLabel+  , let labelInd (CmmLabelOff l _) = Just l+        labelInd (CmmLabel l) = Just l+        labelInd _ = Nothing+  , Just ind' <- labelInd ind+  , alias `mayRedirectTo` ind' = do+    label <- strCLabel_llvm alias+    label' <- strCLabel_llvm ind'+    let link     = linkage alias+        link'    = linkage ind'+        -- the LLVM type we give the alias is an empty struct type+        -- but it doesn't really matter, as the pointer is only+        -- used for (bit/int)casting.+        tyAlias  = LMAlias (label `appendFS` structStr, LMStructU [])++        aliasDef = LMGlobalVar label tyAlias link Nothing Nothing Alias+        -- we don't know the type of the indirectee here+        indType  = panic "will be filled by 'aliasify', later"+        orig     = LMStaticPointer $ LMGlobalVar label' indType link' Nothing Nothing Alias++    pure ([LMGlobal aliasDef $ Just orig], [tyAlias])+ genLlvmData (sec, Statics lbl xs) = do     label <- strCLabel_llvm lbl     static <- mapM genData xs@@ -45,11 +74,10 @@     let types   = map getStatType static          strucTy = LMStruct types-        tyAlias = LMAlias ((label `appendFS` structStr), strucTy)+        tyAlias = LMAlias (label `appendFS` structStr, strucTy)          struct         = Just $ LMStaticStruc static tyAlias-        link           = if (externallyVisibleCLabel lbl)-                            then ExternallyVisible else Internal+        link           = linkage lbl         align          = case sec of                             Section CString _ -> Just 1                             _                 -> Nothing
compiler/llvmGen/LlvmCodeGen/Ppr.hs view
@@ -71,7 +71,7 @@        let fun = LlvmFunction funDec funArgs llvmStdFunAttrs funSect                               prefix lmblocks            name = decName $ funcDecl fun-           defName = name `appendFS` fsLit "$def"+           defName = llvmDefLabel name            funcDecl' = (funcDecl fun) { decName = defName }            fun' = fun { funcDecl = funcDecl' }            funTy = LMFunction funcDecl'
compiler/main/DriverPipeline.hs view
@@ -1218,17 +1218,8 @@          ghcVersionH <- liftIO $ getGhcVersionPathName dflags -        let gcc_lang_opt | cc_phase `eqPhase` Ccxx    = "c++"-                         | cc_phase `eqPhase` Cobjc   = "objective-c"-                         | cc_phase `eqPhase` Cobjcxx = "objective-c++"-                         | otherwise                  = "c"-        liftIO $ SysTools.runCc dflags (-                -- force the C compiler to interpret this file as C when-                -- compiling .hc files, by adding the -x c option.-                -- Also useful for plain .c files, just in case GHC saw a-                -- -x c option.-                        [ SysTools.Option "-x", SysTools.Option gcc_lang_opt-                        , SysTools.FileOption "" input_fn+        liftIO $ SysTools.runCc (phaseForeignLanguage cc_phase) dflags (+                        [ SysTools.FileOption "" input_fn                         , SysTools.Option "-o"                         , SysTools.FileOption "" output_fn                         ]@@ -1917,7 +1908,7 @@     let verbFlags = getVerbFlags dflags      let cpp_prog args | raw       = SysTools.runCpp dflags args-                      | otherwise = SysTools.runCc dflags (SysTools.Option "-E" : args)+                      | otherwise = SysTools.runCc Nothing dflags (SysTools.Option "-E" : args)      let target_defs =           [ "-D" ++ HOST_OS     ++ "_BUILD_OS",
compiler/main/Finder.hs view
@@ -313,8 +313,10 @@       , ("lhsig",  mkHomeModLocationSearched dflags mod_name "lhsig")       ] -     hi_exts = [ (hisuf,                mkHiOnlyModLocation dflags hisuf)-               , (addBootSuffix hisuf,  mkHiOnlyModLocation dflags hisuf)+     -- we use mkHomeModHiOnlyLocation instead of mkHiOnlyModLocation so that+     -- when hiDir field is set in dflags, we know to look there (see #16500)+     hi_exts = [ (hisuf,                mkHomeModHiOnlyLocation dflags mod_name)+               , (addBootSuffix hisuf,  mkHomeModHiOnlyLocation dflags mod_name)                ]          -- In compilation manager modes, we look for source files in the home@@ -488,6 +490,15 @@                         ml_hi_file   = hi_fn,                         ml_obj_file  = obj_fn,                         ml_hie_file  = hie_fn })++mkHomeModHiOnlyLocation :: DynFlags+                        -> ModuleName+                        -> FilePath+                        -> BaseName+                        -> IO ModLocation+mkHomeModHiOnlyLocation dflags mod path basename = do+   loc <- mkHomeModLocation2 dflags mod (path </> basename) ""+   return loc { ml_hs_file = Nothing }  mkHiOnlyModLocation :: DynFlags -> Suffix -> FilePath -> String                     -> IO ModLocation
compiler/main/HscMain.hs view
@@ -1470,6 +1470,8 @@     let dflags = hsc_dflags hsc_env      let stg_binds_w_fvs = annTopBindingsFreeVars stg_binds+    dumpIfSet_dyn dflags Opt_D_dump_stg_final+                  "STG for code gen:" (pprGenStgTopBindings stg_binds_w_fvs)     let cmm_stream :: Stream IO CmmGroup ()         cmm_stream = {-# SCC "StgCmm" #-}             StgCmm.codeGen dflags this_mod data_tycons
compiler/main/SysTools.hs view
@@ -199,15 +199,9 @@        let unreg_gcc_args = if targetUnregisterised                             then ["-DNO_REGS", "-DUSE_MINIINTERPRETER"]                             else []-           -- TABLES_NEXT_TO_CODE affects the info table layout.-           tntc_gcc_args-            | mkTablesNextToCode targetUnregisterised-               = ["-DTABLES_NEXT_TO_CODE"]-            | otherwise = []            cpp_args= map Option (words cpp_args_str)            gcc_args = map Option (words gcc_args_str-                               ++ unreg_gcc_args-                               ++ tntc_gcc_args)+                               ++ unreg_gcc_args)        ldSupportsCompactUnwind <- getBooleanSetting "ld supports compact unwind"        ldSupportsBuildId       <- getBooleanSetting "ld supports build-id"        ldSupportsFilelist      <- getBooleanSetting "ld supports filelist"@@ -301,6 +295,7 @@                     sOpt_P_fingerprint = fingerprint0,                     sOpt_F       = [],                     sOpt_c       = [],+                    sOpt_cxx     = [],                     sOpt_a       = [],                     sOpt_l       = [],                     sOpt_windres = [],
compiler/main/SysTools/ExtraObj.hs view
@@ -40,7 +40,7 @@       oFile <- newTempName dflags TFL_GhcSession "o"       writeFile cFile xs       ccInfo <- liftIO $ getCompilerInfo dflags-      runCc dflags+      runCc Nothing dflags             ([Option        "-c",               FileOption "" cFile,               Option        "-o",
compiler/main/SysTools/Tasks.hs view
@@ -10,6 +10,7 @@  import Exception import ErrUtils+import HscTypes import DynFlags import Outputable import Platform@@ -58,11 +59,12 @@       opts = map Option (getOpts dflags opt_F)   runSomething dflags "Haskell pre-processor" prog (args ++ opts) -runCc :: DynFlags -> [Option] -> IO ()-runCc dflags args =   do+-- | Run compiler of C-like languages and raw objects (such as gcc or clang).+runCc :: Maybe ForeignSrcLang -> DynFlags -> [Option] -> IO ()+runCc mLanguage dflags args =   do   let (p,args0) = pgm_c dflags-      args1 = map Option (getOpts dflags opt_c)-      args2 = args0 ++ args ++ args1+      args1 = map Option userOpts+      args2 = args0 ++ languageOptions ++ args ++ args1       -- We take care to pass -optc flags in args1 last to ensure that the       -- user can override flags passed by GHC. See #14452.   mb_env <- getGccEnv args2@@ -117,6 +119,21 @@   wantedWarning w    | "warning: call-clobbered register used" `isContainedIn` w = False    | otherwise = True++  -- force the C compiler to interpret this file as C when+  -- compiling .hc files, by adding the -x c option.+  -- Also useful for plain .c files, just in case GHC saw a+  -- -x c option.+  (languageOptions, userOpts) = case mLanguage of+    Nothing -> ([], userOpts_c)+    Just language -> ([Option "-x", Option languageName], opts) where+      (languageName, opts) = case language of+        LangCxx    -> ("c++",           userOpts_cxx)+        LangObjc   -> ("objective-c",   userOpts_c)+        LangObjcxx -> ("objective-c++", userOpts_cxx)+        _          -> ("c",             userOpts_c)+  userOpts_c   = getOpts dflags opt_c+  userOpts_cxx = getOpts dflags opt_cxx  isContainedIn :: String -> String -> Bool xs `isContainedIn` ys = any (xs `isPrefixOf`) (tails ys)
compiler/nativeGen/AsmCodeGen.hs view
@@ -179,7 +179,7 @@ x86NcgImpl :: DynFlags -> NcgImpl (Alignment, CmmStatics)                                   X86.Instr.Instr X86.Instr.JumpDest x86NcgImpl dflags- = (x86_64NcgImpl dflags) { ncg_x86fp_kludge = map x86fp_kludge }+ = (x86_64NcgImpl dflags)  x86_64NcgImpl :: DynFlags -> NcgImpl (Alignment, CmmStatics)                                   X86.Instr.Instr X86.Instr.JumpDest@@ -194,7 +194,6 @@        ,pprNatCmmDecl             = X86.Ppr.pprNatCmmDecl        ,maxSpillSlots             = X86.Instr.maxSpillSlots dflags        ,allocatableRegs           = X86.Regs.allocatableRegs platform-       ,ncg_x86fp_kludge          = id        ,ncgAllocMoreStack         = X86.Instr.allocMoreStack platform        ,ncgExpandTop              = id        ,ncgMakeFarBranches        = const id@@ -215,7 +214,6 @@        ,pprNatCmmDecl             = PPC.Ppr.pprNatCmmDecl        ,maxSpillSlots             = PPC.Instr.maxSpillSlots dflags        ,allocatableRegs           = PPC.Regs.allocatableRegs platform-       ,ncg_x86fp_kludge          = id        ,ncgAllocMoreStack         = PPC.Instr.allocMoreStack platform        ,ncgExpandTop              = id        ,ncgMakeFarBranches        = PPC.Instr.makeFarBranches@@ -236,7 +234,6 @@        ,pprNatCmmDecl             = SPARC.Ppr.pprNatCmmDecl        ,maxSpillSlots             = SPARC.Instr.maxSpillSlots dflags        ,allocatableRegs           = SPARC.Regs.allocatableRegs-       ,ncg_x86fp_kludge          = id        ,ncgAllocMoreStack         = noAllocMoreStack        ,ncgExpandTop              = map SPARC.CodeGen.Expand.expandTop        ,ncgMakeFarBranches        = const id@@ -680,19 +677,10 @@                 foldl' (\m (from,to) -> addImmediateSuccessor from to m )                        cfgWithFixupBlks stack_updt_blks -        ---- x86fp_kludge.  This pass inserts ffree instructions to clear-        ---- the FPU stack on x86.  The x86 ABI requires that the FPU stack-        ---- is clear, and library functions can return odd results if it-        ---- isn't.-        -----        ---- NB. must happen before shortcutBranches, because that-        ---- generates JXX_GBLs which we can't fix up in x86fp_kludge.-        let kludged = {-# SCC "x86fp_kludge" #-} ncg_x86fp_kludge ncgImpl alloced-         ---- generate jump tables         let tabled      =                 {-# SCC "generateJumpTables" #-}-                generateJumpTables ncgImpl kludged+                generateJumpTables ncgImpl alloced          dumpIfSet_dyn dflags                 Opt_D_dump_cfg_weights "CFG Update information"@@ -786,12 +774,6 @@         getBlockIds (CmmData _ _) = setEmpty         getBlockIds (CmmProc _ _ _ (ListGraph blocks)) =                 setFromList $ map blockId blocks---x86fp_kludge :: NatCmmDecl (Alignment, CmmStatics) X86.Instr.Instr -> NatCmmDecl (Alignment, CmmStatics) X86.Instr.Instr-x86fp_kludge top@(CmmData _ _) = top-x86fp_kludge (CmmProc info lbl live (ListGraph code)) =-        CmmProc info lbl live (ListGraph $ X86.Instr.i386_insert_ffrees code)  -- | Compute unwinding tables for the blocks of a procedure computeUnwinding :: Instruction instr
compiler/nativeGen/Format.hs view
@@ -47,7 +47,6 @@         | II64         | FF32         | FF64-        | FF80         deriving (Show, Eq)  @@ -70,7 +69,7 @@  = case width of         W32     -> FF32         W64     -> FF64-        W80     -> FF80+         other   -> pprPanic "Format.floatFormat" (ppr other)  @@ -80,7 +79,6 @@  = case format of         FF32    -> True         FF64    -> True-        FF80    -> True         _       -> False  @@ -101,7 +99,7 @@         II64            -> W64         FF32            -> W32         FF64            -> W64-        FF80            -> W80+  formatInBytes :: Format -> Int formatInBytes = widthInBytes . formatToWidth
compiler/nativeGen/NCGMonad.hs view
@@ -76,7 +76,6 @@     pprNatCmmDecl             :: NatCmmDecl statics instr -> SDoc,     maxSpillSlots             :: Int,     allocatableRegs           :: [RealReg],-    ncg_x86fp_kludge          :: [NatCmmDecl statics instr] -> [NatCmmDecl statics instr],     ncgExpandTop              :: [NatCmmDecl statics instr] -> [NatCmmDecl statics instr],     ncgAllocMoreStack         :: Int -> NatCmmDecl statics instr                               -> UniqSM (NatCmmDecl statics instr, [(BlockId,BlockId)]),
compiler/nativeGen/PPC/CodeGen.hs view
@@ -1593,7 +1593,7 @@     -> [CmmActual]        -- arguments (of mixed type)     -> NatM InstrBlock -{- +{-     PowerPC Linux uses the System V Release 4 Calling Convention     for PowerPC. It is described in the     "System V Application Binary Interface PowerPC Processor Supplement".@@ -1906,7 +1906,7 @@                           FF32 -> (1, 1, 4, fprs)                           FF64 -> (2, 1, 8, fprs)                           II64 -> panic "genCCall' passArguments II64"-                          FF80 -> panic "genCCall' passArguments FF80"+                       GCP32ELF ->                           case cmmTypeFormat rep of                           II8  -> (1, 0, 4, gprs)@@ -1916,7 +1916,6 @@                           FF32 -> (0, 1, 4, fprs)                           FF64 -> (0, 1, 8, fprs)                           II64 -> panic "genCCall' passArguments II64"-                          FF80 -> panic "genCCall' passArguments FF80"                       GCP64ELF _ ->                           case cmmTypeFormat rep of                           II8  -> (1, 0, 8, gprs)@@ -1928,7 +1927,6 @@                           -- the FPRs.                           FF32 -> (1, 1, 8, fprs)                           FF64 -> (1, 1, 8, fprs)-                          FF80 -> panic "genCCall' passArguments FF80"          moveResult reduceToFF32 =             case dest_regs of
compiler/nativeGen/PPC/Ppr.hs view
@@ -27,6 +27,7 @@  import BlockId import CLabel+import PprCmmExpr ()  import Unique                ( pprUniqueAlways, getUnique ) import Platform@@ -119,6 +120,16 @@   pprDatas :: CmmStatics -> SDoc+-- See note [emit-time elimination of static indirections] in CLabel.+pprDatas (Statics alias [CmmStaticLit (CmmLabel lbl), CmmStaticLit ind, _, _])+  | lbl == mkIndStaticInfoLabel+  , let labelInd (CmmLabelOff l _) = Just l+        labelInd (CmmLabel l) = Just l+        labelInd _ = Nothing+  , Just ind' <- labelInd ind+  , alias `mayRedirectTo` ind'+  = pprGloblDecl alias+    $$ text ".equiv" <+> ppr alias <> comma <> ppr (CmmLabel ind') pprDatas (Statics lbl dats) = vcat (pprLabel lbl : map pprData dats)  pprData :: CmmStatic -> SDoc@@ -161,7 +172,7 @@       RegVirtual (VirtualRegHi u)  -> text "%vHi_"  <> pprUniqueAlways u       RegVirtual (VirtualRegF  u)  -> text "%vF_"   <> pprUniqueAlways u       RegVirtual (VirtualRegD  u)  -> text "%vD_"   <> pprUniqueAlways u-      RegVirtual (VirtualRegSSE u) -> text "%vSSE_" <> pprUniqueAlways u+   where     ppr_reg_no :: Int -> SDoc     ppr_reg_no i@@ -179,8 +190,7 @@                 II32 -> sLit "w"                 II64 -> sLit "d"                 FF32 -> sLit "fs"-                FF64 -> sLit "fd"-                _    -> panic "PPC.Ppr.pprFormat: no match")+                FF64 -> sLit "fd")   pprCond :: Cond -> SDoc@@ -365,7 +375,6 @@             II64 -> sLit "d"             FF32 -> sLit "fs"             FF64 -> sLit "fd"-            _         -> panic "PPC.Ppr.pprInstr: no match"             ),         case addr of AddrRegImm _ _ -> empty                      AddrRegReg _ _ -> char 'x',@@ -405,7 +414,6 @@             II64 -> sLit "d"             FF32 -> sLit "fs"             FF64 -> sLit "fd"-            _         -> panic "PPC.Ppr.pprInstr: no match"             ),         case addr of AddrRegImm _ _ -> empty                      AddrRegReg _ _ -> char 'x',
compiler/nativeGen/PPC/Regs.hs view
@@ -131,7 +131,7 @@         RcInteger       -> text "blue"         RcFloat         -> text "red"         RcDouble        -> text "green"-        RcDoubleSSE     -> text "yellow"+   -- immediates ------------------------------------------------------------------
compiler/nativeGen/Reg.hs view
@@ -56,7 +56,7 @@         | VirtualRegHi {-# UNPACK #-} !Unique  -- High part of 2-word register         | VirtualRegF  {-# UNPACK #-} !Unique         | VirtualRegD  {-# UNPACK #-} !Unique-        | VirtualRegSSE {-# UNPACK #-} !Unique+         deriving (Eq, Show)  -- This is laborious, but necessary. We can't derive Ord because@@ -69,17 +69,16 @@   compare (VirtualRegHi a) (VirtualRegHi b) = nonDetCmpUnique a b   compare (VirtualRegF a) (VirtualRegF b) = nonDetCmpUnique a b   compare (VirtualRegD a) (VirtualRegD b) = nonDetCmpUnique a b-  compare (VirtualRegSSE a) (VirtualRegSSE b) = nonDetCmpUnique a b+   compare VirtualRegI{} _ = LT   compare _ VirtualRegI{} = GT   compare VirtualRegHi{} _ = LT   compare _ VirtualRegHi{} = GT   compare VirtualRegF{} _ = LT   compare _ VirtualRegF{} = GT-  compare VirtualRegD{} _ = LT-  compare _ VirtualRegD{} = GT  + instance Uniquable VirtualReg where         getUnique reg          = case reg of@@ -87,18 +86,20 @@                 VirtualRegHi u  -> u                 VirtualRegF u   -> u                 VirtualRegD u   -> u-                VirtualRegSSE u -> u  instance Outputable VirtualReg where         ppr reg          = case reg of                 VirtualRegI  u  -> text "%vI_"   <> pprUniqueAlways u                 VirtualRegHi u  -> text "%vHi_"  <> pprUniqueAlways u-                VirtualRegF  u  -> text "%vF_"   <> pprUniqueAlways u-                VirtualRegD  u  -> text "%vD_"   <> pprUniqueAlways u-                VirtualRegSSE u -> text "%vSSE_" <> pprUniqueAlways u+                -- this code is kinda wrong on x86+                -- because float and double occupy the same register set+                -- namely SSE2 register xmm0 .. xmm15+                VirtualRegF  u  -> text "%vFloat_"   <> pprUniqueAlways u+                VirtualRegD  u  -> text "%vDouble_"   <> pprUniqueAlways u  + renameVirtualReg :: Unique -> VirtualReg -> VirtualReg renameVirtualReg u r  = case r of@@ -106,7 +107,6 @@         VirtualRegHi _  -> VirtualRegHi u         VirtualRegF _   -> VirtualRegF  u         VirtualRegD _   -> VirtualRegD  u-        VirtualRegSSE _ -> VirtualRegSSE u   classOfVirtualReg :: VirtualReg -> RegClass@@ -116,7 +116,7 @@         VirtualRegHi{}  -> RcInteger         VirtualRegF{}   -> RcFloat         VirtualRegD{}   -> RcDouble-        VirtualRegSSE{} -> RcDoubleSSE+   -- Determine the upper-half vreg for a 64-bit quantity on a 32-bit platform
compiler/nativeGen/RegAlloc/Graph/TrivColorable.hs view
@@ -134,6 +134,10 @@ trivColorable platform virtualRegSqueeze realRegSqueeze RcFloat conflicts exclusions         | let cALLOCATABLE_REGS_FLOAT                   =        (case platformArch platform of+                    -- On x86_64 and x86, Float and RcDouble+                    -- use the same registers,+                    -- so we only use RcDouble to represent the+                    -- register allocation problem on those types.                             ArchX86       -> 0                             ArchX86_64    -> 0                             ArchPPC       -> 0@@ -160,8 +164,14 @@ trivColorable platform virtualRegSqueeze realRegSqueeze RcDouble conflicts exclusions         | let cALLOCATABLE_REGS_DOUBLE                   =        (case platformArch platform of-                            ArchX86       -> 6-                            ArchX86_64    -> 0+                            ArchX86       -> 8+                            -- in x86 32bit mode sse2 there are only+                            -- 8 XMM registers xmm0 ... xmm7+                            ArchX86_64    -> 10+                            -- in x86_64 there are 16 XMM registers+                            -- xmm0 .. xmm15, here 10 is a+                            -- "dont need to solve conflicts" count that+                            -- was chosen at some point in the past.                             ArchPPC       -> 26                             ArchSPARC     -> 11                             ArchSPARC64   -> panic "trivColorable ArchSPARC64"@@ -183,31 +193,7 @@          = count3 < cALLOCATABLE_REGS_DOUBLE -trivColorable platform virtualRegSqueeze realRegSqueeze RcDoubleSSE conflicts exclusions-        | let cALLOCATABLE_REGS_SSE-                  =        (case platformArch platform of-                            ArchX86       -> 8-                            ArchX86_64    -> 10-                            ArchPPC       -> 0-                            ArchSPARC     -> 0-                            ArchSPARC64   -> panic "trivColorable ArchSPARC64"-                            ArchPPC_64 _  -> 0-                            ArchARM _ _ _ -> panic "trivColorable ArchARM"-                            ArchARM64     -> panic "trivColorable ArchARM64"-                            ArchAlpha     -> panic "trivColorable ArchAlpha"-                            ArchMipseb    -> panic "trivColorable ArchMipseb"-                            ArchMipsel    -> panic "trivColorable ArchMipsel"-                            ArchJavaScript-> panic "trivColorable ArchJavaScript"-                            ArchUnknown   -> panic "trivColorable ArchUnknown")-        , count2        <- accSqueeze 0 cALLOCATABLE_REGS_SSE-                                (virtualRegSqueeze RcDoubleSSE)-                                conflicts -        , count3        <- accSqueeze  count2    cALLOCATABLE_REGS_SSE-                                (realRegSqueeze   RcDoubleSSE)-                                exclusions--        = count3 < cALLOCATABLE_REGS_SSE   -- Specification Code ----------------------------------------------------------
compiler/nativeGen/RegClass.hs view
@@ -18,7 +18,6 @@         = RcInteger         | RcFloat         | RcDouble-        | RcDoubleSSE -- x86 only: the SSE regs are a separate class         deriving Eq  @@ -26,10 +25,8 @@     getUnique RcInteger = mkRegClassUnique 0     getUnique RcFloat   = mkRegClassUnique 1     getUnique RcDouble  = mkRegClassUnique 2-    getUnique RcDoubleSSE = mkRegClassUnique 3  instance Outputable RegClass where     ppr RcInteger       = Outputable.text "I"     ppr RcFloat         = Outputable.text "F"     ppr RcDouble        = Outputable.text "D"-    ppr RcDoubleSSE     = Outputable.text "S"
compiler/nativeGen/SPARC/Instr.hs view
@@ -384,7 +384,6 @@                         RcInteger -> II32                         RcFloat   -> FF32                         RcDouble  -> FF64-                        _         -> panic "sparc_mkSpillInstr"      in ST fmt reg (fpRel (negate off_w)) @@ -405,7 +404,6 @@                         RcInteger -> II32                         RcFloat   -> FF32                         RcDouble  -> FF64-                        _         -> panic "sparc_mkLoadInstr"          in LD fmt (fpRel (- off_w)) reg @@ -454,7 +452,6 @@                 RcInteger -> ADD  False False src (RIReg g0) dst                 RcDouble  -> FMOV FF64 src dst                 RcFloat   -> FMOV FF32 src dst-                _         -> panic "sparc_mkRegRegMoveInstr"          | otherwise         = panic "SPARC.Instr.mkRegRegMoveInstr: classes of src and dest not the same"
compiler/nativeGen/SPARC/Ppr.hs view
@@ -102,6 +102,16 @@   pprDatas :: CmmStatics -> SDoc+-- See note [emit-time elimination of static indirections] in CLabel.+pprDatas (Statics alias [CmmStaticLit (CmmLabel lbl), CmmStaticLit ind, _, _])+  | lbl == mkIndStaticInfoLabel+  , let labelInd (CmmLabelOff l _) = Just l+        labelInd (CmmLabel l) = Just l+        labelInd _ = Nothing+  , Just ind' <- labelInd ind+  , alias `mayRedirectTo` ind'+  = pprGloblDecl alias+    $$ text ".equiv" <+> ppr alias <> comma <> ppr (CmmLabel ind') pprDatas (Statics lbl dats) = vcat (pprLabel lbl : map pprData dats)  pprData :: CmmStatic -> SDoc@@ -143,8 +153,8 @@                 VirtualRegHi  u -> text "%vHi_"  <> pprUniqueAlways u                 VirtualRegF   u -> text "%vF_"   <> pprUniqueAlways u                 VirtualRegD   u -> text "%vD_"   <> pprUniqueAlways u-                VirtualRegSSE u -> text "%vSSE_" <> pprUniqueAlways u +         RegReal rr          -> case rr of                 RealRegSingle r1@@ -211,8 +221,7 @@         II32    -> sLit ""         II64    -> sLit "d"         FF32    -> sLit ""-        FF64    -> sLit "d"-        _       -> panic "SPARC.Ppr.pprFormat: no match")+        FF64    -> sLit "d")   -- | Pretty print a format for an instruction suffix.@@ -226,10 +235,10 @@         II32  -> sLit ""         II64  -> sLit "x"         FF32  -> sLit ""-        FF64  -> sLit "d"-        _       -> panic "SPARC.Ppr.pprFormat: no match")+        FF64  -> sLit "d")  + -- | Pretty print a condition code. pprCond :: Cond -> SDoc pprCond c@@ -635,4 +644,3 @@  pp_comma_a :: SDoc pp_comma_a        = text ",a"-
compiler/nativeGen/SPARC/Regs.hs view
@@ -104,7 +104,6 @@                 VirtualRegD{}           -> 1                 _other                  -> 0 -        _other -> 0  {-# INLINE realRegSqueeze #-} realRegSqueeze :: RegClass -> RealReg -> Int@@ -135,7 +134,6 @@                  RealRegPair{}           -> 1 -        _other -> 0  -- | All the allocatable registers in the machine, --      including register pairs.
compiler/nativeGen/X86/CodeGen.hs view
@@ -98,17 +98,25 @@ sse2Enabled :: NatM Bool sse2Enabled = do   dflags <- getDynFlags-  return (isSse2Enabled dflags)+  case platformArch (targetPlatform dflags) of+  -- We Assume  SSE1 and SSE2 operations are available on both+  -- x86 and x86_64. Historically we didn't default to SSE2 and+  -- SSE1 on x86, which results in defacto nondeterminism for how+  -- rounding behaves in the associated x87 floating point instructions+  -- because variations in the spill/fpu stack placement of arguments for+  -- operations would change the precision and final result of what+  -- would otherwise be the same expressions with respect to single or+  -- double precision IEEE floating point computations.+    ArchX86_64 -> return True+    ArchX86    -> return True+    _          -> panic "trying to generate x86/x86_64 on the wrong platform" + sse4_2Enabled :: NatM Bool sse4_2Enabled = do   dflags <- getDynFlags   return (isSse4_2Enabled dflags) -if_sse2 :: NatM a -> NatM a -> NatM a-if_sse2 sse2 x87 = do-  b <- sse2Enabled-  if b then sse2 else x87  cmmTopCodeGen         :: RawCmmDecl@@ -128,7 +136,7 @@       Nothing -> return tops  cmmTopCodeGen (CmmData sec dat) = do-  return [CmmData sec (1, dat)]  -- no translation, we just use CmmStatic+  return [CmmData sec (mkAlignment 1, dat)]  -- no translation, we just use CmmStatic   basicBlockCodeGen@@ -284,15 +292,14 @@   -- | Grab the Reg for a CmmReg-getRegisterReg :: Platform -> Bool -> CmmReg -> Reg+getRegisterReg :: Platform  -> CmmReg -> Reg -getRegisterReg _ use_sse2 (CmmLocal (LocalReg u pk))-  = let fmt = cmmTypeFormat pk in-    if isFloatFormat fmt && not use_sse2-       then RegVirtual (mkVirtualReg u FF80)-       else RegVirtual (mkVirtualReg u fmt)+getRegisterReg _   (CmmLocal (LocalReg u pk))+  = -- by Assuming SSE2, Int,Word,Float,Double all can be register allocated+   let fmt = cmmTypeFormat pk in+        RegVirtual (mkVirtualReg u fmt) -getRegisterReg platform _ (CmmGlobal mid)+getRegisterReg platform  (CmmGlobal mid)   = case globalRegMaybe platform mid of         Just reg -> RegReal $ reg         Nothing  -> pprPanic "getRegisterReg-memory" (ppr $ CmmGlobal mid)@@ -513,15 +520,14 @@             do reg' <- getPicBaseNat (archWordFormat is32Bit)                return (Fixed (archWordFormat is32Bit) reg' nilOL)         _ ->-            do use_sse2 <- sse2Enabled+            do                let                  fmt = cmmTypeFormat (cmmRegType dflags reg)-                 format | not use_sse2 && isFloatFormat fmt = FF80-                        | otherwise                         = fmt+                 format  = fmt                --                let platform = targetPlatform dflags                return (Fixed format-                             (getRegisterReg platform use_sse2 reg)+                             (getRegisterReg platform  reg)                              nilOL)  @@ -557,8 +563,7 @@   return $ Fixed II32 rlo code  getRegister' _ _ (CmmLit lit@(CmmFloat f w)) =-  if_sse2 float_const_sse2 float_const_x87- where+  float_const_sse2  where   float_const_sse2     | f == 0.0 = do       let@@ -569,22 +574,8 @@       return (Any format code)     | otherwise = do-      Amode addr code <- memConstant (widthInBytes w) lit-      loadFloatAmode True w addr code--  float_const_x87 = case w of-    W64-      | f == 0.0 ->-        let code dst = unitOL (GLDZ dst)-        in  return (Any FF80 code)--      | f == 1.0 ->-        let code dst = unitOL (GLD1 dst)-        in  return (Any FF80 code)--    _otherwise -> do-      Amode addr code <- memConstant (widthInBytes w) lit-      loadFloatAmode False w addr code+      Amode addr code <- memConstant (mkAlignment $ widthInBytes w) lit+      loadFloatAmode w addr code  -- catch simple cases of zero- or sign-extended load getRegister' _ _ (CmmMachOp (MO_UU_Conv W8 W32) [CmmLoad addr _]) = do@@ -641,12 +632,10 @@         LEA II64 (OpAddr (ripRel (litToImm displacement))) (OpReg dst))  getRegister' dflags is32Bit (CmmMachOp mop [x]) = do -- unary MachOps-    sse2 <- sse2Enabled     case mop of-      MO_F_Neg w-         | sse2      -> sse2NegCode w x-         | otherwise -> trivialUFCode FF80 (GNEG FF80) x+      MO_F_Neg w  -> sse2NegCode w x +       MO_S_Neg w -> triv_ucode NEGI (intFormat w)       MO_Not w   -> triv_ucode NOT  (intFormat w) @@ -711,10 +700,9 @@       MO_XX_Conv W16 W64 | not is32Bit -> integerExtend W16 W64 MOV x       MO_XX_Conv W32 W64 | not is32Bit -> integerExtend W32 W64 MOV x -      MO_FF_Conv W32 W64-        | sse2      -> coerceFP2FP W64 x-        | otherwise -> conversionNop FF80 x+      MO_FF_Conv W32 W64 -> coerceFP2FP W64 x +       MO_FF_Conv W64 W32 -> coerceFP2FP W32 x        MO_FS_Conv from to -> coerceFP2Int from to x@@ -776,7 +764,6 @@   getRegister' _ is32Bit (CmmMachOp mop [x, y]) = do -- dyadic MachOps-  sse2 <- sse2Enabled   case mop of       MO_F_Eq _ -> condFltReg is32Bit EQQ x y       MO_F_Ne _ -> condFltReg is32Bit NE  x y@@ -800,15 +787,15 @@       MO_U_Lt _ -> condIntReg LU  x y       MO_U_Le _ -> condIntReg LEU x y -      MO_F_Add w  | sse2      -> trivialFCode_sse2 w ADD  x y-                  | otherwise -> trivialFCode_x87    GADD x y-      MO_F_Sub w  | sse2      -> trivialFCode_sse2 w SUB  x y-                  | otherwise -> trivialFCode_x87    GSUB x y-      MO_F_Quot w | sse2      -> trivialFCode_sse2 w FDIV x y-                  | otherwise -> trivialFCode_x87    GDIV x y-      MO_F_Mul w  | sse2      -> trivialFCode_sse2 w MUL x y-                  | otherwise -> trivialFCode_x87    GMUL x y+      MO_F_Add w   -> trivialFCode_sse2 w ADD  x y +      MO_F_Sub w   -> trivialFCode_sse2 w SUB  x y++      MO_F_Quot w  -> trivialFCode_sse2 w FDIV x y++      MO_F_Mul w   -> trivialFCode_sse2 w MUL x y++       MO_Add rep -> add_code rep x y       MO_Sub rep -> sub_code rep x y @@ -1001,8 +988,7 @@   | isFloatType pk   = do     Amode addr mem_code <- getAmode mem-    use_sse2 <- sse2Enabled-    loadFloatAmode use_sse2 (typeWidth pk) addr mem_code+    loadFloatAmode  (typeWidth pk) addr mem_code  getRegister' _ is32Bit (CmmLoad mem pk)   | is32Bit && not (isWord64 pk)@@ -1132,9 +1118,7 @@                 return (reg, code)  reg2reg :: Format -> Reg -> Reg -> Instr-reg2reg format src dst-  | format == FF80 = GMOV src dst-  | otherwise    = MOV format (OpReg src) (OpReg dst)+reg2reg format src dst = MOV format (OpReg src) (OpReg dst)   --------------------------------------------------------------------------------@@ -1243,11 +1227,10 @@  getNonClobberedOperand :: CmmExpr -> NatM (Operand, InstrBlock) getNonClobberedOperand (CmmLit lit) = do-  use_sse2 <- sse2Enabled-  if use_sse2 && isSuitableFloatingPointLit lit+  if  isSuitableFloatingPointLit lit     then do       let CmmFloat _ w = lit-      Amode addr code <- memConstant (widthInBytes w) lit+      Amode addr code <- memConstant (mkAlignment $ widthInBytes w) lit       return (OpAddr addr, code)      else do @@ -1259,9 +1242,12 @@  getNonClobberedOperand (CmmLoad mem pk) = do   is32Bit <- is32BitPlatform-  use_sse2 <- sse2Enabled-  if (not (isFloatType pk) || use_sse2)-      && (if is32Bit then not (isWord64 pk) else True)+  -- this logic could be simplified+  -- TODO FIXME+  if   (if is32Bit then not (isWord64 pk) else True)+      -- if 32bit and pk is at float/double/simd value+      -- or if 64bit+      --  this could use some eyeballs or i'll need to stare at it more later     then do       dflags <- getDynFlags       let platform = targetPlatform dflags@@ -1278,6 +1264,7 @@                    return (src, nilOL)       return (OpAddr src', mem_code `appOL` save_code)     else do+      -- if its a word or gcptr on 32bit?       getNonClobberedOperand_generic (CmmLoad mem pk)  getNonClobberedOperand e = getNonClobberedOperand_generic e@@ -1303,7 +1290,7 @@   if (use_sse2 && isSuitableFloatingPointLit lit)     then do       let CmmFloat _ w = lit-      Amode addr code <- memConstant (widthInBytes w) lit+      Amode addr code <- memConstant (mkAlignment $ widthInBytes w) lit       return (OpAddr addr, code)     else do @@ -1351,7 +1338,7 @@              , JXX_GBL NE $ ImmCLbl mkBadAlignmentLabel              ] -memConstant :: Int -> CmmLit -> NatM Amode+memConstant :: Alignment -> CmmLit -> NatM Amode memConstant align lit = do   lbl <- getNewLabelNat   let rosection = Section ReadOnlyData lbl@@ -1370,16 +1357,15 @@   return (Amode addr code)  -loadFloatAmode :: Bool -> Width -> AddrMode -> InstrBlock -> NatM Register-loadFloatAmode use_sse2 w addr addr_code = do+loadFloatAmode :: Width -> AddrMode -> InstrBlock -> NatM Register+loadFloatAmode w addr addr_code = do   let format = floatFormat w       code dst = addr_code `snocOL`-                 if use_sse2-                    then MOV format (OpAddr addr) (OpReg dst)-                    else GLD format addr dst-  return (Any (if use_sse2 then format else FF80) code)+                    MOV format (OpAddr addr) (OpReg dst) +  return (Any format code) + -- if we want a floating-point literal as an operand, we can -- use it directly from memory.  However, if the literal is -- zero, we're better off generating it into a register using@@ -1538,19 +1524,9 @@ condFltCode :: Cond -> CmmExpr -> CmmExpr -> NatM CondCode  condFltCode cond x y-  = if_sse2 condFltCode_sse2 condFltCode_x87+  =  condFltCode_sse2   where -  condFltCode_x87-    = ASSERT(cond `elem` ([EQQ, NE, LE, LTT, GE, GTT])) do-    (x_reg, x_code) <- getNonClobberedReg x-    (y_reg, y_code) <- getSomeReg y-    let-        code = x_code `appOL` y_code `snocOL`-                GCMP cond x_reg y_reg-    -- The GCMP insn does the test and sets the zero flag if comparable-    -- and true.  Hence we always supply EQQ as the condition to test.-    return (CondCode True EQQ code)    -- in the SSE2 comparison ops (ucomiss, ucomisd) the left arg may be   -- an operand, but the right must be a reg.  We can probably do better@@ -1634,35 +1610,33 @@   load_code <- intLoadCode (MOV pk) src   dflags <- getDynFlags   let platform = targetPlatform dflags-  return (load_code (getRegisterReg platform False{-no sse2-} reg))+  return (load_code (getRegisterReg platform reg))  -- dst is a reg, but src could be anything assignReg_IntCode _ reg src = do   dflags <- getDynFlags   let platform = targetPlatform dflags   code <- getAnyReg src-  return (code (getRegisterReg platform False{-no sse2-} reg))+  return (code (getRegisterReg platform reg))   -- Floating point assignment to memory assignMem_FltCode pk addr src = do   (src_reg, src_code) <- getNonClobberedReg src   Amode addr addr_code <- getAmode addr-  use_sse2 <- sse2Enabled   let         code = src_code `appOL`                addr_code `snocOL`-                if use_sse2 then MOV pk (OpReg src_reg) (OpAddr addr)-                            else GST pk src_reg addr+               MOV pk (OpReg src_reg) (OpAddr addr)+   return code  -- Floating point assignment to a register/temporary assignReg_FltCode _ reg src = do-  use_sse2 <- sse2Enabled   src_code <- getAnyReg src   dflags <- getDynFlags   let platform = targetPlatform dflags-  return (src_code (getRegisterReg platform use_sse2 reg))+  return (src_code (getRegisterReg platform  reg))   genJump :: CmmExpr{-the branch target-} -> [Reg] -> NatM InstrBlock@@ -1793,12 +1767,11 @@  -- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - --- Unroll memcpy calls if the source and destination pointers are at--- least DWORD aligned and the number of bytes to copy isn't too+-- Unroll memcpy calls if the number of bytes to copy isn't too -- large.  Otherwise, call C's memcpy.-genCCall dflags is32Bit (PrimTarget (MO_Memcpy align)) _+genCCall dflags _ (PrimTarget (MO_Memcpy align)) _          [dst, src, CmmLit (CmmInt n _)] _-    | fromInteger insns <= maxInlineMemcpyInsns dflags && align .&. 3 == 0 = do+    | fromInteger insns <= maxInlineMemcpyInsns dflags = do         code_dst <- getAnyReg dst         dst_r <- getNewRegNat format         code_src <- getAnyReg src@@ -1811,7 +1784,9 @@     -- instructions per move.     insns = 2 * ((n + sizeBytes - 1) `div` sizeBytes) -    format = if align .&. 4 /= 0 then II32 else (archWordFormat is32Bit)+    maxAlignment = wordAlignment dflags -- only machine word wide MOVs are supported+    effectiveAlignment = min (alignmentOf align) maxAlignment+    format = intFormat . widthFromBytes $ alignmentBytes effectiveAlignment      -- The size of each move, in bytes.     sizeBytes :: Integer@@ -1848,17 +1823,25 @@           CmmLit (CmmInt c _),           CmmLit (CmmInt n _)]          _-    | fromInteger insns <= maxInlineMemsetInsns dflags && align .&. 3 == 0 = do+    | fromInteger insns <= maxInlineMemsetInsns dflags = do         code_dst <- getAnyReg dst         dst_r <- getNewRegNat format-        return $ code_dst dst_r `appOL` go dst_r (fromInteger n)+        if format == II64 && n >= 8 then do+          code_imm8byte <- getAnyReg (CmmLit (CmmInt c8 W64))+          imm8byte_r <- getNewRegNat II64+          return $ code_dst dst_r `appOL`+                   code_imm8byte imm8byte_r `appOL`+                   go8 dst_r imm8byte_r (fromInteger n)+        else+          return $ code_dst dst_r `appOL`+                   go4 dst_r (fromInteger n)   where-    (format, val) = case align .&. 3 of-        2 -> (II16, c2)-        0 -> (II32, c4)-        _ -> (II8, c)+    maxAlignment = wordAlignment dflags -- only machine word wide MOVs are supported+    effectiveAlignment = min (alignmentOf align) maxAlignment+    format = intFormat . widthFromBytes $ alignmentBytes effectiveAlignment     c2 = c `shiftL` 8 .|. c     c4 = c2 `shiftL` 16 .|. c2+    c8 = c4 `shiftL` 32 .|. c4      -- The number of instructions we will generate (approx). We need 1     -- instructions per move.@@ -1868,26 +1851,46 @@     sizeBytes :: Integer     sizeBytes = fromIntegral (formatInBytes format) -    go :: Reg -> Integer -> OrdList Instr-    go dst i-        -- TODO: Add movabs instruction and support 64-bit sets.-        | i >= sizeBytes =  -- This might be smaller than the below sizes-            unitOL (MOV format (OpImm (ImmInteger val)) (OpAddr dst_addr)) `appOL`-            go dst (i - sizeBytes)-        | i >= 4 =  -- Will never happen on 32-bit-            unitOL (MOV II32 (OpImm (ImmInteger c4)) (OpAddr dst_addr)) `appOL`-            go dst (i - 4)-        | i >= 2 =-            unitOL (MOV II16 (OpImm (ImmInteger c2)) (OpAddr dst_addr)) `appOL`-            go dst (i - 2)-        | i >= 1 =-            unitOL (MOV II8 (OpImm (ImmInteger c)) (OpAddr dst_addr)) `appOL`-            go dst (i - 1)-        | otherwise = nilOL+    -- Depending on size returns the widest MOV instruction and its+    -- width.+    gen4 :: AddrMode -> Integer -> (InstrBlock, Integer)+    gen4 addr size+        | size >= 4 =+            (unitOL (MOV II32 (OpImm (ImmInteger c4)) (OpAddr addr)), 4)+        | size >= 2 =+            (unitOL (MOV II16 (OpImm (ImmInteger c2)) (OpAddr addr)), 2)+        | size >= 1 =+            (unitOL (MOV II8 (OpImm (ImmInteger c)) (OpAddr addr)), 1)+        | otherwise = (nilOL, 0)++    -- Generates a 64-bit wide MOV instruction from REG to MEM.+    gen8 :: AddrMode -> Reg -> InstrBlock+    gen8 addr reg8byte =+      unitOL (MOV format (OpReg reg8byte) (OpAddr addr))++    -- Unrolls memset when the widest MOV is <= 4 bytes.+    go4 :: Reg -> Integer -> InstrBlock+    go4 dst left =+      if left <= 0 then nilOL+      else curMov `appOL` go4 dst (left - curWidth)       where-        dst_addr = AddrBaseIndex (EABaseReg dst) EAIndexNone-                   (ImmInteger (n - i))+        possibleWidth = minimum [left, sizeBytes]+        dst_addr = AddrBaseIndex (EABaseReg dst) EAIndexNone (ImmInteger (n - left))+        (curMov, curWidth) = gen4 dst_addr possibleWidth +    -- Unrolls memset when the widest MOV is 8 bytes (thus another Reg+    -- argument). Falls back to go4 when all 8 byte moves are+    -- exhausted.+    go8 :: Reg -> Reg -> Integer -> InstrBlock+    go8 dst reg8byte left =+      if possibleWidth >= 8 then+        let curMov = gen8 dst_addr reg8byte+        in  curMov `appOL` go8 dst reg8byte (left - 8)+      else go4 dst left+      where+        possibleWidth = minimum [left, sizeBytes]+        dst_addr = AddrBaseIndex (EABaseReg dst) EAIndexNone (ImmInteger (n - left))+ genCCall _ _ (PrimTarget MO_WriteBarrier) _ _ _ = return nilOL         -- write barrier compiles to no code on x86/x86-64;         -- we keep it this long in order to prevent earlier optimisations.@@ -1917,7 +1920,7 @@  genCCall dflags is32Bit (PrimTarget (MO_BSwap width)) [dst] [src] _ = do     let platform = targetPlatform dflags-    let dst_r = getRegisterReg platform False (CmmLocal dst)+    let dst_r = getRegisterReg platform (CmmLocal dst)     case width of         W64 | is32Bit -> do                ChildCode64 vcode rlo <- iselExpr64 src@@ -1944,7 +1947,7 @@     if sse4_2         then do code_src <- getAnyReg src                 src_r <- getNewRegNat format-                let dst_r = getRegisterReg platform False (CmmLocal dst)+                let dst_r = getRegisterReg platform  (CmmLocal dst)                 return $ code_src src_r `appOL`                     (if width == W8 then                          -- The POPCNT instruction doesn't take a r/m8@@ -1976,7 +1979,7 @@                 code_mask <- getAnyReg mask                 src_r     <- getNewRegNat format                 mask_r    <- getNewRegNat format-                let dst_r = getRegisterReg platform False (CmmLocal dst)+                let dst_r = getRegisterReg platform  (CmmLocal dst)                 return $ code_src src_r `appOL` code_mask mask_r `appOL`                     (if width == W8 then                          -- The PDEP instruction doesn't take a r/m8@@ -2009,7 +2012,7 @@                 code_mask <- getAnyReg mask                 src_r     <- getNewRegNat format                 mask_r    <- getNewRegNat format-                let dst_r = getRegisterReg platform False (CmmLocal dst)+                let dst_r = getRegisterReg platform  (CmmLocal dst)                 return $ code_src src_r `appOL` code_mask mask_r `appOL`                     (if width == W8 then                          -- The PEXT instruction doesn't take a r/m8@@ -2045,7 +2048,7 @@    | otherwise = do     code_src <- getAnyReg src-    let dst_r = getRegisterReg platform False (CmmLocal dst)+    let dst_r = getRegisterReg platform (CmmLocal dst)     if isBmi2Enabled dflags         then do             src_r <- getNewRegNat (intFormat width)@@ -2082,7 +2085,7 @@   | is32Bit, width == W64 = do       ChildCode64 vcode rlo <- iselExpr64 src       let rhi     = getHiVRegFromLo rlo-          dst_r   = getRegisterReg platform False (CmmLocal dst)+          dst_r   = getRegisterReg platform  (CmmLocal dst)       lbl1 <- getBlockIdNat       lbl2 <- getBlockIdNat       let format = if width == W8 then II16 else intFormat width@@ -2122,7 +2125,7 @@    | otherwise = do     code_src <- getAnyReg src-    let dst_r = getRegisterReg platform False (CmmLocal dst)+    let dst_r = getRegisterReg platform (CmmLocal dst)      if isBmi2Enabled dflags     then do@@ -2173,9 +2176,8 @@         else getSimpleAmode dflags is32Bit addr  -- See genCCall for MO_Cmpxchg     arg <- getNewRegNat format     arg_code <- getAnyReg n-    use_sse2 <- sse2Enabled     let platform = targetPlatform dflags-        dst_r    = getRegisterReg platform use_sse2 (CmmLocal dst)+        dst_r    = getRegisterReg platform  (CmmLocal dst)     code <- op_code dst_r arg amode     return $ addr_code `appOL` arg_code arg `appOL` code   where@@ -2232,9 +2234,9 @@ genCCall dflags _ (PrimTarget (MO_AtomicRead width)) [dst] [addr] _ = do   load_code <- intLoadCode (MOV (intFormat width)) addr   let platform = targetPlatform dflags-  use_sse2 <- sse2Enabled-  return (load_code (getRegisterReg platform use_sse2 (CmmLocal dst))) +  return (load_code (getRegisterReg platform  (CmmLocal dst)))+ genCCall _ _ (PrimTarget (MO_AtomicWrite width)) [] [addr, val] _ = do     code <- assignMem_IntCode (intFormat width) addr val     return $ code `snocOL` MFENCE@@ -2248,9 +2250,8 @@     newval_code <- getAnyReg new     oldval <- getNewRegNat format     oldval_code <- getAnyReg old-    use_sse2 <- sse2Enabled     let platform = targetPlatform dflags-        dst_r    = getRegisterReg platform use_sse2 (CmmLocal dst)+        dst_r    = getRegisterReg platform  (CmmLocal dst)         code     = toOL                    [ MOV format (OpReg oldval) (OpReg eax)                    , LOCK (CMPXCHG format (OpReg newval) (OpAddr amode))@@ -2264,14 +2265,12 @@ genCCall _ is32Bit target dest_regs args bid = do   dflags <- getDynFlags   let platform = targetPlatform dflags-      sse2     = isSse2Enabled dflags   case (target, dest_regs) of     -- void return type prim op     (PrimTarget op, []) ->         outOfLineCmmOp bid op Nothing args     -- we only cope with a single result for foreign calls-    (PrimTarget op, [r])-      | sse2 -> case op of+    (PrimTarget op, [r])  -> case op of           MO_F32_Fabs -> case args of             [x] -> sse2FabsCode W32 x             _ -> panic "genCCall: Wrong number of arguments for fabs"@@ -2282,36 +2281,16 @@           MO_F32_Sqrt -> actuallyInlineSSE2Op (\fmt r -> SQRT fmt (OpReg r)) FF32 args           MO_F64_Sqrt -> actuallyInlineSSE2Op (\fmt r -> SQRT fmt (OpReg r)) FF64 args           _other_op -> outOfLineCmmOp bid op (Just r) args-      | otherwise -> do-        l1 <- getNewLabelNat-        l2 <- getNewLabelNat-        if sse2-          then outOfLineCmmOp bid op (Just r) args-          else case op of-              MO_F32_Sqrt -> actuallyInlineFloatOp GSQRT FF32 args-              MO_F64_Sqrt -> actuallyInlineFloatOp GSQRT FF64 args -              MO_F32_Sin  -> actuallyInlineFloatOp (\s -> GSIN s l1 l2) FF32 args-              MO_F64_Sin  -> actuallyInlineFloatOp (\s -> GSIN s l1 l2) FF64 args--              MO_F32_Cos  -> actuallyInlineFloatOp (\s -> GCOS s l1 l2) FF32 args-              MO_F64_Cos  -> actuallyInlineFloatOp (\s -> GCOS s l1 l2) FF64 args--              MO_F32_Tan  -> actuallyInlineFloatOp (\s -> GTAN s l1 l2) FF32 args-              MO_F64_Tan  -> actuallyInlineFloatOp (\s -> GTAN s l1 l2) FF64 args--              _other_op   -> outOfLineCmmOp bid op (Just r) args-        where-        actuallyInlineFloatOp = actuallyInlineFloatOp' False-        actuallyInlineSSE2Op = actuallyInlineFloatOp' True+        actuallyInlineSSE2Op = actuallyInlineFloatOp' -        actuallyInlineFloatOp' usesSSE instr format [x]+        actuallyInlineFloatOp'  instr format [x]               = do res <- trivialUFCode format (instr format) x                    any <- anyReg res-                   return (any (getRegisterReg platform usesSSE (CmmLocal r)))+                   return (any (getRegisterReg platform  (CmmLocal r))) -        actuallyInlineFloatOp' _ _ _ args+        actuallyInlineFloatOp' _ _ args               = panic $ "genCCall.actuallyInlineFloatOp': bad number of arguments! ("                       ++ show (length args) ++ ")" @@ -2322,7 +2301,7 @@           let             const | FF32 <- fmt = CmmInt 0x7fffffff W32                   | otherwise   = CmmInt 0x7fffffffffffffff W64-          Amode amode amode_code <- memConstant (widthInBytes w) const+          Amode amode amode_code <- memConstant (mkAlignment $ widthInBytes w) const           tmp <- getNewRegNat fmt           let             code dst = x_code dst `appOL` amode_code `appOL` toOL [@@ -2330,7 +2309,7 @@                 AND fmt (OpReg tmp) (OpReg dst)                 ] -          return $ code (getRegisterReg platform True (CmmLocal r))+          return $ code (getRegisterReg platform (CmmLocal r))      (PrimTarget (MO_S_QuotRem  width), _) -> divOp1 platform True  width dest_regs args     (PrimTarget (MO_U_QuotRem  width), _) -> divOp1 platform False width dest_regs args@@ -2342,8 +2321,8 @@                let format = intFormat width                lCode <- anyReg =<< trivialCode width (ADD_CC format)                                      (Just (ADD_CC format)) arg_x arg_y-               let reg_l = getRegisterReg platform True (CmmLocal res_l)-                   reg_h = getRegisterReg platform True (CmmLocal res_h)+               let reg_l = getRegisterReg platform (CmmLocal res_l)+                   reg_h = getRegisterReg platform (CmmLocal res_h)                    code = hCode reg_h `appOL`                           lCode reg_l `snocOL`                           ADC format (OpImm (ImmInteger 0)) (OpReg reg_h)@@ -2363,8 +2342,8 @@             do (y_reg, y_code) <- getRegOrMem arg_y                x_code <- getAnyReg arg_x                let format = intFormat width-                   reg_h = getRegisterReg platform True (CmmLocal res_h)-                   reg_l = getRegisterReg platform True (CmmLocal res_l)+                   reg_h = getRegisterReg platform (CmmLocal res_h)+                   reg_l = getRegisterReg platform (CmmLocal res_l)                    code = y_code `appOL`                           x_code rax `appOL`                           toOL [MUL2 format y_reg,@@ -2400,8 +2379,8 @@         divOp platform signed width [res_q, res_r]               m_arg_x_high arg_x_low arg_y             = do let format = intFormat width-                     reg_q = getRegisterReg platform True (CmmLocal res_q)-                     reg_r = getRegisterReg platform True (CmmLocal res_r)+                     reg_q = getRegisterReg platform (CmmLocal res_q)+                     reg_r = getRegisterReg platform (CmmLocal res_r)                      widen | signed    = CLTD format                            | otherwise = XOR format (OpReg rdx) (OpReg rdx)                      instr | signed    = IDIV@@ -2428,8 +2407,8 @@                  rCode <- anyReg =<< trivialCode width (instr format)                                        (mrevinstr format) arg_x arg_y                  reg_tmp <- getNewRegNat II8-                 let reg_c = getRegisterReg platform True (CmmLocal res_c)-                     reg_r = getRegisterReg platform True (CmmLocal res_r)+                 let reg_c = getRegisterReg platform  (CmmLocal res_c)+                     reg_r = getRegisterReg platform  (CmmLocal res_r)                      code = rCode reg_r `snocOL`                             SETCC cond (OpReg reg_tmp) `snocOL`                             MOVZxL II8 (OpReg reg_tmp) (OpReg reg_c)@@ -2473,8 +2452,7 @@         delta0 <- getDeltaNat         setDeltaNat (delta0 - arg_pad_size) -        use_sse2 <- sse2Enabled-        push_codes <- mapM (push_arg use_sse2) (reverse prom_args)+        push_codes <- mapM push_arg (reverse prom_args)         delta <- getDeltaNat         MASSERT(delta == delta0 - tot_arg_size) @@ -2527,18 +2505,21 @@             assign_code []     = nilOL             assign_code [dest]               | isFloatType ty =-                 if use_sse2-                    then let tmp_amode = AddrBaseIndex (EABaseReg esp)+                  -- we assume SSE2+                  let tmp_amode = AddrBaseIndex (EABaseReg esp)                                                        EAIndexNone                                                        (ImmInt 0)-                             fmt = floatFormat w+                      fmt = floatFormat w                          in toOL [ SUB II32 (OpImm (ImmInt b)) (OpReg esp),                                    DELTA (delta0 - b),-                                   GST fmt fake0 tmp_amode,+                                   X87Store fmt  tmp_amode,+                                   -- X87Store only supported for the CDECL ABI+                                   -- NB: This code will need to be+                                   -- revisted once GHC does more work around+                                   -- SIGFPE f                                    MOV fmt (OpAddr tmp_amode) (OpReg r_dest),                                    ADD II32 (OpImm (ImmInt b)) (OpReg esp),                                    DELTA delta0]-                    else unitOL (GMOV fake0 r_dest)               | isWord64 ty    = toOL [MOV II32 (OpReg eax) (OpReg r_dest),                                         MOV II32 (OpReg edx) (OpReg r_dest_hi)]               | otherwise      = unitOL (MOV (intFormat w)@@ -2549,7 +2530,7 @@                     w  = typeWidth ty                     b  = widthInBytes w                     r_dest_hi = getHiVRegFromLo r_dest-                    r_dest    = getRegisterReg platform use_sse2 (CmmLocal dest)+                    r_dest    = getRegisterReg platform  (CmmLocal dest)             assign_code many = pprPanic "genCCall.assign_code - too many return values:" (ppr many)          return (push_code `appOL`@@ -2564,10 +2545,10 @@         roundTo a x | x `mod` a == 0 = x                     | otherwise = x + a - (x `mod` a) -        push_arg :: Bool -> CmmActual {-current argument-}+        push_arg :: CmmActual {-current argument-}                         -> NatM InstrBlock  -- code -        push_arg use_sse2 arg -- we don't need the hints on x86+        push_arg  arg -- we don't need the hints on x86           | isWord64 arg_ty = do             ChildCode64 code r_lo <- iselExpr64 arg             delta <- getDeltaNat@@ -2591,9 +2572,10 @@                                                             (ImmInt 0)                                       format = floatFormat (typeWidth arg_ty)                                   in-                                  if use_sse2-                                     then MOV format (OpReg reg) (OpAddr addr)-                                     else GST format reg addr++                                  -- assume SSE2+                                   MOV format (OpReg reg) (OpAddr addr)+                                  ]                            ) @@ -2721,7 +2703,7 @@                 _ -> unitOL (MOV (cmmTypeFormat rep) (OpReg rax) (OpReg r_dest))           where                 rep = localRegType dest-                r_dest = getRegisterReg platform True (CmmLocal dest)+                r_dest = getRegisterReg platform  (CmmLocal dest)         assign_code _many = panic "genCCall.assign_code many"      return (adjust_rsp          `appOL`@@ -3051,7 +3033,7 @@                           where blockLabel = blockLbl blockid                   in map jumpTableEntryRel ids             | otherwise = map (jumpTableEntry dflags) ids-      in CmmData section (1, Statics lbl jumpTable)+      in CmmData section (mkAlignment 1, Statics lbl jumpTable)  extractUnwindPoints :: [Instr] -> [UnwindPoint] extractUnwindPoints instrs =@@ -3134,18 +3116,10 @@ -- and plays better with the uOP cache.  condFltReg :: Bool -> Cond -> CmmExpr -> CmmExpr -> NatM Register-condFltReg is32Bit cond x y = if_sse2 condFltReg_sse2 condFltReg_x87+condFltReg is32Bit cond x y = condFltReg_sse2  where-  condFltReg_x87 = do-    CondCode _ cond cond_code <- condFltCode cond x y-    tmp <- getNewRegNat II8-    let-        code dst = cond_code `appOL` toOL [-                    SETCC cond (OpReg tmp),-                    MOVZxL II8 (OpReg tmp) (OpReg dst)-                  ]-    return (Any II32 code) +   condFltReg_sse2 = do     CondCode _ cond cond_code <- condFltCode cond x y     tmp1 <- getNewRegNat (archWordFormat is32Bit)@@ -3308,18 +3282,6 @@  ----------- -trivialFCode_x87 :: (Format -> Reg -> Reg -> Reg -> Instr)-                 -> CmmExpr -> CmmExpr -> NatM Register-trivialFCode_x87 instr x y = do-  (x_reg, x_code) <- getNonClobberedReg x -- these work for float regs too-  (y_reg, y_code) <- getSomeReg y-  let-     format = FF80 -- always, on x87-     code dst =-        x_code `appOL`-        y_code `snocOL`-        instr format x_reg y_reg dst-  return (Any format code)  trivialFCode_sse2 :: Width -> (Format -> Operand -> Operand -> Instr)                   -> CmmExpr -> CmmExpr -> NatM Register@@ -3340,17 +3302,8 @@  -------------------------------------------------------------------------------- coerceInt2FP :: Width -> Width -> CmmExpr -> NatM Register-coerceInt2FP from to x = if_sse2 coerce_sse2 coerce_x87+coerceInt2FP from to x =  coerce_sse2  where-   coerce_x87 = do-     (x_reg, x_code) <- getSomeReg x-     let-           opc  = case to of W32 -> GITOF; W64 -> GITOD;-                             n -> panic $ "coerceInt2FP.x87: unhandled width ("-                                         ++ show n ++ ")"-           code dst = x_code `snocOL` opc x_reg dst-        -- ToDo: works for non-II32 reps?-     return (Any FF80 code)     coerce_sse2 = do      (x_op, x_code) <- getOperand x  -- ToDo: could be a safe operand@@ -3364,18 +3317,8 @@  -------------------------------------------------------------------------------- coerceFP2Int :: Width -> Width -> CmmExpr -> NatM Register-coerceFP2Int from to x = if_sse2 coerceFP2Int_sse2 coerceFP2Int_x87+coerceFP2Int from to x =  coerceFP2Int_sse2  where-   coerceFP2Int_x87 = do-     (x_reg, x_code) <- getSomeReg x-     let-           opc  = case from of W32 -> GFTOI; W64 -> GDTOI-                               n -> panic $ "coerceFP2Int.x87: unhandled width ("-                                           ++ show n ++ ")"-           code dst = x_code `snocOL` opc x_reg dst-        -- ToDo: works for non-II32 reps?-     return (Any (intFormat to) code)-    coerceFP2Int_sse2 = do      (x_op, x_code) <- getOperand x  -- ToDo: could be a safe operand      let@@ -3390,15 +3333,13 @@ -------------------------------------------------------------------------------- coerceFP2FP :: Width -> CmmExpr -> NatM Register coerceFP2FP to x = do-  use_sse2 <- sse2Enabled   (x_reg, x_code) <- getSomeReg x   let-        opc | use_sse2  = case to of W32 -> CVTSD2SS; W64 -> CVTSS2SD;+        opc  = case to of W32 -> CVTSD2SS; W64 -> CVTSS2SD;                                      n -> panic $ "coerceFP2FP: unhandled width ("                                                  ++ show n ++ ")"-            | otherwise = GDTOF         code dst = x_code `snocOL` opc x_reg dst-  return (Any (if use_sse2 then floatFormat to else FF80) code)+  return (Any ( floatFormat to) code)  -------------------------------------------------------------------------------- @@ -3415,10 +3356,10 @@       x@II16 -> wrongFmt x       x@II32 -> wrongFmt x       x@II64 -> wrongFmt x-      x@FF80 -> wrongFmt x+       where         wrongFmt x = panic $ "sse2NegCode: " ++ show x-  Amode amode amode_code <- memConstant (widthInBytes w) const+  Amode amode amode_code <- memConstant (mkAlignment $ widthInBytes w) const   tmp <- getNewRegNat fmt   let     code dst = x_code dst `appOL` amode_code `appOL` toOL [
compiler/nativeGen/X86/Instr.hs view
@@ -10,7 +10,7 @@  module X86.Instr (Instr(..), Operand(..), PrefetchVariant(..), JumpDest(..),                   getJumpDestBlockId, canShortcut, shortcutStatics,-                  shortcutJump, i386_insert_ffrees, allocMoreStack,+                  shortcutJump, allocMoreStack,                   maxSpillSlots, archWordFormat ) where @@ -240,46 +240,14 @@         | BT          Format Imm Operand         | NOP -        -- x86 Float Arithmetic.-        -- Note that we cheat by treating G{ABS,MOV,NEG} of doubles-        -- as single instructions right up until we spit them out.-        -- all the 3-operand fake fp insns are src1 src2 dst-        -- and furthermore are constrained to be fp regs only.-        -- IMPORTANT: keep is_G_insn up to date with any changes here-        | GMOV        Reg Reg -- src(fpreg), dst(fpreg)-        | GLD         Format AddrMode Reg -- src, dst(fpreg)-        | GST         Format Reg AddrMode -- src(fpreg), dst -        | GLDZ        Reg -- dst(fpreg)-        | GLD1        Reg -- dst(fpreg)--        | GFTOI       Reg Reg -- src(fpreg), dst(intreg)-        | GDTOI       Reg Reg -- src(fpreg), dst(intreg)--        | GITOF       Reg Reg -- src(intreg), dst(fpreg)-        | GITOD       Reg Reg -- src(intreg), dst(fpreg)--        | GDTOF       Reg Reg -- src(fpreg), dst(fpreg)--        | GADD        Format Reg Reg Reg -- src1, src2, dst-        | GDIV        Format Reg Reg Reg -- src1, src2, dst-        | GSUB        Format Reg Reg Reg -- src1, src2, dst-        | GMUL        Format Reg Reg Reg -- src1, src2, dst--                -- FP compare.  Cond must be `elem` [EQQ, NE, LE, LTT, GE, GTT]-                -- Compare src1 with src2; set the Zero flag iff the numbers are-                -- comparable and the comparison is True.  Subsequent code must-                -- test the %eflags zero flag regardless of the supplied Cond.-        | GCMP        Cond Reg Reg -- src1, src2--        | GABS        Format Reg Reg -- src, dst-        | GNEG        Format Reg Reg -- src, dst-        | GSQRT       Format Reg Reg -- src, dst-        | GSIN        Format CLabel CLabel Reg Reg -- src, dst-        | GCOS        Format CLabel CLabel Reg Reg -- src, dst-        | GTAN        Format CLabel CLabel Reg Reg -- src, dst--        | GFREE         -- do ffree on all x86 regs; an ugly hack+        -- We need to support the FSTP (x87 store and pop) instruction+        -- so that we can correctly read off the return value of an+        -- x86 CDECL C function call when its floating point.+        -- so we dont include a register argument, and just use st(0)+        -- this instruction is used ONLY for return values of C ffi calls+        -- in x86_32 abi+        | X87Store         Format  AddrMode -- st(0), dst           -- SSE2 floating point: we use a restricted set of the available SSE2@@ -427,33 +395,7 @@     CLTD   _            -> mkRU [eax] [edx]     NOP                 -> mkRU [] [] -    GMOV   src dst      -> mkRU [src] [dst]-    GLD    _ src dst    -> mkRU (use_EA src []) [dst]-    GST    _ src dst    -> mkRUR (src : use_EA dst [])--    GLDZ   dst          -> mkRU [] [dst]-    GLD1   dst          -> mkRU [] [dst]--    GFTOI  src dst      -> mkRU [src] [dst]-    GDTOI  src dst      -> mkRU [src] [dst]--    GITOF  src dst      -> mkRU [src] [dst]-    GITOD  src dst      -> mkRU [src] [dst]--    GDTOF  src dst      -> mkRU [src] [dst]--    GADD   _ s1 s2 dst  -> mkRU [s1,s2] [dst]-    GSUB   _ s1 s2 dst  -> mkRU [s1,s2] [dst]-    GMUL   _ s1 s2 dst  -> mkRU [s1,s2] [dst]-    GDIV   _ s1 s2 dst  -> mkRU [s1,s2] [dst]--    GCMP   _ src1 src2   -> mkRUR [src1,src2]-    GABS   _ src dst     -> mkRU [src] [dst]-    GNEG   _ src dst     -> mkRU [src] [dst]-    GSQRT  _ src dst     -> mkRU [src] [dst]-    GSIN   _ _ _ src dst -> mkRU [src] [dst]-    GCOS   _ _ _ src dst -> mkRU [src] [dst]-    GTAN   _ _ _ src dst -> mkRU [src] [dst]+    X87Store    _  dst    -> mkRUR ( use_EA dst [])      CVTSS2SD   src dst  -> mkRU [src] [dst]     CVTSD2SS   src dst  -> mkRU [src] [dst]@@ -603,33 +545,8 @@     JMP op regs          -> JMP (patchOp op) regs     JMP_TBL op ids s lbl -> JMP_TBL (patchOp op) ids s lbl -    GMOV src dst         -> GMOV (env src) (env dst)-    GLD  fmt src dst     -> GLD fmt (lookupAddr src) (env dst)-    GST  fmt src dst     -> GST fmt (env src) (lookupAddr dst)--    GLDZ dst            -> GLDZ (env dst)-    GLD1 dst            -> GLD1 (env dst)--    GFTOI src dst       -> GFTOI (env src) (env dst)-    GDTOI src dst       -> GDTOI (env src) (env dst)--    GITOF src dst       -> GITOF (env src) (env dst)-    GITOD src dst       -> GITOD (env src) (env dst)--    GDTOF src dst       -> GDTOF (env src) (env dst)--    GADD fmt s1 s2 dst   -> GADD fmt (env s1) (env s2) (env dst)-    GSUB fmt s1 s2 dst   -> GSUB fmt (env s1) (env s2) (env dst)-    GMUL fmt s1 s2 dst   -> GMUL fmt (env s1) (env s2) (env dst)-    GDIV fmt s1 s2 dst   -> GDIV fmt (env s1) (env s2) (env dst)--    GCMP fmt src1 src2   -> GCMP fmt (env src1) (env src2)-    GABS fmt src dst     -> GABS fmt (env src) (env dst)-    GNEG fmt src dst     -> GNEG fmt (env src) (env dst)-    GSQRT fmt src dst    -> GSQRT fmt (env src) (env dst)-    GSIN fmt l1 l2 src dst       -> GSIN fmt l1 l2 (env src) (env dst)-    GCOS fmt l1 l2 src dst       -> GCOS fmt l1 l2 (env src) (env dst)-    GTAN fmt l1 l2 src dst       -> GTAN fmt l1 l2 (env src) (env dst)+    -- literally only support storing the top x87 stack value st(0)+    X87Store  fmt  dst     -> X87Store fmt  (lookupAddr dst)      CVTSS2SD src dst    -> CVTSS2SD (env src) (env dst)     CVTSD2SS src dst    -> CVTSD2SS (env src) (env dst)@@ -752,8 +669,7 @@     case targetClassOfReg platform reg of            RcInteger   -> MOV (archWordFormat is32Bit)                               (OpReg reg) (OpAddr (spRel dflags off))-           RcDouble    -> GST FF80 reg (spRel dflags off) {- RcFloat/RcDouble -}-           RcDoubleSSE -> MOV FF64 (OpReg reg) (OpAddr (spRel dflags off))+           RcDouble    -> MOV FF64 (OpReg reg) (OpAddr (spRel dflags off))            _         -> panic "X86.mkSpillInstr: no match"     where platform = targetPlatform dflags           is32Bit = target32Bit platform@@ -772,8 +688,7 @@         case targetClassOfReg platform reg of               RcInteger -> MOV (archWordFormat is32Bit)                                (OpAddr (spRel dflags off)) (OpReg reg)-              RcDouble  -> GLD FF80 (spRel dflags off) reg {- RcFloat/RcDouble -}-              RcDoubleSSE -> MOV FF64 (OpAddr (spRel dflags off)) (OpReg reg)+              RcDouble  -> MOV FF64 (OpAddr (spRel dflags off)) (OpReg reg)               _           -> panic "X86.x86_mkLoadInstr"     where platform = targetPlatform dflags           is32Bit = target32Bit platform@@ -827,6 +742,7 @@   +---  TODO: why is there -- | Make a reg-reg move instruction. --      On SPARC v8 there are no instructions to move directly between --      floating point and integer regs. If we need to do that then we@@ -844,8 +760,10 @@                      ArchX86    -> MOV II32 (OpReg src) (OpReg dst)                      ArchX86_64 -> MOV II64 (OpReg src) (OpReg dst)                      _          -> panic "x86_mkRegRegMoveInstr: Bad arch"-        RcDouble    -> GMOV src dst-        RcDoubleSSE -> MOV FF64 (OpReg src) (OpReg dst)+        RcDouble    ->  MOV FF64 (OpReg src) (OpReg dst)+        -- this code is the lie we tell ourselves because both float and double+        -- use the same register class.on x86_64 and x86 32bit with SSE2,+        -- more plainly, both use the XMM registers         _     -> panic "X86.RegInfo.mkRegRegMoveInstr: no match"  -- | Check whether an instruction represents a reg-reg move.@@ -969,58 +887,6 @@       ArchX86    -> [ADD II32 (OpImm (ImmInt amount)) (OpReg esp)]       ArchX86_64 -> [ADD II64 (OpImm (ImmInt amount)) (OpReg rsp)]       _ -> panic "x86_mkStackDeallocInstr"--i386_insert_ffrees-        :: [GenBasicBlock Instr]-        -> [GenBasicBlock Instr]--i386_insert_ffrees blocks-   | any (any is_G_instr) [ instrs | BasicBlock _ instrs <- blocks ]-   = map insertGFREEs blocks-   | otherwise-   = blocks- where-   insertGFREEs (BasicBlock id insns)-     = BasicBlock id (insertBeforeNonlocalTransfers GFREE insns)--insertBeforeNonlocalTransfers :: Instr -> [Instr] -> [Instr]-insertBeforeNonlocalTransfers insert insns-     = foldr p [] insns-     where p insn r = case insn of-                        CALL _ _    -> insert : insn : r-                        JMP _ _     -> insert : insn : r-                        JXX_GBL _ _ -> panic "insertBeforeNonlocalTransfers: cannot handle JXX_GBL"-                        _           -> insn : r----- if you ever add a new FP insn to the fake x86 FP insn set,--- you must update this too-is_G_instr :: Instr -> Bool-is_G_instr instr-   = case instr of-        GMOV{}          -> True-        GLD{}           -> True-        GST{}           -> True-        GLDZ{}          -> True-        GLD1{}          -> True-        GFTOI{}         -> True-        GDTOI{}         -> True-        GITOF{}         -> True-        GITOD{}         -> True-        GDTOF{}         -> True-        GADD{}          -> True-        GDIV{}          -> True-        GSUB{}          -> True-        GMUL{}          -> True-        GCMP{}          -> True-        GABS{}          -> True-        GNEG{}          -> True-        GSQRT{}         -> True-        GSIN{}          -> True-        GCOS{}          -> True-        GTAN{}          -> True-        GFREE           -> panic "is_G_instr: GFREE (!)"-        _               -> False   --
compiler/nativeGen/X86/Ppr.hs view
@@ -36,7 +36,7 @@  import Hoopl.Collections import Hoopl.Label-import BasicTypes       (Alignment)+import BasicTypes       (Alignment, mkAlignment, alignmentBytes) import DynFlags import Cmm              hiding (topInfoTable) import BlockId@@ -72,7 +72,7 @@  pprProcAlignment :: SDoc pprProcAlignment = sdocWithDynFlags $ \dflags ->-  (maybe empty pprAlign . cmmProcAlignment $ dflags)+  (maybe empty (pprAlign . mkAlignment) (cmmProcAlignment dflags))  pprNatCmmDecl :: NatCmmDecl (Alignment, CmmStatics) Instr -> SDoc pprNatCmmDecl (CmmData section dats) =@@ -145,7 +145,19 @@       (l@LOCATION{} : _) -> pprInstr l       _other             -> empty + pprDatas :: (Alignment, CmmStatics) -> SDoc+-- See note [emit-time elimination of static indirections] in CLabel.+pprDatas (_, Statics alias [CmmStaticLit (CmmLabel lbl), CmmStaticLit ind, _, _])+  | lbl == mkIndStaticInfoLabel+  , let labelInd (CmmLabelOff l _) = Just l+        labelInd (CmmLabel l) = Just l+        labelInd _ = Nothing+  , Just ind' <- labelInd ind+  , alias `mayRedirectTo` ind'+  = pprGloblDecl alias+    $$ text ".equiv" <+> ppr alias <> comma <> ppr (CmmLabel ind')+ pprDatas (align, (Statics lbl dats))  = vcat (pprAlign align : pprLabel lbl : map pprData dats) @@ -236,14 +248,15 @@             $$ pprTypeDecl lbl             $$ (ppr lbl <> char ':') -pprAlign :: Int -> SDoc-pprAlign bytes+pprAlign :: Alignment -> SDoc+pprAlign alignment         = sdocWithPlatform $ \platform ->-          text ".align " <> int (alignment platform)+          text ".align " <> int (alignmentOn platform)   where-        alignment platform = if platformOS platform == OSDarwin-                             then log2 bytes-                             else      bytes+        bytes = alignmentBytes alignment+        alignmentOn platform = if platformOS platform == OSDarwin+                               then log2 bytes+                               else      bytes          log2 :: Int -> Int  -- cache the common ones         log2 1 = 0@@ -271,7 +284,7 @@       RegVirtual (VirtualRegHi u)  -> text "%vHi_"  <> pprUniqueAlways u       RegVirtual (VirtualRegF  u)  -> text "%vF_"   <> pprUniqueAlways u       RegVirtual (VirtualRegD  u)  -> text "%vD_"   <> pprUniqueAlways u-      RegVirtual (VirtualRegSSE u) -> text "%vSSE_" <> pprUniqueAlways u+   where     ppr32_reg_no :: Format -> Int -> SDoc     ppr32_reg_no II8   = ppr32_reg_byte@@ -363,17 +376,14 @@  ppr_reg_float :: Int -> PtrString ppr_reg_float i = case i of-        16 -> sLit "%fake0";  17 -> sLit "%fake1"-        18 -> sLit "%fake2";  19 -> sLit "%fake3"-        20 -> sLit "%fake4";  21 -> sLit "%fake5"-        24 -> sLit "%xmm0";   25 -> sLit "%xmm1"-        26 -> sLit "%xmm2";   27 -> sLit "%xmm3"-        28 -> sLit "%xmm4";   29 -> sLit "%xmm5"-        30 -> sLit "%xmm6";   31 -> sLit "%xmm7"-        32 -> sLit "%xmm8";   33 -> sLit "%xmm9"-        34 -> sLit "%xmm10";  35 -> sLit "%xmm11"-        36 -> sLit "%xmm12";  37 -> sLit "%xmm13"-        38 -> sLit "%xmm14";  39 -> sLit "%xmm15"+        16 -> sLit "%xmm0" ;   17 -> sLit "%xmm1"+        18 -> sLit "%xmm2" ;   19 -> sLit "%xmm3"+        20 -> sLit "%xmm4" ;   21 -> sLit "%xmm5"+        22 -> sLit "%xmm6" ;   23 -> sLit "%xmm7"+        24 -> sLit "%xmm8" ;   25 -> sLit "%xmm9"+        26 -> sLit "%xmm10";   27 -> sLit "%xmm11"+        28 -> sLit "%xmm12";   29 -> sLit "%xmm13"+        30 -> sLit "%xmm14";   31 -> sLit "%xmm15"         _  -> sLit "very naughty x86 register"  pprFormat :: Format -> SDoc@@ -385,7 +395,6 @@                 II64  -> sLit "q"                 FF32  -> sLit "ss"      -- "scalar single-precision float" (SSE2)                 FF64  -> sLit "sd"      -- "scalar double-precision float" (SSE2)-                FF80  -> sLit "t"                 )  pprFormat_x87 :: Format -> SDoc@@ -393,9 +402,9 @@   = ptext $ case x of                 FF32  -> sLit "s"                 FF64  -> sLit "l"-                FF80  -> sLit "t"                 _     -> panic "X86.Ppr.pprFormat_x87" + pprCond :: Cond -> SDoc pprCond c  = ptext (case c of {@@ -806,225 +815,13 @@           ]  --- -------------------------------------------------------------------------------- i386 floating-point---- Simulating a flat register set on the x86 FP stack is tricky.--- you have to free %st(7) before pushing anything on the FP reg stack--- so as to preclude the possibility of a FP stack overflow exception.-pprInstr g@(GMOV src dst)-   | src == dst-   = empty-   | otherwise-   = pprG g (hcat [gtab, gpush src 0, gsemi, gpop dst 1])---- GLD fmt addr dst ==> FLDsz addr ; FSTP (dst+1)-pprInstr g@(GLD fmt addr dst)- = pprG g (hcat [gtab, text "fld", pprFormat_x87 fmt, gsp,-                 pprAddr addr, gsemi, gpop dst 1])-+-- the -- GST fmt src addr ==> FLD dst ; FSTPsz addr-pprInstr g@(GST fmt src addr)- | src == fake0 && fmt /= FF80 -- fstt instruction doesn't exist- = pprG g (hcat [gtab,-                 text "fst", pprFormat_x87 fmt, gsp, pprAddr addr])- | otherwise- = pprG g (hcat [gtab, gpush src 0, gsemi,+pprInstr g@(X87Store fmt  addr)+ = pprX87 g (hcat [gtab,                  text "fstp", pprFormat_x87 fmt, gsp, pprAddr addr]) -pprInstr g@(GLDZ dst)- = pprG g (hcat [gtab, text "fldz ; ", gpop dst 1])-pprInstr g@(GLD1 dst)- = pprG g (hcat [gtab, text "fld1 ; ", gpop dst 1]) -pprInstr (GFTOI src dst)-   = pprInstr (GDTOI src dst)--pprInstr g@(GDTOI src dst)-   = pprG g (vcat [-         hcat [gtab, text "subl $8, %esp ; fnstcw 4(%esp)"],-         hcat [gtab, gpush src 0],-         hcat [gtab, text "movzwl 4(%esp), ", reg,-                     text " ; orl $0xC00, ", reg],-         hcat [gtab, text "movl ", reg, text ", 0(%esp) ; fldcw 0(%esp)"],-         hcat [gtab, text "fistpl 0(%esp)"],-         hcat [gtab, text "fldcw 4(%esp) ; movl 0(%esp), ", reg],-         hcat [gtab, text "addl $8, %esp"]-     ])-   where-     reg = pprReg II32 dst--pprInstr (GITOF src dst)-   = pprInstr (GITOD src dst)--pprInstr g@(GITOD src dst)-   = pprG g (hcat [gtab, text "pushl ", pprReg II32 src,-                   text " ; fildl (%esp) ; ",-                   gpop dst 1, text " ; addl $4,%esp"])--pprInstr g@(GDTOF src dst)-  = pprG g (vcat [gtab <> gpush src 0,-                  gtab <> text "subl $4,%esp ; fstps (%esp) ; flds (%esp) ; addl $4,%esp ;",-                  gtab <> gpop dst 1])--{- Gruesome swamp follows.  If you're unfortunate enough to have ventured-   this far into the jungle AND you give a Rat's Ass (tm) what's going-   on, here's the deal.  Generate code to do a floating point comparison-   of src1 and src2, of kind cond, and set the Zero flag if true.--   The complications are to do with handling NaNs correctly.  We want the-   property that if either argument is NaN, then the result of the-   comparison is False ... except if we're comparing for inequality,-   in which case the answer is True.--   Here's how the general (non-inequality) case works.  As an-   example, consider generating the an equality test:--     pushl %eax         -- we need to mess with this-     <get src1 to top of FPU stack>-     fcomp <src2 location in FPU stack> and pop pushed src1-                -- Result of comparison is in FPU Status Register bits-                -- C3 C2 and C0-     fstsw %ax  -- Move FPU Status Reg to %ax-     sahf       -- move C3 C2 C0 from %ax to integer flag reg-     -- now the serious magic begins-     setpo %ah     -- %ah = if comparable(neither arg was NaN) then 1 else 0-     sete  %al     -- %al = if arg1 == arg2 then 1 else 0-     andb %ah,%al  -- %al &= %ah-                   -- so %al == 1 iff (comparable && same); else it holds 0-     decb %al      -- %al == 0, ZeroFlag=1  iff (comparable && same);-                      else %al == 0xFF, ZeroFlag=0-     -- the zero flag is now set as we desire.-     popl %eax--   The special case of inequality differs thusly:--     setpe %ah     -- %ah = if incomparable(either arg was NaN) then 1 else 0-     setne %al     -- %al = if arg1 /= arg2 then 1 else 0-     orb %ah,%al   -- %al = if (incomparable || different) then 1 else 0-     decb %al      -- if (incomparable || different) then (%al == 0, ZF=1)-                                                     else (%al == 0xFF, ZF=0)--}-pprInstr g@(GCMP cond src1 src2)-   | case cond of { NE -> True; _ -> False }-   = pprG g (vcat [-        hcat [gtab, text "pushl %eax ; ",gpush src1 0],-        hcat [gtab, text "fcomp ", greg src2 1,-                    text "; fstsw %ax ; sahf ;  setpe %ah"],-        hcat [gtab, text "setne %al ;  ",-              text "orb %ah,%al ;  decb %al ;  popl %eax"]-    ])-   | otherwise-   = pprG g (vcat [-        hcat [gtab, text "pushl %eax ; ",gpush src1 0],-        hcat [gtab, text "fcomp ", greg src2 1,-                    text "; fstsw %ax ; sahf ;  setpo %ah"],-        hcat [gtab, text "set", pprCond (fix_FP_cond cond), text " %al ;  ",-              text "andb %ah,%al ;  decb %al ;  popl %eax"]-    ])-    where-        {- On the 486, the flags set by FP compare are the unsigned ones!-           (This looks like a HACK to me.  WDP 96/03)-        -}-        fix_FP_cond :: Cond -> Cond-        fix_FP_cond GE   = GEU-        fix_FP_cond GTT  = GU-        fix_FP_cond LTT  = LU-        fix_FP_cond LE   = LEU-        fix_FP_cond EQQ  = EQQ-        fix_FP_cond NE   = NE-        fix_FP_cond _    = panic "X86.Ppr.fix_FP_cond: no match"-        -- there should be no others---pprInstr g@(GABS _ src dst)-   = pprG g (hcat [gtab, gpush src 0, text " ; fabs ; ", gpop dst 1])--pprInstr g@(GNEG _ src dst)-   = pprG g (hcat [gtab, gpush src 0, text " ; fchs ; ", gpop dst 1])--pprInstr g@(GSQRT fmt src dst)-   = pprG g (hcat [gtab, gpush src 0, text " ; fsqrt"] $$-             hcat [gtab, gcoerceto fmt, gpop dst 1])--pprInstr g@(GSIN fmt l1 l2 src dst)-   = pprG g (pprTrigOp "fsin" False l1 l2 src dst fmt)--pprInstr g@(GCOS fmt l1 l2 src dst)-   = pprG g (pprTrigOp "fcos" False l1 l2 src dst fmt)--pprInstr g@(GTAN fmt l1 l2 src dst)-   = pprG g (pprTrigOp "fptan" True l1 l2 src dst fmt)---- In the translations for GADD, GMUL, GSUB and GDIV,--- the first two cases are mere optimisations.  The otherwise clause--- generates correct code under all circumstances.--pprInstr g@(GADD _ src1 src2 dst)-   | src1 == dst-   = pprG g (text "\t#GADD-xxxcase1" $$-             hcat [gtab, gpush src2 0,-                   text " ; faddp %st(0),", greg src1 1])-   | src2 == dst-   = pprG g (text "\t#GADD-xxxcase2" $$-             hcat [gtab, gpush src1 0,-                   text " ; faddp %st(0),", greg src2 1])-   | otherwise-   = pprG g (hcat [gtab, gpush src1 0,-                   text " ; fadd ", greg src2 1, text ",%st(0)",-                   gsemi, gpop dst 1])---pprInstr g@(GMUL _ src1 src2 dst)-   | src1 == dst-   = pprG g (text "\t#GMUL-xxxcase1" $$-             hcat [gtab, gpush src2 0,-                   text " ; fmulp %st(0),", greg src1 1])-   | src2 == dst-   = pprG g (text "\t#GMUL-xxxcase2" $$-             hcat [gtab, gpush src1 0,-                   text " ; fmulp %st(0),", greg src2 1])-   | otherwise-   = pprG g (hcat [gtab, gpush src1 0,-             text " ; fmul ", greg src2 1, text ",%st(0)",-             gsemi, gpop dst 1])---pprInstr g@(GSUB _ src1 src2 dst)-   | src1 == dst-   = pprG g (text "\t#GSUB-xxxcase1" $$-             hcat [gtab, gpush src2 0,-                   text " ; fsubrp %st(0),", greg src1 1])-   | src2 == dst-   = pprG g (text "\t#GSUB-xxxcase2" $$-             hcat [gtab, gpush src1 0,-                   text " ; fsubp %st(0),", greg src2 1])-   | otherwise-   = pprG g (hcat [gtab, gpush src1 0,-                   text " ; fsub ", greg src2 1, text ",%st(0)",-                   gsemi, gpop dst 1])---pprInstr g@(GDIV _ src1 src2 dst)-   | src1 == dst-   = pprG g (text "\t#GDIV-xxxcase1" $$-             hcat [gtab, gpush src2 0,-                   text " ; fdivrp %st(0),", greg src1 1])-   | src2 == dst-   = pprG g (text "\t#GDIV-xxxcase2" $$-             hcat [gtab, gpush src1 0,-                   text " ; fdivp %st(0),", greg src2 1])-   | otherwise-   = pprG g (hcat [gtab, gpush src1 0,-                   text " ; fdiv ", greg src2 1, text ",%st(0)",-                   gsemi, gpop dst 1])---pprInstr GFREE-   = vcat [ text "\tffree %st(0) ;ffree %st(1) ;ffree %st(2) ;ffree %st(3)",-            text "\tffree %st(4) ;ffree %st(5)"-          ]- -- Atomics  pprInstr (LOCK i) = text "\tlock" $$ pprInstr i@@ -1037,116 +834,27 @@    = pprFormatOpOp (sLit "cmpxchg") format src dst  -pprTrigOp :: String -> Bool -> CLabel -> CLabel-          -> Reg -> Reg -> Format -> SDoc-pprTrigOp op -- fsin, fcos or fptan-          isTan -- we need a couple of extra steps if we're doing tan-          l1 l2 -- internal labels for us to use-          src dst fmt-    = -- We'll be needing %eax later on-      hcat [gtab, text "pushl %eax;"] $$-      -- tan is going to use an extra space on the FP stack-      (if isTan then hcat [gtab, text "ffree %st(6)"] else empty) $$-      -- First put the value in %st(0) and try to apply the op to it-      hcat [gpush src 0, text ("; " ++ op)] $$-      -- Now look to see if C2 was set (overflow, |value| >= 2^63)-      hcat [gtab, text "fnstsw %ax"] $$-      hcat [gtab, text "test   $0x400,%eax"] $$-      -- If we were in bounds then jump to the end-      hcat [gtab, text "je     " <> ppr l1] $$-      -- Otherwise we need to shrink the value. Start by-      -- loading pi, doubleing it (by adding it to itself),-      -- and then swapping pi with the value, so the value we-      -- want to apply op to is in %st(0) again-      hcat [gtab, text "ffree %st(7); fldpi"] $$-      hcat [gtab, text "fadd   %st(0),%st"] $$-      hcat [gtab, text "fxch   %st(1)"] $$-      -- Now we have a loop in which we make the value smaller,-      -- see if it's small enough, and loop if not-      (ppr l2 <> char ':') $$-      hcat [gtab, text "fprem1"] $$-      -- My Debian libc uses fstsw here for the tan code, but I can't-      -- see any reason why it should need to be different for tan.-      hcat [gtab, text "fnstsw %ax"] $$-      hcat [gtab, text "test   $0x400,%eax"] $$-      hcat [gtab, text "jne    " <> ppr l2] $$-      hcat [gtab, text "fstp   %st(1)"] $$-      hcat [gtab, text op] $$-      (ppr l1 <> char ':') $$-      -- Pop the 1.0 tan gave us-      (if isTan then hcat [gtab, text "fstp %st(0)"] else empty) $$-      -- Restore %eax-      hcat [gtab, text "popl %eax;"] $$-      -- And finally make the result the right size-      hcat [gtab, gcoerceto fmt, gpop dst 1]  --------------------------+-- some left over --- coerce %st(0) to the specified size-gcoerceto :: Format -> SDoc-gcoerceto FF64 = empty-gcoerceto FF32 = empty --text "subl $4,%esp ; fstps (%esp) ; flds (%esp) ; addl $4,%esp ; "-gcoerceto _    = panic "X86.Ppr.gcoerceto: no match" -gpush :: Reg -> RegNo -> SDoc-gpush reg offset-   = hcat [text "fld ", greg reg offset] -gpop :: Reg -> RegNo -> SDoc-gpop reg offset-   = hcat [text "fstp ", greg reg offset]--greg :: Reg -> RegNo -> SDoc-greg reg offset = text "%st(" <> int (gregno reg - firstfake+offset) <> char ')'--gsemi :: SDoc-gsemi = text " ; "- gtab :: SDoc gtab  = char '\t'  gsp :: SDoc gsp   = char ' ' -gregno :: Reg -> RegNo-gregno (RegReal (RealRegSingle i)) = i-gregno _           = --pprPanic "gregno" (ppr other)-                     999   -- bogus; only needed for debug printing -pprG :: Instr -> SDoc -> SDoc-pprG fake actual-   = (char '#' <> pprGInstr fake) $$ actual --pprGInstr :: Instr -> SDoc-pprGInstr (GMOV src dst)   = pprFormatRegReg (sLit "gmov") FF64 src dst-pprGInstr (GLD fmt src dst) = pprFormatAddrReg (sLit "gld") fmt src dst-pprGInstr (GST fmt src dst) = pprFormatRegAddr (sLit "gst") fmt src dst--pprGInstr (GLDZ dst) = pprFormatReg (sLit "gldz") FF64 dst-pprGInstr (GLD1 dst) = pprFormatReg (sLit "gld1") FF64 dst--pprGInstr (GFTOI src dst) = pprFormatFormatRegReg (sLit "gftoi") FF32 II32 src dst-pprGInstr (GDTOI src dst) = pprFormatFormatRegReg (sLit "gdtoi") FF64 II32 src dst--pprGInstr (GITOF src dst) = pprFormatFormatRegReg (sLit "gitof") II32 FF32 src dst-pprGInstr (GITOD src dst) = pprFormatFormatRegReg (sLit "gitod") II32 FF64 src dst-pprGInstr (GDTOF src dst) = pprFormatFormatRegReg (sLit "gdtof") FF64 FF32 src dst--pprGInstr (GCMP co src dst) = pprCondRegReg (sLit "gcmp_") FF64 co src dst-pprGInstr (GABS fmt src dst) = pprFormatRegReg (sLit "gabs") fmt src dst-pprGInstr (GNEG fmt src dst) = pprFormatRegReg (sLit "gneg") fmt src dst-pprGInstr (GSQRT fmt src dst) = pprFormatRegReg (sLit "gsqrt") fmt src dst-pprGInstr (GSIN fmt _ _ src dst) = pprFormatRegReg (sLit "gsin") fmt src dst-pprGInstr (GCOS fmt _ _ src dst) = pprFormatRegReg (sLit "gcos") fmt src dst-pprGInstr (GTAN fmt _ _ src dst) = pprFormatRegReg (sLit "gtan") fmt src dst--pprGInstr (GADD fmt src1 src2 dst) = pprFormatRegRegReg (sLit "gadd") fmt src1 src2 dst-pprGInstr (GSUB fmt src1 src2 dst) = pprFormatRegRegReg (sLit "gsub") fmt src1 src2 dst-pprGInstr (GMUL fmt src1 src2 dst) = pprFormatRegRegReg (sLit "gmul") fmt src1 src2 dst-pprGInstr (GDIV fmt src1 src2 dst) = pprFormatRegRegReg (sLit "gdiv") fmt src1 src2 dst+pprX87 :: Instr -> SDoc -> SDoc+pprX87 fake actual+   = (char '#' <> pprX87Instr fake) $$ actual -pprGInstr _ = panic "X86.Ppr.pprGInstr: no match"+pprX87Instr :: Instr -> SDoc+pprX87Instr (X87Store fmt  dst) = pprFormatAddr (sLit "gst") fmt  dst+pprX87Instr _ = panic "X86.Ppr.pprX87Instr: no match"  pprDollImm :: Imm -> SDoc pprDollImm i = text "$" <> pprImm i@@ -1214,24 +922,7 @@     ]  -pprFormatReg :: PtrString -> Format -> Reg -> SDoc-pprFormatReg name format reg1-  = hcat [-        pprMnemonic name format,-        pprReg format reg1-    ] --pprFormatRegReg :: PtrString -> Format -> Reg -> Reg -> SDoc-pprFormatRegReg name format reg1 reg2-  = hcat [-        pprMnemonic name format,-        pprReg format reg1,-        comma,-        pprReg format reg2-    ]-- pprRegReg :: PtrString -> Reg -> Reg -> SDoc pprRegReg name reg1 reg2   = sdocWithPlatform $ \platform ->@@ -1265,31 +956,6 @@         pprReg format reg2     ] -pprCondRegReg :: PtrString -> Format -> Cond -> Reg -> Reg -> SDoc-pprCondRegReg name format cond reg1 reg2-  = hcat [-        char '\t',-        ptext name,-        pprCond cond,-        space,-        pprReg format reg1,-        comma,-        pprReg format reg2-    ]--pprFormatFormatRegReg :: PtrString -> Format -> Format -> Reg -> Reg -> SDoc-pprFormatFormatRegReg name format1 format2 reg1 reg2-  = hcat [-        char '\t',-        ptext name,-        pprFormat format1,-        pprFormat format2,-        space,-        pprReg format1 reg1,-        comma,-        pprReg format2 reg2-    ]- pprFormatFormatOpReg :: PtrString -> Format -> Format -> Operand -> Reg -> SDoc pprFormatFormatOpReg name format1 format2 op1 reg2   = hcat [@@ -1299,17 +965,6 @@         pprReg format2 reg2     ] -pprFormatRegRegReg :: PtrString -> Format -> Reg -> Reg -> Reg -> SDoc-pprFormatRegRegReg name format reg1 reg2 reg3-  = hcat [-        pprMnemonic name format,-        pprReg format reg1,-        comma,-        pprReg format reg2,-        comma,-        pprReg format reg3-    ]- pprFormatOpOpReg :: PtrString -> Format -> Operand -> Operand -> Reg -> SDoc pprFormatOpOpReg name format op1 op2 reg3   = hcat [@@ -1321,25 +976,15 @@         pprReg format reg3     ] -pprFormatAddrReg :: PtrString -> Format -> AddrMode -> Reg -> SDoc-pprFormatAddrReg name format op dst-  = hcat [-        pprMnemonic name format,-        pprAddr op,-        comma,-        pprReg format dst-    ]  -pprFormatRegAddr :: PtrString -> Format -> Reg -> AddrMode -> SDoc-pprFormatRegAddr name format src op+pprFormatAddr :: PtrString -> Format -> AddrMode -> SDoc+pprFormatAddr name format  op   = hcat [         pprMnemonic name format,-        pprReg format src,         comma,         pprAddr op     ]-  pprShift :: PtrString -> Format -> Operand -> Operand -> SDoc pprShift name format src dest
compiler/nativeGen/X86/RegInfo.hs view
@@ -25,10 +25,13 @@ mkVirtualReg :: Unique -> Format -> VirtualReg mkVirtualReg u format    = case format of-        FF32    -> VirtualRegSSE u-        FF64    -> VirtualRegSSE u-        FF80    -> VirtualRegD   u-        _other  -> VirtualRegI   u+        FF32    -> VirtualRegD u+        -- for scalar F32, we use the same xmm as F64!+        -- this is a hack that needs some improvement.+        -- For now we map both to being allocated as "Double" Registers+        -- on X86/X86_64+        FF64    -> VirtualRegD u+        _other  -> VirtualRegI u  regDotColor :: Platform -> RealReg -> SDoc regDotColor platform reg@@ -37,11 +40,12 @@         _        -> panic "Register not assigned a color"  regColors :: Platform -> UniqFM [Char]-regColors platform = listToUFM (normalRegColors platform ++ fpRegColors platform)+regColors platform = listToUFM (normalRegColors platform)  normalRegColors :: Platform -> [(Reg,String)] normalRegColors platform =     zip (map regSingle [0..lastint platform]) colors+        ++ zip (map regSingle [firstxmm..lastxmm platform]) greys   where     -- 16 colors - enough for amd64 gp regs     colors = ["#800000","#ff0000","#808000","#ffff00","#008000"@@ -49,17 +53,6 @@              ,"#800080","#ff00ff","#87005f","#875f00","#87af00"              ,"#ff00af"] -fpRegColors :: Platform -> [(Reg,String)]-fpRegColors platform =-        [ (fake0, "red")-        , (fake1, "red")-        , (fake2, "red")-        , (fake3, "red")-        , (fake4, "red")-        , (fake5, "red") ]--        ++ zip (map regSingle [firstxmm..lastxmm platform]) greys-  where     -- 16 shades of grey, enough for the currently supported     -- SSE extensions.     greys = ["#0e0e0e","#1c1c1c","#2a2a2a","#383838","#464646"
compiler/nativeGen/X86/Regs.hs view
@@ -29,8 +29,8 @@         EABase(..), EAIndex(..), addrModeRegs,          eax, ebx, ecx, edx, esi, edi, ebp, esp,-        fake0, fake1, fake2, fake3, fake4, fake5, firstfake, +         rax, rbx, rcx, rdx, rsi, rdi, rbp, rsp,         r8,  r9,  r10, r11, r12, r13, r14, r15,         lastint,@@ -86,10 +86,6 @@                 VirtualRegF{}           -> 0                 _other                  -> 0 -        RcDoubleSSE-         -> case vr of-                VirtualRegSSE{}         -> 1-                _other                  -> 0          _other -> 0 @@ -100,7 +96,7 @@         RcInteger          -> case rr of                 RealRegSingle regNo-                        | regNo < firstfake -> 1+                        | regNo < firstxmm -> 1                         | otherwise     -> 0                  RealRegPair{}           -> 0@@ -108,15 +104,11 @@         RcDouble          -> case rr of                 RealRegSingle regNo-                        | regNo >= firstfake && regNo <= lastfake -> 1+                        | regNo >= firstxmm  -> 1                         | otherwise     -> 0                  RealRegPair{}           -> 0 -        RcDoubleSSE-         -> case rr of-                RealRegSingle regNo | regNo >= firstxmm -> 1-                _otherwise                        -> 0          _other -> 0 @@ -210,17 +202,16 @@ -- use a Word32 to represent the set of free registers in the register -- allocator. -firstfake, lastfake :: RegNo-firstfake = 16-lastfake  = 21 + firstxmm :: RegNo-firstxmm  = 24+firstxmm  = 16 +--  on 32bit platformOSs, only the first 8 XMM/YMM/ZMM registers are available lastxmm :: Platform -> RegNo lastxmm platform- | target32Bit platform = 31- | otherwise            = 39+ | target32Bit platform = firstxmm + 7  -- xmm0 - xmmm7+ | otherwise            = firstxmm + 15 -- xmm0 -xmm15  lastint :: Platform -> RegNo lastint platform@@ -230,14 +221,13 @@ intregnos :: Platform -> [RegNo] intregnos platform = [0 .. lastint platform] -fakeregnos :: [RegNo]-fakeregnos  = [firstfake .. lastfake] + xmmregnos :: Platform -> [RegNo] xmmregnos platform = [firstxmm  .. lastxmm platform]  floatregnos :: Platform -> [RegNo]-floatregnos platform = fakeregnos ++ xmmregnos platform+floatregnos platform = xmmregnos platform  -- argRegs is the set of regs which are read for an n-argument call to C. -- For archs which pass all args on the stack (x86), is empty.@@ -257,20 +247,19 @@ -- However, we can get away without this at the moment because the -- only allocatable integer regs are also 8-bit compatible (1, 3, 4). classOfRealReg platform reg- = case reg of+    = case reg of         RealRegSingle i-          | i <= lastint platform -> RcInteger-          | i <= lastfake         -> RcDouble-          | otherwise             -> RcDoubleSSE--        RealRegPair{}   -> panic "X86.Regs.classOfRealReg: RegPairs on this arch"+            | i <= lastint platform -> RcInteger+            | i <= lastxmm platform -> RcDouble+            | otherwise             -> panic "X86.Reg.classOfRealReg registerSingle too high"+        _   -> panic "X86.Regs.classOfRealReg: RegPairs on this arch"  -- | Get the name of the register with this number.+-- NOTE: fixme, we dont track which "way" the XMM registers are used showReg :: Platform -> RegNo -> String showReg platform n-        | n >= firstxmm  = "%xmm" ++ show (n-firstxmm)-        | n >= firstfake = "%fake" ++ show (n-firstfake)-        | n >= 8         = "%r" ++ show n+        | n >= firstxmm && n <= lastxmm  platform = "%xmm" ++ show (n-firstxmm)+        | n >= 8   && n < firstxmm      = "%r" ++ show n         | otherwise      = regNames platform A.! n  regNames :: Platform -> A.Array Int String@@ -290,18 +279,17 @@ - Only ebx, esi, edi and esp are available across a C call (they are callee-saves). - Registers 0-7 have 16-bit counterparts (ax, bx etc.) - Registers 0-3 have 8 bit counterparts (ah, bh etc.)-- Registers fake0..fake5 are fakes; we pretend x86 has 6 conventionally-addressable-  fp registers, and 3-operand insns for them, and we translate this into-  real stack-based x86 fp code after register allocation.  The fp registers are all Double registers; we don't have any RcFloat class regs.  @regClass@ barfs if you give it a VirtualRegF, and mkVReg above should never generate them.++TODO: cleanup modelling float vs double registers and how they are the same class. -} -fake0, fake1, fake2, fake3, fake4, fake5,-       eax, ebx, ecx, edx, esp, ebp, esi, edi :: Reg +eax, ebx, ecx, edx, esp, ebp, esi, edi :: Reg+ eax   = regSingle 0 ebx   = regSingle 1 ecx   = regSingle 2@@ -310,15 +298,10 @@ edi   = regSingle 5 ebp   = regSingle 6 esp   = regSingle 7-fake0 = regSingle 16-fake1 = regSingle 17-fake2 = regSingle 18-fake3 = regSingle 19-fake4 = regSingle 20-fake5 = regSingle 21   + {- AMD x86_64 architecture: - All 16 integer registers are addressable as 8, 16, 32 and 64-bit values:@@ -362,22 +345,22 @@ r13   = regSingle 13 r14   = regSingle 14 r15   = regSingle 15-xmm0  = regSingle 24-xmm1  = regSingle 25-xmm2  = regSingle 26-xmm3  = regSingle 27-xmm4  = regSingle 28-xmm5  = regSingle 29-xmm6  = regSingle 30-xmm7  = regSingle 31-xmm8  = regSingle 32-xmm9  = regSingle 33-xmm10 = regSingle 34-xmm11 = regSingle 35-xmm12 = regSingle 36-xmm13 = regSingle 37-xmm14 = regSingle 38-xmm15 = regSingle 39+xmm0  = regSingle 16+xmm1  = regSingle 17+xmm2  = regSingle 18+xmm3  = regSingle 19+xmm4  = regSingle 20+xmm5  = regSingle 21+xmm6  = regSingle 22+xmm7  = regSingle 23+xmm8  = regSingle 24+xmm9  = regSingle 25+xmm10 = regSingle 26+xmm11 = regSingle 27+xmm12 = regSingle 28+xmm13 = regSingle 29+xmm14 = regSingle 30+xmm15 = regSingle 31  ripRel :: Displacement -> AddrMode ripRel imm      = AddrBaseIndex EABaseRip EAIndexNone imm@@ -411,7 +394,7 @@    -- Only xmm0-5 are caller-saves registers on 64bit windows.    -- ( https://docs.microsoft.com/en-us/cpp/build/register-usage )    -- For details check the Win64 ABI.-   ++ map regSingle fakeregnos ++ map xmm [0  .. 5]+   ++ map xmm [0  .. 5]  | otherwise     -- all xmm regs are caller-saves     -- caller-saves registers@@ -430,11 +413,15 @@     = panic "X86.Regs.allIntArgRegs: not defined for this platform"  | otherwise = [rdi,rsi,rdx,rcx,r8,r9] ++-- | on 64bit platforms we pass the first 8 float/double arguments+-- in the xmm registers. allFPArgRegs :: Platform -> [Reg] allFPArgRegs platform  | platformOS platform == OSMinGW32     = panic "X86.Regs.allFPArgRegs: not defined for this platform"- | otherwise = map regSingle [firstxmm .. firstxmm+7]+ | otherwise = map regSingle [firstxmm .. firstxmm + 7 ]+  -- Machine registers which might be clobbered by instructions that -- generate results into fixed registers, or need arguments in a fixed
compiler/prelude/THNames.hs view
@@ -27,7 +27,7 @@ -- Should stay in sync with the import list of DsMeta  templateHaskellNames = [-    returnQName, bindQName, sequenceQName, newNameName, liftName,+    returnQName, bindQName, sequenceQName, newNameName, liftName, liftTypedName,     mkNameName, mkNameG_vName, mkNameG_dName, mkNameG_tcName, mkNameLName,     mkNameSName,     liftStringName,@@ -206,7 +206,7 @@ returnQName, bindQName, sequenceQName, newNameName, liftName,     mkNameName, mkNameG_vName, mkNameG_dName, mkNameG_tcName,     mkNameLName, mkNameSName, liftStringName, unTypeName, unTypeQName,-    unsafeTExpCoerceName :: Name+    unsafeTExpCoerceName, liftTypedName :: Name returnQName    = thFun (fsLit "returnQ")   returnQIdKey bindQName      = thFun (fsLit "bindQ")     bindQIdKey sequenceQName  = thFun (fsLit "sequenceQ") sequenceQIdKey@@ -222,6 +222,7 @@ unTypeName     = thFun (fsLit "unType")     unTypeIdKey unTypeQName    = thFun (fsLit "unTypeQ")    unTypeQIdKey unsafeTExpCoerceName = thFun (fsLit "unsafeTExpCoerce") unsafeTExpCoerceIdKey+liftTypedName = thFun (fsLit "liftTyped") liftTypedIdKey   -------------------- TH.Lib -----------------------@@ -726,7 +727,7 @@ returnQIdKey, bindQIdKey, sequenceQIdKey, liftIdKey, newNameIdKey,     mkNameIdKey, mkNameG_vIdKey, mkNameG_dIdKey, mkNameG_tcIdKey,     mkNameLIdKey, mkNameSIdKey, unTypeIdKey, unTypeQIdKey,-    unsafeTExpCoerceIdKey :: Unique+    unsafeTExpCoerceIdKey, liftTypedIdKey :: Unique returnQIdKey        = mkPreludeMiscIdUnique 200 bindQIdKey          = mkPreludeMiscIdUnique 201 sequenceQIdKey      = mkPreludeMiscIdUnique 202@@ -741,6 +742,7 @@ unTypeIdKey          = mkPreludeMiscIdUnique 211 unTypeQIdKey         = mkPreludeMiscIdUnique 212 unsafeTExpCoerceIdKey = mkPreludeMiscIdUnique 213+liftTypedIdKey        = mkPreludeMiscIdUnique 214   -- data Lit = ...@@ -1078,8 +1080,9 @@ ************************************************************************ -} -lift_RDR, mkNameG_dRDR, mkNameG_vRDR :: RdrName+lift_RDR, liftTyped_RDR, mkNameG_dRDR, mkNameG_vRDR :: RdrName lift_RDR     = nameRdrName liftName+liftTyped_RDR = nameRdrName liftTypedName mkNameG_dRDR = nameRdrName mkNameG_dName mkNameG_vRDR = nameRdrName mkNameG_vName 
compiler/simplStg/StgCse.hs view
@@ -245,8 +245,8 @@     new_id = uniqAway (ce_in_scope env) old_id     no_change = new_id == old_id     env' = env { ce_in_scope = ce_in_scope env `extendInScopeSet` new_id }-    new_env | no_change = env' { ce_subst = extendVarEnv (ce_subst env) old_id new_id }-            | otherwise = env'+    new_env | no_change = env'+            | otherwise = env' { ce_subst = extendVarEnv (ce_subst env) old_id new_id }  substBndrs :: CseEnv -> [InVar] -> (CseEnv, [OutVar]) substBndrs env bndrs = mapAccumL substBndr env bndrs
compiler/specialise/Specialise.hs view
@@ -730,28 +730,35 @@         ; return (rules2 ++ rules1, final_binds) } -  |  warnMissingSpecs dflags callers-  = do { warnMsg (vcat [ hang (text "Could not specialise imported function" <+> quotes (ppr fn))-                            2 (vcat [ text "when specialising" <+> quotes (ppr caller)-                                    | caller <- callers])-                      , whenPprDebug (text "calls:" <+> vcat (map (pprCallInfo fn) calls_for_fn))-                      , text "Probable fix: add INLINABLE pragma on" <+> quotes (ppr fn) ])-       ; return ([], []) }+  | otherwise = do { tryWarnMissingSpecs dflags callers fn calls_for_fn+                   ; return ([], [])} -  | otherwise-  = return ([], [])   where     unfolding = realIdUnfolding fn   -- We want to see the unfolding even for loop breakers -warnMissingSpecs :: DynFlags -> [Id] -> Bool+-- | Returns whether or not to show a missed-spec warning.+-- If -Wall-missed-specializations is on, show the warning.+-- Otherwise, if -Wmissed-specializations is on, only show a warning+-- if there is at least one imported function being specialized,+-- and if all imported functions are marked with an inline pragma+-- Use the most specific warning as the reason.+tryWarnMissingSpecs :: DynFlags -> [Id] -> Id -> [CallInfo] -> CoreM () -- See Note [Warning about missed specialisations]-warnMissingSpecs dflags callers-  | wopt Opt_WarnAllMissedSpecs dflags = True-  | not (wopt Opt_WarnMissedSpecs dflags) = False-  | null callers                       = False-  | otherwise                          = all has_inline_prag callers+tryWarnMissingSpecs dflags callers fn calls_for_fn+  | wopt Opt_WarnMissedSpecs dflags+    && not (null callers)+    && allCallersInlined                  = doWarn $ Reason Opt_WarnMissedSpecs+  | wopt Opt_WarnAllMissedSpecs dflags    = doWarn $ Reason Opt_WarnAllMissedSpecs+  | otherwise                             = return ()   where-    has_inline_prag id = isAnyInlinePragma (idInlinePragma id)+    allCallersInlined = all (isAnyInlinePragma . idInlinePragma) callers+    doWarn reason = +      warnMsg reason+        (vcat [ hang (text ("Could not specialise imported function") <+> quotes (ppr fn))+                2 (vcat [ text "when specialising" <+> quotes (ppr caller)+                        | caller <- callers])+          , whenPprDebug (text "calls:" <+> vcat (map (pprCallInfo fn) calls_for_fn))+          , text "Probable fix: add INLINABLE pragma on" <+> quotes (ppr fn) ])  wantSpecImport :: DynFlags -> Unfolding -> Bool -- See Note [Specialise imported INLINABLE things]
compiler/stgSyn/StgSyn.hs view
@@ -831,18 +831,31 @@     else sep [ ppr tickish, pprStgExpr expr ]  +-- Don't indent for a single case alternative.+pprStgExpr (StgCase expr bndr alt_type [alt])+  = sep [sep [text "case",+           nest 4 (hsep [pprStgExpr expr,+             whenPprDebug (dcolon <+> ppr alt_type)]),+           text "of", pprBndr CaseBind bndr, char '{'],+           pprStgAlt False alt,+           char '}']+ pprStgExpr (StgCase expr bndr alt_type alts)   = sep [sep [text "case",            nest 4 (hsep [pprStgExpr expr,              whenPprDebug (dcolon <+> ppr alt_type)]),            text "of", pprBndr CaseBind bndr, char '{'],-           nest 2 (vcat (map pprStgAlt alts)),+           nest 2 (vcat (map (pprStgAlt True) alts)),            char '}'] -pprStgAlt :: OutputablePass pass => GenStgAlt pass -> SDoc-pprStgAlt (con, params, expr)-  = hang (hsep [ppr con, sep (map (pprBndr CasePatBind) params), text "->"])-         4 (ppr expr <> semi)++pprStgAlt :: OutputablePass pass => Bool -> GenStgAlt pass -> SDoc+pprStgAlt indent (con, params, expr)+  | indent    = hang altPattern 4 (ppr expr <> semi)+  | otherwise = sep [altPattern, ppr expr <> semi]+    where+      altPattern = (hsep [ppr con, sep (map (pprBndr CasePatBind) params), text "->"])+  pprStgOp :: StgOp -> SDoc pprStgOp (StgPrimOp  op)   = ppr op
compiler/typecheck/Inst.hs view
@@ -78,24 +78,30 @@ ************************************************************************ -} -newMethodFromName :: CtOrigin -> Name -> TcRhoType -> TcM (HsExpr GhcTcId)--- Used when Name is the wired-in name for a wired-in class method,+newMethodFromName+  :: CtOrigin              -- ^ why do we need this?+  -> Name                  -- ^ name of the method+  -> [TcRhoType]           -- ^ types with which to instantiate the class+  -> TcM (HsExpr GhcTcId)+-- ^ Used when 'Name' is the wired-in name for a wired-in class method, -- so the caller knows its type for sure, which should be of form---    forall a. C a => <blah>--- newMethodFromName is supposed to instantiate just the outer+--+-- > forall a. C a => <blah>+--+-- 'newMethodFromName' is supposed to instantiate just the outer -- type variable and constraint -newMethodFromName origin name inst_ty+newMethodFromName origin name ty_args   = do { id <- tcLookupId name               -- Use tcLookupId not tcLookupGlobalId; the method is almost               -- always a class op, but with -XRebindableSyntax GHC is               -- meant to find whatever thing is in scope, and that may               -- be an ordinary function. -       ; let ty = piResultTy (idType id) inst_ty+       ; let ty = piResultTys (idType id) ty_args              (theta, _caller_knows_this) = tcSplitPhiTy ty        ; wrap <- ASSERT( not (isForAllTy ty) && isSingleton theta )-                 instCall origin [inst_ty] theta+                 instCall origin ty_args theta         ; return (mkHsWrap wrap (HsVar noExt (noLoc id))) } @@ -607,7 +613,7 @@  tcSyntaxName orig ty (std_nm, HsVar _ (L _ user_nm))   | std_nm == user_nm-  = do rhs <- newMethodFromName orig std_nm ty+  = do rhs <- newMethodFromName orig std_nm [ty]        return (std_nm, rhs)  tcSyntaxName orig ty (std_nm, user_nm_expr) = do
compiler/typecheck/TcCanonical.hs view
@@ -1015,7 +1015,7 @@             -- Done: unify phi1 ~ phi2             go [] subst bndrs2               = ASSERT( null bndrs2 )-                unify loc (eqRelRole eq_rel) phi1' (substTy subst phi2)+                unify loc (eqRelRole eq_rel) phi1' (substTyUnchecked subst phi2)              go _ _ _ = panic "cna_eq_nc_forall"  -- case (s:ss) [] 
compiler/typecheck/TcDeriv.hs view
@@ -335,6 +335,8 @@     -- (See Note [Newtype-deriving instances] in TcGenDeriv)     unsetXOptM LangExt.RebindableSyntax $     -- See Note [Avoid RebindableSyntax when deriving]+    setXOptM LangExt.TemplateHaskellQuotes $+    -- DeriveLift makes uses of quotes     do  {         -- Bring the extra deriving stuff into scope         -- before renaming the instances themselves
compiler/typecheck/TcDerivUtils.hs view
@@ -738,8 +738,10 @@                          (cond_isProduct `andCond` cond_args cls)  cond_args :: Class -> Condition--- For some classes (eg Eq, Ord) we allow unlifted arg types--- by generating specialised code.  For others (eg Data) we don't.+-- ^ For some classes (eg 'Eq', 'Ord') we allow unlifted arg types+-- by generating specialised code.  For others (eg 'Data') we don't.+-- For even others (eg 'Lift'), unlifted types aren't even a special+-- consideration! cond_args cls _ _ rep_tc   = case bad_args of       []     -> IsValid@@ -748,7 +750,7 @@   where     bad_args = [ arg_ty | con <- tyConDataCons rep_tc                         , arg_ty <- dataConOrigArgTys con-                        , isUnliftedType arg_ty+                        , isLiftedType_maybe arg_ty /= Just True                         , not (ok_ty arg_ty) ]      cls_key = classKey cls@@ -756,7 +758,7 @@      | cls_key == eqClassKey   = check_in arg_ty ordOpTbl      | cls_key == ordClassKey  = check_in arg_ty ordOpTbl      | cls_key == showClassKey = check_in arg_ty boxConTbl-     | cls_key == liftClassKey = check_in arg_ty litConTbl+     | cls_key == liftClassKey = True     -- Lift is levity-polymorphic      | otherwise               = False    -- Read, Ix etc      check_in :: Type -> [(Type,a)] -> Bool
compiler/typecheck/TcExpr.hs view
@@ -639,7 +639,8 @@         ; emitStaticConstraints lie          -- Wrap the static form with the 'fromStaticPtr' call.-        ; fromStaticPtr <- newMethodFromName StaticOrigin fromStaticPtrName p_ty+        ; fromStaticPtr <- newMethodFromName StaticOrigin fromStaticPtrName+                                             [p_ty]         ; let wrap = mkWpTyApps [expr_ty]         ; loc <- getSrcSpanM         ; return $ mkHsWrapCo co $ HsApp noExt@@ -1040,7 +1041,7 @@   = do { (wrap, elt_ty, wit') <- arithSeqEltType witness res_ty        ; expr' <- tcPolyExpr expr elt_ty        ; enum_from <- newMethodFromName (ArithSeqOrigin seq)-                              enumFromName elt_ty+                              enumFromName [elt_ty]        ; return $ mkHsWrap wrap $          ArithSeq enum_from wit' (From expr') } @@ -1049,7 +1050,7 @@        ; expr1' <- tcPolyExpr expr1 elt_ty        ; expr2' <- tcPolyExpr expr2 elt_ty        ; enum_from_then <- newMethodFromName (ArithSeqOrigin seq)-                              enumFromThenName elt_ty+                              enumFromThenName [elt_ty]        ; return $ mkHsWrap wrap $          ArithSeq enum_from_then wit' (FromThen expr1' expr2') } @@ -1058,7 +1059,7 @@        ; expr1' <- tcPolyExpr expr1 elt_ty        ; expr2' <- tcPolyExpr expr2 elt_ty        ; enum_from_to <- newMethodFromName (ArithSeqOrigin seq)-                              enumFromToName elt_ty+                              enumFromToName [elt_ty]        ; return $ mkHsWrap wrap $          ArithSeq enum_from_to wit' (FromTo expr1' expr2') } @@ -1068,7 +1069,7 @@         ; expr2' <- tcPolyExpr expr2 elt_ty         ; expr3' <- tcPolyExpr expr3 elt_ty         ; eft <- newMethodFromName (ArithSeqOrigin seq)-                              enumFromThenToName elt_ty+                              enumFromThenToName [elt_ty]         ; return $ mkHsWrap wrap $           ArithSeq eft wit' (FromThenTo expr1' expr2' expr3') } @@ -2041,7 +2042,8 @@                      setConstraintVar lie_var   $                           -- Put the 'lift' constraint into the right LIE                      newMethodFromName (OccurrenceOf id_name)-                                       THNames.liftName id_ty+                                       THNames.liftName+                                       [getRuntimeRep id_ty, id_ty]                     -- Update the pending splices         ; ps <- readMutVar ps_var
compiler/typecheck/TcGenDeriv.hs view
@@ -54,8 +54,6 @@ import FamInstEnv import PrelNames import THNames-import Module ( moduleName, moduleNameString-              , moduleUnitId, unitIdString ) import MkId ( coerceId ) import PrimOp import SrcLoc@@ -1559,68 +1557,36 @@     ==>      instance (Lift a) => Lift (Foo a) where-        lift (Foo a)-          = appE-              (conE-                (mkNameG_d "package-name" "ModuleName" "Foo"))-              (lift a)-        lift (u :^: v)-          = infixApp-              (lift u)-              (conE-                (mkNameG_d "package-name" "ModuleName" ":^:"))-              (lift v)+        lift (Foo a) = [| Foo a |]+        lift ((:^:) u v) = [| (:^:) u v |] -Note that (mkNameG_d "package-name" "ModuleName" "Foo") is equivalent to what-'Foo would be when using the -XTemplateHaskell extension. To make sure that--XDeriveLift can be used on stage-1 compilers, however, we explicitly invoke-makeG_d.+        liftTyped (Foo a) = [|| Foo a ||]+        liftTyped ((:^:) u v) = [|| (:^:) u v ||] -} + gen_Lift_binds :: SrcSpan -> TyCon -> (LHsBinds GhcPs, BagDerivStuff)-gen_Lift_binds loc tycon = (unitBag lift_bind, emptyBag)+gen_Lift_binds loc tycon = (listToBag [lift_bind, liftTyped_bind], emptyBag)   where-    lift_bind = mkFunBindEC 1 loc lift_RDR (nlHsApp pure_Expr)-                            (map pats_etc data_cons)+    lift_bind      = mkFunBindEC 1 loc lift_RDR (nlHsApp pure_Expr)+                                 (map (pats_etc mk_exp) data_cons)+    liftTyped_bind = mkFunBindEC 1 loc liftTyped_RDR (nlHsApp pure_Expr)+                                 (map (pats_etc mk_texp) data_cons)++    mk_exp = ExpBr NoExt+    mk_texp = TExpBr NoExt     data_cons = tyConDataCons tycon -    pats_etc data_con+    pats_etc mk_bracket data_con       = ([con_pat], lift_Expr)        where             con_pat      = nlConVarPat data_con_RDR as_needed             data_con_RDR = getRdrName data_con             con_arity    = dataConSourceArity data_con             as_needed    = take con_arity as_RDRs-            lifted_as    = zipWithEqual "mk_lift_app" mk_lift_app-                             tys_needed as_needed-            tycon_name   = tyConName tycon-            is_infix     = dataConIsInfix data_con-            tys_needed   = dataConOrigArgTys data_con--            mk_lift_app ty a-              | not (isUnliftedType ty) = nlHsApp (nlHsVar lift_RDR)-                                                  (nlHsVar a)-              | otherwise = nlHsApp (nlHsVar litE_RDR)-                              (primLitOp (mkBoxExp (nlHsVar a)))-              where (primLitOp, mkBoxExp) = primLitOps "Lift" ty--            pkg_name = unitIdString . moduleUnitId-                     . nameModule $ tycon_name-            mod_name = moduleNameString . moduleName . nameModule $ tycon_name-            con_name = occNameString . nameOccName . dataConName $ data_con--            conE_Expr = nlHsApp (nlHsVar conE_RDR)-                                (nlHsApps mkNameG_dRDR-                                  (map (nlHsLit . mkHsString)-                                    [pkg_name, mod_name, con_name]))--            lift_Expr-              | is_infix  = nlHsApps infixApp_RDR [a1, conE_Expr, a2]-              | otherwise = foldl' mk_appE_app conE_Expr lifted_as-            (a1:a2:_) = lifted_as--mk_appE_app :: LHsExpr GhcPs -> LHsExpr GhcPs -> LHsExpr GhcPs-mk_appE_app a b = nlHsApps appE_RDR [a, b]+            lift_Expr    = noLoc (HsBracket NoExt (mk_bracket br_body))+            br_body      = nlHsApps (Exact (dataConName data_con))+                                    (map nlHsVar as_needed)  {- ************************************************************************@@ -2133,17 +2099,6 @@            -> (RdrName, RdrName, RdrName, RdrName, RdrName)  -- (lt,le,eq,ge,gt) -- See Note [Deriving and unboxed types] in TcDerivInfer primOrdOps str ty = assoc_ty_id str ordOpTbl ty--primLitOps :: String -- The class involved-           -> Type   -- The type-           -> ( LHsExpr GhcPs -> LHsExpr GhcPs -- Constructs a Q Exp value-              , LHsExpr GhcPs -> LHsExpr GhcPs -- Constructs a boxed value-              )-primLitOps str ty = (assoc_ty_id str litConTbl ty, \v -> boxed v)-  where-    boxed v-      | ty `eqType` addrPrimTy = nlHsVar unpackCString_RDR `nlHsApp` v-      | otherwise = assoc_ty_id str boxConTbl ty v  ordOpTbl :: [(Type, (RdrName, RdrName, RdrName, RdrName, RdrName))] ordOpTbl
compiler/typecheck/TcMType.hs view
@@ -1496,7 +1496,7 @@                -> TcTyVar                -> Bool quantifiableTv outer_tclvl tcv-  | isTcTyVar tcv  -- Might be a CoVar; change this when gather covars separtely+  | isTcTyVar tcv  -- Might be a CoVar; change this when gather covars separately   = tcTyVarLevel tcv > outer_tclvl   | otherwise   = False
compiler/typecheck/TcSigs.hs view
@@ -515,7 +515,7 @@                              , sig_inst_skols = tv_prs                              , sig_inst_wcs   = wcs                              , sig_inst_wcx   = wcx-                             , sig_inst_theta = substTys subst theta+                             , sig_inst_theta = substTysUnchecked subst theta                              , sig_inst_tau   = substTyUnchecked  subst tau }        ; traceTc "End partial sig }" (ppr inst_sig)        ; return inst_sig }
compiler/typecheck/TcSplice.hs view
@@ -177,13 +177,14 @@        ; (_tc_expr, expr_ty) <- setStage (Brack cur_stage (TcPending ps_ref lie_var)) $                                 tcInferRhoNC expr                                 -- NC for no context; tcBracket does that+       ; let rep = getRuntimeRep expr_ty         ; meta_ty <- tcTExpTy expr_ty        ; ps' <- readMutVar ps_ref        ; texpco <- tcLookupId unsafeTExpCoerceName        ; tcWrapResultO (Shouldn'tHappenOrigin "TExpBr")                        rn_expr-                       (unLoc (mkHsApp (nlHsTyApp texpco [expr_ty])+                       (unLoc (mkHsApp (nlHsTyApp texpco [rep, expr_ty])                                       (noLoc (HsTcBracketOut noExt brack ps'))))                        meta_ty res_ty } tcTypedBracket _ other_brack _@@ -230,7 +231,8 @@   = do { unless (isTauTy exp_ty) $ addErr (err_msg exp_ty)        ; q    <- tcLookupTyCon qTyConName        ; texp <- tcLookupTyCon tExpTyConName-       ; return (mkTyConApp q [mkTyConApp texp [exp_ty]]) }+       ; let rep = getRuntimeRep exp_ty+       ; return (mkTyConApp q [mkTyConApp texp [rep, exp_ty]]) }   where     err_msg ty       = vcat [ text "Illegal polytype:" <+> ppr ty@@ -469,12 +471,13 @@     -- A splice inside brackets tcNestedSplice pop_stage (TcPending ps_var lie_var) splice_name expr res_ty   = do { res_ty <- expTypeToType res_ty+       ; let rep = getRuntimeRep res_ty        ; meta_exp_ty <- tcTExpTy res_ty        ; expr' <- setStage pop_stage $                   setConstraintVar lie_var $                   tcMonoExpr expr (mkCheckExpType meta_exp_ty)        ; untypeq <- tcLookupId unTypeQName-       ; let expr'' = mkHsApp (nlHsTyApp untypeq [res_ty]) expr'+       ; let expr'' = mkHsApp (nlHsTyApp untypeq [rep, res_ty]) expr'        ; ps <- readMutVar ps_var        ; writeMutVar ps_var (PendingTcSplice splice_name expr'' : ps) 
compiler/typecheck/TcTyClsDecls.hs view
@@ -1497,7 +1497,7 @@   = -- See Note [Type-checking default assoc decls]     setSrcSpan loc $     tcAddFamInstCtxt (text "default type instance") tc_name $-    do { traceTc "tcDefaultAssocDecl" (ppr tc_name)+    do { traceTc "tcDefaultAssocDecl 1" (ppr tc_name)        ; let fam_tc_name = tyConName fam_tc              fam_arity = length (tyConVisibleTyVars fam_tc) @@ -1524,14 +1524,46 @@                                                     imp_vars exp_vars                                                     hs_pats hs_rhs_ty -         -- See Note [Type-checking default assoc decls]-       ; traceTc "tcDefault" (vcat [ppr (tyConTyVars fam_tc), ppr qtvs, ppr pats])-       ; case tcMatchTys pats (mkTyVarTys (tyConTyVars fam_tc)) of-           Just subst -> return (Just (substTyUnchecked subst rhs_ty, loc) )-           Nothing    -> failWithTc (defaultAssocKindErr fam_tc)-           -- We check for well-formedness and validity later,-           -- in checkValidClass+       ; let fam_tvs = tyConTyVars fam_tc+       ; traceTc "tcDefaultAssocDecl 2" (vcat+           [ text "fam_tvs" <+> ppr fam_tvs+           , text "qtvs"    <+> ppr qtvs+           , text "pats"    <+> ppr pats+           , text "rhs_ty"  <+> ppr rhs_ty+           ])+       ; pat_tvs <- traverse (extract_tv pats rhs_ty) pats+       ; let subst = zipTvSubst pat_tvs (mkTyVarTys fam_tvs)+       ; pure $ Just (substTyUnchecked subst rhs_ty, loc)+           -- We also perform other checks for well-formedness and validity+           -- later, in checkValidClass      }+  where+    -- Checks that a pattern on the LHS of a default is a type+    -- variable. If so, return the underlying type variable, and if+    -- not, throw an error.+    -- See Note [Type-checking default assoc decls]+    extract_tv :: [Type] -- All default instance type patterns+                         -- (only used for error message purposes)+               -> Type   -- The default instance's right-hand side type+                         -- (only used for error message purposes)+               -> Type   -- The particular type pattern from which to extract+                         -- its underlying type variable+               -> TcM TyVar+    extract_tv pats rhs_ty pat =+      case getTyVar_maybe pat of+        Just tv -> pure tv+        Nothing ->+          -- Per Note [Type-checking default assoc decls], we already+          -- know by this point that if any arguments in the default+          -- instance aren't type variables, then they must be+          -- invisible kind arguments. Therefore, always display the+          -- error message with -fprint-explicit-kinds enabled.+          failWithTc $ pprWithExplicitKindsWhen True $+          hang (text "Illegal argument" <+> quotes (ppr pat) <+> text "in:")+             2 (vcat [ quotes (text "type" <+> ppr (mkTyConApp fam_tc pats)+                       <+> equals <+> ppr rhs_ty)+                     , text "The arguments to" <+> quotes (ppr fam_tc)+                       <+> text "must all be type variables" ]) tcDefaultAssocDecl _ [dL->L _ (XFamEqn _)] = panic "tcDefaultAssocDecl" tcDefaultAssocDecl _ [dL->L _ (FamEqn _ _ _ (XLHsQTyVars _) _ _)]   = panic "tcDefaultAssocDecl"@@ -1544,8 +1576,8 @@ Consider this default declaration for an associated type     class C a where-      type F (a :: k) b :: *-      type F x y = Proxy x -> y+      type F (a :: k) b :: Type+      type F (x :: j) y = Proxy x -> y  Note that the class variable 'a' doesn't scope over the default assoc decl (rather oddly I think), and (less oddly) neither does the second@@ -1555,17 +1587,26 @@  However we store the default rhs (Proxy x -> y) in F's TyCon, using F's own type variables, so we need to convert it to (Proxy a -> b).-We do this by calling tcMatchTys to match them up.  This also ensures-that x's kind matches a's and similarly for y and b.  The error-message isn't great, mind you.  (#11361 was caused by not doing a-proper tcMatchTys here.)+We do this by creating a substitution [j |-> k, x |-> a, b |-> y] and+applying this substitution to the RHS. -Recall also that the left-hand side of an associated type family-default is always just variables -- no tycons here. Accordingly,-the patterns used in the tcMatchTys won't actually be knot-tied,-even though we're in the knot. This is too delicate for my taste,-but it works.+In order to create this substitution, we must first ensure that all of+the arguments in the default instance consist of type variables. The parser+already checks this to a certain degree (see RdrHsSyn.checkTyVars), but+we must be wary of kind arguments being instantiated, which the parser cannot+catch so easily. Consider this erroneous program (inspired by #11361): +   class C a where+      type F (a :: k) b :: Type+      type F x        b = x++If you squint, you'll notice that the kind of `x` is actually Type. However,+we cannot substitute from [Type |-> k], so we reject this default.++Since the LHS of an associated type family default is always just variables,+it won't contain any tycons. Accordingly, the patterns used in the substitution+won't actually be knot-tied, even though we're in the knot. This is too+delicate for my taste, but it works. -}  {- *********************************************************************@@ -3848,11 +3889,6 @@ wrongNumberOfParmsErr max_args   = text "Number of parameters must match family declaration; expected"     <+> ppr max_args--defaultAssocKindErr :: TyCon -> SDoc-defaultAssocKindErr fam_tc-  = text "Kind mis-match on LHS of default declaration for"-    <+> quotes (ppr fam_tc)  badRoleAnnot :: Name -> Role -> Role -> SDoc badRoleAnnot var annot inferred
ghc-lib.cabal view
@@ -1,7 +1,7 @@ cabal-version: >=1.22 build-type: Simple name: ghc-lib-version: 0.20190402+version: 0.20190423 license: BSD3 license-file: LICENSE category: Development@@ -52,7 +52,7 @@ tested-with:GHC==8.6.3 source-repository head     type: git-    location: git://git.haskell.org/ghc.git+    location: git@github.com:digital-asset/ghc-lib.git  library     default-language:   Haskell2010@@ -84,7 +84,7 @@         transformers == 0.5.*,         process >= 1 && < 1.7,         hpc == 0.6.*,-        ghc-lib-parser == 0.20190402+        ghc-lib-parser == 0.20190423     build-tools: alex >= 3.1, happy >= 1.19.4     other-extensions:         BangPatterns
ghc-lib/generated/ghcversion.h view
@@ -5,7 +5,8 @@ # define __GLASGOW_HASKELL__ 809 #endif -#define __GLASGOW_HASKELL_PATCHLEVEL1__ 20190402+#define __GLASGOW_HASKELL_PATCHLEVEL1__ 0+#define __GLASGOW_HASKELL_PATCHLEVEL2__ 20190423  #define MIN_VERSION_GLASGOW_HASKELL(ma,mi,pl1,pl2) (\    ((ma)*100+(mi)) <  __GLASGOW_HASKELL__ || \
ghc-lib/stage1/lib/settings view
@@ -1,35 +1,34 @@-[("GCC extra via C opts", " -fwrapv -fno-builtin"),- ("C compiler command", "gcc"),- ("C compiler flags", ""),- ("C compiler link flags", " "),- ("C compiler supports -no-pie", "NO"),- ("Haskell CPP command","gcc"),- ("Haskell CPP flags","-E -undef -traditional -Wno-invalid-pp-token -Wno-unicode -Wno-trigraphs"),- ("ld command", "ld"),- ("ld flags", ""),- ("ld supports compact unwind", "YES"),- ("ld supports build-id", "NO"),- ("ld supports filelist", "YES"),- ("ld is GNU ld", "NO"),- ("ar command", "ar"),- ("ar flags", "qcls"),- ("ar supports at file", "NO"),- ("ranlib command", "ranlib"),- ("touch command", "touch"),- ("dllwrap command", "/bin/false"),- ("windres command", "/bin/false"),- ("libtool command", "libtool"),- ("cross compiling", "NO"),- ("target os", "OSDarwin"),- ("target arch", "ArchX86_64"),- ("target word size", "8"),- ("target has GNU nonexec stack", "False"),- ("target has .ident directive", "True"),- ("target has subsections via symbols", "True"),- ("target has RTS linker", "YES"),- ("Unregisterised", "NO"),- ("LLVM llc command", "llc"),- ("LLVM opt command", "opt"),- ("LLVM clang command", "clang")- ]-+[("GCC extra via C opts", " -fwrapv -fno-builtin")+,("C compiler command", "gcc")+,("C compiler flags", "")+,("C compiler link flags", " ")+,("C compiler supports -no-pie", "NO")+,("Haskell CPP command", "gcc")+,("Haskell CPP flags", "-E -undef -traditional -Wno-invalid-pp-token -Wno-unicode -Wno-trigraphs")+,("ld command", "ld")+,("ld flags", "")+,("ld supports compact unwind", "YES")+,("ld supports build-id", "NO")+,("ld supports filelist", "YES")+,("ld is GNU ld", "NO")+,("ar command", "ar")+,("ar flags", "qcls")+,("ar supports at file", "NO")+,("ranlib command", "ranlib")+,("touch command", "touch")+,("dllwrap command", "/bin/false")+,("windres command", "/bin/false")+,("libtool command", "libtool")+,("cross compiling", "NO")+,("target os", "OSDarwin")+,("target arch", "ArchX86_64")+,("target word size", "8")+,("target has GNU nonexec stack", "False")+,("target has .ident directive", "True")+,("target has subsections via symbols", "True")+,("target has RTS linker", "YES")+,("Unregisterised", "NO")+,("LLVM llc command", "llc")+,("LLVM opt command", "opt")+,("LLVM clang command", "clang")+]
ghc/GHCi/UI.hs view
@@ -102,7 +102,7 @@ import Data.Function import Data.IORef ( IORef, modifyIORef, newIORef, readIORef, writeIORef ) import Data.List ( find, group, intercalate, intersperse, isPrefixOf, nub,-                   partition, sort, sortBy )+                   partition, sort, sortBy, (\\) ) import qualified Data.Set as S import Data.Maybe import Data.Map (Map)@@ -351,13 +351,16 @@   "\n" ++   "   :set <option> ...           set options\n" ++   "   :seti <option> ...          set options for interactive evaluation only\n" +++  "   :set local-config { source | ignore }\n" +++  "                               set whether to source .ghci in current dir\n" +++  "                               (loading untrusted config is a security issue)\n" ++   "   :set args <arg> ...         set the arguments returned by System.getArgs\n" ++   "   :set prog <progname>        set the value returned by System.getProgName\n" ++   "   :set prompt <prompt>        set the prompt used in GHCi\n" ++   "   :set prompt-cont <prompt>   set the continuation prompt used in GHCi\n" ++   "   :set prompt-function <expr> set the function to handle the prompt\n" ++-  "   :set prompt-cont-function <expr>" ++-                     "set the function to handle the continuation prompt\n" +++  "   :set prompt-cont-function <expr>\n" +++  "                               set the function to handle the continuation prompt\n" ++   "   :set editor <cmd>           set the command used for :edit\n" ++   "   :set stop [<n>] <cmd>       set the command to run when a breakpoint is hit\n" ++   "   :unset <option> ...         unset options\n" ++@@ -482,6 +485,7 @@                    stop               = default_stop,                    editor             = default_editor,                    options            = [],+                   localConfig        = SourceLocalConfig,                    -- We initialize line number as 0, not 1, because we use                    -- current line number while reporting errors which is                    -- incremented after reading a line.@@ -566,8 +570,6 @@   let    ignore_dot_ghci = gopt Opt_IgnoreDotGhci dflags -   current_dir = return (Just ".ghci")-    app_user_dir = liftIO $ withGhcAppData                     (\dir -> return (Just (dir </> "ghci.conf")))                     (return Nothing)@@ -606,18 +608,45 @@    setGHCContextFromGHCiState -  dot_cfgs <- if ignore_dot_ghci then return [] else do-    dot_files <- catMaybes <$> sequence [ current_dir, app_user_dir, home_dir ]-    liftIO $ filterM checkFileAndDirPerms dot_files-  mdot_cfgs <- liftIO $ mapM canonicalizePath' dot_cfgs+  processedCfgs <- if ignore_dot_ghci+    then pure []+    else do+      userCfgs <- do+        paths <- catMaybes <$> sequence [ app_user_dir, home_dir ]+        checkedPaths <- liftIO $ filterM checkFileAndDirPerms paths+        liftIO . fmap (nub . catMaybes) $ mapM canonicalizePath' checkedPaths +      localCfg <- do+        let path = ".ghci"+        ok <- liftIO $ checkFileAndDirPerms path+        if ok then liftIO $ canonicalizePath' path else pure Nothing++      mapM_ sourceConfigFile userCfgs+        -- Process the global and user .ghci+        -- (but not $CWD/.ghci or CLI args, yet)++      behaviour <- localConfig <$> getGHCiState++      processedLocalCfg <- case localCfg of+        Just path | path `notElem` userCfgs ->+          -- don't read .ghci twice if CWD is $HOME+          case behaviour of+            SourceLocalConfig -> localCfg <$ sourceConfigFile path+            IgnoreLocalConfig -> pure Nothing+        _ -> pure Nothing++      pure $ maybe id (:) processedLocalCfg userCfgs+   let arg_cfgs = reverse $ ghciScripts dflags     -- -ghci-script are collected in reverse order     -- We don't require that a script explicitly added by -ghci-script     -- is owned by the current user. (#6017)-  mapM_ sourceConfigFile $ nub $ (catMaybes mdot_cfgs) ++ arg_cfgs-    -- nub, because we don't want to read .ghci twice if the CWD is $HOME. +  mapM_ sourceConfigFile $ nub arg_cfgs \\ processedCfgs+    -- Dedup, and remove any configs we already processed.+    -- Importantly, if $PWD/.ghci was ignored due to configuration,+    -- explicitly specifying it does cause it to be processed.+   -- Perform a :load for files given on the GHCi command line   -- When in -e mode, if the load fails then we want to stop   -- immediately rather than going on to evaluate the expression.@@ -2117,7 +2146,9 @@      let fs    = mkFastString fp         span' = mkRealSrcSpan (mkRealSrcLoc fs sl sc)-                              (mkRealSrcLoc fs el ec)+                              -- End column of RealSrcSpan is the column+                              -- after the end of the span.+                              (mkRealSrcLoc fs el (ec + 1))      return (span',trailer)   where@@ -2163,7 +2194,9 @@     sl = srcSpanStartLine spn     sc = srcSpanStartCol  spn     el = srcSpanEndLine   spn-    ec = srcSpanEndCol    spn+    -- The end column is the column after the end of the span see the+    -- RealSrcSpan module+    ec = let ec' = srcSpanEndCol    spn in if ec' == 0 then 0 else ec' - 1  ----------------------------------------------------------------------------- -- | @:kind@ command@@ -2663,6 +2696,8 @@      Right ("editor",  rest) -> setEditor  $ dropWhile isSpace rest     Right ("stop",    rest) -> setStop    $ dropWhile isSpace rest+    Right ("local-config", rest) ->+        setLocalConfigBehaviour $ dropWhile isSpace rest     _ -> case toArgs str of          Left err -> liftIO (hPutStrLn stderr err)          Right wds -> setOptions wds@@ -2728,6 +2763,7 @@  setArgs, setOptions :: GhciMonad m => [String] -> m () setProg, setEditor, setStop :: GhciMonad m => String -> m ()+setLocalConfigBehaviour :: GhciMonad m => String -> m ()  setArgs args = do   st <- getGHCiState@@ -2740,6 +2776,14 @@   setGHCiState st { progname = prog, evalWrapper = wrapper }  setEditor cmd = modifyGHCiState (\st -> st { editor = cmd })++setLocalConfigBehaviour s+  | s == "source" =+      modifyGHCiState (\st -> st { localConfig = SourceLocalConfig })+  | s == "ignore" =+      modifyGHCiState (\st -> st { localConfig = IgnoreLocalConfig })+  | otherwise = throwGhcException+      (CmdLineError "syntax:  :set local-config { source | ignore }")  setStop str@(c:_) | isDigit c   = do let (nm_str,rest) = break (not.isDigit) str
ghc/GHCi/UI/Info.hs view
@@ -75,6 +75,9 @@       -- locality, definition location, etc.     } +instance Outputable SpanInfo where+  ppr (SpanInfo s t i) = ppr s <+> ppr t <+> ppr i+ -- | Test whether second span is contained in (or equal to) first span. -- This is basically 'containsSpan' for 'SpanInfo' containsSpanInfo :: SpanInfo -> SpanInfo -> Bool
ghc/GHCi/UI/Monad.hs view
@@ -15,6 +15,7 @@         GHCiState(..), GhciMonad(..),         GHCiOption(..), isOptionSet, setOption, unsetOption,         Command(..), CommandResult(..), cmdSuccess,+        LocalConfigBehaviour(..),         PromptFunction,         BreakLocation(..),         TickArray,@@ -79,6 +80,7 @@         prompt_cont    :: PromptFunction,         editor         :: String,         stop           :: String,+        localConfig    :: LocalConfigBehaviour,         options        :: [GHCiOption],         line_number    :: !Int,         -- ^ input line         break_ctr      :: !Int,@@ -196,6 +198,15 @@         | CollectInfo           -- collect and cache information about                                 -- modules after load         deriving Eq++-- | Treatment of ./.ghci files.  For now we either load or+-- ignore.  But later we could implement a "safe mode" where+-- only safe operations are performed.+--+data LocalConfigBehaviour+  = SourceLocalConfig+  | IgnoreLocalConfig+  deriving (Eq)  data BreakLocation    = BreakLocation
includes/CodeGen.Platform.hs view
@@ -41,65 +41,59 @@ #  define r15   15 # endif -# define fake0 16-# define fake1 17-# define fake2 18-# define fake3 19-# define fake4 20-# define fake5 21  -- N.B. XMM, YMM, and ZMM are all aliased to the same hardware registers hence -- being assigned the same RegNos.-# define xmm0  24-# define xmm1  25-# define xmm2  26-# define xmm3  27-# define xmm4  28-# define xmm5  29-# define xmm6  30-# define xmm7  31-# define xmm8  32-# define xmm9  33-# define xmm10 34-# define xmm11 35-# define xmm12 36-# define xmm13 37-# define xmm14 38-# define xmm15 39+# define xmm0  16+# define xmm1  17+# define xmm2  18+# define xmm3  19+# define xmm4  20+# define xmm5  21+# define xmm6  22+# define xmm7  23+# define xmm8  24+# define xmm9  25+# define xmm10 26+# define xmm11 27+# define xmm12 28+# define xmm13 29+# define xmm14 30+# define xmm15 31 -# define ymm0  24-# define ymm1  25-# define ymm2  26-# define ymm3  27-# define ymm4  28-# define ymm5  29-# define ymm6  30-# define ymm7  31-# define ymm8  32-# define ymm9  33-# define ymm10 34-# define ymm11 35-# define ymm12 36-# define ymm13 37-# define ymm14 38-# define ymm15 39+# define ymm0  16+# define ymm1  17+# define ymm2  18+# define ymm3  19+# define ymm4  20+# define ymm5  21+# define ymm6  22+# define ymm7  23+# define ymm8  24+# define ymm9  25+# define ymm10 26+# define ymm11 27+# define ymm12 28+# define ymm13 29+# define ymm14 30+# define ymm15 31 -# define zmm0  24-# define zmm1  25-# define zmm2  26-# define zmm3  27-# define zmm4  28-# define zmm5  29-# define zmm6  30-# define zmm7  31-# define zmm8  32-# define zmm9  33-# define zmm10 34-# define zmm11 35-# define zmm12 36-# define zmm13 37-# define zmm14 38-# define zmm15 39+# define zmm0  16+# define zmm1  17+# define zmm2  18+# define zmm3  19+# define zmm4  20+# define zmm5  21+# define zmm6  22+# define zmm7  23+# define zmm8  24+# define zmm9  25+# define zmm10 26+# define zmm11 27+# define zmm12 28+# define zmm13 29+# define zmm14 30+# define zmm15 31  -- Note: these are only needed for ARM/ARM64 because globalRegMaybe is now used in CmmSink.hs. -- Since it's only used to check 'isJust', the actual values don't matter, thus