diff options
author | Alex Mason <Axman6@gmail.com> | 2023-01-13 22:38:13 +1100 |
---|---|---|
committer | Marge Bot <ben+marge-bot@smart-cactus.org> | 2023-03-21 18:11:04 -0400 |
commit | e8b4aac437b2620d93546a57eb5818f317a4549e (patch) | |
tree | a7987467436407b25e5fd169b86390e664a4b7cf | |
parent | be1d4be8d09072091b77cb68ccf234434754af00 (diff) | |
download | haskell-e8b4aac437b2620d93546a57eb5818f317a4549e.tar.gz |
Allow LLVM backend to use HDoc for faster file generation.
Also remove the MetaStmt constructor from LlvmStatement and places the annotations into the Store statement.
Includes “Implement a workaround for -no-asm-shortcutting bug“ (https://gitlab.haskell.org/ghc/ghc/-/commit/2fda9e0df886cc551e2cd6b9c2a384192bdc3045)
-rw-r--r-- | compiler/GHC/CmmToLlvm.hs | 48 | ||||
-rw-r--r-- | compiler/GHC/CmmToLlvm/Base.hs | 8 | ||||
-rw-r--r-- | compiler/GHC/CmmToLlvm/CodeGen.hs | 60 | ||||
-rw-r--r-- | compiler/GHC/CmmToLlvm/Ppr.hs | 19 | ||||
-rw-r--r-- | compiler/GHC/Llvm/MetaData.hs | 7 | ||||
-rw-r--r-- | compiler/GHC/Llvm/Ppr.hs | 457 | ||||
-rw-r--r-- | compiler/GHC/Llvm/Syntax.hs | 7 | ||||
-rw-r--r-- | compiler/GHC/Llvm/Types.hs | 266 |
8 files changed, 524 insertions, 348 deletions
diff --git a/compiler/GHC/CmmToLlvm.hs b/compiler/GHC/CmmToLlvm.hs index ea5884405e..cce31e630e 100644 --- a/compiler/GHC/CmmToLlvm.hs +++ b/compiler/GHC/CmmToLlvm.hs @@ -91,7 +91,7 @@ llvmCodeGen logger cfg h cmm_stream llvmCodeGen' :: LlvmCgConfig -> Stream.Stream IO RawCmmGroup a -> LlvmM a llvmCodeGen' cfg cmm_stream = do -- Preamble - renderLlvm header + renderLlvm (llvmHeader cfg) (llvmHeader cfg) ghcInternalFunctions cmmMetaLlvmPrelude @@ -99,20 +99,23 @@ llvmCodeGen' cfg cmm_stream a <- Stream.consume cmm_stream liftIO llvmGroupLlvmGens -- Declare aliases for forward references - renderLlvm . pprLlvmData cfg =<< generateExternDecls + decls <- generateExternDecls + renderLlvm (pprLlvmData cfg decls) + (pprLlvmData cfg decls) -- Postamble cmmUsedLlvmGens return a - where - header :: SDoc - header = - let target = llvmCgLlvmTarget cfg - llvmCfg = llvmCgLlvmConfig cfg - in (text "target datalayout = \"" <> text (getDataLayout llvmCfg target) <> text "\"") - $+$ (text "target triple = \"" <> text target <> text "\"") +llvmHeader :: IsDoc doc => LlvmCgConfig -> doc +llvmHeader cfg = + let target = llvmCgLlvmTarget cfg + llvmCfg = llvmCgLlvmConfig cfg + in lines_ + [ text "target datalayout = \"" <> text (getDataLayout llvmCfg target) <> text "\"" + , text "target triple = \"" <> text target <> text "\"" ] + where getDataLayout :: LlvmConfig -> String -> String getDataLayout config target = case lookup target (llvmTargets config) of @@ -121,6 +124,8 @@ llvmCodeGen' cfg cmm_stream text "Target:" <+> text target $$ hang (text "Available targets:") 4 (vcat $ map (text . fst) $ llvmTargets config) +{-# SPECIALIZE llvmHeader :: LlvmCgConfig -> SDoc #-} +{-# SPECIALIZE llvmHeader :: LlvmCgConfig -> HDoc #-} -- see Note [SPECIALIZE to HDoc] in GHC.Utils.Outputable llvmGroupLlvmGens :: RawCmmGroup -> LlvmM () llvmGroupLlvmGens cmm = do @@ -156,10 +161,11 @@ cmmDataLlvmGens statics = funInsert l ty regGlobal _ = pure () mapM_ regGlobal gs - gss' <- mapM aliasify $ gs + gss' <- mapM aliasify gs cfg <- getConfig - renderLlvm $ pprLlvmData cfg (concat gss', concat tss) + renderLlvm (pprLlvmData cfg (concat gss', concat tss)) + (pprLlvmData cfg (concat gss', concat tss)) -- | Complete LLVM code generation phase for a single top-level chunk of Cmm. cmmLlvmGen ::RawCmmDecl -> LlvmM () @@ -175,12 +181,12 @@ cmmLlvmGen cmm@CmmProc{} = do -- generate llvm code from cmm llvmBC <- withClearVars $ genLlvmProc fixed_cmm - -- pretty print - (docs, ivars) <- fmap unzip $ mapM pprLlvmCmmDecl llvmBC - - -- Output, note down used variables - renderLlvm (vcat docs) - mapM_ markUsedVar $ concat ivars + -- pretty print - print as we go, since we produce HDocs, we know + -- no nesting state needs to be maintained for the SDocs. + forM_ llvmBC (\decl -> do + (hdoc, sdoc) <- pprLlvmCmmDecl decl + renderLlvm (hdoc $$ empty) (sdoc $$ empty) + ) cmmLlvmGen _ = return () @@ -204,7 +210,8 @@ cmmMetaLlvmPrelude = do -- name. Nothing -> [ MetaStr name ] cfg <- getConfig - renderLlvm $ ppLlvmMetas cfg metas + renderLlvm (ppLlvmMetas cfg metas) + (ppLlvmMetas cfg metas) -- ----------------------------------------------------------------------------- -- | Marks variables as used where necessary @@ -229,4 +236,7 @@ cmmUsedLlvmGens = do lmUsed = LMGlobal lmUsedVar (Just usedArray) if null ivars then return () - else getConfig >>= renderLlvm . flip pprLlvmData ([lmUsed], []) + else do + cfg <- getConfig + renderLlvm (pprLlvmData cfg ([lmUsed], [])) + (pprLlvmData cfg ([lmUsed], [])) diff --git a/compiler/GHC/CmmToLlvm/Base.hs b/compiler/GHC/CmmToLlvm/Base.hs index d625ae341e..0c9605cd3b 100644 --- a/compiler/GHC/CmmToLlvm/Base.hs +++ b/compiler/GHC/CmmToLlvm/Base.hs @@ -371,13 +371,13 @@ dumpIfSetLlvm flag hdr fmt doc = do liftIO $ putDumpFileMaybe logger flag hdr fmt doc -- | Prints the given contents to the output handle -renderLlvm :: Outp.SDoc -> LlvmM () -renderLlvm sdoc = do +renderLlvm :: Outp.HDoc -> Outp.SDoc -> LlvmM () +renderLlvm hdoc sdoc = do -- Write to output ctx <- llvmCgContext <$> getConfig out <- getEnv envOutput - liftIO $ Outp.bufLeftRenderSDoc ctx out sdoc + liftIO $ Outp.bPutHDoc out ctx hdoc -- Dump, if requested dumpIfSetLlvm Opt_D_dump_llvm "LLVM Code" FormatLLVM sdoc @@ -428,7 +428,7 @@ ghcInternalFunctions = do let n' = fsLit n decl = LlvmFunctionDecl n' ExternallyVisible CC_Ccc ret FixedArgs (tysToParams args) Nothing - renderLlvm $ ppLlvmFunctionDecl decl + renderLlvm (ppLlvmFunctionDecl decl) (ppLlvmFunctionDecl decl) funInsert n' (LMFunction decl) -- ---------------------------------------------------------------------------- diff --git a/compiler/GHC/CmmToLlvm/CodeGen.hs b/compiler/GHC/CmmToLlvm/CodeGen.hs index 60eb1624b2..1d658b359e 100644 --- a/compiler/GHC/CmmToLlvm/CodeGen.hs +++ b/compiler/GHC/CmmToLlvm/CodeGen.hs @@ -207,7 +207,7 @@ genCall (PrimTarget (MO_UF_Conv w)) [dst] [e] = runStmtsDecls $ do castV <- lift $ mkLocalVar ty ve <- exprToVarW e statement $ Assignment castV $ Cast LM_Uitofp ve width - statement $ Store castV dstV Nothing + statement $ Store castV dstV Nothing [] genCall (PrimTarget (MO_UF_Conv _)) [_] args = panic $ "genCall: Too many arguments to MO_UF_Conv. " ++ @@ -263,12 +263,12 @@ genCall (PrimTarget (MO_AtomicRMW width amop)) [dst] [addr, n] = runStmtsDecls $ AMO_Or -> LAO_Or AMO_Xor -> LAO_Xor retVar <- doExprW targetTy $ AtomicRMW op ptrVar nVar SyncSeqCst - statement $ Store retVar dstVar Nothing + statement $ Store retVar dstVar Nothing [] genCall (PrimTarget (MO_AtomicRead _ mem_ord)) [dst] [addr] = runStmtsDecls $ do dstV <- getCmmRegW (CmmLocal dst) v1 <- genLoadW (Just mem_ord) addr (localRegType dst) NaturallyAligned - statement $ Store v1 dstV Nothing + statement $ Store v1 dstV Nothing [] genCall (PrimTarget (MO_Cmpxchg _width)) [dst] [addr, old, new] = runStmtsDecls $ do @@ -282,7 +282,7 @@ genCall (PrimTarget (MO_Cmpxchg _width)) retVar <- doExprW (LMStructU [targetTy,i1]) $ CmpXChg ptrVar oldVar newVar SyncSeqCst SyncSeqCst retVar' <- doExprW targetTy $ ExtractV retVar 0 - statement $ Store retVar' dstVar Nothing + statement $ Store retVar' dstVar Nothing [] genCall (PrimTarget (MO_Xchg _width)) [dst] [addr, val] = runStmtsDecls $ do dstV <- getCmmRegW (CmmLocal dst) :: WriterT LlvmAccum LlvmM LlvmVar @@ -292,7 +292,7 @@ genCall (PrimTarget (MO_Xchg _width)) [dst] [addr, val] = runStmtsDecls $ do ptrExpr = Cast LM_Inttoptr addrVar ptrTy ptrVar <- doExprW ptrTy ptrExpr resVar <- doExprW (getVarType valVar) (AtomicRMW LAO_Xchg ptrVar valVar SyncSeqCst) - statement $ Store resVar dstV Nothing + statement $ Store resVar dstV Nothing [] genCall (PrimTarget (MO_AtomicWrite _width mem_ord)) [] [addr, val] = runStmtsDecls $ do addrVar <- exprToVarW addr @@ -353,8 +353,8 @@ genCall (PrimTarget (MO_U_Mul2 w)) [dstH, dstL] [lhs, rhs] = runStmtsDecls $ do retH <- doExprW width $ Cast LM_Trunc retShifted width dstRegL <- getCmmRegW (CmmLocal dstL) dstRegH <- getCmmRegW (CmmLocal dstH) - statement $ Store retL dstRegL Nothing - statement $ Store retH dstRegH Nothing + statement $ Store retL dstRegL Nothing [] + statement $ Store retH dstRegH Nothing [] genCall (PrimTarget (MO_S_Mul2 w)) [dstC, dstH, dstL] [lhs, rhs] = runStmtsDecls $ do let width = widthToLlvmInt w @@ -385,9 +385,9 @@ genCall (PrimTarget (MO_S_Mul2 w)) [dstC, dstH, dstL] [lhs, rhs] = runStmtsDecls dstRegL <- getCmmRegW (CmmLocal dstL) dstRegH <- getCmmRegW (CmmLocal dstH) dstRegC <- getCmmRegW (CmmLocal dstC) - statement $ Store retL dstRegL Nothing - statement $ Store retH dstRegH Nothing - statement $ Store retC dstRegC Nothing + statement $ Store retL dstRegL Nothing [] + statement $ Store retH dstRegH Nothing [] + statement $ Store retC dstRegC Nothing [] -- MO_U_QuotRem2 is another case we handle by widening the registers to double -- the width and use normal LLVM instructions (similarly to the MO_U_Mul2). The @@ -421,8 +421,8 @@ genCall (PrimTarget (MO_U_QuotRem2 w)) retRem <- narrow retExtRem dstRegQ <- lift $ getCmmReg (CmmLocal dstQ) dstRegR <- lift $ getCmmReg (CmmLocal dstR) - statement $ Store retDiv dstRegQ Nothing - statement $ Store retRem dstRegR Nothing + statement $ Store retDiv dstRegQ Nothing [] + statement $ Store retRem dstRegR Nothing [] -- Handle the MO_{Add,Sub}IntC separately. LLVM versions return a record from -- which we need to extract the actual values. @@ -529,7 +529,7 @@ genCall target res args = do vreg <- getCmmRegW (CmmLocal creg) if retTy == pLower (getVarType vreg) then do - statement $ Store v1 vreg Nothing + statement $ Store v1 vreg Nothing [] doReturn else do let ty = pLower $ getVarType vreg @@ -541,7 +541,7 @@ genCall target res args = do ++ " returned type!" v2 <- doExprW ty $ Cast op v1 ty - statement $ Store v2 vreg Nothing + statement $ Store v2 vreg Nothing [] doReturn -- | Generate a call to an LLVM intrinsic that performs arithmetic operation @@ -570,8 +570,8 @@ genCallWithOverflow t@(PrimTarget op) w [dstV, dstO] [lhs, rhs] = do (overflow, zext) <- doExpr width $ Cast LM_Zext overflowBit width dstRegV <- getCmmReg (CmmLocal dstV) dstRegO <- getCmmReg (CmmLocal dstO) - let storeV = Store value dstRegV Nothing - storeO = Store overflow dstRegO Nothing + let storeV = Store value dstRegV Nothing [] + storeO = Store overflow dstRegO Nothing [] return (stmts `snocOL` zext `snocOL` storeV `snocOL` storeO, top) genCallWithOverflow _ _ _ _ = panic "genCallExtract: wrong ForeignTarget or number of arguments" @@ -636,7 +636,7 @@ genCallSimpleCast w t@(PrimTarget op) [dst] args = do (retV, s1) <- doExpr width $ Call StdCall fptr argsV' [] (retVs', stmts5) <- castVars (cmmPrimOpRetValSignage op) [(retV,dstTy)] let retV' = singletonPanic "genCallSimpleCast" retVs' - let s2 = Store retV' dstV Nothing + let s2 = Store retV' dstV Nothing [] let stmts = stmts2 `appOL` stmts4 `snocOL` s1 `appOL` stmts5 `snocOL` s2 @@ -668,7 +668,7 @@ genCallSimpleCast2 w t@(PrimTarget op) [dst] args = do (retV, s1) <- doExpr width $ Call StdCall fptr argsV' [] (retVs', stmts5) <- castVars (cmmPrimOpRetValSignage op) [(retV,dstTy)] let retV' = singletonPanic "genCallSimpleCast2" retVs' - let s2 = Store retV' dstV Nothing + let s2 = Store retV' dstV Nothing [] let stmts = stmts2 `appOL` stmts4 `snocOL` s1 `appOL` stmts5 `snocOL` s2 @@ -1098,16 +1098,16 @@ genAssign reg val = do -- Some registers are pointer types, so need to cast value to pointer LMPointer _ | getVarType vval == llvmWord platform -> do (v, s1) <- doExpr ty $ Cast LM_Inttoptr vval ty - let s2 = Store v vreg Nothing + let s2 = Store v vreg Nothing [] return (stmts `snocOL` s1 `snocOL` s2, top2) LMVector _ _ -> do (v, s1) <- doExpr ty $ Cast LM_Bitcast vval ty - let s2 = mkStore v vreg NaturallyAligned + let s2 = mkStore v vreg NaturallyAligned [] return (stmts `snocOL` s1 `snocOL` s2, top2) _ -> do - let s1 = Store vval vreg Nothing + let s1 = Store vval vreg Nothing [] return (stmts `snocOL` s1, top2) @@ -1158,7 +1158,7 @@ genStore_fast addr r n val alignment case pLower grt == getVarType vval of -- were fine True -> do - let s3 = MetaStmt meta $ mkStore vval ptr alignment + let s3 = mkStore vval ptr alignment meta return (stmts `appOL` s1 `snocOL` s2 `snocOL` s3, top) @@ -1166,7 +1166,7 @@ genStore_fast addr r n val alignment False -> do let ty = (pLift . getVarType) vval (ptr', s3) <- doExpr ty $ Cast LM_Bitcast ptr ty - let s4 = MetaStmt meta $ mkStore vval ptr' alignment + let s4 = mkStore vval ptr' alignment meta return (stmts `appOL` s1 `snocOL` s2 `snocOL` s3 `snocOL` s4, top) @@ -1189,17 +1189,17 @@ genStore_slow addr val alignment meta = do -- sometimes we need to cast an int to a pointer before storing LMPointer ty@(LMPointer _) | getVarType vval == llvmWord platform -> do (v, s1) <- doExpr ty $ Cast LM_Inttoptr vval ty - let s2 = MetaStmt meta $ mkStore v vaddr alignment + let s2 = mkStore v vaddr alignment meta return (stmts `snocOL` s1 `snocOL` s2, top1 ++ top2) LMPointer _ -> do - let s1 = MetaStmt meta $ mkStore vval vaddr alignment + let s1 = mkStore vval vaddr alignment meta return (stmts `snocOL` s1, top1 ++ top2) i@(LMInt _) | i == llvmWord platform -> do let vty = pLift $ getVarType vval (vptr, s1) <- doExpr vty $ Cast LM_Inttoptr vaddr vty - let s2 = MetaStmt meta $ mkStore vval vptr alignment + let s2 = mkStore vval vptr alignment meta return (stmts `snocOL` s1 `snocOL` s2, top1 ++ top2) other -> @@ -1209,9 +1209,9 @@ genStore_slow addr val alignment meta = do text "Size of var:" <+> ppr (llvmWidthInBits platform other) $$ text "Var:" <+> ppVar cfg vaddr) -mkStore :: LlvmVar -> LlvmVar -> AlignmentSpec -> LlvmStatement -mkStore vval vptr alignment = - Store vval vptr align +mkStore :: LlvmVar -> LlvmVar -> AlignmentSpec -> [MetaAnnot] -> LlvmStatement +mkStore vval vptr alignment metas = + Store vval vptr align metas where ty = pLower (getVarType vptr) align = case alignment of @@ -2072,7 +2072,7 @@ funPrologue live cmmBlocks = do rval = if isLive r then arg else trash alloc = Assignment reg $ Alloca (pLower $ getVarType reg) 1 markStackReg r - return $ toOL [alloc, Store rval reg Nothing] + return $ toOL [alloc, Store rval reg Nothing []] return (concatOL stmtss `snocOL` jumpToEntry, []) where diff --git a/compiler/GHC/CmmToLlvm/Ppr.hs b/compiler/GHC/CmmToLlvm/Ppr.hs index 8b0577bad7..5838233f3b 100644 --- a/compiler/GHC/CmmToLlvm/Ppr.hs +++ b/compiler/GHC/CmmToLlvm/Ppr.hs @@ -26,22 +26,28 @@ import GHC.Types.Unique -- -- | Pretty print LLVM data code -pprLlvmData :: LlvmCgConfig -> LlvmData -> SDoc +pprLlvmData :: IsDoc doc => LlvmCgConfig -> LlvmData -> doc pprLlvmData cfg (globals, types) = - let ppLlvmTys (LMAlias a) = ppLlvmAlias a + let ppLlvmTys (LMAlias a) = line $ ppLlvmAlias a ppLlvmTys (LMFunction f) = ppLlvmFunctionDecl f ppLlvmTys _other = empty types' = vcat $ map ppLlvmTys types globals' = ppLlvmGlobals cfg globals - in types' $+$ globals' + in types' $$ globals' +{-# SPECIALIZE pprLlvmData :: LlvmCgConfig -> LlvmData -> SDoc #-} +{-# SPECIALIZE pprLlvmData :: LlvmCgConfig -> LlvmData -> HDoc #-} -- see Note [SPECIALIZE to HDoc] in GHC.Utils.Outputable -- | Pretty print LLVM code -pprLlvmCmmDecl :: LlvmCmmDecl -> LlvmM (SDoc, [LlvmVar]) +-- The HDoc we return is used to produce the final LLVM file, with the +-- SDoc being returned alongside for use when @Opt_D_dump_llvm@ is set +-- as we can't (currently) dump HDocs. +pprLlvmCmmDecl :: LlvmCmmDecl -> LlvmM (HDoc, SDoc) pprLlvmCmmDecl (CmmData _ lmdata) = do opts <- getConfig - return (vcat $ map (pprLlvmData opts) lmdata, []) + return ( vcat $ map (pprLlvmData opts) lmdata + , vcat $ map (pprLlvmData opts) lmdata) pprLlvmCmmDecl (CmmProc mb_info entry_lbl live (ListGraph blks)) = do let lbl = case mb_info of @@ -92,7 +98,8 @@ pprLlvmCmmDecl (CmmProc mb_info entry_lbl live (ListGraph blks)) (Just $ LMBitc (LMStaticPointer defVar) i8Ptr) - return (ppLlvmGlobal cfg alias $+$ ppLlvmFunction cfg fun', []) + return ( vcat [line $ ppLlvmGlobal cfg alias, ppLlvmFunction cfg fun'] + , vcat [line $ ppLlvmGlobal cfg alias, ppLlvmFunction cfg fun']) -- | The section we are putting info tables and their entry code into, should diff --git a/compiler/GHC/Llvm/MetaData.hs b/compiler/GHC/Llvm/MetaData.hs index f46ae0a101..3f8818ee45 100644 --- a/compiler/GHC/Llvm/MetaData.hs +++ b/compiler/GHC/Llvm/MetaData.hs @@ -64,7 +64,12 @@ newtype MetaId = MetaId Int deriving (Eq, Ord, Enum) instance Outputable MetaId where - ppr (MetaId n) = char '!' <> int n + ppr = ppMetaId + +ppMetaId :: IsLine doc => MetaId -> doc +ppMetaId (MetaId n) = char '!' <> int n +{-# SPECIALIZE ppMetaId :: MetaId -> SDoc #-} +{-# SPECIALIZE ppMetaId :: MetaId -> HLine #-} -- see Note [SPECIALIZE to HDoc] in GHC.Utils.Outputable -- | LLVM metadata expressions data MetaExpr = MetaStr !LMString diff --git a/compiler/GHC/Llvm/Ppr.hs b/compiler/GHC/Llvm/Ppr.hs index 787b6efcf7..36bfdf3405 100644 --- a/compiler/GHC/Llvm/Ppr.hs +++ b/compiler/GHC/Llvm/Ppr.hs @@ -1,5 +1,6 @@ {-# LANGUAGE LambdaCase #-} +{-# LANGUAGE TypeApplications #-} -------------------------------------------------------------------------------- -- | Pretty print LLVM IR Code. @@ -36,7 +37,6 @@ import GHC.Llvm.Syntax import GHC.Llvm.MetaData import GHC.Llvm.Types -import Data.Int import Data.List ( intersperse ) import GHC.Utils.Outputable @@ -49,30 +49,39 @@ import GHC.Types.Unique -------------------------------------------------------------------------------- -- | Print out a whole LLVM module. -ppLlvmModule :: LlvmCgConfig -> LlvmModule -> SDoc +ppLlvmModule :: IsDoc doc => LlvmCgConfig -> LlvmModule -> doc ppLlvmModule opts (LlvmModule comments aliases meta globals decls funcs) - = ppLlvmComments comments $+$ newLine - $+$ ppLlvmAliases aliases $+$ newLine - $+$ ppLlvmMetas opts meta $+$ newLine - $+$ ppLlvmGlobals opts globals $+$ newLine - $+$ ppLlvmFunctionDecls decls $+$ newLine - $+$ ppLlvmFunctions opts funcs + = ppLlvmComments comments $$ newLine + $$ ppLlvmAliases aliases $$ newLine + $$ ppLlvmMetas opts meta $$ newLine + $$ ppLlvmGlobals opts globals $$ newLine + $$ ppLlvmFunctionDecls decls $$ newLine + $$ ppLlvmFunctions opts funcs +{-# SPECIALIZE ppLlvmModule :: LlvmCgConfig -> LlvmModule -> SDoc #-} +{-# SPECIALIZE ppLlvmModule :: LlvmCgConfig -> LlvmModule -> HDoc #-} -- see Note [SPECIALIZE to HDoc] in GHC.Utils.Outputable + -- | Print out a multi-line comment, can be inside a function or on its own -ppLlvmComments :: [LMString] -> SDoc -ppLlvmComments comments = vcat $ map ppLlvmComment comments +ppLlvmComments :: IsDoc doc => [LMString] -> doc +ppLlvmComments comments = lines_ $ map ppLlvmComment comments +{-# SPECIALIZE ppLlvmComments :: [LMString] -> SDoc #-} +{-# SPECIALIZE ppLlvmComments :: [LMString] -> HDoc #-} -- see Note [SPECIALIZE to HDoc] in GHC.Utils.Outputable -- | Print out a comment, can be inside a function or on its own -ppLlvmComment :: LMString -> SDoc +ppLlvmComment :: IsLine doc => LMString -> doc ppLlvmComment com = semi <+> ftext com +{-# SPECIALIZE ppLlvmComment :: LMString -> SDoc #-} +{-# SPECIALIZE ppLlvmComment :: LMString -> HLine #-} -- see Note [SPECIALIZE to HDoc] in GHC.Utils.Outputable -- | Print out a list of global mutable variable definitions -ppLlvmGlobals :: LlvmCgConfig -> [LMGlobal] -> SDoc -ppLlvmGlobals opts ls = vcat $ map (ppLlvmGlobal opts) ls +ppLlvmGlobals :: IsDoc doc => LlvmCgConfig -> [LMGlobal] -> doc +ppLlvmGlobals opts ls = lines_ $ map (ppLlvmGlobal opts) ls +{-# SPECIALIZE ppLlvmGlobals :: LlvmCgConfig -> [LMGlobal] -> SDoc #-} +{-# SPECIALIZE ppLlvmGlobals :: LlvmCgConfig -> [LMGlobal] -> HDoc #-} -- see Note [SPECIALIZE to HDoc] in GHC.Utils.Outputable -- | Print out a global mutable variable definition -ppLlvmGlobal :: LlvmCgConfig -> LMGlobal -> SDoc +ppLlvmGlobal :: IsLine doc => LlvmCgConfig -> LMGlobal -> doc ppLlvmGlobal opts (LMGlobal var@(LMGlobalVar _ _ link x a c) dat) = let sect = case x of Just x' -> text ", section" <+> doubleQuotes (ftext x') @@ -84,7 +93,7 @@ ppLlvmGlobal opts (LMGlobal var@(LMGlobalVar _ _ link x a c) dat) = rhs = case dat of Just stat -> pprSpecialStatic opts stat - Nothing -> ppr (pLower $ getVarType var) + Nothing -> ppLlvmType (pLower $ getVarType var) -- Position of linkage is different for aliases. const = case c of @@ -92,105 +101,130 @@ ppLlvmGlobal opts (LMGlobal var@(LMGlobalVar _ _ link x a c) dat) = Constant -> "constant" Alias -> "alias" - in ppAssignment opts var $ ppr link <+> text const <+> rhs <> sect <> align - $+$ newLine + in ppAssignment opts var $ ppLlvmLinkageType link <+> text const <+> rhs <> sect <> align ppLlvmGlobal opts (LMGlobal var val) = pprPanic "ppLlvmGlobal" $ - text "Non Global var ppr as global! " <> ppVar opts var <> text "=" <> ppr (fmap (ppStatic opts) val) + text "Non Global var ppr as global! " <> ppVar opts var <> text "=" <> ppr (fmap (ppStatic @SDoc opts) val) +{-# SPECIALIZE ppLlvmGlobal :: LlvmCgConfig -> LMGlobal -> SDoc #-} +{-# SPECIALIZE ppLlvmGlobal :: LlvmCgConfig -> LMGlobal -> HLine #-} -- see Note [SPECIALIZE to HDoc] in GHC.Utils.Outputable -- | Print out a list of LLVM type aliases. -ppLlvmAliases :: [LlvmAlias] -> SDoc -ppLlvmAliases tys = vcat $ map ppLlvmAlias tys +ppLlvmAliases :: IsDoc doc => [LlvmAlias] -> doc +ppLlvmAliases tys = lines_ $ map ppLlvmAlias tys +{-# SPECIALIZE ppLlvmAliases :: [LlvmAlias] -> SDoc #-} +{-# SPECIALIZE ppLlvmAliases :: [LlvmAlias] -> HDoc #-} -- see Note [SPECIALIZE to HDoc] in GHC.Utils.Outputable -- | Print out an LLVM type alias. -ppLlvmAlias :: LlvmAlias -> SDoc +ppLlvmAlias :: IsLine doc => LlvmAlias -> doc ppLlvmAlias (name, ty) - = char '%' <> ftext name <+> equals <+> text "type" <+> ppr ty + = char '%' <> ftext name <+> equals <+> text "type" <+> ppLlvmType ty +{-# SPECIALIZE ppLlvmAlias :: LlvmAlias -> SDoc #-} +{-# SPECIALIZE ppLlvmAlias :: LlvmAlias -> HLine #-} -- see Note [SPECIALIZE to HDoc] in GHC.Utils.Outputable -- | Print out a list of LLVM metadata. -ppLlvmMetas :: LlvmCgConfig -> [MetaDecl] -> SDoc -ppLlvmMetas opts metas = vcat $ map (ppLlvmMeta opts) metas +ppLlvmMetas :: IsDoc doc => LlvmCgConfig -> [MetaDecl] -> doc +ppLlvmMetas opts metas = lines_ $ map (ppLlvmMeta opts) metas +{-# SPECIALIZE ppLlvmMetas :: LlvmCgConfig -> [MetaDecl] -> SDoc #-} +{-# SPECIALIZE ppLlvmMetas :: LlvmCgConfig -> [MetaDecl] -> HDoc #-} -- see Note [SPECIALIZE to HDoc] in GHC.Utils.Outputable -- | Print out an LLVM metadata definition. -ppLlvmMeta :: LlvmCgConfig -> MetaDecl -> SDoc +ppLlvmMeta :: IsLine doc => LlvmCgConfig -> MetaDecl -> doc ppLlvmMeta opts (MetaUnnamed n m) - = ppr n <+> equals <+> ppMetaExpr opts m + = ppMetaId n <+> equals <+> ppMetaExpr opts m ppLlvmMeta _opts (MetaNamed n m) = exclamation <> ftext n <+> equals <+> exclamation <> braces nodes where - nodes = hcat $ intersperse comma $ map ppr m + nodes = hcat $ intersperse comma $ map ppMetaId m +{-# SPECIALIZE ppLlvmMeta :: LlvmCgConfig -> MetaDecl -> SDoc #-} +{-# SPECIALIZE ppLlvmMeta :: LlvmCgConfig -> MetaDecl -> HLine #-} -- see Note [SPECIALIZE to HDoc] in GHC.Utils.Outputable -- | Print out a list of function definitions. -ppLlvmFunctions :: LlvmCgConfig -> LlvmFunctions -> SDoc +ppLlvmFunctions :: IsDoc doc => LlvmCgConfig -> LlvmFunctions -> doc ppLlvmFunctions opts funcs = vcat $ map (ppLlvmFunction opts) funcs +{-# SPECIALIZE ppLlvmFunctions :: LlvmCgConfig -> LlvmFunctions -> SDoc #-} +{-# SPECIALIZE ppLlvmFunctions :: LlvmCgConfig -> LlvmFunctions -> HDoc #-} -- see Note [SPECIALIZE to HDoc] in GHC.Utils.Outputable -- | Print out a function definition. -ppLlvmFunction :: LlvmCgConfig -> LlvmFunction -> SDoc +ppLlvmFunction :: IsDoc doc => LlvmCgConfig -> LlvmFunction -> doc ppLlvmFunction opts fun = - let attrDoc = ppSpaceJoin (funcAttrs fun) + let attrDoc = ppSpaceJoin ppLlvmFuncAttr (funcAttrs fun) secDoc = case funcSect fun of Just s' -> text "section" <+> (doubleQuotes $ ftext s') Nothing -> empty prefixDoc = case funcPrefix fun of Just v -> text "prefix" <+> ppStatic opts v Nothing -> empty - in text "define" <+> ppLlvmFunctionHeader (funcDecl fun) (funcArgs fun) - <+> attrDoc <+> secDoc <+> prefixDoc - $+$ lbrace - $+$ ppLlvmBlocks opts (funcBody fun) - $+$ rbrace - $+$ newLine - $+$ newLine + in vcat + [line $ text "define" <+> ppLlvmFunctionHeader (funcDecl fun) (funcArgs fun) + <+> attrDoc <+> secDoc <+> prefixDoc + , line lbrace + , ppLlvmBlocks opts (funcBody fun) + , line rbrace + , newLine + , newLine] +{-# SPECIALIZE ppLlvmFunction :: LlvmCgConfig -> LlvmFunction -> SDoc #-} +{-# SPECIALIZE ppLlvmFunction :: LlvmCgConfig -> LlvmFunction -> HDoc #-} -- see Note [SPECIALIZE to HDoc] in GHC.Utils.Outputable -- | Print out a function definition header. -ppLlvmFunctionHeader :: LlvmFunctionDecl -> [LMString] -> SDoc +ppLlvmFunctionHeader :: IsLine doc => LlvmFunctionDecl -> [LMString] -> doc ppLlvmFunctionHeader (LlvmFunctionDecl n l c r varg p a) args = let varg' = case varg of VarArgs | null p -> text "..." | otherwise -> text ", ..." _otherwise -> text "" align = case a of - Just a' -> text " align " <> ppr a' + Just a' -> text " align " <> int a' Nothing -> empty - args' = map (\((ty,p),n) -> ppr ty <+> ppSpaceJoin p <+> char '%' + args' = zipWith (\(ty,p) n -> ppLlvmType ty <+> ppSpaceJoin ppLlvmParamAttr p <+> char '%' <> ftext n) - (zip p args) - in ppr l <+> ppr c <+> ppr r <+> char '@' <> ftext n <> lparen <> - (hsep $ punctuate comma args') <> varg' <> rparen <> align + p + args + in ppLlvmLinkageType l <+> ppLlvmCallConvention c <+> ppLlvmType r <+> char '@' <> ftext n <> lparen <> + hsep (punctuate comma args') <> varg' <> rparen <> align +{-# SPECIALIZE ppLlvmFunctionHeader :: LlvmFunctionDecl -> [LMString] -> SDoc #-} +{-# SPECIALIZE ppLlvmFunctionHeader :: LlvmFunctionDecl -> [LMString] -> HLine #-} -- see Note [SPECIALIZE to HDoc] in GHC.Utils.Outputable -- | Print out a list of function declaration. -ppLlvmFunctionDecls :: LlvmFunctionDecls -> SDoc +ppLlvmFunctionDecls :: IsDoc doc => LlvmFunctionDecls -> doc ppLlvmFunctionDecls decs = vcat $ map ppLlvmFunctionDecl decs +{-# SPECIALIZE ppLlvmFunctionDecls :: LlvmFunctionDecls -> SDoc #-} +{-# SPECIALIZE ppLlvmFunctionDecls :: LlvmFunctionDecls -> HDoc #-} -- see Note [SPECIALIZE to HDoc] in GHC.Utils.Outputable -- | Print out a function declaration. -- Declarations define the function type but don't define the actual body of -- the function. -ppLlvmFunctionDecl :: LlvmFunctionDecl -> SDoc +ppLlvmFunctionDecl :: IsDoc doc => LlvmFunctionDecl -> doc ppLlvmFunctionDecl (LlvmFunctionDecl n l c r varg p a) = let varg' = case varg of VarArgs | null p -> text "..." | otherwise -> text ", ..." _otherwise -> text "" align = case a of - Just a' -> text " align" <+> ppr a' + Just a' -> text " align" <+> int a' Nothing -> empty args = hcat $ intersperse (comma <> space) $ - map (\(t,a) -> ppr t <+> ppSpaceJoin a) p - in text "declare" <+> ppr l <+> ppr c <+> ppr r <+> char '@' <> - ftext n <> lparen <> args <> varg' <> rparen <> align $+$ newLine + map (\(t,a) -> ppLlvmType t <+> ppSpaceJoin ppLlvmParamAttr a) p + in lines_ + [ text "declare" <+> ppLlvmLinkageType l <+> ppLlvmCallConvention c + <+> ppLlvmType r <+> char '@' <> ftext n <> lparen <> args <> varg' <> rparen <> align + , empty] +{-# SPECIALIZE ppLlvmFunctionDecl :: LlvmFunctionDecl -> SDoc #-} +{-# SPECIALIZE ppLlvmFunctionDecl :: LlvmFunctionDecl -> HDoc #-} -- see Note [SPECIALIZE to HDoc] in GHC.Utils.Outputable -- | Print out a list of LLVM blocks. -ppLlvmBlocks :: LlvmCgConfig -> LlvmBlocks -> SDoc +ppLlvmBlocks :: IsDoc doc => LlvmCgConfig -> LlvmBlocks -> doc ppLlvmBlocks opts blocks = vcat $ map (ppLlvmBlock opts) blocks +{-# SPECIALIZE ppLlvmBlocks :: LlvmCgConfig -> LlvmBlocks -> SDoc #-} +{-# SPECIALIZE ppLlvmBlocks :: LlvmCgConfig -> LlvmBlocks -> HDoc #-} -- see Note [SPECIALIZE to HDoc] in GHC.Utils.Outputable -- | Print out an LLVM block. -- It must be part of a function definition. -ppLlvmBlock :: LlvmCgConfig -> LlvmBlock -> SDoc +ppLlvmBlock :: IsDoc doc => LlvmCgConfig -> LlvmBlock -> doc ppLlvmBlock opts (LlvmBlock blockId stmts) = let isLabel (MkLabel _) = True isLabel _ = False @@ -198,39 +232,44 @@ ppLlvmBlock opts (LlvmBlock blockId stmts) = ppRest = case rest of MkLabel id:xs -> ppLlvmBlock opts (LlvmBlock id xs) _ -> empty - in ppLlvmBlockLabel blockId - $+$ (vcat $ map (ppLlvmStatement opts) block) - $+$ newLine - $+$ ppRest + in vcat $ + line (ppLlvmBlockLabel blockId) + : map (ppLlvmStatement opts) block + ++ [ empty , ppRest ] +{-# SPECIALIZE ppLlvmBlock :: LlvmCgConfig -> LlvmBlock -> SDoc #-} +{-# SPECIALIZE ppLlvmBlock :: LlvmCgConfig -> LlvmBlock -> HDoc #-} -- see Note [SPECIALIZE to HDoc] in GHC.Utils.Outputable -- | Print out an LLVM block label. -ppLlvmBlockLabel :: LlvmBlockId -> SDoc +ppLlvmBlockLabel :: IsLine doc => LlvmBlockId -> doc ppLlvmBlockLabel id = pprUniqueAlways id <> colon +{-# SPECIALIZE ppLlvmBlockLabel :: LlvmBlockId -> SDoc #-} +{-# SPECIALIZE ppLlvmBlockLabel :: LlvmBlockId -> HLine #-} -- see Note [SPECIALIZE to HDoc] in GHC.Utils.Outputable --- | Print out an LLVM statement. -ppLlvmStatement :: LlvmCgConfig -> LlvmStatement -> SDoc +-- | Print out an LLVM statement, with any metadata to append to the statement. +ppLlvmStatement :: IsDoc doc => LlvmCgConfig -> LlvmStatement -> doc ppLlvmStatement opts stmt = - let ind = (text " " <>) + let ind = line . (text " " <>) in case stmt of Assignment dst expr -> ind $ ppAssignment opts dst (ppLlvmExpression opts expr) Fence st ord -> ind $ ppFence st ord Branch target -> ind $ ppBranch opts target BranchIf cond ifT ifF -> ind $ ppBranchIf opts cond ifT ifF - Comment comments -> ind $ ppLlvmComments comments - MkLabel label -> ppLlvmBlockLabel label - Store value ptr align - -> ind $ ppStore opts value ptr align - Switch scrut def tgs -> ind $ ppSwitch opts scrut def tgs + Comment comments -> ppLlvmComments comments + MkLabel label -> line $ ppLlvmBlockLabel label + Store value ptr align metas + -> ind $ ppStore opts value ptr align metas + Switch scrut def tgs -> ppSwitch opts scrut def tgs Return result -> ind $ ppReturn opts result Expr expr -> ind $ ppLlvmExpression opts expr Unreachable -> ind $ text "unreachable" - Nop -> empty - MetaStmt meta s -> ppMetaStatement opts meta s + Nop -> line empty +{-# SPECIALIZE ppLlvmStatement :: LlvmCgConfig -> LlvmStatement -> SDoc #-} +{-# SPECIALIZE ppLlvmStatement :: LlvmCgConfig -> LlvmStatement -> HDoc #-} -- see Note [SPECIALIZE to HDoc] in GHC.Utils.Outputable -- | Print out an LLVM expression. -ppLlvmExpression :: LlvmCgConfig -> LlvmExpression -> SDoc +ppLlvmExpression :: IsLine doc => LlvmCgConfig -> LlvmExpression -> doc ppLlvmExpression opts expr = case expr of Alloca tp amount -> ppAlloca opts tp amount @@ -251,14 +290,18 @@ ppLlvmExpression opts expr Phi tp predecessors -> ppPhi opts tp predecessors Asm asm c ty v se sk -> ppAsm opts asm c ty v se sk MExpr meta expr -> ppMetaAnnotExpr opts meta expr +{-# SPECIALIZE ppLlvmExpression :: LlvmCgConfig -> LlvmExpression -> SDoc #-} +{-# SPECIALIZE ppLlvmExpression :: LlvmCgConfig -> LlvmExpression -> HLine #-} -- see Note [SPECIALIZE to HDoc] in GHC.Utils.Outputable -ppMetaExpr :: LlvmCgConfig -> MetaExpr -> SDoc +ppMetaExpr :: IsLine doc => LlvmCgConfig -> MetaExpr -> doc ppMetaExpr opts = \case MetaVar (LMLitVar (LMNullLit _)) -> text "null" MetaStr s -> char '!' <> doubleQuotes (ftext s) - MetaNode n -> ppr n + MetaNode n -> ppMetaId n MetaVar v -> ppVar opts v - MetaStruct es -> char '!' <> braces (ppCommaJoin (map (ppMetaExpr opts) es)) + MetaStruct es -> char '!' <> braces (ppCommaJoin (ppMetaExpr opts) es) +{-# SPECIALIZE ppMetaExpr :: LlvmCgConfig -> MetaExpr -> SDoc #-} +{-# SPECIALIZE ppMetaExpr :: LlvmCgConfig -> MetaExpr -> HLine #-} -- see Note [SPECIALIZE to HDoc] in GHC.Utils.Outputable -------------------------------------------------------------------------------- @@ -267,7 +310,8 @@ ppMetaExpr opts = \case -- | Should always be a function pointer. So a global var of function type -- (since globals are always pointers) or a local var of pointer function type. -ppCall :: LlvmCgConfig -> LlvmCallType -> LlvmVar -> [MetaExpr] -> [LlvmFuncAttr] -> SDoc +ppCall :: forall doc. IsLine doc => LlvmCgConfig -> LlvmCallType -> LlvmVar -> [MetaExpr] + -> [LlvmFuncAttr] -> doc ppCall opts ct fptr args attrs = case fptr of -- -- if local var function pointer, unwrap @@ -285,32 +329,36 @@ ppCall opts ct fptr args attrs = case fptr of ppCall' (LlvmFunctionDecl _ _ cc ret argTy params _) = let tc = if ct == TailCall then text "tail " else empty ppValues = ppCallParams opts (map snd params) args - ppArgTy = (ppCommaJoin $ map (ppr . fst) params) <> + ppArgTy = ppCommaJoin (ppLlvmType . fst) params <> (case argTy of VarArgs -> text ", ..." FixedArgs -> empty) fnty = space <> lparen <> ppArgTy <> rparen - attrDoc = ppSpaceJoin attrs - in tc <> text "call" <+> ppr cc <+> ppr ret + attrDoc = ppSpaceJoin ppLlvmFuncAttr attrs + in tc <> text "call" <+> ppLlvmCallConvention cc <+> ppLlvmType ret <> fnty <+> ppName opts fptr <> lparen <+> ppValues <+> rparen <+> attrDoc - ppCallParams :: LlvmCgConfig -> [[LlvmParamAttr]] -> [MetaExpr] -> SDoc + ppCallParams :: LlvmCgConfig -> [[LlvmParamAttr]] -> [MetaExpr] -> doc ppCallParams opts attrs args = hsep $ punctuate comma $ zipWith ppCallMetaExpr attrs args where -- Metadata needs to be marked as having the `metadata` type when used -- in a call argument ppCallMetaExpr attrs (MetaVar v) = ppVar' attrs opts v ppCallMetaExpr _ v = text "metadata" <+> ppMetaExpr opts v +{-# SPECIALIZE ppCall :: LlvmCgConfig -> LlvmCallType -> LlvmVar -> [MetaExpr] -> [LlvmFuncAttr] -> SDoc #-} +{-# SPECIALIZE ppCall :: LlvmCgConfig -> LlvmCallType -> LlvmVar -> [MetaExpr] -> [LlvmFuncAttr] -> HLine #-} -- see Note [SPECIALIZE to HDoc] in GHC.Utils.Outputable -ppMachOp :: LlvmCgConfig -> LlvmMachOp -> LlvmVar -> LlvmVar -> SDoc +ppMachOp :: IsLine doc => LlvmCgConfig -> LlvmMachOp -> LlvmVar -> LlvmVar -> doc ppMachOp opts op left right = - (ppr op) <+> (ppr (getVarType left)) <+> ppName opts left + ppLlvmMachOp op <+> ppLlvmType (getVarType left) <+> ppName opts left <> comma <+> ppName opts right +{-# SPECIALIZE ppMachOp :: LlvmCgConfig -> LlvmMachOp -> LlvmVar -> LlvmVar -> SDoc #-} +{-# SPECIALIZE ppMachOp :: LlvmCgConfig -> LlvmMachOp -> LlvmVar -> LlvmVar -> HLine #-} -- see Note [SPECIALIZE to HDoc] in GHC.Utils.Outputable -ppCmpOp :: LlvmCgConfig -> LlvmCmpOp -> LlvmVar -> LlvmVar -> SDoc +ppCmpOp :: IsLine doc => LlvmCgConfig -> LlvmCmpOp -> LlvmVar -> LlvmVar -> doc ppCmpOp opts op left right = let cmpOp | isInt (getVarType left) && isInt (getVarType right) = text "icmp" @@ -321,28 +369,36 @@ ppCmpOp opts op left right = ++ (show $ getVarType left) ++ ", right = " ++ (show $ getVarType right)) -} - in cmpOp <+> ppr op <+> ppr (getVarType left) + in cmpOp <+> ppLlvmCmpOp op <+> ppLlvmType (getVarType left) <+> ppName opts left <> comma <+> ppName opts right +{-# SPECIALIZE ppCmpOp :: LlvmCgConfig -> LlvmCmpOp -> LlvmVar -> LlvmVar -> SDoc #-} +{-# SPECIALIZE ppCmpOp :: LlvmCgConfig -> LlvmCmpOp -> LlvmVar -> LlvmVar -> HLine #-} -- see Note [SPECIALIZE to HDoc] in GHC.Utils.Outputable -ppAssignment :: LlvmCgConfig -> LlvmVar -> SDoc -> SDoc +ppAssignment :: IsLine doc => LlvmCgConfig -> LlvmVar -> doc -> doc ppAssignment opts var expr = ppName opts var <+> equals <+> expr +{-# SPECIALIZE ppAssignment :: LlvmCgConfig -> LlvmVar -> SDoc -> SDoc #-} +{-# SPECIALIZE ppAssignment :: LlvmCgConfig -> LlvmVar -> HLine -> HLine #-} -- see Note [SPECIALIZE to HDoc] in GHC.Utils.Outputable -ppFence :: Bool -> LlvmSyncOrdering -> SDoc +ppFence :: IsLine doc => Bool -> LlvmSyncOrdering -> doc ppFence st ord = let singleThread = case st of True -> text "singlethread" False -> empty in text "fence" <+> singleThread <+> ppSyncOrdering ord +{-# SPECIALIZE ppFence :: Bool -> LlvmSyncOrdering -> SDoc #-} +{-# SPECIALIZE ppFence :: Bool -> LlvmSyncOrdering -> HLine #-} -- see Note [SPECIALIZE to HDoc] in GHC.Utils.Outputable -ppSyncOrdering :: LlvmSyncOrdering -> SDoc +ppSyncOrdering :: IsLine doc => LlvmSyncOrdering -> doc ppSyncOrdering SyncUnord = text "unordered" ppSyncOrdering SyncMonotonic = text "monotonic" ppSyncOrdering SyncAcquire = text "acquire" ppSyncOrdering SyncRelease = text "release" ppSyncOrdering SyncAcqRel = text "acq_rel" ppSyncOrdering SyncSeqCst = text "seq_cst" +{-# SPECIALIZE ppSyncOrdering :: LlvmSyncOrdering -> SDoc #-} +{-# SPECIALIZE ppSyncOrdering :: LlvmSyncOrdering -> HLine #-} -- see Note [SPECIALIZE to HDoc] in GHC.Utils.Outputable -ppAtomicOp :: LlvmAtomicOp -> SDoc +ppAtomicOp :: IsLine doc => LlvmAtomicOp -> doc ppAtomicOp LAO_Xchg = text "xchg" ppAtomicOp LAO_Add = text "add" ppAtomicOp LAO_Sub = text "sub" @@ -354,184 +410,222 @@ ppAtomicOp LAO_Max = text "max" ppAtomicOp LAO_Min = text "min" ppAtomicOp LAO_Umax = text "umax" ppAtomicOp LAO_Umin = text "umin" +{-# SPECIALIZE ppAtomicOp :: LlvmAtomicOp -> SDoc #-} +{-# SPECIALIZE ppAtomicOp :: LlvmAtomicOp -> HLine #-} -- see Note [SPECIALIZE to HDoc] in GHC.Utils.Outputable -ppAtomicRMW :: LlvmCgConfig -> LlvmAtomicOp -> LlvmVar -> LlvmVar -> LlvmSyncOrdering -> SDoc +ppAtomicRMW :: IsLine doc => LlvmCgConfig -> LlvmAtomicOp -> LlvmVar -> LlvmVar -> LlvmSyncOrdering -> doc ppAtomicRMW opts aop tgt src ordering = text "atomicrmw" <+> ppAtomicOp aop <+> ppVar opts tgt <> comma <+> ppVar opts src <+> ppSyncOrdering ordering +{-# SPECIALIZE ppAtomicRMW :: LlvmCgConfig -> LlvmAtomicOp -> LlvmVar -> LlvmVar -> LlvmSyncOrdering -> SDoc #-} +{-# SPECIALIZE ppAtomicRMW :: LlvmCgConfig -> LlvmAtomicOp -> LlvmVar -> LlvmVar -> LlvmSyncOrdering -> HLine #-} -- see Note [SPECIALIZE to HDoc] in GHC.Utils.Outputable -ppCmpXChg :: LlvmCgConfig -> LlvmVar -> LlvmVar -> LlvmVar - -> LlvmSyncOrdering -> LlvmSyncOrdering -> SDoc +ppCmpXChg :: IsLine doc => LlvmCgConfig -> LlvmVar -> LlvmVar -> LlvmVar + -> LlvmSyncOrdering -> LlvmSyncOrdering -> doc ppCmpXChg opts addr old new s_ord f_ord = text "cmpxchg" <+> ppVar opts addr <> comma <+> ppVar opts old <> comma <+> ppVar opts new <+> ppSyncOrdering s_ord <+> ppSyncOrdering f_ord +{-# SPECIALIZE ppCmpXChg :: LlvmCgConfig -> LlvmVar -> LlvmVar -> LlvmVar -> LlvmSyncOrdering -> LlvmSyncOrdering -> SDoc #-} +{-# SPECIALIZE ppCmpXChg :: LlvmCgConfig -> LlvmVar -> LlvmVar -> LlvmVar -> LlvmSyncOrdering -> LlvmSyncOrdering -> HLine #-} -- see Note [SPECIALIZE to HDoc] in GHC.Utils.Outputable -ppLoad :: LlvmCgConfig -> LlvmVar -> LMAlign -> SDoc +ppLoad :: IsLine doc => LlvmCgConfig -> LlvmVar -> LMAlign -> doc ppLoad opts var alignment = - text "load" <+> ppr derefType <> comma <+> ppVar opts var <> align + text "load" <+> ppLlvmType derefType <> comma <+> ppVar opts var <> align where derefType = pLower $ getVarType var align = case alignment of - Just n -> text ", align" <+> ppr n + Just n -> text ", align" <+> int n Nothing -> empty +{-# SPECIALIZE ppLoad :: LlvmCgConfig -> LlvmVar -> LMAlign -> SDoc #-} +{-# SPECIALIZE ppLoad :: LlvmCgConfig -> LlvmVar -> LMAlign -> HLine #-} -- see Note [SPECIALIZE to HDoc] in GHC.Utils.Outputable -ppALoad :: LlvmCgConfig -> LlvmSyncOrdering -> SingleThreaded -> LlvmVar -> SDoc +ppALoad :: IsLine doc => LlvmCgConfig -> LlvmSyncOrdering -> SingleThreaded -> LlvmVar -> doc ppALoad opts ord st var = let alignment = llvmWidthInBits (llvmCgPlatform opts) (getVarType var) `quot` 8 - align = text ", align" <+> ppr alignment + align = text ", align" <+> int alignment sThreaded | st = text " singlethread" | otherwise = empty derefType = pLower $ getVarType var - in text "load atomic" <+> ppr derefType <> comma <+> ppVar opts var <> sThreaded + in text "load atomic" <+> ppLlvmType derefType <> comma <+> ppVar opts var <> sThreaded <+> ppSyncOrdering ord <> align +{-# SPECIALIZE ppALoad :: LlvmCgConfig -> LlvmSyncOrdering -> SingleThreaded -> LlvmVar -> SDoc #-} +{-# SPECIALIZE ppALoad :: LlvmCgConfig -> LlvmSyncOrdering -> SingleThreaded -> LlvmVar -> HLine #-} -- see Note [SPECIALIZE to HDoc] in GHC.Utils.Outputable -ppStore :: LlvmCgConfig -> LlvmVar -> LlvmVar -> LMAlign -> SDoc -ppStore opts val dst alignment = - text "store" <+> ppVar opts val <> comma <+> ppVar opts dst <> align +ppStore :: IsLine doc => LlvmCgConfig -> LlvmVar -> LlvmVar -> LMAlign -> [MetaAnnot] -> doc +ppStore opts val dst alignment metas = + text "store" <+> ppVar opts val <> comma <+> ppVar opts dst <> align <+> ppMetaAnnots opts metas where align = case alignment of - Just n -> text ", align" <+> ppr n + Just n -> text ", align" <+> int n Nothing -> empty +{-# SPECIALIZE ppStore :: LlvmCgConfig -> LlvmVar -> LlvmVar -> LMAlign -> [MetaAnnot] -> SDoc #-} +{-# SPECIALIZE ppStore :: LlvmCgConfig -> LlvmVar -> LlvmVar -> LMAlign -> [MetaAnnot] -> HLine #-} -- see Note [SPECIALIZE to HDoc] in GHC.Utils.Outputable -ppCast :: LlvmCgConfig -> LlvmCastOp -> LlvmVar -> LlvmType -> SDoc +ppCast :: IsLine doc => LlvmCgConfig -> LlvmCastOp -> LlvmVar -> LlvmType -> doc ppCast opts op from to - = ppr op - <+> ppr (getVarType from) <+> ppName opts from + = ppLlvmCastOp op + <+> ppLlvmType (getVarType from) <+> ppName opts from <+> text "to" - <+> ppr to + <+> ppLlvmType to +{-# SPECIALIZE ppCast :: LlvmCgConfig -> LlvmCastOp -> LlvmVar -> LlvmType -> SDoc #-} +{-# SPECIALIZE ppCast :: LlvmCgConfig -> LlvmCastOp -> LlvmVar -> LlvmType -> HLine #-} -- see Note [SPECIALIZE to HDoc] in GHC.Utils.Outputable -ppMalloc :: LlvmCgConfig -> LlvmType -> Int -> SDoc +ppMalloc :: IsLine doc => LlvmCgConfig -> LlvmType -> Int -> doc ppMalloc opts tp amount = let amount' = LMLitVar $ LMIntLit (toInteger amount) i32 - in text "malloc" <+> ppr tp <> comma <+> ppVar opts amount' - + in text "malloc" <+> ppLlvmType tp <> comma <+> ppVar opts amount' +{-# SPECIALIZE ppMalloc :: LlvmCgConfig -> LlvmType -> Int -> SDoc #-} +{-# SPECIALIZE ppMalloc :: LlvmCgConfig -> LlvmType -> Int -> HLine #-} -- see Note [SPECIALIZE to HDoc] in GHC.Utils.Outputable -ppAlloca :: LlvmCgConfig -> LlvmType -> Int -> SDoc +ppAlloca :: IsLine doc => LlvmCgConfig -> LlvmType -> Int -> doc ppAlloca opts tp amount = let amount' = LMLitVar $ LMIntLit (toInteger amount) i32 - in text "alloca" <+> ppr tp <> comma <+> ppVar opts amount' - + in text "alloca" <+> ppLlvmType tp <> comma <+> ppVar opts amount' +{-# SPECIALIZE ppAlloca :: LlvmCgConfig -> LlvmType -> Int -> SDoc #-} +{-# SPECIALIZE ppAlloca :: LlvmCgConfig -> LlvmType -> Int -> HLine #-} -- see Note [SPECIALIZE to HDoc] in GHC.Utils.Outputable -ppGetElementPtr :: LlvmCgConfig -> Bool -> LlvmVar -> [LlvmVar] -> SDoc +ppGetElementPtr :: IsLine doc => LlvmCgConfig -> Bool -> LlvmVar -> [LlvmVar] -> doc ppGetElementPtr opts inb ptr idx = - let indexes = comma <+> ppCommaJoin (map (ppVar opts) idx) + let indexes = comma <+> ppCommaJoin (ppVar opts) idx inbound = if inb then text "inbounds" else empty derefType = pLower $ getVarType ptr - in text "getelementptr" <+> inbound <+> ppr derefType <> comma <+> ppVar opts ptr + in text "getelementptr" <+> inbound <+> ppLlvmType derefType <> comma <+> ppVar opts ptr <> indexes +{-# SPECIALIZE ppGetElementPtr :: LlvmCgConfig -> Bool -> LlvmVar -> [LlvmVar] -> SDoc #-} +{-# SPECIALIZE ppGetElementPtr :: LlvmCgConfig -> Bool -> LlvmVar -> [LlvmVar] -> HLine #-} -- see Note [SPECIALIZE to HDoc] in GHC.Utils.Outputable -ppReturn :: LlvmCgConfig -> Maybe LlvmVar -> SDoc +ppReturn :: IsLine doc => LlvmCgConfig -> Maybe LlvmVar -> doc ppReturn opts (Just var) = text "ret" <+> ppVar opts var -ppReturn _ Nothing = text "ret" <+> ppr LMVoid +ppReturn _ Nothing = text "ret" <+> ppLlvmType LMVoid +{-# SPECIALIZE ppReturn :: LlvmCgConfig -> Maybe LlvmVar -> SDoc #-} +{-# SPECIALIZE ppReturn :: LlvmCgConfig -> Maybe LlvmVar -> HLine #-} -- see Note [SPECIALIZE to HDoc] in GHC.Utils.Outputable - -ppBranch :: LlvmCgConfig -> LlvmVar -> SDoc +ppBranch :: IsLine doc => LlvmCgConfig -> LlvmVar -> doc ppBranch opts var = text "br" <+> ppVar opts var +{-# SPECIALIZE ppBranch :: LlvmCgConfig -> LlvmVar -> SDoc #-} +{-# SPECIALIZE ppBranch :: LlvmCgConfig -> LlvmVar -> HLine #-} -- see Note [SPECIALIZE to HDoc] in GHC.Utils.Outputable -ppBranchIf :: LlvmCgConfig -> LlvmVar -> LlvmVar -> LlvmVar -> SDoc +ppBranchIf :: IsLine doc => LlvmCgConfig -> LlvmVar -> LlvmVar -> LlvmVar -> doc ppBranchIf opts cond trueT falseT = text "br" <+> ppVar opts cond <> comma <+> ppVar opts trueT <> comma <+> ppVar opts falseT +{-# SPECIALIZE ppBranchIf :: LlvmCgConfig -> LlvmVar -> LlvmVar -> LlvmVar -> SDoc #-} +{-# SPECIALIZE ppBranchIf :: LlvmCgConfig -> LlvmVar -> LlvmVar -> LlvmVar -> HLine #-} -- see Note [SPECIALIZE to HDoc] in GHC.Utils.Outputable -ppPhi :: LlvmCgConfig -> LlvmType -> [(LlvmVar,LlvmVar)] -> SDoc +ppPhi :: IsLine doc => LlvmCgConfig -> LlvmType -> [(LlvmVar,LlvmVar)] -> doc ppPhi opts tp preds = let ppPreds (val, label) = brackets $ ppName opts val <> comma <+> ppName opts label - in text "phi" <+> ppr tp <+> hsep (punctuate comma $ map ppPreds preds) + in text "phi" <+> ppLlvmType tp <+> hsep (punctuate comma $ map ppPreds preds) +{-# SPECIALIZE ppPhi :: LlvmCgConfig -> LlvmType -> [(LlvmVar,LlvmVar)] -> SDoc #-} +{-# SPECIALIZE ppPhi :: LlvmCgConfig -> LlvmType -> [(LlvmVar,LlvmVar)] -> HLine #-} -- see Note [SPECIALIZE to HDoc] in GHC.Utils.Outputable -ppSwitch :: LlvmCgConfig -> LlvmVar -> LlvmVar -> [(LlvmVar,LlvmVar)] -> SDoc +ppSwitch :: IsDoc doc => LlvmCgConfig -> LlvmVar -> LlvmVar -> [(LlvmVar,LlvmVar)] -> doc ppSwitch opts scrut dflt targets = - let ppTarget (val, lab) = ppVar opts val <> comma <+> ppVar opts lab - ppTargets xs = brackets $ vcat (map ppTarget xs) - in text "switch" <+> ppVar opts scrut <> comma <+> ppVar opts dflt - <+> ppTargets targets + let ppTarget (val, lab) = text " " <> ppVar opts val <> comma <+> ppVar opts lab + in lines_ $ concat + [ [text "switch" <+> ppVar opts scrut <> comma <+> ppVar opts dflt <+> char '['] + , map ppTarget targets + , [char ']'] + ] +{-# SPECIALIZE ppSwitch :: LlvmCgConfig -> LlvmVar -> LlvmVar -> [(LlvmVar,LlvmVar)] -> SDoc #-} +{-# SPECIALIZE ppSwitch :: LlvmCgConfig -> LlvmVar -> LlvmVar -> [(LlvmVar,LlvmVar)] -> HDoc #-} -- see Note [SPECIALIZE to HDoc] in GHC.Utils.Outputable -ppAsm :: LlvmCgConfig -> LMString -> LMString -> LlvmType -> [LlvmVar] -> Bool -> Bool -> SDoc +ppAsm :: IsLine doc => LlvmCgConfig -> LMString -> LMString -> LlvmType -> [LlvmVar] -> Bool -> Bool -> doc ppAsm opts asm constraints rty vars sideeffect alignstack = let asm' = doubleQuotes $ ftext asm cons = doubleQuotes $ ftext constraints - rty' = ppr rty - vars' = lparen <+> ppCommaJoin (map (ppVar opts) vars) <+> rparen + rty' = ppLlvmType rty + vars' = lparen <+> ppCommaJoin (ppVar opts) vars <+> rparen side = if sideeffect then text "sideeffect" else empty align = if alignstack then text "alignstack" else empty in text "call" <+> rty' <+> text "asm" <+> side <+> align <+> asm' <> comma <+> cons <> vars' +{-# SPECIALIZE ppAsm :: LlvmCgConfig -> LMString -> LMString -> LlvmType -> [LlvmVar] -> Bool -> Bool -> SDoc #-} +{-# SPECIALIZE ppAsm :: LlvmCgConfig -> LMString -> LMString -> LlvmType -> [LlvmVar] -> Bool -> Bool -> HLine #-} -- see Note [SPECIALIZE to HDoc] in GHC.Utils.Outputable -ppExtract :: LlvmCgConfig -> LlvmVar -> LlvmVar -> SDoc +ppExtract :: IsLine doc => LlvmCgConfig -> LlvmVar -> LlvmVar -> doc ppExtract opts vec idx = text "extractelement" - <+> ppr (getVarType vec) <+> ppName opts vec <> comma + <+> ppLlvmType (getVarType vec) <+> ppName opts vec <> comma <+> ppVar opts idx +{-# SPECIALIZE ppExtract :: LlvmCgConfig -> LlvmVar -> LlvmVar -> SDoc #-} +{-# SPECIALIZE ppExtract :: LlvmCgConfig -> LlvmVar -> LlvmVar -> HLine #-} -- see Note [SPECIALIZE to HDoc] in GHC.Utils.Outputable -ppExtractV :: LlvmCgConfig -> LlvmVar -> Int -> SDoc +ppExtractV :: IsLine doc => LlvmCgConfig -> LlvmVar -> Int -> doc ppExtractV opts struct idx = text "extractvalue" - <+> ppr (getVarType struct) <+> ppName opts struct <> comma - <+> ppr idx + <+> ppLlvmType (getVarType struct) <+> ppName opts struct <> comma + <+> int idx +{-# SPECIALIZE ppExtractV :: LlvmCgConfig -> LlvmVar -> Int -> SDoc #-} +{-# SPECIALIZE ppExtractV :: LlvmCgConfig -> LlvmVar -> Int -> HLine #-} -- see Note [SPECIALIZE to HDoc] in GHC.Utils.Outputable -ppInsert :: LlvmCgConfig -> LlvmVar -> LlvmVar -> LlvmVar -> SDoc +ppInsert :: IsLine doc => LlvmCgConfig -> LlvmVar -> LlvmVar -> LlvmVar -> doc ppInsert opts vec elt idx = text "insertelement" - <+> ppr (getVarType vec) <+> ppName opts vec <> comma - <+> ppr (getVarType elt) <+> ppName opts elt <> comma + <+> ppLlvmType (getVarType vec) <+> ppName opts vec <> comma + <+> ppLlvmType (getVarType elt) <+> ppName opts elt <> comma <+> ppVar opts idx +{-# SPECIALIZE ppInsert :: LlvmCgConfig -> LlvmVar -> LlvmVar -> LlvmVar -> SDoc #-} +{-# SPECIALIZE ppInsert :: LlvmCgConfig -> LlvmVar -> LlvmVar -> LlvmVar -> HLine #-} -- see Note [SPECIALIZE to HDoc] in GHC.Utils.Outputable - -ppMetaStatement :: LlvmCgConfig -> [MetaAnnot] -> LlvmStatement -> SDoc -ppMetaStatement opts meta stmt = - ppLlvmStatement opts stmt <> ppMetaAnnots opts meta - -ppMetaAnnotExpr :: LlvmCgConfig -> [MetaAnnot] -> LlvmExpression -> SDoc +ppMetaAnnotExpr :: IsLine doc => LlvmCgConfig -> [MetaAnnot] -> LlvmExpression -> doc ppMetaAnnotExpr opts meta expr = ppLlvmExpression opts expr <> ppMetaAnnots opts meta +{-# SPECIALIZE ppMetaAnnotExpr :: LlvmCgConfig -> [MetaAnnot] -> LlvmExpression -> SDoc #-} +{-# SPECIALIZE ppMetaAnnotExpr :: LlvmCgConfig -> [MetaAnnot] -> LlvmExpression -> HLine #-} -- see Note [SPECIALIZE to HDoc] in GHC.Utils.Outputable -ppMetaAnnots :: LlvmCgConfig -> [MetaAnnot] -> SDoc +ppMetaAnnots :: IsLine doc => LlvmCgConfig -> [MetaAnnot] -> doc ppMetaAnnots opts meta = hcat $ map ppMeta meta where ppMeta (MetaAnnot name e) = comma <+> exclamation <> ftext name <+> case e of - MetaNode n -> ppr n - MetaStruct ms -> exclamation <> braces (ppCommaJoin (map (ppMetaExpr opts) ms)) + MetaNode n -> ppMetaId n + MetaStruct ms -> exclamation <> braces (ppCommaJoin (ppMetaExpr opts) ms) other -> exclamation <> braces (ppMetaExpr opts other) -- possible? +{-# SPECIALIZE ppMetaAnnots :: LlvmCgConfig -> [MetaAnnot] -> SDoc #-} +{-# SPECIALIZE ppMetaAnnots :: LlvmCgConfig -> [MetaAnnot] -> HLine #-} -- see Note [SPECIALIZE to HDoc] in GHC.Utils.Outputable -- | Return the variable name or value of the 'LlvmVar' -- in Llvm IR textual representation (e.g. @\@x@, @%y@ or @42@). -ppName :: LlvmCgConfig -> LlvmVar -> SDoc +ppName :: IsLine doc => LlvmCgConfig -> LlvmVar -> doc ppName opts v = case v of LMGlobalVar {} -> char '@' <> ppPlainName opts v LMLocalVar {} -> char '%' <> ppPlainName opts v LMNLocalVar {} -> char '%' <> ppPlainName opts v LMLitVar {} -> ppPlainName opts v +{-# SPECIALIZE ppName :: LlvmCgConfig -> LlvmVar -> SDoc #-} +{-# SPECIALIZE ppName :: LlvmCgConfig -> LlvmVar -> HLine #-} -- see Note [SPECIALIZE to HDoc] in GHC.Utils.Outputable -- | Return the variable name or value of the 'LlvmVar' -- in a plain textual representation (e.g. @x@, @y@ or @42@). -ppPlainName :: LlvmCgConfig -> LlvmVar -> SDoc +ppPlainName :: IsLine doc => LlvmCgConfig -> LlvmVar -> doc ppPlainName opts v = case v of (LMGlobalVar x _ _ _ _ _) -> ftext x (LMLocalVar x LMLabel ) -> pprUniqueAlways x (LMLocalVar x _ ) -> char 'l' <> pprUniqueAlways x (LMNLocalVar x _ ) -> ftext x (LMLitVar x ) -> ppLit opts x +{-# SPECIALIZE ppPlainName :: LlvmCgConfig -> LlvmVar -> SDoc #-} +{-# SPECIALIZE ppPlainName :: LlvmCgConfig -> LlvmVar -> HLine #-} -- see Note [SPECIALIZE to HDoc] in GHC.Utils.Outputable -- | Print a literal value. No type. -ppLit :: LlvmCgConfig -> LlvmLit -> SDoc +ppLit :: IsLine doc => LlvmCgConfig -> LlvmLit -> doc ppLit opts l = case l of - (LMIntLit i (LMInt 32)) -> ppr (fromInteger i :: Int32) - (LMIntLit i (LMInt 64)) -> ppr (fromInteger i :: Int64) - (LMIntLit i _ ) -> ppr ((fromInteger i)::Int) + (LMIntLit i _ ) -> integer i (LMFloatLit r LMFloat ) -> ppFloat (llvmCgPlatform opts) $ narrowFp r (LMFloatLit r LMDouble) -> ppDouble (llvmCgPlatform opts) r f@(LMFloatLit _ _) -> pprPanic "ppLit" (text "Can't print this float literal: " <> ppTypeLit opts f) - (LMVectorLit ls ) -> char '<' <+> ppCommaJoin (map (ppTypeLit opts) ls) <+> char '>' + (LMVectorLit ls ) -> char '<' <+> ppCommaJoin (ppTypeLit opts) ls <+> char '>' (LMNullLit _ ) -> text "null" -- #11487 was an issue where we passed undef for some arguments -- that were actually live. By chance the registers holding those @@ -544,61 +638,76 @@ ppLit opts l = case l of | llvmCgFillUndefWithGarbage opts , Just lit <- garbageLit t -> ppLit opts lit | otherwise -> text "undef" +{-# SPECIALIZE ppLit :: LlvmCgConfig -> LlvmLit -> SDoc #-} +{-# SPECIALIZE ppLit :: LlvmCgConfig -> LlvmLit -> HLine #-} -- see Note [SPECIALIZE to HDoc] in GHC.Utils.Outputable -ppVar :: LlvmCgConfig -> LlvmVar -> SDoc +ppVar :: IsLine doc => LlvmCgConfig -> LlvmVar -> doc ppVar = ppVar' [] +{-# SPECIALIZE ppVar :: LlvmCgConfig -> LlvmVar -> SDoc #-} +{-# SPECIALIZE ppVar :: LlvmCgConfig -> LlvmVar -> HLine #-} -- see Note [SPECIALIZE to HDoc] in GHC.Utils.Outputable -ppVar' :: [LlvmParamAttr] -> LlvmCgConfig -> LlvmVar -> SDoc +ppVar' :: IsLine doc => [LlvmParamAttr] -> LlvmCgConfig -> LlvmVar -> doc ppVar' attrs opts v = case v of LMLitVar x -> ppTypeLit' attrs opts x - x -> ppr (getVarType x) <+> ppSpaceJoin attrs <+> ppName opts x + x -> ppLlvmType (getVarType x) <+> ppSpaceJoin ppLlvmParamAttr attrs <+> ppName opts x +{-# SPECIALIZE ppVar' :: [LlvmParamAttr] -> LlvmCgConfig -> LlvmVar -> SDoc #-} +{-# SPECIALIZE ppVar' :: [LlvmParamAttr] -> LlvmCgConfig -> LlvmVar -> HLine #-} -- see Note [SPECIALIZE to HDoc] in GHC.Utils.Outputable -ppTypeLit :: LlvmCgConfig -> LlvmLit -> SDoc +ppTypeLit :: IsLine doc => LlvmCgConfig -> LlvmLit -> doc ppTypeLit = ppTypeLit' [] +{-# SPECIALIZE ppTypeLit :: LlvmCgConfig -> LlvmLit -> SDoc #-} +{-# SPECIALIZE ppTypeLit :: LlvmCgConfig -> LlvmLit -> HLine #-} -- see Note [SPECIALIZE to HDoc] in GHC.Utils.Outputable -ppTypeLit' :: [LlvmParamAttr] -> LlvmCgConfig -> LlvmLit -> SDoc +ppTypeLit' :: IsLine doc => [LlvmParamAttr] -> LlvmCgConfig -> LlvmLit -> doc ppTypeLit' attrs opts l = case l of LMVectorLit {} -> ppLit opts l - _ -> ppr (getLitType l) <+> ppSpaceJoin attrs <+> ppLit opts l + _ -> ppLlvmType (getLitType l) <+> ppSpaceJoin ppLlvmParamAttr attrs <+> ppLit opts l +{-# SPECIALIZE ppTypeLit' :: [LlvmParamAttr] -> LlvmCgConfig -> LlvmLit -> SDoc #-} +{-# SPECIALIZE ppTypeLit' :: [LlvmParamAttr] -> LlvmCgConfig -> LlvmLit -> HLine #-} -- see Note [SPECIALIZE to HDoc] in GHC.Utils.Outputable -ppStatic :: LlvmCgConfig -> LlvmStatic -> SDoc +ppStatic :: IsLine doc => LlvmCgConfig -> LlvmStatic -> doc ppStatic opts st = case st of LMComment s -> text "; " <> ftext s LMStaticLit l -> ppTypeLit opts l - LMUninitType t -> ppr t <> text " undef" - LMStaticStr s t -> ppr t <> text " c\"" <> ftext s <> text "\\00\"" - LMStaticArray d t -> ppr t <> text " [" <> ppCommaJoin (map (ppStatic opts) d) <> char ']' - LMStaticStruc d t -> ppr t <> text "<{" <> ppCommaJoin (map (ppStatic opts) d) <> text "}>" - LMStaticStrucU d t -> ppr t <> text "{" <> ppCommaJoin (map (ppStatic opts) d) <> text "}" + LMUninitType t -> ppLlvmType t <> text " undef" + LMStaticStr s t -> ppLlvmType t <> text " c\"" <> ftext s <> text "\\00\"" + LMStaticArray d t -> ppLlvmType t <> text " [" <> ppCommaJoin (ppStatic opts) d <> char ']' + LMStaticStruc d t -> ppLlvmType t <> text "<{" <> ppCommaJoin (ppStatic opts) d <> text "}>" + LMStaticStrucU d t -> ppLlvmType t <> text "{" <> ppCommaJoin (ppStatic opts) d <> text "}" LMStaticPointer v -> ppVar opts v - LMTrunc v t -> ppr t <> text " trunc (" <> ppStatic opts v <> text " to " <> ppr t <> char ')' - LMBitc v t -> ppr t <> text " bitcast (" <> ppStatic opts v <> text " to " <> ppr t <> char ')' - LMPtoI v t -> ppr t <> text " ptrtoint (" <> ppStatic opts v <> text " to " <> ppr t <> char ')' + LMTrunc v t -> ppLlvmType t <> text " trunc (" <> ppStatic opts v <> text " to " <> ppLlvmType t <> char ')' + LMBitc v t -> ppLlvmType t <> text " bitcast (" <> ppStatic opts v <> text " to " <> ppLlvmType t <> char ')' + LMPtoI v t -> ppLlvmType t <> text " ptrtoint (" <> ppStatic opts v <> text " to " <> ppLlvmType t <> char ')' LMAdd s1 s2 -> pprStaticArith opts s1 s2 (text "add") (text "fadd") (text "LMAdd") LMSub s1 s2 -> pprStaticArith opts s1 s2 (text "sub") (text "fsub") (text "LMSub") +{-# SPECIALIZE ppStatic :: LlvmCgConfig -> LlvmStatic -> SDoc #-} +{-# SPECIALIZE ppStatic :: LlvmCgConfig -> LlvmStatic -> HLine #-} -- see Note [SPECIALIZE to HDoc] in GHC.Utils.Outputable -pprSpecialStatic :: LlvmCgConfig -> LlvmStatic -> SDoc +pprSpecialStatic :: IsLine doc => LlvmCgConfig -> LlvmStatic -> doc pprSpecialStatic opts stat = case stat of - LMBitc v t -> ppr (pLower t) + LMBitc v t -> ppLlvmType (pLower t) <> text ", bitcast (" - <> ppStatic opts v <> text " to " <> ppr t + <> ppStatic opts v <> text " to " <> ppLlvmType t <> char ')' - LMStaticPointer x -> ppr (pLower $ getVarType x) + LMStaticPointer x -> ppLlvmType (pLower $ getVarType x) <> comma <+> ppStatic opts stat _ -> ppStatic opts stat +{-# SPECIALIZE pprSpecialStatic :: LlvmCgConfig -> LlvmStatic -> SDoc #-} +{-# SPECIALIZE pprSpecialStatic :: LlvmCgConfig -> LlvmStatic -> HLine #-} -- see Note [SPECIALIZE to HDoc] in GHC.Utils.Outputable -pprStaticArith :: LlvmCgConfig -> LlvmStatic -> LlvmStatic -> SDoc -> SDoc - -> SDoc -> SDoc +pprStaticArith :: IsLine doc => LlvmCgConfig -> LlvmStatic -> LlvmStatic -> doc -> doc -> SDoc -> doc pprStaticArith opts s1 s2 int_op float_op op_name = let ty1 = getStatType s1 op = if isFloat ty1 then float_op else int_op in if ty1 == getStatType s2 - then ppr ty1 <+> op <+> lparen <> ppStatic opts s1 <> comma <> ppStatic opts s2 <> rparen + then ppLlvmType ty1 <+> op <+> lparen <> ppStatic opts s1 <> comma <> ppStatic opts s2 <> rparen else pprPanic "pprStaticArith" $ op_name <> text " with different types! s1: " <> ppStatic opts s1 <> text", s2: " <> ppStatic opts s2 +{-# SPECIALIZE pprStaticArith :: LlvmCgConfig -> LlvmStatic -> LlvmStatic -> SDoc -> SDoc -> SDoc -> SDoc #-} +{-# SPECIALIZE pprStaticArith :: LlvmCgConfig -> LlvmStatic -> LlvmStatic -> HLine -> HLine -> SDoc -> HLine #-} -- see Note [SPECIALIZE to HDoc] in GHC.Utils.Outputable -------------------------------------------------------------------------------- @@ -606,9 +715,13 @@ pprStaticArith opts s1 s2 int_op float_op op_name = -------------------------------------------------------------------------------- -- | Blank line. -newLine :: SDoc +newLine :: IsDoc doc => doc newLine = empty +{-# SPECIALIZE newLine :: SDoc #-} +{-# SPECIALIZE newLine :: HDoc #-} -- | Exclamation point. -exclamation :: SDoc +exclamation :: IsLine doc => doc exclamation = char '!' +{-# SPECIALIZE exclamation :: SDoc #-} +{-# SPECIALIZE exclamation :: HLine #-} diff --git a/compiler/GHC/Llvm/Syntax.hs b/compiler/GHC/Llvm/Syntax.hs index 115f5b58c3..882cb0660b 100644 --- a/compiler/GHC/Llvm/Syntax.hs +++ b/compiler/GHC/Llvm/Syntax.hs @@ -150,7 +150,7 @@ data LlvmStatement * value: Variable/Constant to store. * ptr: Location to store the value in -} - | Store LlvmVar LlvmVar LMAlign + | Store LlvmVar LlvmVar LMAlign [MetaAnnot] {- | Multiway branch @@ -186,11 +186,6 @@ data LlvmStatement -} | Nop - {- | - A LLVM statement with metadata attached to it. - -} - | MetaStmt [MetaAnnot] LlvmStatement - deriving (Eq) diff --git a/compiler/GHC/Llvm/Types.hs b/compiler/GHC/Llvm/Types.hs index 77e2ffd10d..f80b261584 100644 --- a/compiler/GHC/Llvm/Types.hs +++ b/compiler/GHC/Llvm/Types.hs @@ -1,6 +1,13 @@ +{-# LANGUAGE CPP #-} {-# LANGUAGE LambdaCase #-} +-- Workaround for #21972. It can be removed once the minimal bootstrapping +-- compiler has a fix for this bug. +#if defined(darwin_HOST_OS) +{-# OPTIONS_GHC -fno-asm-shortcutting #-} +#endif + -------------------------------------------------------------------------------- -- | The LLVM Type System. -- @@ -61,28 +68,30 @@ data LlvmType deriving (Eq) instance Outputable LlvmType where - ppr = ppType + ppr = ppLlvmType -ppType :: LlvmType -> SDoc -ppType t = case t of - LMInt size -> char 'i' <> ppr size +ppLlvmType :: IsLine doc => LlvmType -> doc +ppLlvmType t = case t of + LMInt size -> char 'i' <> int size LMFloat -> text "float" LMDouble -> text "double" LMFloat80 -> text "x86_fp80" LMFloat128 -> text "fp128" - LMPointer x -> ppr x <> char '*' - LMArray nr tp -> char '[' <> ppr nr <> text " x " <> ppr tp <> char ']' - LMVector nr tp -> char '<' <> ppr nr <> text " x " <> ppr tp <> char '>' + LMPointer x -> ppLlvmType x <> char '*' + LMArray nr tp -> char '[' <> int nr <> text " x " <> ppLlvmType tp <> char ']' + LMVector nr tp -> char '<' <> int nr <> text " x " <> ppLlvmType tp <> char '>' LMLabel -> text "label" LMVoid -> text "void" - LMStruct tys -> text "<{" <> ppCommaJoin tys <> text "}>" - LMStructU tys -> text "{" <> ppCommaJoin tys <> text "}" + LMStruct tys -> text "<{" <> ppCommaJoin ppLlvmType tys <> text "}>" + LMStructU tys -> text "{" <> ppCommaJoin ppLlvmType tys <> text "}" LMMetadata -> text "metadata" LMAlias (s,_) -> char '%' <> ftext s LMFunction (LlvmFunctionDecl _ _ _ r varg p _) - -> ppr r <+> lparen <> ppParams varg p <> rparen + -> ppLlvmType r <+> lparen <> ppParams varg p <> rparen +{-# SPECIALIZE ppLlvmType :: LlvmType -> SDoc #-} +{-# SPECIALIZE ppLlvmType :: LlvmType -> HLine #-} -- see Note [SPECIALIZE to HDoc] in GHC.Utils.Outputable -ppParams :: LlvmParameterListType -> [LlvmParameter] -> SDoc +ppParams :: IsLine doc => LlvmParameterListType -> [LlvmParameter] -> doc ppParams varg p = let varg' = case varg of VarArgs | null args -> text "..." @@ -90,7 +99,9 @@ ppParams varg p _otherwise -> text "" -- by default we don't print param attributes args = map fst p - in ppCommaJoin args <> varg' + in ppCommaJoin ppLlvmType args <> varg' +{-# SPECIALIZE ppParams :: LlvmParameterListType -> [LlvmParameter] -> SDoc #-} +{-# SPECIALIZE ppParams :: LlvmParameterListType -> [LlvmParameter] -> HLine #-} -- see Note [SPECIALIZE to HDoc] in GHC.Utils.Outputable -- | An LLVM section definition. If Nothing then let LLVM decide the section type LMSection = Maybe LMString @@ -337,14 +348,6 @@ data LlvmFunctionDecl = LlvmFunctionDecl { } deriving (Eq) -instance Outputable LlvmFunctionDecl where - ppr (LlvmFunctionDecl n l c r varg p a) - = let align = case a of - Just a' -> text " align " <> ppr a' - Nothing -> empty - in ppr l <+> ppr c <+> ppr r <+> char '@' <> ftext n <> - lparen <> ppParams varg p <> rparen <> align - type LlvmFunctionDecls = [LlvmFunctionDecl] type LlvmParameter = (LlvmType, [LlvmParamAttr]) @@ -385,14 +388,19 @@ data LlvmParamAttr deriving (Eq) instance Outputable LlvmParamAttr where - ppr ZeroExt = text "zeroext" - ppr SignExt = text "signext" - ppr InReg = text "inreg" - ppr ByVal = text "byval" - ppr SRet = text "sret" - ppr NoAlias = text "noalias" - ppr NoCapture = text "nocapture" - ppr Nest = text "nest" + ppr = ppLlvmParamAttr + +ppLlvmParamAttr :: IsLine doc => LlvmParamAttr -> doc +ppLlvmParamAttr ZeroExt = text "zeroext" +ppLlvmParamAttr SignExt = text "signext" +ppLlvmParamAttr InReg = text "inreg" +ppLlvmParamAttr ByVal = text "byval" +ppLlvmParamAttr SRet = text "sret" +ppLlvmParamAttr NoAlias = text "noalias" +ppLlvmParamAttr NoCapture = text "nocapture" +ppLlvmParamAttr Nest = text "nest" +{-# SPECIALIZE ppLlvmParamAttr :: LlvmParamAttr -> SDoc #-} +{-# SPECIALIZE ppLlvmParamAttr :: LlvmParamAttr -> HLine #-} -- see Note [SPECIALIZE to HDoc] in GHC.Utils.Outputable -- | Llvm Function Attributes. -- @@ -473,19 +481,24 @@ data LlvmFuncAttr deriving (Eq) instance Outputable LlvmFuncAttr where - ppr AlwaysInline = text "alwaysinline" - ppr InlineHint = text "inlinehint" - ppr NoInline = text "noinline" - ppr OptSize = text "optsize" - ppr NoReturn = text "noreturn" - ppr NoUnwind = text "nounwind" - ppr ReadNone = text "readnone" - ppr ReadOnly = text "readonly" - ppr Ssp = text "ssp" - ppr SspReq = text "ssqreq" - ppr NoRedZone = text "noredzone" - ppr NoImplicitFloat = text "noimplicitfloat" - ppr Naked = text "naked" + ppr = ppLlvmFuncAttr + +ppLlvmFuncAttr :: IsLine doc => LlvmFuncAttr -> doc +ppLlvmFuncAttr AlwaysInline = text "alwaysinline" +ppLlvmFuncAttr InlineHint = text "inlinehint" +ppLlvmFuncAttr NoInline = text "noinline" +ppLlvmFuncAttr OptSize = text "optsize" +ppLlvmFuncAttr NoReturn = text "noreturn" +ppLlvmFuncAttr NoUnwind = text "nounwind" +ppLlvmFuncAttr ReadNone = text "readnone" +ppLlvmFuncAttr ReadOnly = text "readonly" +ppLlvmFuncAttr Ssp = text "ssp" +ppLlvmFuncAttr SspReq = text "ssqreq" +ppLlvmFuncAttr NoRedZone = text "noredzone" +ppLlvmFuncAttr NoImplicitFloat = text "noimplicitfloat" +ppLlvmFuncAttr Naked = text "naked" +{-# SPECIALIZE ppLlvmFuncAttr :: LlvmFuncAttr -> SDoc #-} +{-# SPECIALIZE ppLlvmFuncAttr :: LlvmFuncAttr -> HLine #-} -- see Note [SPECIALIZE to HDoc] in GHC.Utils.Outputable -- | Different types to call a function. @@ -533,12 +546,17 @@ data LlvmCallConvention deriving (Eq) instance Outputable LlvmCallConvention where - ppr CC_Ccc = text "ccc" - ppr CC_Fastcc = text "fastcc" - ppr CC_Coldcc = text "coldcc" - ppr CC_Ghc = text "ghccc" - ppr (CC_Ncc i) = text "cc " <> ppr i - ppr CC_X86_Stdcc = text "x86_stdcallcc" + ppr = ppLlvmCallConvention + +ppLlvmCallConvention :: IsLine doc => LlvmCallConvention -> doc +ppLlvmCallConvention CC_Ccc = text "ccc" +ppLlvmCallConvention CC_Fastcc = text "fastcc" +ppLlvmCallConvention CC_Coldcc = text "coldcc" +ppLlvmCallConvention CC_Ghc = text "ghccc" +ppLlvmCallConvention (CC_Ncc i) = text "cc " <> int i +ppLlvmCallConvention CC_X86_Stdcc = text "x86_stdcallcc" +{-# SPECIALIZE ppLlvmCallConvention :: LlvmCallConvention -> SDoc #-} +{-# SPECIALIZE ppLlvmCallConvention :: LlvmCallConvention -> HLine #-} -- see Note [SPECIALIZE to HDoc] in GHC.Utils.Outputable -- | Functions can have a fixed amount of parameters, or a variable amount. @@ -597,17 +615,22 @@ data LlvmLinkageType deriving (Eq) instance Outputable LlvmLinkageType where - ppr Internal = text "internal" - ppr LinkOnce = text "linkonce" - ppr Weak = text "weak" - ppr Appending = text "appending" - ppr ExternWeak = text "extern_weak" - -- ExternallyVisible does not have a textual representation, it is - -- the linkage type a function resolves to if no other is specified - -- in Llvm. - ppr ExternallyVisible = empty - ppr External = text "external" - ppr Private = text "private" + ppr = ppLlvmLinkageType + +ppLlvmLinkageType :: IsLine doc => LlvmLinkageType -> doc +ppLlvmLinkageType Internal = text "internal" +ppLlvmLinkageType LinkOnce = text "linkonce" +ppLlvmLinkageType Weak = text "weak" +ppLlvmLinkageType Appending = text "appending" +ppLlvmLinkageType ExternWeak = text "extern_weak" +-- ExternallyVisible does not have a textual representation, it is +-- the linkage type a function resolves to if no other is specified +-- in Llvm. +ppLlvmLinkageType ExternallyVisible = empty +ppLlvmLinkageType External = text "external" +ppLlvmLinkageType Private = text "private" +{-# SPECIALIZE ppLlvmLinkageType :: LlvmLinkageType -> SDoc #-} +{-# SPECIALIZE ppLlvmLinkageType :: LlvmLinkageType -> HLine #-} -- see Note [SPECIALIZE to HDoc] in GHC.Utils.Outputable -- ----------------------------------------------------------------------------- -- * LLVM Operations @@ -645,24 +668,29 @@ data LlvmMachOp deriving (Eq) instance Outputable LlvmMachOp where - ppr LM_MO_Add = text "add" - ppr LM_MO_Sub = text "sub" - ppr LM_MO_Mul = text "mul" - ppr LM_MO_UDiv = text "udiv" - ppr LM_MO_SDiv = text "sdiv" - ppr LM_MO_URem = text "urem" - ppr LM_MO_SRem = text "srem" - ppr LM_MO_FAdd = text "fadd" - ppr LM_MO_FSub = text "fsub" - ppr LM_MO_FMul = text "fmul" - ppr LM_MO_FDiv = text "fdiv" - ppr LM_MO_FRem = text "frem" - ppr LM_MO_Shl = text "shl" - ppr LM_MO_LShr = text "lshr" - ppr LM_MO_AShr = text "ashr" - ppr LM_MO_And = text "and" - ppr LM_MO_Or = text "or" - ppr LM_MO_Xor = text "xor" + ppr = ppLlvmMachOp + +ppLlvmMachOp :: IsLine doc => LlvmMachOp -> doc +ppLlvmMachOp LM_MO_Add = text "add" +ppLlvmMachOp LM_MO_Sub = text "sub" +ppLlvmMachOp LM_MO_Mul = text "mul" +ppLlvmMachOp LM_MO_UDiv = text "udiv" +ppLlvmMachOp LM_MO_SDiv = text "sdiv" +ppLlvmMachOp LM_MO_URem = text "urem" +ppLlvmMachOp LM_MO_SRem = text "srem" +ppLlvmMachOp LM_MO_FAdd = text "fadd" +ppLlvmMachOp LM_MO_FSub = text "fsub" +ppLlvmMachOp LM_MO_FMul = text "fmul" +ppLlvmMachOp LM_MO_FDiv = text "fdiv" +ppLlvmMachOp LM_MO_FRem = text "frem" +ppLlvmMachOp LM_MO_Shl = text "shl" +ppLlvmMachOp LM_MO_LShr = text "lshr" +ppLlvmMachOp LM_MO_AShr = text "ashr" +ppLlvmMachOp LM_MO_And = text "and" +ppLlvmMachOp LM_MO_Or = text "or" +ppLlvmMachOp LM_MO_Xor = text "xor" +{-# SPECIALIZE ppLlvmMachOp :: LlvmMachOp -> SDoc #-} +{-# SPECIALIZE ppLlvmMachOp :: LlvmMachOp -> HLine #-} -- see Note [SPECIALIZE to HDoc] in GHC.Utils.Outputable -- | Llvm compare operations. @@ -689,22 +717,27 @@ data LlvmCmpOp deriving (Eq) instance Outputable LlvmCmpOp where - ppr LM_CMP_Eq = text "eq" - ppr LM_CMP_Ne = text "ne" - ppr LM_CMP_Ugt = text "ugt" - ppr LM_CMP_Uge = text "uge" - ppr LM_CMP_Ult = text "ult" - ppr LM_CMP_Ule = text "ule" - ppr LM_CMP_Sgt = text "sgt" - ppr LM_CMP_Sge = text "sge" - ppr LM_CMP_Slt = text "slt" - ppr LM_CMP_Sle = text "sle" - ppr LM_CMP_Feq = text "oeq" - ppr LM_CMP_Fne = text "une" - ppr LM_CMP_Fgt = text "ogt" - ppr LM_CMP_Fge = text "oge" - ppr LM_CMP_Flt = text "olt" - ppr LM_CMP_Fle = text "ole" + ppr = ppLlvmCmpOp + +ppLlvmCmpOp :: IsLine doc => LlvmCmpOp -> doc +ppLlvmCmpOp LM_CMP_Eq = text "eq" +ppLlvmCmpOp LM_CMP_Ne = text "ne" +ppLlvmCmpOp LM_CMP_Ugt = text "ugt" +ppLlvmCmpOp LM_CMP_Uge = text "uge" +ppLlvmCmpOp LM_CMP_Ult = text "ult" +ppLlvmCmpOp LM_CMP_Ule = text "ule" +ppLlvmCmpOp LM_CMP_Sgt = text "sgt" +ppLlvmCmpOp LM_CMP_Sge = text "sge" +ppLlvmCmpOp LM_CMP_Slt = text "slt" +ppLlvmCmpOp LM_CMP_Sle = text "sle" +ppLlvmCmpOp LM_CMP_Feq = text "oeq" +ppLlvmCmpOp LM_CMP_Fne = text "une" +ppLlvmCmpOp LM_CMP_Fgt = text "ogt" +ppLlvmCmpOp LM_CMP_Fge = text "oge" +ppLlvmCmpOp LM_CMP_Flt = text "olt" +ppLlvmCmpOp LM_CMP_Fle = text "ole" +{-# SPECIALIZE ppLlvmCmpOp :: LlvmCmpOp -> SDoc #-} +{-# SPECIALIZE ppLlvmCmpOp :: LlvmCmpOp -> HLine #-} -- see Note [SPECIALIZE to HDoc] in GHC.Utils.Outputable -- | Llvm cast operations. @@ -724,18 +757,23 @@ data LlvmCastOp deriving (Eq) instance Outputable LlvmCastOp where - ppr LM_Trunc = text "trunc" - ppr LM_Zext = text "zext" - ppr LM_Sext = text "sext" - ppr LM_Fptrunc = text "fptrunc" - ppr LM_Fpext = text "fpext" - ppr LM_Fptoui = text "fptoui" - ppr LM_Fptosi = text "fptosi" - ppr LM_Uitofp = text "uitofp" - ppr LM_Sitofp = text "sitofp" - ppr LM_Ptrtoint = text "ptrtoint" - ppr LM_Inttoptr = text "inttoptr" - ppr LM_Bitcast = text "bitcast" + ppr = ppLlvmCastOp + +ppLlvmCastOp :: IsLine doc => LlvmCastOp -> doc +ppLlvmCastOp LM_Trunc = text "trunc" +ppLlvmCastOp LM_Zext = text "zext" +ppLlvmCastOp LM_Sext = text "sext" +ppLlvmCastOp LM_Fptrunc = text "fptrunc" +ppLlvmCastOp LM_Fpext = text "fpext" +ppLlvmCastOp LM_Fptoui = text "fptoui" +ppLlvmCastOp LM_Fptosi = text "fptosi" +ppLlvmCastOp LM_Uitofp = text "uitofp" +ppLlvmCastOp LM_Sitofp = text "sitofp" +ppLlvmCastOp LM_Ptrtoint = text "ptrtoint" +ppLlvmCastOp LM_Inttoptr = text "inttoptr" +ppLlvmCastOp LM_Bitcast = text "bitcast" +{-# SPECIALIZE ppLlvmCastOp :: LlvmCastOp -> SDoc #-} +{-# SPECIALIZE ppLlvmCastOp :: LlvmCastOp -> HLine #-} -- see Note [SPECIALIZE to HDoc] in GHC.Utils.Outputable -- ----------------------------------------------------------------------------- @@ -747,7 +785,7 @@ instance Outputable LlvmCastOp where -- regardless of underlying architecture. -- -- See Note [LLVM Float Types]. -ppDouble :: Platform -> Double -> SDoc +ppDouble :: IsLine doc => Platform -> Double -> doc ppDouble platform d = let bs = doubleToBytes d hex d' = case showHex d' "" of @@ -761,6 +799,8 @@ ppDouble platform d LittleEndian -> reverse str = map toUpper $ concat $ fixEndian $ map hex bs in text "0x" <> text str +{-# SPECIALIZE ppDouble :: Platform -> Double -> SDoc #-} +{-# SPECIALIZE ppDouble :: Platform -> Double -> HLine #-} -- see Note [SPECIALIZE to HDoc] in GHC.Utils.Outputable -- Note [LLVM Float Types] -- ~~~~~~~~~~~~~~~~~~~~~~~ @@ -787,16 +827,22 @@ widenFp :: Float -> Double {-# NOINLINE widenFp #-} widenFp = float2Double -ppFloat :: Platform -> Float -> SDoc +ppFloat :: IsLine doc => Platform -> Float -> doc ppFloat platform = ppDouble platform . widenFp +{-# SPECIALIZE ppFloat :: Platform -> Float -> SDoc #-} +{-# SPECIALIZE ppFloat :: Platform -> Float -> HLine #-} -- see Note [SPECIALIZE to HDoc] in GHC.Utils.Outputable -------------------------------------------------------------------------------- -- * Misc functions -------------------------------------------------------------------------------- -ppCommaJoin :: (Outputable a) => [a] -> SDoc -ppCommaJoin strs = hsep $ punctuate comma (map ppr strs) +ppCommaJoin :: IsLine doc => (a -> doc) -> [a] -> doc +ppCommaJoin ppr strs = hsep $ punctuate comma (map ppr strs) +{-# SPECIALIZE ppCommaJoin :: (a -> SDoc) -> [a] -> SDoc #-} +{-# SPECIALIZE ppCommaJoin :: (a -> HLine) -> [a] -> HLine #-} -- see Note [SPECIALIZE to HDoc] in GHC.Utils.Outputable -ppSpaceJoin :: (Outputable a) => [a] -> SDoc -ppSpaceJoin strs = hsep (map ppr strs) +ppSpaceJoin :: IsLine doc => (a -> doc) -> [a] -> doc +ppSpaceJoin ppr strs = hsep (map ppr strs) +{-# SPECIALIZE ppSpaceJoin :: (a -> SDoc) -> [a] -> SDoc #-} +{-# SPECIALIZE ppSpaceJoin :: (a -> HLine) -> [a] -> HLine #-} -- see Note [SPECIALIZE to HDoc] in GHC.Utils.Outputable |