diff options
Diffstat (limited to 'compiler/GHC/CmmToAsm')
-rw-r--r-- | compiler/GHC/CmmToAsm/AArch64.hs | 6 | ||||
-rw-r--r-- | compiler/GHC/CmmToAsm/AArch64/Ppr.hs | 156 | ||||
-rw-r--r-- | compiler/GHC/CmmToAsm/Dwarf.hs | 63 | ||||
-rw-r--r-- | compiler/GHC/CmmToAsm/Dwarf/Constants.hs | 31 | ||||
-rw-r--r-- | compiler/GHC/CmmToAsm/Dwarf/Types.hs | 149 | ||||
-rw-r--r-- | compiler/GHC/CmmToAsm/Instr.hs | 3 | ||||
-rw-r--r-- | compiler/GHC/CmmToAsm/Monad.hs | 38 | ||||
-rw-r--r-- | compiler/GHC/CmmToAsm/PIC.hs | 48 | ||||
-rw-r--r-- | compiler/GHC/CmmToAsm/PPC.hs | 3 | ||||
-rw-r--r-- | compiler/GHC/CmmToAsm/PPC/CodeGen.hs | 2 | ||||
-rw-r--r-- | compiler/GHC/CmmToAsm/PPC/Instr.hs | 4 | ||||
-rw-r--r-- | compiler/GHC/CmmToAsm/PPC/Ppr.hs | 256 | ||||
-rw-r--r-- | compiler/GHC/CmmToAsm/Ppr.hs | 52 | ||||
-rw-r--r-- | compiler/GHC/CmmToAsm/X86.hs | 3 | ||||
-rw-r--r-- | compiler/GHC/CmmToAsm/X86/CodeGen.hs | 2 | ||||
-rw-r--r-- | compiler/GHC/CmmToAsm/X86/Instr.hs | 3 | ||||
-rw-r--r-- | compiler/GHC/CmmToAsm/X86/Ppr.hs | 232 |
17 files changed, 580 insertions, 471 deletions
diff --git a/compiler/GHC/CmmToAsm/AArch64.hs b/compiler/GHC/CmmToAsm/AArch64.hs index 8b85b12ff6..d814764b2d 100644 --- a/compiler/GHC/CmmToAsm/AArch64.hs +++ b/compiler/GHC/CmmToAsm/AArch64.hs @@ -11,6 +11,7 @@ import GHC.CmmToAsm.Instr import GHC.CmmToAsm.Monad import GHC.CmmToAsm.Config import GHC.CmmToAsm.Types +import GHC.Utils.Outputable (ftext) import qualified GHC.CmmToAsm.AArch64.Instr as AArch64 import qualified GHC.CmmToAsm.AArch64.Ppr as AArch64 @@ -28,7 +29,8 @@ ncgAArch64 config ,canShortcut = AArch64.canShortcut ,shortcutStatics = AArch64.shortcutStatics ,shortcutJump = AArch64.shortcutJump - ,pprNatCmmDecl = AArch64.pprNatCmmDecl config + ,pprNatCmmDeclS = AArch64.pprNatCmmDecl config + ,pprNatCmmDeclH = AArch64.pprNatCmmDecl config ,maxSpillSlots = AArch64.maxSpillSlots config ,allocatableRegs = AArch64.allocatableRegs platform ,ncgAllocMoreStack = AArch64.allocMoreStack platform @@ -55,5 +57,5 @@ instance Instruction AArch64.Instr where mkJumpInstr = AArch64.mkJumpInstr mkStackAllocInstr = AArch64.mkStackAllocInstr mkStackDeallocInstr = AArch64.mkStackDeallocInstr - mkComment = pure . AArch64.COMMENT + mkComment = pure . AArch64.COMMENT . ftext pprInstr = AArch64.pprInstr diff --git a/compiler/GHC/CmmToAsm/AArch64/Ppr.hs b/compiler/GHC/CmmToAsm/AArch64/Ppr.hs index 5ca443f08e..e782bc41a0 100644 --- a/compiler/GHC/CmmToAsm/AArch64/Ppr.hs +++ b/compiler/GHC/CmmToAsm/AArch64/Ppr.hs @@ -29,12 +29,12 @@ import GHC.Utils.Outputable import GHC.Utils.Panic -pprProcAlignment :: NCGConfig -> SDoc +pprProcAlignment :: IsDoc doc => NCGConfig -> doc pprProcAlignment config = maybe empty (pprAlign platform . mkAlignment) (ncgProcAlignment config) where platform = ncgPlatform config -pprNatCmmDecl :: NCGConfig -> NatCmmDecl RawCmmStatics Instr -> SDoc +pprNatCmmDecl :: IsDoc doc => NCGConfig -> NatCmmDecl RawCmmStatics Instr -> doc pprNatCmmDecl config (CmmData section dats) = pprSectionAlign config section $$ pprDatas config dats @@ -50,42 +50,45 @@ pprNatCmmDecl config proc@(CmmProc top_info lbl _ (ListGraph blocks)) = pprLabel platform lbl $$ -- blocks guaranteed not null, so label needed vcat (map (pprBasicBlock config top_info) blocks) $$ (if ncgDwarfEnabled config - then pprAsmLabel platform (mkAsmTempEndLabel lbl) <> char ':' else empty) $$ + then line (pprAsmLabel platform (mkAsmTempEndLabel lbl) <> char ':') else empty) $$ pprSizeDecl platform lbl Just (CmmStaticsRaw info_lbl _) -> pprSectionAlign config (Section Text info_lbl) $$ -- pprProcAlignment config $$ (if platformHasSubsectionsViaSymbols platform - then pprAsmLabel platform (mkDeadStripPreventer info_lbl) <> char ':' + then line (pprAsmLabel platform (mkDeadStripPreventer info_lbl) <> char ':') else empty) $$ vcat (map (pprBasicBlock config top_info) blocks) $$ -- above: Even the first block gets a label, because with branch-chain -- elimination, it might be the target of a goto. (if platformHasSubsectionsViaSymbols platform then -- See Note [Subsections Via Symbols] - text "\t.long " + line + $ text "\t.long " <+> pprAsmLabel platform info_lbl <+> char '-' <+> pprAsmLabel platform (mkDeadStripPreventer info_lbl) else empty) $$ pprSizeDecl platform info_lbl +{-# SPECIALIZE pprNatCmmDecl :: NCGConfig -> NatCmmDecl RawCmmStatics Instr -> SDoc #-} +{-# SPECIALIZE pprNatCmmDecl :: NCGConfig -> NatCmmDecl RawCmmStatics Instr -> HDoc #-} -- see Note [SPECIALIZE to HDoc] in GHC.Utils.Outputable -pprLabel :: Platform -> CLabel -> SDoc +pprLabel :: IsDoc doc => Platform -> CLabel -> doc pprLabel platform lbl = pprGloblDecl platform lbl $$ pprTypeDecl platform lbl - $$ (pprAsmLabel platform lbl <> char ':') + $$ line (pprAsmLabel platform lbl <> char ':') -pprAlign :: Platform -> Alignment -> SDoc +pprAlign :: IsDoc doc => Platform -> Alignment -> doc pprAlign _platform alignment - = text "\t.balign " <> int (alignmentBytes alignment) + = line $ text "\t.balign " <> int (alignmentBytes alignment) -- | Print appropriate alignment for the given section type. -pprAlignForSection :: Platform -> SectionType -> SDoc +pprAlignForSection :: IsDoc doc => Platform -> SectionType -> doc pprAlignForSection _platform _seg -- .balign is stable, whereas .align is platform dependent. - = text "\t.balign 8" -- always 8 + = line (text "\t.balign 8") -- always 8 -- | Print section header and appropriate alignment for that section. -- @@ -94,28 +97,28 @@ pprAlignForSection _platform _seg -- .section .text -- .balign 8 -- -pprSectionAlign :: NCGConfig -> Section -> SDoc +pprSectionAlign :: IsDoc doc => NCGConfig -> Section -> doc pprSectionAlign _config (Section (OtherSection _) _) = panic "AArch64.Ppr.pprSectionAlign: unknown section" pprSectionAlign config sec@(Section seg _) = - pprSectionHeader config sec + line (pprSectionHeader config sec) $$ pprAlignForSection (ncgPlatform config) seg -- | Output the ELF .size directive. -pprSizeDecl :: Platform -> CLabel -> SDoc +pprSizeDecl :: IsDoc doc => Platform -> CLabel -> doc pprSizeDecl platform lbl = if osElfTarget (platformOS platform) - then text "\t.size" <+> pprAsmLabel platform lbl <> text ", .-" <> pprAsmLabel platform lbl + then line (text "\t.size" <+> pprAsmLabel platform lbl <> text ", .-" <> pprAsmLabel platform lbl) else empty -pprBasicBlock :: NCGConfig -> LabelMap RawCmmStatics -> NatBasicBlock Instr - -> SDoc +pprBasicBlock :: IsDoc doc => NCGConfig -> LabelMap RawCmmStatics -> NatBasicBlock Instr + -> doc pprBasicBlock config info_env (BasicBlock blockid instrs) = maybe_infotable $ pprLabel platform asmLbl $$ vcat (map (pprInstr platform) (id {-detectTrivialDeadlock-} optInstrs)) $$ (if ncgDwarfEnabled config - then pprAsmLabel platform (mkAsmTempEndLabel asmLbl) <> char ':' + then line (pprAsmLabel platform (mkAsmTempEndLabel asmLbl) <> char ':') else empty ) where @@ -135,7 +138,7 @@ pprBasicBlock config info_env (BasicBlock blockid instrs) pprLabel platform info_lbl $$ c $$ (if ncgDwarfEnabled config - then pprAsmLabel platform (mkAsmTempEndLabel info_lbl) <> char ':' + then line (pprAsmLabel platform (mkAsmTempEndLabel info_lbl) <> char ':') else empty) -- Make sure the info table has the right .loc for the block -- coming right after it. See Note [Info Offset] @@ -143,7 +146,7 @@ pprBasicBlock config info_env (BasicBlock blockid instrs) (l@LOCATION{} : _) -> pprInstr platform l _other -> empty -pprDatas :: NCGConfig -> RawCmmStatics -> SDoc +pprDatas :: IsDoc doc => NCGConfig -> RawCmmStatics -> doc -- See Note [emit-time elimination of static indirections] in "GHC.Cmm.CLabel". pprDatas config (CmmStaticsRaw alias [CmmStaticLit (CmmLabel lbl), CmmStaticLit ind, _, _]) | lbl == mkIndStaticInfoLabel @@ -153,29 +156,29 @@ pprDatas config (CmmStaticsRaw alias [CmmStaticLit (CmmLabel lbl), CmmStaticLit , Just ind' <- labelInd ind , alias `mayRedirectTo` ind' = pprGloblDecl (ncgPlatform config) alias - $$ text ".equiv" <+> pprAsmLabel (ncgPlatform config) alias <> comma <> pprAsmLabel (ncgPlatform config) ind' + $$ line (text ".equiv" <+> pprAsmLabel (ncgPlatform config) alias <> comma <> pprAsmLabel (ncgPlatform config) ind') pprDatas config (CmmStaticsRaw lbl dats) = vcat (pprLabel platform lbl : map (pprData config) dats) where platform = ncgPlatform config -pprData :: NCGConfig -> CmmStatic -> SDoc -pprData _config (CmmString str) = pprString str -pprData _config (CmmFileEmbed path) = pprFileEmbed path +pprData :: IsDoc doc => NCGConfig -> CmmStatic -> doc +pprData _config (CmmString str) = line (pprString str) +pprData _config (CmmFileEmbed path) = line (pprFileEmbed path) pprData config (CmmUninitialised bytes) - = let platform = ncgPlatform config - in if platformOS platform == OSDarwin - then text ".space " <> int bytes - else text ".skip " <> int bytes + = line $ let platform = ncgPlatform config + in if platformOS platform == OSDarwin + then text ".space " <> int bytes + else text ".skip " <> int bytes pprData config (CmmStaticLit lit) = pprDataItem config lit -pprGloblDecl :: Platform -> CLabel -> SDoc +pprGloblDecl :: IsDoc doc => Platform -> CLabel -> doc pprGloblDecl platform lbl | not (externallyVisibleCLabel lbl) = empty - | otherwise = text "\t.globl " <> pprAsmLabel platform lbl + | otherwise = line (text "\t.globl " <> pprAsmLabel platform lbl) -- Note [Always use objects for info tables] -- ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ @@ -187,7 +190,7 @@ pprGloblDecl platform lbl -- -- Fun fact: The LLVMMangler exists to patch this issue su on the LLVM side as -- well. -pprLabelType' :: Platform -> CLabel -> SDoc +pprLabelType' :: IsLine doc => Platform -> CLabel -> doc pprLabelType' platform lbl = if isCFunctionLabel lbl || functionOkInfoTable then text "@function" @@ -198,15 +201,15 @@ pprLabelType' platform lbl = isInfoTableLabel lbl && not (isCmmInfoTableLabel lbl) && not (isConInfoTableLabel lbl) -- this is called pprTypeAndSizeDecl in PPC.Ppr -pprTypeDecl :: Platform -> CLabel -> SDoc +pprTypeDecl :: IsDoc doc => Platform -> CLabel -> doc pprTypeDecl platform lbl = if osElfTarget (platformOS platform) && externallyVisibleCLabel lbl - then text ".type " <> pprAsmLabel platform lbl <> text ", " <> pprLabelType' platform lbl + then line (text ".type " <> pprAsmLabel platform lbl <> text ", " <> pprLabelType' platform lbl) else empty -pprDataItem :: NCGConfig -> CmmLit -> SDoc +pprDataItem :: IsDoc doc => NCGConfig -> CmmLit -> doc pprDataItem config lit - = vcat (ppr_item (cmmTypeFormat $ cmmLitType platform lit) lit) + = lines_ (ppr_item (cmmTypeFormat $ cmmLitType platform lit) lit) where platform = ncgPlatform config @@ -227,7 +230,7 @@ pprDataItem config lit ppr_item _ _ = pprPanic "pprDataItem:ppr_item" (text $ show lit) -pprImm :: Platform -> Imm -> SDoc +pprImm :: IsLine doc => Platform -> Imm -> doc pprImm _ (ImmInt i) = int i pprImm _ (ImmInteger i) = integer i pprImm p (ImmCLbl l) = pprAsmLabel p l @@ -257,7 +260,7 @@ asmDoubleslashComment c = whenPprDebug $ text "//" <+> c asmMultilineComment :: SDoc -> SDoc asmMultilineComment c = whenPprDebug $ text "/*" $+$ c $+$ text "*/" -pprIm :: Platform -> Imm -> SDoc +pprIm :: IsLine doc => Platform -> Imm -> doc pprIm platform im = case im of ImmInt i -> char '#' <> int i ImmInteger i -> char '#' <> integer i @@ -283,7 +286,7 @@ pprIm platform im = case im of ImmIndex l o -> text "[=" <> pprAsmLabel platform l <> comma <+> char '#' <> int o <> char ']' _ -> panic "AArch64.pprIm" -pprExt :: ExtMode -> SDoc +pprExt :: IsLine doc => ExtMode -> doc pprExt EUXTB = text "uxtb" pprExt EUXTH = text "uxth" pprExt EUXTW = text "uxtw" @@ -293,13 +296,13 @@ pprExt ESXTH = text "sxth" pprExt ESXTW = text "sxtw" pprExt ESXTX = text "sxtx" -pprShift :: ShiftMode -> SDoc +pprShift :: IsLine doc => ShiftMode -> doc pprShift SLSL = text "lsl" pprShift SLSR = text "lsr" pprShift SASR = text "asr" pprShift SROR = text "ror" -pprOp :: Platform -> Operand -> SDoc +pprOp :: IsLine doc => Platform -> Operand -> doc pprOp plat op = case op of OpReg w r -> pprReg w r OpRegExt w r x 0 -> pprReg w r <> comma <+> pprExt x @@ -312,7 +315,7 @@ pprOp plat op = case op of OpAddr (AddrRegImm r1 im) -> char '[' <+> pprReg W64 r1 <> comma <+> pprImm plat im <+> char ']' OpAddr (AddrReg r1) -> char '[' <+> pprReg W64 r1 <+> char ']' -pprReg :: Width -> Reg -> SDoc +pprReg :: forall doc. IsLine doc => Width -> Reg -> doc pprReg w r = case r of RegReal (RealRegSingle i) -> ppr_reg_no w i -- virtual regs should not show up, but this is helpful for debugging. @@ -322,7 +325,7 @@ pprReg w r = case r of _ -> pprPanic "AArch64.pprReg" (text $ show r) where - ppr_reg_no :: Width -> Int -> SDoc + ppr_reg_no :: Width -> Int -> doc ppr_reg_no w 31 | w == W64 = text "sp" | w == W32 = text "wsp" @@ -351,24 +354,27 @@ isFloatOp (OpReg _ (RegVirtual (VirtualRegF _))) = True isFloatOp (OpReg _ (RegVirtual (VirtualRegD _))) = True isFloatOp _ = False -pprInstr :: Platform -> Instr -> SDoc +pprInstr :: IsDoc doc => Platform -> Instr -> doc pprInstr platform instr = case instr of -- Meta Instructions --------------------------------------------------------- - COMMENT s -> asmComment s - MULTILINE_COMMENT s -> asmMultilineComment s - ANN d i -> pprInstr platform i <+> asmDoubleslashComment d - LOCATION file line col _name - -> text "\t.loc" <+> ppr file <+> ppr line <+> ppr col - DELTA d -> asmComment $ text ("\tdelta = " ++ show d) + -- see Note [dualLine and dualDoc] in GHC.Utils.Outputable + COMMENT s -> dualDoc (asmComment s) empty + MULTILINE_COMMENT s -> dualDoc (asmMultilineComment s) empty + ANN d i -> dualDoc (pprInstr platform i <+> asmDoubleslashComment d) (pprInstr platform i) + + LOCATION file line' col _name + -> line (text "\t.loc" <+> int file <+> int line' <+> int col) + DELTA d -> dualDoc (asmComment $ text "\tdelta = " <> int d) empty + -- see Note [dualLine and dualDoc] in GHC.Utils.Outputable NEWBLOCK _ -> panic "PprInstr: NEWBLOCK" LDATA _ _ -> panic "pprInstr: LDATA" -- Pseudo Instructions ------------------------------------------------------- - PUSH_STACK_FRAME -> text "\tstp x29, x30, [sp, #-16]!" - $$ text "\tmov x29, sp" + PUSH_STACK_FRAME -> lines_ [text "\tstp x29, x30, [sp, #-16]!", + text "\tmov x29, sp"] - POP_STACK_FRAME -> text "\tldp x29, x30, [sp], #16" + POP_STACK_FRAME -> line $ text "\tldp x29, x30, [sp], #16" -- =========================================================================== -- AArch64 Instruction Set -- 1. Arithmetic Instructions ------------------------------------------------ @@ -430,28 +436,28 @@ pprInstr platform instr = case instr of -- 4. Branch Instructions ---------------------------------------------------- J t -> pprInstr platform (B t) - B (TBlock bid) -> text "\tb" <+> pprAsmLabel platform (mkLocalBlockLabel (getUnique bid)) - B (TLabel lbl) -> text "\tb" <+> pprAsmLabel platform lbl - B (TReg r) -> text "\tbr" <+> pprReg W64 r + B (TBlock bid) -> line $ text "\tb" <+> pprAsmLabel platform (mkLocalBlockLabel (getUnique bid)) + B (TLabel lbl) -> line $ text "\tb" <+> pprAsmLabel platform lbl + B (TReg r) -> line $ text "\tbr" <+> pprReg W64 r - BL (TBlock bid) _ _ -> text "\tbl" <+> pprAsmLabel platform (mkLocalBlockLabel (getUnique bid)) - BL (TLabel lbl) _ _ -> text "\tbl" <+> pprAsmLabel platform lbl - BL (TReg r) _ _ -> text "\tblr" <+> pprReg W64 r + BL (TBlock bid) _ _ -> line $ text "\tbl" <+> pprAsmLabel platform (mkLocalBlockLabel (getUnique bid)) + BL (TLabel lbl) _ _ -> line $ text "\tbl" <+> pprAsmLabel platform lbl + BL (TReg r) _ _ -> line $ text "\tblr" <+> pprReg W64 r - BCOND c (TBlock bid) -> text "\t" <> pprBcond c <+> pprAsmLabel platform (mkLocalBlockLabel (getUnique bid)) - BCOND c (TLabel lbl) -> text "\t" <> pprBcond c <+> pprAsmLabel platform lbl + BCOND c (TBlock bid) -> line $ text "\t" <> pprBcond c <+> pprAsmLabel platform (mkLocalBlockLabel (getUnique bid)) + BCOND c (TLabel lbl) -> line $ text "\t" <> pprBcond c <+> pprAsmLabel platform lbl BCOND _ (TReg _) -> panic "AArch64.ppr: No conditional branching to registers!" -- 5. Atomic Instructions ---------------------------------------------------- -- 6. Conditional Instructions ----------------------------------------------- - CSET o c -> text "\tcset" <+> pprOp platform o <> comma <+> pprCond c + CSET o c -> line $ text "\tcset" <+> pprOp platform o <> comma <+> pprCond c - CBZ o (TBlock bid) -> text "\tcbz" <+> pprOp platform o <> comma <+> pprAsmLabel platform (mkLocalBlockLabel (getUnique bid)) - CBZ o (TLabel lbl) -> text "\tcbz" <+> pprOp platform o <> comma <+> pprAsmLabel platform lbl + CBZ o (TBlock bid) -> line $ text "\tcbz" <+> pprOp platform o <> comma <+> pprAsmLabel platform (mkLocalBlockLabel (getUnique bid)) + CBZ o (TLabel lbl) -> line $ text "\tcbz" <+> pprOp platform o <> comma <+> pprAsmLabel platform lbl CBZ _ (TReg _) -> panic "AArch64.ppr: No conditional (cbz) branching to registers!" - CBNZ o (TBlock bid) -> text "\tcbnz" <+> pprOp platform o <> comma <+> pprAsmLabel platform (mkLocalBlockLabel (getUnique bid)) - CBNZ o (TLabel lbl) -> text "\tcbnz" <+> pprOp platform o <> comma <+> pprAsmLabel platform lbl + CBNZ o (TBlock bid) -> line $ text "\tcbnz" <+> pprOp platform o <> comma <+> pprAsmLabel platform (mkLocalBlockLabel (getUnique bid)) + CBNZ o (TLabel lbl) -> line $ text "\tcbnz" <+> pprOp platform o <> comma <+> pprAsmLabel platform lbl CBNZ _ (TReg _) -> panic "AArch64.ppr: No conditional (cbnz) branching to registers!" -- 7. Load and Store Instructions -------------------------------------------- @@ -532,23 +538,23 @@ pprInstr platform instr = case instr of LDP _f o1 o2 o3 -> op3 (text "\tldp") o1 o2 o3 -- 8. Synchronization Instructions ------------------------------------------- - DMBSY -> text "\tdmb sy" + DMBSY -> line $ text "\tdmb sy" -- 9. Floating Point Instructions -------------------------------------------- FCVT o1 o2 -> op2 (text "\tfcvt") o1 o2 SCVTF o1 o2 -> op2 (text "\tscvtf") o1 o2 FCVTZS o1 o2 -> op2 (text "\tfcvtzs") o1 o2 FABS o1 o2 -> op2 (text "\tfabs") o1 o2 - where op2 op o1 o2 = op <+> pprOp platform o1 <> comma <+> pprOp platform o2 - op3 op o1 o2 o3 = op <+> pprOp platform o1 <> comma <+> pprOp platform o2 <> comma <+> pprOp platform o3 - op4 op o1 o2 o3 o4 = op <+> pprOp platform o1 <> comma <+> pprOp platform o2 <> comma <+> pprOp platform o3 <> comma <+> pprOp platform o4 - op_ldr o1 rest = text "\tldr" <+> pprOp platform o1 <> comma <+> text "[" <> pprOp platform o1 <> comma <+> rest <> text "]" - op_adrp o1 rest = text "\tadrp" <+> pprOp platform o1 <> comma <+> rest - op_add o1 rest = text "\tadd" <+> pprOp platform o1 <> comma <+> pprOp platform o1 <> comma <+> rest - -pprBcond :: Cond -> SDoc + where op2 op o1 o2 = line $ op <+> pprOp platform o1 <> comma <+> pprOp platform o2 + op3 op o1 o2 o3 = line $ op <+> pprOp platform o1 <> comma <+> pprOp platform o2 <> comma <+> pprOp platform o3 + op4 op o1 o2 o3 o4 = line $ op <+> pprOp platform o1 <> comma <+> pprOp platform o2 <> comma <+> pprOp platform o3 <> comma <+> pprOp platform o4 + op_ldr o1 rest = line $ text "\tldr" <+> pprOp platform o1 <> comma <+> text "[" <> pprOp platform o1 <> comma <+> rest <> text "]" + op_adrp o1 rest = line $ text "\tadrp" <+> pprOp platform o1 <> comma <+> rest + op_add o1 rest = line $ text "\tadd" <+> pprOp platform o1 <> comma <+> pprOp platform o1 <> comma <+> rest + +pprBcond :: IsLine doc => Cond -> doc pprBcond c = text "b." <> pprCond c -pprCond :: Cond -> SDoc +pprCond :: IsLine doc => Cond -> doc pprCond c = case c of ALWAYS -> text "al" -- Always EQ -> text "eq" -- Equal diff --git a/compiler/GHC/CmmToAsm/Dwarf.hs b/compiler/GHC/CmmToAsm/Dwarf.hs index 407050d045..0eef6ecb49 100644 --- a/compiler/GHC/CmmToAsm/Dwarf.hs +++ b/compiler/GHC/CmmToAsm/Dwarf.hs @@ -26,50 +26,47 @@ import Data.List ( sortBy ) import Data.Ord ( comparing ) import qualified Data.Map as Map import System.FilePath -import System.Directory ( getCurrentDirectory ) import qualified GHC.Cmm.Dataflow.Label as H import qualified GHC.Cmm.Dataflow.Collections as H -- | Generate DWARF/debug information -dwarfGen :: NCGConfig -> ModLocation -> UniqSupply -> [DebugBlock] - -> IO (SDoc, UniqSupply) -dwarfGen _ _ us [] = return (empty, us) -dwarfGen config modLoc us blocks = do +dwarfGen :: IsDoc doc => String -> NCGConfig -> ModLocation -> UniqSupply -> [DebugBlock] + -> (doc, UniqSupply) +dwarfGen _ _ _ us [] = (empty, us) +dwarfGen compPath config modLoc us blocks = let platform = ncgPlatform config - -- Convert debug data structures to DWARF info records - let procs = debugSplitProcs blocks + -- Convert debug data structures to DWARF info records + procs = debugSplitProcs blocks stripBlocks dbg | ncgDwarfStripBlockInfo config = dbg { dblBlocks = [] } | otherwise = dbg - compPath <- getCurrentDirectory - let lowLabel = dblCLabel $ head procs + lowLabel = dblCLabel $ head procs highLabel = mkAsmTempProcEndLabel $ dblCLabel $ last procs dwarfUnit = DwarfCompileUnit { dwChildren = map (procToDwarf config) (map stripBlocks procs) , dwName = fromMaybe "" (ml_hs_file modLoc) , dwCompDir = addTrailingPathSeparator compPath , dwProducer = cProjectName ++ " " ++ cProjectVersion - , dwLowLabel = pprAsmLabel platform lowLabel - , dwHighLabel = pprAsmLabel platform highLabel - , dwLineLabel = dwarfLineLabel + , dwLowLabel = lowLabel + , dwHighLabel = highLabel } - -- Check whether we have any source code information, so we do not - -- end up writing a pointer to an empty .debug_line section - -- (dsymutil on Mac Os gets confused by this). - let haveSrcIn blk = isJust (dblSourceTick blk) && isJust (dblPosition blk) + -- Check whether we have any source code information, so we do not + -- end up writing a pointer to an empty .debug_line section + -- (dsymutil on Mac Os gets confused by this). + haveSrcIn blk = isJust (dblSourceTick blk) && isJust (dblPosition blk) || any haveSrcIn (dblBlocks blk) haveSrc = any haveSrcIn procs -- .debug_abbrev section: Declare the format we're using - let abbrevSct = pprAbbrevDecls platform haveSrc + abbrevSct = pprAbbrevDecls platform haveSrc -- .debug_info section: Information records on procedures and blocks - let -- unique to identify start and end compilation unit .debug_inf + -- unique to identify start and end compilation unit .debug_inf (unitU, us') = takeUniqFromSupply us - infoSct = vcat [ dwarfInfoLabel <> colon + infoSct = vcat [ line (dwarfInfoLabel <> colon) , dwarfInfoSection platform , compileUnitHeader platform unitU , pprDwarfInfo platform haveSrc dwarfUnit @@ -78,21 +75,23 @@ dwarfGen config modLoc us blocks = do -- .debug_line section: Generated mainly by the assembler, but we -- need to label it - let lineSct = dwarfLineSection platform $$ - dwarfLineLabel <> colon + lineSct = dwarfLineSection platform $$ + line (dwarfLineLabel <> colon) -- .debug_frame section: Information about the layout of the GHC stack - let (framesU, us'') = takeUniqFromSupply us' + (framesU, us'') = takeUniqFromSupply us' frameSct = dwarfFrameSection platform $$ - dwarfFrameLabel <> colon $$ + line (dwarfFrameLabel <> colon) $$ pprDwarfFrame platform (debugFrame framesU procs) -- .aranges section: Information about the bounds of compilation units - let aranges' | ncgSplitSections config = map mkDwarfARange procs + aranges' | ncgSplitSections config = map mkDwarfARange procs | otherwise = [DwarfARange lowLabel highLabel] - let aranges = dwarfARangesSection platform $$ pprDwarfARanges platform aranges' unitU + aranges = dwarfARangesSection platform $$ pprDwarfARanges platform aranges' unitU - return (infoSct $$ abbrevSct $$ lineSct $$ frameSct $$ aranges, us'') + in (infoSct $$ abbrevSct $$ lineSct $$ frameSct $$ aranges, us'') +{-# SPECIALIZE dwarfGen :: String -> NCGConfig -> ModLocation -> UniqSupply -> [DebugBlock] -> (SDoc, UniqSupply) #-} +{-# SPECIALIZE dwarfGen :: String -> NCGConfig -> ModLocation -> UniqSupply -> [DebugBlock] -> (HDoc, UniqSupply) #-} -- see Note [SPECIALIZE to HDoc] in GHC.Utils.Outputable -- | Build an address range entry for one proc. -- With split sections, each proc needs its own entry, since they may get @@ -106,24 +105,24 @@ mkDwarfARange proc = DwarfARange lbl end -- | Header for a compilation unit, establishing global format -- parameters -compileUnitHeader :: Platform -> Unique -> SDoc +compileUnitHeader :: IsDoc doc => Platform -> Unique -> doc compileUnitHeader platform unitU = let cuLabel = mkAsmTempLabel unitU -- sits right before initialLength field length = pprAsmLabel platform (mkAsmTempEndLabel cuLabel) <> char '-' <> pprAsmLabel platform cuLabel <> text "-4" -- length of initialLength field - in vcat [ pprAsmLabel platform cuLabel <> colon - , text "\t.long " <> length -- compilation unit size + in vcat [ line (pprAsmLabel platform cuLabel <> colon) + , line (text "\t.long " <> length) -- compilation unit size , pprHalf 3 -- DWARF version , sectionOffset platform dwarfAbbrevLabel dwarfAbbrevLabel -- abbrevs offset - , text "\t.byte " <> ppr (platformWordSizeInBytes platform) -- word size + , line (text "\t.byte " <> int (platformWordSizeInBytes platform)) -- word size ] -- | Compilation unit footer, mainly establishing size of debug sections -compileUnitFooter :: Platform -> Unique -> SDoc +compileUnitFooter :: IsDoc doc => Platform -> Unique -> doc compileUnitFooter platform unitU = let cuEndLabel = mkAsmTempEndLabel $ mkAsmTempLabel unitU - in pprAsmLabel platform cuEndLabel <> colon + in line (pprAsmLabel platform cuEndLabel <> colon) -- | Splits the blocks by procedures. In the result all nested blocks -- will come from the same procedure as the top-level block. See diff --git a/compiler/GHC/CmmToAsm/Dwarf/Constants.hs b/compiler/GHC/CmmToAsm/Dwarf/Constants.hs index b8fb5706cb..58e123176e 100644 --- a/compiler/GHC/CmmToAsm/Dwarf/Constants.hs +++ b/compiler/GHC/CmmToAsm/Dwarf/Constants.hs @@ -144,17 +144,29 @@ dW_OP_call_frame_cfa = 0x9c -- * Dwarf section declarations dwarfInfoSection, dwarfAbbrevSection, dwarfLineSection, - dwarfFrameSection, dwarfGhcSection, dwarfARangesSection :: Platform -> SDoc + dwarfFrameSection, dwarfGhcSection, dwarfARangesSection :: IsDoc doc => Platform -> doc dwarfInfoSection platform = dwarfSection platform "info" dwarfAbbrevSection platform = dwarfSection platform "abbrev" dwarfLineSection platform = dwarfSection platform "line" dwarfFrameSection platform = dwarfSection platform "frame" dwarfGhcSection platform = dwarfSection platform "ghc" dwarfARangesSection platform = dwarfSection platform "aranges" +{-# SPECIALIZE dwarfInfoSection :: Platform -> SDoc #-} +{-# SPECIALIZE dwarfInfoSection :: Platform -> HDoc #-} -- see Note [SPECIALIZE to HDoc] in GHC.Utils.Outputable +{-# SPECIALIZE dwarfAbbrevSection :: Platform -> SDoc #-} +{-# SPECIALIZE dwarfAbbrevSection :: Platform -> HDoc #-} -- see Note [SPECIALIZE to HDoc] in GHC.Utils.Outputable +{-# SPECIALIZE dwarfLineSection :: Platform -> SDoc #-} +{-# SPECIALIZE dwarfLineSection :: Platform -> HDoc #-} -- see Note [SPECIALIZE to HDoc] in GHC.Utils.Outputable +{-# SPECIALIZE dwarfFrameSection :: Platform -> SDoc #-} +{-# SPECIALIZE dwarfFrameSection :: Platform -> HDoc #-} -- see Note [SPECIALIZE to HDoc] in GHC.Utils.Outputable +{-# SPECIALIZE dwarfGhcSection :: Platform -> SDoc #-} +{-# SPECIALIZE dwarfGhcSection :: Platform -> HDoc #-} -- see Note [SPECIALIZE to HDoc] in GHC.Utils.Outputable +{-# SPECIALIZE dwarfARangesSection :: Platform -> SDoc #-} +{-# SPECIALIZE dwarfARangesSection :: Platform -> HDoc #-} -- see Note [SPECIALIZE to HDoc] in GHC.Utils.Outputable -dwarfSection :: Platform -> String -> SDoc +dwarfSection :: IsDoc doc => Platform -> String -> doc dwarfSection platform name = - case platformOS platform of + line $ case platformOS platform of os | osElfTarget os -> text "\t.section .debug_" <> text name <> text ",\"\"," <> sectionType platform "progbits" @@ -162,13 +174,24 @@ dwarfSection platform name = -> text "\t.section __DWARF,__debug_" <> text name <> text ",regular,debug" | otherwise -> text "\t.section .debug_" <> text name <> text ",\"dr\"" +{-# SPECIALIZE dwarfSection :: Platform -> String -> SDoc #-} +{-# SPECIALIZE dwarfSection :: Platform -> String -> HDoc #-} -- see Note [SPECIALIZE to HDoc] in GHC.Utils.Outputable + -- * Dwarf section labels -dwarfInfoLabel, dwarfAbbrevLabel, dwarfLineLabel, dwarfFrameLabel :: SDoc +dwarfInfoLabel, dwarfAbbrevLabel, dwarfLineLabel, dwarfFrameLabel :: IsLine doc => doc dwarfInfoLabel = text ".Lsection_info" dwarfAbbrevLabel = text ".Lsection_abbrev" dwarfLineLabel = text ".Lsection_line" dwarfFrameLabel = text ".Lsection_frame" +{-# SPECIALIZE dwarfInfoLabel :: SDoc #-} +{-# SPECIALIZE dwarfInfoLabel :: HLine #-} -- see Note [SPECIALIZE to HDoc] in GHC.Utils.Outputable +{-# SPECIALIZE dwarfAbbrevLabel :: SDoc #-} +{-# SPECIALIZE dwarfAbbrevLabel :: HLine #-} -- see Note [SPECIALIZE to HDoc] in GHC.Utils.Outputable +{-# SPECIALIZE dwarfLineLabel :: SDoc #-} +{-# SPECIALIZE dwarfLineLabel :: HLine #-} -- see Note [SPECIALIZE to HDoc] in GHC.Utils.Outputable +{-# SPECIALIZE dwarfFrameLabel :: SDoc #-} +{-# SPECIALIZE dwarfFrameLabel :: HLine #-} -- see Note [SPECIALIZE to HDoc] in GHC.Utils.Outputable -- | Mapping of registers to DWARF register numbers dwarfRegNo :: Platform -> Reg -> Word8 diff --git a/compiler/GHC/CmmToAsm/Dwarf/Types.hs b/compiler/GHC/CmmToAsm/Dwarf/Types.hs index 236ddb5ffc..5722e07a3a 100644 --- a/compiler/GHC/CmmToAsm/Dwarf/Types.hs +++ b/compiler/GHC/CmmToAsm/Dwarf/Types.hs @@ -59,9 +59,8 @@ data DwarfInfo , dwName :: String , dwProducer :: String , dwCompDir :: String - , dwLowLabel :: SDoc - , dwHighLabel :: SDoc - , dwLineLabel :: SDoc } + , dwLowLabel :: CLabel + , dwHighLabel :: CLabel } | DwarfSubprogram { dwChildren :: [DwarfInfo] , dwName :: String , dwLabel :: CLabel @@ -88,13 +87,13 @@ data DwarfAbbrev deriving (Eq, Enum) -- | Generate assembly for the given abbreviation code -pprAbbrev :: DwarfAbbrev -> SDoc +pprAbbrev :: IsDoc doc => DwarfAbbrev -> doc pprAbbrev = pprLEBWord . fromIntegral . fromEnum -- | Abbreviation declaration. This explains the binary encoding we -- use for representing 'DwarfInfo'. Be aware that this must be updated -- along with 'pprDwarfInfo'. -pprAbbrevDecls :: Platform -> Bool -> SDoc +pprAbbrevDecls :: IsDoc doc => Platform -> Bool -> doc pprAbbrevDecls platform haveDebugLine = let mkAbbrev abbr tag chld flds = let fld (tag, form) = pprLEBWord tag $$ pprLEBWord form @@ -111,7 +110,7 @@ pprAbbrevDecls platform haveDebugLine = , (dW_AT_frame_base, dW_FORM_block1) ] in dwarfAbbrevSection platform $$ - dwarfAbbrevLabel <> colon $$ + line (dwarfAbbrevLabel <> colon) $$ mkAbbrev DwAbbrCompileUnit dW_TAG_compile_unit dW_CHILDREN_yes ([(dW_AT_name, dW_FORM_string) , (dW_AT_producer, dW_FORM_string) @@ -144,9 +143,11 @@ pprAbbrevDecls platform haveDebugLine = , (dW_AT_ghc_span_end_col, dW_FORM_data2) ] $$ pprByte 0 +{-# SPECIALIZE pprAbbrevDecls :: Platform -> Bool -> SDoc #-} +{-# SPECIALIZE pprAbbrevDecls :: Platform -> Bool -> HDoc #-} -- see Note [SPECIALIZE to HDoc] in GHC.Utils.Outputable -- | Generate assembly for DWARF data -pprDwarfInfo :: Platform -> Bool -> DwarfInfo -> SDoc +pprDwarfInfo :: IsDoc doc => Platform -> Bool -> DwarfInfo -> doc pprDwarfInfo platform haveSrc d = case d of DwarfCompileUnit {} -> hasChildren @@ -159,9 +160,11 @@ pprDwarfInfo platform haveSrc d vcat (map (pprDwarfInfo platform haveSrc) (dwChildren d)) $$ pprDwarfInfoClose noChildren = pprDwarfInfoOpen platform haveSrc d +{-# SPECIALIZE pprDwarfInfo :: Platform -> Bool -> DwarfInfo -> SDoc #-} +{-# SPECIALIZE pprDwarfInfo :: Platform -> Bool -> DwarfInfo -> HDoc #-} -- see Note [SPECIALIZE to HDoc] in GHC.Utils.Outputable -- | Print a CLabel name in a ".stringz \"LABEL\"" -pprLabelString :: Platform -> CLabel -> SDoc +pprLabelString :: IsDoc doc => Platform -> CLabel -> doc pprLabelString platform label = pprString' -- we don't need to escape the string as labels don't contain exotic characters $ pprCLabel platform CStyle label -- pretty-print as C label (foreign labels may be printed differently in Asm) @@ -169,22 +172,22 @@ pprLabelString platform label = -- | Prints assembler data corresponding to DWARF info records. Note -- that the binary format of this is parameterized in @abbrevDecls@ and -- has to be kept in synch. -pprDwarfInfoOpen :: Platform -> Bool -> DwarfInfo -> SDoc +pprDwarfInfoOpen :: IsDoc doc => Platform -> Bool -> DwarfInfo -> doc pprDwarfInfoOpen platform haveSrc (DwarfCompileUnit _ name producer compDir lowLabel - highLabel lineLbl) = + highLabel) = pprAbbrev DwAbbrCompileUnit $$ pprString name $$ pprString producer $$ pprData4 dW_LANG_Haskell $$ pprString compDir -- Offset due to Note [Info Offset] - $$ pprWord platform (lowLabel <> text "-1") - $$ pprWord platform highLabel + $$ pprWord platform (pprAsmLabel platform lowLabel <> text "-1") + $$ pprWord platform (pprAsmLabel platform highLabel) $$ if haveSrc - then sectionOffset platform lineLbl dwarfLineLabel + then sectionOffset platform dwarfLineLabel dwarfLineLabel else empty pprDwarfInfoOpen platform _ (DwarfSubprogram _ name label parent) = - pprAsmLabel platform (mkAsmTempDieLabel label) <> colon + line (pprAsmLabel platform (mkAsmTempDieLabel label) <> colon) $$ pprAbbrev abbrev $$ pprString name $$ pprLabelString platform label @@ -201,11 +204,11 @@ pprDwarfInfoOpen platform _ (DwarfSubprogram _ name label parent) = parentValue = maybe empty pprParentDie parent pprParentDie sym = sectionOffset platform (pprAsmLabel platform sym) dwarfInfoLabel pprDwarfInfoOpen platform _ (DwarfBlock _ label Nothing) = - pprAsmLabel platform (mkAsmTempDieLabel label) <> colon + line (pprAsmLabel platform (mkAsmTempDieLabel label) <> colon) $$ pprAbbrev DwAbbrBlockWithoutCode $$ pprLabelString platform label pprDwarfInfoOpen platform _ (DwarfBlock _ label (Just marker)) = - pprAsmLabel platform (mkAsmTempDieLabel label) <> colon + line (pprAsmLabel platform (mkAsmTempDieLabel label) <> colon) $$ pprAbbrev DwAbbrBlock $$ pprLabelString platform label $$ pprWord platform (pprAsmLabel platform marker) @@ -219,7 +222,7 @@ pprDwarfInfoOpen _ _ (DwarfSrcNote ss) = $$ pprHalf (fromIntegral $ srcSpanEndCol ss) -- | Close a DWARF info record with children -pprDwarfInfoClose :: SDoc +pprDwarfInfoClose :: IsDoc doc => doc pprDwarfInfoClose = pprAbbrev DwAbbrNull -- | A DWARF address range. This is used by the debugger to quickly locate @@ -233,7 +236,7 @@ data DwarfARange -- | Print assembler directives corresponding to a DWARF @.debug_aranges@ -- address table entry. -pprDwarfARanges :: Platform -> [DwarfARange] -> Unique -> SDoc +pprDwarfARanges :: IsDoc doc => Platform -> [DwarfARange] -> Unique -> doc pprDwarfARanges platform arngs unitU = let wordSize = platformWordSizeInBytes platform paddingSize = 4 :: Int @@ -243,7 +246,7 @@ pprDwarfARanges platform arngs unitU = pad n = vcat $ replicate n $ pprByte 0 -- Fix for #17428 initialLength = 8 + paddingSize + (1 + length arngs) * 2 * wordSize - in pprDwWord (ppr initialLength) + in pprDwWord (int initialLength) $$ pprHalf 2 $$ sectionOffset platform (pprAsmLabel platform $ mkAsmTempLabel $ unitU) dwarfInfoLabel $$ pprByte (fromIntegral wordSize) @@ -254,8 +257,10 @@ pprDwarfARanges platform arngs unitU = -- terminus $$ pprWord platform (char '0') $$ pprWord platform (char '0') +{-# SPECIALIZE pprDwarfARanges :: Platform -> [DwarfARange] -> Unique -> SDoc #-} +{-# SPECIALIZE pprDwarfARanges :: Platform -> [DwarfARange] -> Unique -> HDoc #-} -- see Note [SPECIALIZE to HDoc] in GHC.Utils.Outputable -pprDwarfARange :: Platform -> DwarfARange -> SDoc +pprDwarfARange :: IsDoc doc => Platform -> DwarfARange -> doc pprDwarfARange platform arng = -- Offset due to Note [Info Offset]. pprWord platform (pprAsmLabel platform (dwArngStartLabel arng) <> text "-1") @@ -299,7 +304,7 @@ instance OutputableP Platform DwarfFrameBlock where -- | Header for the @.debug_frame@ section. Here we emit the "Common -- Information Entry" record that establishes general call frame -- parameters and the default stack layout. -pprDwarfFrame :: Platform -> DwarfFrame -> SDoc +pprDwarfFrame :: forall doc. IsDoc doc => Platform -> DwarfFrame -> doc pprDwarfFrame platform DwarfFrame{dwCieLabel=cieLabel,dwCieInit=cieInit,dwCieProcs=procs} = let cieStartLabel= mkAsmTempDerivedLabel cieLabel (fsLit "_start") cieEndLabel = mkAsmTempEndLabel cieLabel @@ -307,7 +312,7 @@ pprDwarfFrame platform DwarfFrame{dwCieLabel=cieLabel,dwCieInit=cieInit,dwCiePro spReg = dwarfGlobalRegNo platform Sp retReg = dwarfReturnRegNo platform wordSize = platformWordSizeInBytes platform - pprInit :: (GlobalReg, Maybe UnwindExpr) -> SDoc + pprInit :: (GlobalReg, Maybe UnwindExpr) -> doc pprInit (g, uw) = pprSetUnwind platform g (Nothing, uw) -- Preserve C stack pointer: This necessary to override that default @@ -316,9 +321,9 @@ pprDwarfFrame platform DwarfFrame{dwCieLabel=cieLabel,dwCieInit=cieInit,dwCiePro ArchX86 -> pprByte dW_CFA_same_value $$ pprLEBWord 4 ArchX86_64 -> pprByte dW_CFA_same_value $$ pprLEBWord 7 _ -> empty - in vcat [ pprAsmLabel platform cieLabel <> colon + in vcat [ line (pprAsmLabel platform cieLabel <> colon) , pprData4' length -- Length of CIE - , pprAsmLabel platform cieStartLabel <> colon + , line (pprAsmLabel platform cieStartLabel <> colon) , pprData4' (text "-1") -- Common Information Entry marker (-1 = 0xf..f) , pprByte 3 -- CIE version (we require DWARF 3) @@ -346,23 +351,25 @@ pprDwarfFrame platform DwarfFrame{dwCieLabel=cieLabel,dwCieInit=cieInit,dwCiePro , pprLEBWord 0 ] $$ wordAlign platform $$ - pprAsmLabel platform cieEndLabel <> colon $$ + line (pprAsmLabel platform cieEndLabel <> colon) $$ -- Procedure unwind tables vcat (map (pprFrameProc platform cieLabel cieInit) procs) +{-# SPECIALIZE pprDwarfFrame :: Platform -> DwarfFrame -> SDoc #-} +{-# SPECIALIZE pprDwarfFrame :: Platform -> DwarfFrame -> HDoc #-} -- see Note [SPECIALIZE to HDoc] in GHC.Utils.Outputable -- | Writes a "Frame Description Entry" for a procedure. This consists -- mainly of referencing the CIE and writing state machine -- instructions to describe how the frame base (CFA) changes. -pprFrameProc :: Platform -> CLabel -> UnwindTable -> DwarfFrameProc -> SDoc +pprFrameProc :: IsDoc doc => Platform -> CLabel -> UnwindTable -> DwarfFrameProc -> doc pprFrameProc platform frameLbl initUw (DwarfFrameProc procLbl hasInfo blocks) = let fdeLabel = mkAsmTempDerivedLabel procLbl (fsLit "_fde") fdeEndLabel = mkAsmTempDerivedLabel procLbl (fsLit "_fde_end") procEnd = mkAsmTempProcEndLabel procLbl ifInfo str = if hasInfo then text str else empty -- see Note [Info Offset] - in vcat [ whenPprDebug $ text "# Unwinding for" <+> pprAsmLabel platform procLbl <> colon + in vcat [ whenPprDebug $ line $ text "# Unwinding for" <+> pprAsmLabel platform procLbl <> colon , pprData4' (pprAsmLabel platform fdeEndLabel <> char '-' <> pprAsmLabel platform fdeLabel) - , pprAsmLabel platform fdeLabel <> colon + , line (pprAsmLabel platform fdeLabel <> colon) , pprData4' (pprAsmLabel platform frameLbl <> char '-' <> dwarfFrameLabel) -- Reference to CIE , pprWord platform (pprAsmLabel platform procLbl <> ifInfo "-1") -- Code pointer , pprWord platform (pprAsmLabel platform procEnd <> char '-' <> @@ -370,17 +377,17 @@ pprFrameProc platform frameLbl initUw (DwarfFrameProc procLbl hasInfo blocks) ] $$ vcat (S.evalState (mapM (pprFrameBlock platform) blocks) initUw) $$ wordAlign platform $$ - pprAsmLabel platform fdeEndLabel <> colon + line (pprAsmLabel platform fdeEndLabel <> colon) -- | Generates unwind information for a block. We only generate -- instructions where unwind information actually changes. This small -- optimisations saves a lot of space, as subsequent blocks often have -- the same unwind information. -pprFrameBlock :: Platform -> DwarfFrameBlock -> S.State UnwindTable SDoc +pprFrameBlock :: forall doc. IsDoc doc => Platform -> DwarfFrameBlock -> S.State UnwindTable doc pprFrameBlock platform (DwarfFrameBlock hasInfo uws0) = vcat <$> zipWithM pprFrameDecl (True : repeat False) uws0 where - pprFrameDecl :: Bool -> UnwindPoint -> S.State UnwindTable SDoc + pprFrameDecl :: Bool -> UnwindPoint -> S.State UnwindTable doc pprFrameDecl firstDecl (UnwindPoint lbl uws) = S.state $ \oldUws -> let -- Did a register's unwind expression change? isChanged :: GlobalReg -> Maybe UnwindExpr @@ -450,12 +457,12 @@ dwarfGlobalRegNo p reg = maybe 0 (dwarfRegNo p . RegReal) $ globalRegMaybe p reg -- | Generate code for setting the unwind information for a register, -- optimized using its known old value in the table. Note that "Sp" is -- special: We see it as synonym for the CFA. -pprSetUnwind :: Platform +pprSetUnwind :: IsDoc doc => Platform -> GlobalReg -- ^ the register to produce an unwinding table entry for -> (Maybe UnwindExpr, Maybe UnwindExpr) -- ^ the old and new values of the register - -> SDoc + -> doc pprSetUnwind plat g (_, Nothing) = pprUndefUnwind plat g pprSetUnwind _ Sp (Just (UwReg s _), Just (UwReg s' o')) | s == s' @@ -495,13 +502,13 @@ pprSetUnwind plat g (_, Just uw) -- | Print the register number of the given 'GlobalReg' as an unsigned LEB128 -- encoded number. -pprLEBRegNo :: Platform -> GlobalReg -> SDoc +pprLEBRegNo :: IsDoc doc => Platform -> GlobalReg -> doc pprLEBRegNo plat = pprLEBWord . fromIntegral . dwarfGlobalRegNo plat -- | Generates a DWARF expression for the given unwind expression. If -- @spIsCFA@ is true, we see @Sp@ as the frame base CFA where it gets -- mentioned. -pprUnwindExpr :: Platform -> Bool -> UnwindExpr -> SDoc +pprUnwindExpr :: IsDoc doc => Platform -> Bool -> UnwindExpr -> doc pprUnwindExpr platform spIsCFA expr = let pprE (UwConst i) | i >= 0 && i < 32 = pprByte (dW_OP_lit0 + fromIntegral i) @@ -517,84 +524,100 @@ pprUnwindExpr platform spIsCFA expr pprE (UwPlus u1 u2) = pprE u1 $$ pprE u2 $$ pprByte dW_OP_plus pprE (UwMinus u1 u2) = pprE u1 $$ pprE u2 $$ pprByte dW_OP_minus pprE (UwTimes u1 u2) = pprE u1 $$ pprE u2 $$ pprByte dW_OP_mul - in text "\t.uleb128 2f-1f" $$ -- DW_FORM_block length + in line (text "\t.uleb128 2f-1f") $$ -- DW_FORM_block length -- computed as the difference of the following local labels 2: and 1: - text "1:" $$ + line (text "1:") $$ pprE expr $$ - text "2:" + line (text "2:") -- | Generate code for re-setting the unwind information for a -- register to @undefined@ -pprUndefUnwind :: Platform -> GlobalReg -> SDoc +pprUndefUnwind :: IsDoc doc => Platform -> GlobalReg -> doc pprUndefUnwind plat g = pprByte dW_CFA_undefined $$ pprLEBRegNo plat g -- | Align assembly at (machine) word boundary -wordAlign :: Platform -> SDoc +wordAlign :: IsDoc doc => Platform -> doc wordAlign plat = - text "\t.align " <> case platformOS plat of + line $ text "\t.align " <> case platformOS plat of OSDarwin -> case platformWordSize plat of PW8 -> char '3' PW4 -> char '2' - _other -> ppr (platformWordSizeInBytes plat) + _other -> int (platformWordSizeInBytes plat) +{-# SPECIALIZE wordAlign :: Platform -> SDoc #-} +{-# SPECIALIZE wordAlign :: Platform -> HDoc #-} -- see Note [SPECIALIZE to HDoc] in GHC.Utils.Outputable -- | Assembly for a single byte of constant DWARF data -pprByte :: Word8 -> SDoc -pprByte x = text "\t.byte " <> ppr (fromIntegral x :: Word) +pprByte :: IsDoc doc => Word8 -> doc +pprByte x = line $ text "\t.byte " <> integer (fromIntegral x) +{-# SPECIALIZE pprByte :: Word8 -> SDoc #-} +{-# SPECIALIZE pprByte :: Word8 -> HDoc #-} -- see Note [SPECIALIZE to HDoc] in GHC.Utils.Outputable -- | Assembly for a two-byte constant integer -pprHalf :: Word16 -> SDoc -pprHalf x = text "\t.short" <+> ppr (fromIntegral x :: Word) +pprHalf :: IsDoc doc => Word16 -> doc +pprHalf x = line $ text "\t.short" <+> integer (fromIntegral x) +{-# SPECIALIZE pprHalf :: Word16 -> SDoc #-} +{-# SPECIALIZE pprHalf :: Word16 -> HDoc #-} -- see Note [SPECIALIZE to HDoc] in GHC.Utils.Outputable -- | Assembly for a constant DWARF flag -pprFlag :: Bool -> SDoc +pprFlag :: IsDoc doc => Bool -> doc pprFlag f = pprByte (if f then 0xff else 0x00) -- | Assembly for 4 bytes of dynamic DWARF data -pprData4' :: SDoc -> SDoc -pprData4' x = text "\t.long " <> x +pprData4' :: IsDoc doc => Line doc -> doc +pprData4' x = line (text "\t.long " <> x) +{-# SPECIALIZE pprData4' :: SDoc -> SDoc #-} +{-# SPECIALIZE pprData4' :: HLine -> HDoc #-} -- see Note [SPECIALIZE to HDoc] in GHC.Utils.Outputable -- | Assembly for 4 bytes of constant DWARF data -pprData4 :: Word -> SDoc -pprData4 = pprData4' . ppr +pprData4 :: IsDoc doc => Word -> doc +pprData4 = pprData4' . integer . fromIntegral -- | Assembly for a DWARF word of dynamic data. This means 32 bit, as -- we are generating 32 bit DWARF. -pprDwWord :: SDoc -> SDoc +pprDwWord :: IsDoc doc => Line doc -> doc pprDwWord = pprData4' +{-# SPECIALIZE pprDwWord :: SDoc -> SDoc #-} +{-# SPECIALIZE pprDwWord :: HLine -> HDoc #-} -- see Note [SPECIALIZE to HDoc] in GHC.Utils.Outputable -- | Assembly for a machine word of dynamic data. Depends on the -- architecture we are currently generating code for. -pprWord :: Platform -> SDoc -> SDoc +pprWord :: IsDoc doc => Platform -> Line doc -> doc pprWord plat s = - case platformWordSize plat of + line $ case platformWordSize plat of PW4 -> text "\t.long " <> s PW8 -> text "\t.quad " <> s +{-# SPECIALIZE pprWord :: Platform -> SDoc -> SDoc #-} +{-# SPECIALIZE pprWord :: Platform -> HLine -> HDoc #-} -- see Note [SPECIALIZE to HDoc] in GHC.Utils.Outputable -- | Prints a number in "little endian base 128" format. The idea is -- to optimize for small numbers by stopping once all further bytes -- would be 0. The highest bit in every byte signals whether there -- are further bytes to read. -pprLEBWord :: Word -> SDoc +pprLEBWord :: IsDoc doc => Word -> doc pprLEBWord x | x < 128 = pprByte (fromIntegral x) | otherwise = pprByte (fromIntegral $ 128 .|. (x .&. 127)) $$ pprLEBWord (x `shiftR` 7) +{-# SPECIALIZE pprLEBWord :: Word -> SDoc #-} +{-# SPECIALIZE pprLEBWord :: Word -> HDoc #-} -- see Note [SPECIALIZE to HDoc] in GHC.Utils.Outputable -- | Same as @pprLEBWord@, but for a signed number -pprLEBInt :: Int -> SDoc +pprLEBInt :: IsDoc doc => Int -> doc pprLEBInt x | x >= -64 && x < 64 = pprByte (fromIntegral (x .&. 127)) | otherwise = pprByte (fromIntegral $ 128 .|. (x .&. 127)) $$ pprLEBInt (x `shiftR` 7) +{-# SPECIALIZE pprLEBInt :: Int -> SDoc #-} +{-# SPECIALIZE pprLEBInt :: Int -> HDoc #-} -- see Note [SPECIALIZE to HDoc] in GHC.Utils.Outputable -- | Generates a dynamic null-terminated string. If required the -- caller needs to make sure that the string is escaped properly. -pprString' :: SDoc -> SDoc -pprString' str = text "\t.asciz \"" <> str <> char '"' +pprString' :: IsDoc doc => Line doc -> doc +pprString' str = line (text "\t.asciz \"" <> str <> char '"') -- | Generate a string constant. We take care to escape the string. -pprString :: String -> SDoc +pprString :: IsDoc doc => String -> doc pprString str = pprString' $ hcat $ map escapeChar $ if str `lengthIs` utf8EncodedLength str @@ -602,7 +625,7 @@ pprString str else map (chr . fromIntegral) $ BS.unpack $ utf8EncodeByteString str -- | Escape a single non-unicode character -escapeChar :: Char -> SDoc +escapeChar :: IsLine doc => Char -> doc escapeChar '\\' = text "\\\\" escapeChar '\"' = text "\\\"" escapeChar '\n' = text "\\n" @@ -621,9 +644,11 @@ escapeChar c -- us to just reference the target directly, and will figure out on -- their own that we actually need an offset. Finally, Windows has -- a special directive to refer to relative offsets. Fun. -sectionOffset :: Platform -> SDoc -> SDoc -> SDoc +sectionOffset :: IsDoc doc => Platform -> Line doc -> Line doc -> doc sectionOffset plat target section = case platformOS plat of OSDarwin -> pprDwWord (target <> char '-' <> section) - OSMinGW32 -> text "\t.secrel32 " <> target + OSMinGW32 -> line (text "\t.secrel32 " <> target) _other -> pprDwWord target +{-# SPECIALIZE sectionOffset :: Platform -> SDoc -> SDoc -> SDoc #-} +{-# SPECIALIZE sectionOffset :: Platform -> HLine -> HLine -> HDoc #-} -- see Note [SPECIALIZE to HDoc] in GHC.Utils.Outputable diff --git a/compiler/GHC/CmmToAsm/Instr.hs b/compiler/GHC/CmmToAsm/Instr.hs index bc2e2969e6..aa8f538e07 100644 --- a/compiler/GHC/CmmToAsm/Instr.hs +++ b/compiler/GHC/CmmToAsm/Instr.hs @@ -15,6 +15,7 @@ import GHC.Utils.Outputable (SDoc) import GHC.Cmm.BlockId import GHC.CmmToAsm.Config +import GHC.Data.FastString -- | Holds a list of source and destination registers used by a -- particular instruction. @@ -160,4 +161,4 @@ class Instruction instr where pprInstr :: Platform -> instr -> SDoc -- Create a comment instruction - mkComment :: SDoc -> [instr] + mkComment :: FastString -> [instr] diff --git a/compiler/GHC/CmmToAsm/Monad.hs b/compiler/GHC/CmmToAsm/Monad.hs index eb445649c3..2a61ff0314 100644 --- a/compiler/GHC/CmmToAsm/Monad.hs +++ b/compiler/GHC/CmmToAsm/Monad.hs @@ -67,7 +67,7 @@ import GHC.Types.Unique.Supply import GHC.Types.Unique ( Unique ) import GHC.Unit.Module -import GHC.Utils.Outputable (SDoc, ppr) +import GHC.Utils.Outputable (SDoc, HDoc, ppr) import GHC.Utils.Panic (pprPanic) import GHC.Utils.Monad.State.Strict (State (..), runState, state) import GHC.Utils.Misc @@ -84,7 +84,9 @@ data NcgImpl statics instr jumpDest = NcgImpl { shortcutJump :: (BlockId -> Maybe jumpDest) -> instr -> instr, -- | 'Module' is only for printing internal labels. See Note [Internal proc -- labels] in CLabel. - pprNatCmmDecl :: NatCmmDecl statics instr -> SDoc, + pprNatCmmDeclS :: NatCmmDecl statics instr -> SDoc, + pprNatCmmDeclH :: NatCmmDecl statics instr -> HDoc, + -- see Note [pprNatCmmDeclS and pprNatCmmDeclH] maxSpillSlots :: Int, allocatableRegs :: [RealReg], ncgAllocMoreStack :: Int -> NatCmmDecl statics instr @@ -103,6 +105,38 @@ data NcgImpl statics instr jumpDest = NcgImpl { -- when possible. } +{- Note [pprNatCmmDeclS and pprNatCmmDeclH] +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +Each NcgImpl provides two implementations of its CmmDecl printer, pprNatCmmDeclS +and pprNatCmmDeclH, which are specialized to SDoc and HDoc, respectively +(see Note [SDoc versus HDoc] in GHC.Utils.Outputable). These are both internally +implemented as a single, polymorphic function, but they need to be stored using +monomorphic types to ensure the specialized versions are used, which is +essential for performance (see Note [SPECIALIZE to HDoc] in GHC.Utils.Outputable). + +One might wonder why we bother with pprNatCmmDeclS and SDoc at all, since we +have a perfectly serviceable HDoc-based implementation that is more efficient. +However, it turns out we benefit from keeping both, for two (related) reasons: + + 1. Although we absolutely want to take care to use pprNatCmmDeclH for actual + code generation (the improved performance there is why we have HDoc at + all!), we also sometimes print assembly for debug dumps, when requested via + -ddump-asm. In this case, it’s more convenient to produce an SDoc, which + can be concatenated with other SDocs for consistency with the general- + purpose dump file infrastructure. + + 2. Some debug information is sometimes useful to include in -ddump-asm that is + neither necessary nor useful in normal code generation, and it turns out to + be tricky to format neatly using the one-line-at-a-time model of HLine/HDoc. + +Therefore, we provide both pprNatCmmDeclS and pprNatCmmDeclH, and we sometimes +include additional information in the SDoc variant using dualDoc +(see Note [dualLine and dualDoc] in GHC.Utils.Outputable). However, it is +absolutely *critical* that pprNatCmmDeclS is not actually used unless -ddump-asm +is provided, as that would rather defeat the whole point. (Fortunately, the +difference in allocations between the two implementations is so vast that such a +mistake would readily show up in performance tests). -} + data NatM_State = NatM_State { natm_us :: UniqSupply, diff --git a/compiler/GHC/CmmToAsm/PIC.hs b/compiler/GHC/CmmToAsm/PIC.hs index 0b92afbfe6..e4b47f91f9 100644 --- a/compiler/GHC/CmmToAsm/PIC.hs +++ b/compiler/GHC/CmmToAsm/PIC.hs @@ -532,11 +532,11 @@ gotLabel -- -- We don't need to declare any offset tables. -- However, for PIC on x86, we need a small helper function. -pprGotDeclaration :: NCGConfig -> SDoc +pprGotDeclaration :: NCGConfig -> HDoc pprGotDeclaration config = case (arch,os) of (ArchX86, OSDarwin) | ncgPIC config - -> vcat [ + -> lines_ [ text ".section __TEXT,__textcoal_nt,coalesced,no_toc", text ".weak_definition ___i686.get_pc_thunk.ax", text ".private_extern ___i686.get_pc_thunk.ax", @@ -548,26 +548,26 @@ pprGotDeclaration config = case (arch,os) of -- Emit XCOFF TOC section (_, OSAIX) - -> vcat $ [ text ".toc" - , text ".tc ghc_toc_table[TC],.LCTOC1" - , text ".csect ghc_toc_table[RW]" - -- See Note [.LCTOC1 in PPC PIC code] - , text ".set .LCTOC1,$+0x8000" - ] + -> lines_ $ [ text ".toc" + , text ".tc ghc_toc_table[TC],.LCTOC1" + , text ".csect ghc_toc_table[RW]" + -- See Note [.LCTOC1 in PPC PIC code] + , text ".set .LCTOC1,$+0x8000" + ] -- PPC 64 ELF v1 needs a Table Of Contents (TOC) (ArchPPC_64 ELF_V1, _) - -> text ".section \".toc\",\"aw\"" + -> line $ text ".section \".toc\",\"aw\"" -- In ELF v2 we also need to tell the assembler that we want ABI -- version 2. This would normally be done at the top of the file -- right after a file directive, but I could not figure out how -- to do that. (ArchPPC_64 ELF_V2, _) - -> vcat [ text ".abiversion 2", - text ".section \".toc\",\"aw\"" - ] + -> lines_ [ text ".abiversion 2", + text ".section \".toc\",\"aw\"" + ] (arch, os) | osElfTarget os @@ -577,7 +577,7 @@ pprGotDeclaration config = case (arch,os) of | osElfTarget os , arch /= ArchPPC_64 ELF_V1 && arch /= ArchPPC_64 ELF_V2 - -> vcat [ + -> lines_ [ -- See Note [.LCTOC1 in PPC PIC code] text ".section \".got2\",\"aw\"", text ".LCTOC1 = .+32768" ] @@ -595,15 +595,16 @@ pprGotDeclaration config = case (arch,os) of -- and one for non-PIC. -- -pprImportedSymbol :: NCGConfig -> CLabel -> SDoc +pprImportedSymbol :: NCGConfig -> CLabel -> HDoc pprImportedSymbol config importedLbl = case (arch,os) of + (ArchX86, OSDarwin) | Just (CodeStub, lbl) <- dynamicLinkerLabelInfo importedLbl -> if not pic then - vcat [ + lines_ [ text ".symbol_stub", - text "L" <> ppr_lbl lbl <> text "$stub:", + (text "L" <> ppr_lbl lbl <> text "$stub:"), text "\t.indirect_symbol" <+> ppr_lbl lbl, text "\tjmp *L" <> ppr_lbl lbl <> text "$lazy_ptr", @@ -614,7 +615,7 @@ pprImportedSymbol config importedLbl = case (arch,os) of text "\tjmp dyld_stub_binding_helper" ] else - vcat [ + lines_ [ text ".section __TEXT,__picsymbolstub2," <> text "symbol_stubs,pure_instructions,25", text "L" <> ppr_lbl lbl <> text "$stub:", @@ -631,7 +632,8 @@ pprImportedSymbol config importedLbl = case (arch,os) of text "\tpushl %eax", text "\tjmp dyld_stub_binding_helper" ] - $+$ vcat [ text ".section __DATA, __la_sym_ptr" + $$ lines_ [ + text ".section __DATA, __la_sym_ptr" <> (if pic then int 2 else int 3) <> text ",lazy_symbol_pointers", text "L" <> ppr_lbl lbl <> text "$lazy_ptr:", @@ -640,7 +642,7 @@ pprImportedSymbol config importedLbl = case (arch,os) of <> text "$stub_binder"] | Just (SymbolPtr, lbl) <- dynamicLinkerLabelInfo importedLbl - -> vcat [ + -> lines_ [ text ".non_lazy_symbol_pointer", char 'L' <> ppr_lbl lbl <> text "$non_lazy_ptr:", text "\t.indirect_symbol" <+> ppr_lbl lbl, @@ -667,7 +669,7 @@ pprImportedSymbol config importedLbl = case (arch,os) of (_, OSAIX) -> case dynamicLinkerLabelInfo importedLbl of Just (SymbolPtr, lbl) - -> vcat [ + -> lines_ [ text "LC.." <> ppr_lbl lbl <> char ':', text "\t.long" <+> ppr_lbl lbl ] _ -> empty @@ -700,12 +702,11 @@ pprImportedSymbol config importedLbl = case (arch,os) of -- When needImportedSymbols is defined, -- the NCG will keep track of all DynamicLinkerLabels it uses -- and output each of them using pprImportedSymbol. - (ArchPPC_64 _, _) | osElfTarget os -> case dynamicLinkerLabelInfo importedLbl of Just (SymbolPtr, lbl) - -> vcat [ + -> lines_ [ text ".LC_" <> ppr_lbl lbl <> char ':', text "\t.quad" <+> ppr_lbl lbl ] _ -> empty @@ -718,7 +719,7 @@ pprImportedSymbol config importedLbl = case (arch,os) of W64 -> text "\t.quad" _ -> panic "Unknown wordRep in pprImportedSymbol" - in vcat [ + in lines_ [ text ".section \".got2\", \"aw\"", text ".LC_" <> ppr_lbl lbl <> char ':', symbolSize <+> ppr_lbl lbl ] @@ -729,6 +730,7 @@ pprImportedSymbol config importedLbl = case (arch,os) of _ -> panic "PIC.pprImportedSymbol: no match" where platform = ncgPlatform config + ppr_lbl :: CLabel -> HLine ppr_lbl = pprAsmLabel platform arch = platformArch platform os = platformOS platform diff --git a/compiler/GHC/CmmToAsm/PPC.hs b/compiler/GHC/CmmToAsm/PPC.hs index cbfbdb539c..40a629907f 100644 --- a/compiler/GHC/CmmToAsm/PPC.hs +++ b/compiler/GHC/CmmToAsm/PPC.hs @@ -28,7 +28,8 @@ ncgPPC config = NcgImpl , canShortcut = PPC.canShortcut , shortcutStatics = PPC.shortcutStatics , shortcutJump = PPC.shortcutJump - , pprNatCmmDecl = PPC.pprNatCmmDecl config + , pprNatCmmDeclH = PPC.pprNatCmmDecl config + , pprNatCmmDeclS = PPC.pprNatCmmDecl config , maxSpillSlots = PPC.maxSpillSlots config , allocatableRegs = PPC.allocatableRegs platform , ncgAllocMoreStack = PPC.allocMoreStack platform diff --git a/compiler/GHC/CmmToAsm/PPC/CodeGen.hs b/compiler/GHC/CmmToAsm/PPC/CodeGen.hs index f8563004b5..9ddcdc32dd 100644 --- a/compiler/GHC/CmmToAsm/PPC/CodeGen.hs +++ b/compiler/GHC/CmmToAsm/PPC/CodeGen.hs @@ -162,7 +162,7 @@ stmtToInstrs stmt = do config <- getConfig platform <- getPlatform case stmt of - CmmComment s -> return (unitOL (COMMENT $ ftext s)) + CmmComment s -> return (unitOL (COMMENT s)) CmmTick {} -> return nilOL CmmUnwind {} -> return nilOL diff --git a/compiler/GHC/CmmToAsm/PPC/Instr.hs b/compiler/GHC/CmmToAsm/PPC/Instr.hs index c852789bbe..639ae979f8 100644 --- a/compiler/GHC/CmmToAsm/PPC/Instr.hs +++ b/compiler/GHC/CmmToAsm/PPC/Instr.hs @@ -52,7 +52,6 @@ import GHC.Cmm.Dataflow.Label import GHC.Cmm import GHC.Cmm.Info import GHC.Cmm.CLabel -import GHC.Utils.Outputable import GHC.Utils.Panic import GHC.Platform import GHC.Types.Unique.FM (listToUFM, lookupUFM) @@ -60,6 +59,7 @@ import GHC.Types.Unique.Supply import Data.Foldable (toList) import qualified Data.List.NonEmpty as NE +import GHC.Data.FastString (FastString) import Data.Maybe (fromMaybe) @@ -179,7 +179,7 @@ data RI data Instr -- comment pseudo-op - = COMMENT SDoc + = COMMENT FastString -- location pseudo-op (file, line, col, name) | LOCATION Int Int Int String diff --git a/compiler/GHC/CmmToAsm/PPC/Ppr.hs b/compiler/GHC/CmmToAsm/PPC/Ppr.hs index 19de3cd1e2..f03f56f6d8 100644 --- a/compiler/GHC/CmmToAsm/PPC/Ppr.hs +++ b/compiler/GHC/CmmToAsm/PPC/Ppr.hs @@ -46,7 +46,7 @@ import Data.Int -- ----------------------------------------------------------------------------- -- Printing this stuff out -pprNatCmmDecl :: NCGConfig -> NatCmmDecl RawCmmStatics Instr -> SDoc +pprNatCmmDecl :: IsDoc doc => NCGConfig -> NatCmmDecl RawCmmStatics Instr -> doc pprNatCmmDecl config (CmmData section dats) = pprSectionAlign config section $$ pprDatas (ncgPlatform config) dats @@ -63,15 +63,15 @@ pprNatCmmDecl config proc@(CmmProc top_info lbl _ (ListGraph blocks)) = _ -> pprLabel platform lbl) $$ -- blocks guaranteed not null, -- so label needed vcat (map (pprBasicBlock config top_info) blocks) $$ - ppWhen (ncgDwarfEnabled config) (pprAsmLabel platform (mkAsmTempEndLabel lbl) - <> char ':' $$ - pprProcEndLabel platform lbl) $$ + ppWhen (ncgDwarfEnabled config) (line (pprAsmLabel platform (mkAsmTempEndLabel lbl) + <> char ':') $$ + line (pprProcEndLabel platform lbl)) $$ pprSizeDecl platform lbl Just (CmmStaticsRaw info_lbl _) -> pprSectionAlign config (Section Text info_lbl) $$ (if platformHasSubsectionsViaSymbols platform - then pprAsmLabel platform (mkDeadStripPreventer info_lbl) <> char ':' + then line (pprAsmLabel platform (mkDeadStripPreventer info_lbl) <> char ':') else empty) $$ vcat (map (pprBasicBlock config top_info) blocks) $$ -- above: Even the first block gets a label, because with branch-chain @@ -79,18 +79,20 @@ pprNatCmmDecl config proc@(CmmProc top_info lbl _ (ListGraph blocks)) = (if platformHasSubsectionsViaSymbols platform then -- See Note [Subsections Via Symbols] in X86/Ppr.hs - text "\t.long " - <+> pprAsmLabel platform info_lbl - <+> char '-' - <+> pprAsmLabel platform (mkDeadStripPreventer info_lbl) + line (text "\t.long " + <+> pprAsmLabel platform info_lbl + <+> char '-' + <+> pprAsmLabel platform (mkDeadStripPreventer info_lbl)) else empty) $$ pprSizeDecl platform info_lbl +{-# SPECIALIZE pprNatCmmDecl :: NCGConfig -> NatCmmDecl RawCmmStatics Instr -> SDoc #-} +{-# SPECIALIZE pprNatCmmDecl :: NCGConfig -> NatCmmDecl RawCmmStatics Instr -> HDoc #-} -- see Note [SPECIALIZE to HDoc] in GHC.Utils.Outputable -- | Output the ELF .size directive. -pprSizeDecl :: Platform -> CLabel -> SDoc +pprSizeDecl :: IsDoc doc => Platform -> CLabel -> doc pprSizeDecl platform lbl = if osElfTarget (platformOS platform) - then text "\t.size" <+> prettyLbl <> text ", .-" <> codeLbl + then line (text "\t.size" <+> prettyLbl <> text ", .-" <> codeLbl) else empty where prettyLbl = pprAsmLabel platform lbl @@ -98,47 +100,45 @@ pprSizeDecl platform lbl | platformArch platform == ArchPPC_64 ELF_V1 = char '.' <> prettyLbl | otherwise = prettyLbl -pprFunctionDescriptor :: Platform -> CLabel -> SDoc -pprFunctionDescriptor platform lab = pprGloblDecl platform lab - $$ text "\t.section \".opd\", \"aw\"" - $$ text "\t.align 3" - $$ pprAsmLabel platform lab <> char ':' - $$ text "\t.quad ." - <> pprAsmLabel platform lab - <> text ",.TOC.@tocbase,0" - $$ text "\t.previous" - $$ text "\t.type" - <+> pprAsmLabel platform lab - <> text ", @function" - $$ char '.' <> pprAsmLabel platform lab <> char ':' - -pprFunctionPrologue :: Platform -> CLabel ->SDoc -pprFunctionPrologue platform lab = pprGloblDecl platform lab - $$ text ".type " - <> pprAsmLabel platform lab - <> text ", @function" - $$ pprAsmLabel platform lab <> char ':' - $$ text "0:\taddis\t" <> pprReg toc - <> text ",12,.TOC.-0b@ha" - $$ text "\taddi\t" <> pprReg toc - <> char ',' <> pprReg toc <> text ",.TOC.-0b@l" - $$ text "\t.localentry\t" <> pprAsmLabel platform lab - <> text ",.-" <> pprAsmLabel platform lab - -pprProcEndLabel :: Platform -> CLabel -- ^ Procedure name - -> SDoc +pprFunctionDescriptor :: IsDoc doc => Platform -> CLabel -> doc +pprFunctionDescriptor platform lab = + vcat [pprGloblDecl platform lab, + line (text "\t.section \".opd\", \"aw\""), + line (text "\t.align 3"), + line (pprAsmLabel platform lab <> char ':'), + line (text "\t.quad ." + <> pprAsmLabel platform lab + <> text ",.TOC.@tocbase,0"), + line (text "\t.previous"), + line (text "\t.type" + <+> pprAsmLabel platform lab + <> text ", @function"), + line (char '.' <> pprAsmLabel platform lab <> char ':')] + +pprFunctionPrologue :: IsDoc doc => Platform -> CLabel -> doc +pprFunctionPrologue platform lab = + vcat [pprGloblDecl platform lab, + line (text ".type " <> pprAsmLabel platform lab <> text ", @function"), + line (pprAsmLabel platform lab <> char ':'), + line (text "0:\taddis\t" <> pprReg toc <> text ",12,.TOC.-0b@ha"), + line (text "\taddi\t" <> pprReg toc <> char ',' <> pprReg toc <> text ",.TOC.-0b@l"), + line (text "\t.localentry\t" <> pprAsmLabel platform lab <> + text ",.-" <> pprAsmLabel platform lab)] + +pprProcEndLabel :: IsLine doc => Platform -> CLabel -- ^ Procedure name + -> doc pprProcEndLabel platform lbl = pprAsmLabel platform (mkAsmTempProcEndLabel lbl) <> char ':' -pprBasicBlock :: NCGConfig -> LabelMap RawCmmStatics -> NatBasicBlock Instr - -> SDoc +pprBasicBlock :: IsDoc doc => NCGConfig -> LabelMap RawCmmStatics -> NatBasicBlock Instr + -> doc pprBasicBlock config info_env (BasicBlock blockid instrs) = maybe_infotable $$ pprLabel platform asmLbl $$ vcat (map (pprInstr platform) instrs) $$ ppWhen (ncgDwarfEnabled config) ( - pprAsmLabel platform (mkAsmTempEndLabel asmLbl) <> char ':' - <> pprProcEndLabel platform asmLbl + line (pprAsmLabel platform (mkAsmTempEndLabel asmLbl) <> char ':' + <> pprProcEndLabel platform asmLbl) ) where asmLbl = blockLbl blockid @@ -152,7 +152,7 @@ pprBasicBlock config info_env (BasicBlock blockid instrs) -pprDatas :: Platform -> RawCmmStatics -> SDoc +pprDatas :: IsDoc doc => Platform -> RawCmmStatics -> doc -- See Note [emit-time elimination of static indirections] in "GHC.Cmm.CLabel". pprDatas platform (CmmStaticsRaw alias [CmmStaticLit (CmmLabel lbl), CmmStaticLit ind, _, _]) | lbl == mkIndStaticInfoLabel @@ -162,38 +162,38 @@ pprDatas platform (CmmStaticsRaw alias [CmmStaticLit (CmmLabel lbl), CmmStaticLi , Just ind' <- labelInd ind , alias `mayRedirectTo` ind' = pprGloblDecl platform alias - $$ text ".equiv" <+> pprAsmLabel platform alias <> comma <> pprAsmLabel platform ind' + $$ line (text ".equiv" <+> pprAsmLabel platform alias <> comma <> pprAsmLabel platform ind') pprDatas platform (CmmStaticsRaw lbl dats) = vcat (pprLabel platform lbl : map (pprData platform) dats) -pprData :: Platform -> CmmStatic -> SDoc +pprData :: IsDoc doc => Platform -> CmmStatic -> doc pprData platform d = case d of - CmmString str -> pprString str - CmmFileEmbed path -> pprFileEmbed path - CmmUninitialised bytes -> text ".space " <> int bytes + CmmString str -> line (pprString str) + CmmFileEmbed path -> line (pprFileEmbed path) + CmmUninitialised bytes -> line (text ".space " <> int bytes) CmmStaticLit lit -> pprDataItem platform lit -pprGloblDecl :: Platform -> CLabel -> SDoc +pprGloblDecl :: IsDoc doc => Platform -> CLabel -> doc pprGloblDecl platform lbl | not (externallyVisibleCLabel lbl) = empty - | otherwise = text ".globl " <> pprAsmLabel platform lbl + | otherwise = line (text ".globl " <> pprAsmLabel platform lbl) -pprTypeAndSizeDecl :: Platform -> CLabel -> SDoc +pprTypeAndSizeDecl :: IsLine doc => Platform -> CLabel -> doc pprTypeAndSizeDecl platform lbl = if platformOS platform == OSLinux && externallyVisibleCLabel lbl then text ".type " <> pprAsmLabel platform lbl <> text ", @object" else empty -pprLabel :: Platform -> CLabel -> SDoc +pprLabel :: IsDoc doc => Platform -> CLabel -> doc pprLabel platform lbl = pprGloblDecl platform lbl - $$ pprTypeAndSizeDecl platform lbl - $$ (pprAsmLabel platform lbl <> char ':') + $$ line (pprTypeAndSizeDecl platform lbl) + $$ line (pprAsmLabel platform lbl <> char ':') -- ----------------------------------------------------------------------------- -- pprInstr: print an 'Instr' -pprReg :: Reg -> SDoc +pprReg :: forall doc. IsLine doc => Reg -> doc pprReg r = case r of @@ -204,7 +204,7 @@ pprReg r RegVirtual (VirtualRegD u) -> text "%vD_" <> pprUniqueAlways u where - ppr_reg_no :: Int -> SDoc + ppr_reg_no :: Int -> doc ppr_reg_no i | i <= 31 = int i -- GPRs | i <= 63 = int (i-32) -- FPRs @@ -212,7 +212,7 @@ pprReg r -pprFormat :: Format -> SDoc +pprFormat :: IsLine doc => Format -> doc pprFormat x = case x of II8 -> text "b" @@ -223,7 +223,7 @@ pprFormat x FF64 -> text "fd" -pprCond :: Cond -> SDoc +pprCond :: IsLine doc => Cond -> doc pprCond c = case c of { ALWAYS -> text ""; @@ -234,7 +234,7 @@ pprCond c GU -> text "gt"; LEU -> text "le"; } -pprImm :: Platform -> Imm -> SDoc +pprImm :: IsLine doc => Platform -> Imm -> doc pprImm platform = \case ImmInt i -> int i ImmInteger i -> integer i @@ -264,7 +264,7 @@ pprImm platform = \case HIGHESTA i -> pprImm platform i <> text "@highesta" -pprAddr :: Platform -> AddrMode -> SDoc +pprAddr :: IsLine doc => Platform -> AddrMode -> doc pprAddr platform = \case AddrRegReg r1 r2 -> pprReg r1 <> char ',' <+> pprReg r2 AddrRegImm r1 (ImmInt i) -> hcat [ int i, char '(', pprReg r1, char ')' ] @@ -272,14 +272,14 @@ pprAddr platform = \case AddrRegImm r1 imm -> hcat [ pprImm platform imm, char '(', pprReg r1, char ')' ] -pprSectionAlign :: NCGConfig -> Section -> SDoc +pprSectionAlign :: IsDoc doc => NCGConfig -> Section -> doc pprSectionAlign config sec@(Section seg _) = - pprSectionHeader config sec $$ + line (pprSectionHeader config sec) $$ pprAlignForSection (ncgPlatform config) seg -- | Print appropriate alignment for the given section type. -pprAlignForSection :: Platform -> SectionType -> SDoc -pprAlignForSection platform seg = +pprAlignForSection :: IsDoc doc => Platform -> SectionType -> doc +pprAlignForSection platform seg = line $ let ppc64 = not $ target32Bit platform in case seg of Text -> text ".align 2" @@ -304,9 +304,9 @@ pprAlignForSection platform seg = | otherwise -> text ".align 2" OtherSection _ -> panic "PprMach.pprSectionAlign: unknown section" -pprDataItem :: Platform -> CmmLit -> SDoc +pprDataItem :: IsDoc doc => Platform -> CmmLit -> doc pprDataItem platform lit - = vcat (ppr_item (cmmTypeFormat $ cmmLitType platform lit) lit) + = lines_ (ppr_item (cmmTypeFormat $ cmmLitType platform lit) lit) where imm = litToImm lit archPPC_64 = not $ target32Bit platform @@ -333,21 +333,21 @@ pprDataItem platform lit = panic "PPC.Ppr.pprDataItem: no match" -asmComment :: SDoc -> SDoc +asmComment :: IsLine doc => doc -> doc asmComment c = whenPprDebug $ text "#" <+> c -pprInstr :: Platform -> Instr -> SDoc +pprInstr :: IsDoc doc => Platform -> Instr -> doc pprInstr platform instr = case instr of COMMENT s - -> asmComment s + -> line (asmComment (ftext s)) - LOCATION file line col _name - -> text "\t.loc" <+> ppr file <+> ppr line <+> ppr col + LOCATION file line' col _name + -> line (text "\t.loc" <+> int file <+> int line' <+> int col) DELTA d - -> asmComment $ text ("\tdelta = " ++ show d) + -> line (asmComment $ text ("\tdelta = " ++ show d)) NEWBLOCK _ -> panic "PprMach.pprInstr: NEWBLOCK" @@ -374,7 +374,7 @@ pprInstr platform instr = case instr of -} LD fmt reg addr - -> hcat [ + -> line $ hcat [ char '\t', text "l", (case fmt of @@ -403,7 +403,7 @@ pprInstr platform instr = case instr of -> panic "PPC.Ppr.pprInstr LDFAR: no match" LDR fmt reg1 addr - -> hcat [ + -> line $ hcat [ text "\tl", case fmt of II32 -> char 'w' @@ -416,7 +416,7 @@ pprInstr platform instr = case instr of ] LA fmt reg addr - -> hcat [ + -> line $ hcat [ char '\t', text "l", (case fmt of @@ -436,7 +436,7 @@ pprInstr platform instr = case instr of ] ST fmt reg addr - -> hcat [ + -> line $ hcat [ char '\t', text "st", pprFormat fmt, @@ -457,7 +457,7 @@ pprInstr platform instr = case instr of -> panic "PPC.Ppr.pprInstr STFAR: no match" STU fmt reg addr - -> hcat [ + -> line $ hcat [ char '\t', text "st", pprFormat fmt, @@ -471,7 +471,7 @@ pprInstr platform instr = case instr of ] STC fmt reg1 addr - -> hcat [ + -> line $ hcat [ text "\tst", case fmt of II32 -> char 'w' @@ -484,7 +484,7 @@ pprInstr platform instr = case instr of ] LIS reg imm - -> hcat [ + -> line $ hcat [ char '\t', text "lis", char '\t', @@ -494,7 +494,7 @@ pprInstr platform instr = case instr of ] LI reg imm - -> hcat [ + -> line $ hcat [ char '\t', text "li", char '\t', @@ -505,7 +505,7 @@ pprInstr platform instr = case instr of MR reg1 reg2 | reg1 == reg2 -> empty - | otherwise -> hcat [ + | otherwise -> line $ hcat [ char '\t', case targetClassOfReg platform reg1 of RcInteger -> text "mr" @@ -517,7 +517,7 @@ pprInstr platform instr = case instr of ] CMP fmt reg ri - -> hcat [ + -> line $ hcat [ char '\t', op, char '\t', @@ -535,7 +535,7 @@ pprInstr platform instr = case instr of ] CMPL fmt reg ri - -> hcat [ + -> line $ hcat [ char '\t', op, char '\t', @@ -553,7 +553,7 @@ pprInstr platform instr = case instr of ] BCC cond blockid prediction - -> hcat [ + -> line $ hcat [ char '\t', text "b", pprCond cond, @@ -568,7 +568,7 @@ pprInstr platform instr = case instr of Just False -> char '-' BCCFAR cond blockid prediction - -> vcat [ + -> lines_ [ hcat [ text "\tb", pprCond (condNegate cond), @@ -590,7 +590,7 @@ pprInstr platform instr = case instr of -- We never jump to ForeignLabels; if we ever do, c.f. handling for "BL" | isForeignLabel lbl -> panic "PPC.Ppr.pprInstr: JMP to ForeignLabel" | otherwise -> - hcat [ -- an alias for b that takes a CLabel + lines_ [ -- an alias for b that takes a CLabel char '\t', text "b", char '\t', @@ -598,7 +598,7 @@ pprInstr platform instr = case instr of ] MTCTR reg - -> hcat [ + -> line $ hcat [ char '\t', text "mtctr", char '\t', @@ -606,7 +606,7 @@ pprInstr platform instr = case instr of ] BCTR _ _ _ - -> hcat [ + -> line $ hcat [ char '\t', text "bctr" ] @@ -623,18 +623,18 @@ pprInstr platform instr = case instr of -- but when profiling the codegen inserts calls via -- 'emitRtsCallGen' which are 'CmmLabel's even though -- they'd technically be more like 'ForeignLabel's. - hcat [ + line $ hcat [ text "\tbl\t.", pprAsmLabel platform lbl ] _ -> - hcat [ + line $ hcat [ text "\tbl\t", pprAsmLabel platform lbl ] BCTRL _ - -> hcat [ + -> line $ hcat [ char '\t', text "bctrl" ] @@ -643,7 +643,7 @@ pprInstr platform instr = case instr of -> pprLogic platform (text "add") reg1 reg2 ri ADDIS reg1 reg2 imm - -> hcat [ + -> line $ hcat [ char '\t', text "addis", char '\t', @@ -673,7 +673,7 @@ pprInstr platform instr = case instr of -> pprLogic platform (text "subfo") reg1 reg2 (RIReg reg3) SUBFC reg1 reg2 ri - -> hcat [ + -> line $ hcat [ char '\t', text "subf", case ri of @@ -694,7 +694,7 @@ pprInstr platform instr = case instr of -> pprMul platform fmt reg1 reg2 ri MULLO fmt reg1 reg2 reg3 - -> hcat [ + -> line $ hcat [ char '\t', text "mull", case fmt of @@ -711,13 +711,13 @@ pprInstr platform instr = case instr of MFOV fmt reg -> vcat [ - hcat [ + lines_ [ char '\t', text "mfxer", char '\t', pprReg reg ], - hcat [ + lines_ [ char '\t', text "extr", case fmt of @@ -737,7 +737,7 @@ pprInstr platform instr = case instr of ] MULHU fmt reg1 reg2 reg3 - -> hcat [ + -> line $ hcat [ char '\t', text "mulh", case fmt of @@ -758,7 +758,7 @@ pprInstr platform instr = case instr of -- for some reason, "andi" doesn't exist. -- we'll use "andi." instead. AND reg1 reg2 (RIImm imm) - -> hcat [ + -> line $ hcat [ char '\t', text "andi.", char '\t', @@ -785,7 +785,7 @@ pprInstr platform instr = case instr of -> pprLogic platform (text "xor") reg1 reg2 ri ORIS reg1 reg2 imm - -> hcat [ + -> line $ hcat [ char '\t', text "oris", char '\t', @@ -797,7 +797,7 @@ pprInstr platform instr = case instr of ] XORIS reg1 reg2 imm - -> hcat [ + -> line $ hcat [ char '\t', text "xoris", char '\t', @@ -809,7 +809,7 @@ pprInstr platform instr = case instr of ] EXTS fmt reg1 reg2 - -> hcat [ + -> line $ hcat [ char '\t', text "exts", pprFormat fmt, @@ -820,7 +820,7 @@ pprInstr platform instr = case instr of ] CNTLZ fmt reg1 reg2 - -> hcat [ + -> line $ hcat [ char '\t', text "cntlz", case fmt of @@ -881,7 +881,7 @@ pprInstr platform instr = case instr of in pprLogic platform op reg1 reg2 (limitShiftRI fmt ri) RLWINM reg1 reg2 sh mb me - -> hcat [ + -> line $ hcat [ text "\trlwinm\t", pprReg reg1, text ", ", @@ -895,7 +895,7 @@ pprInstr platform instr = case instr of ] CLRLI fmt reg1 reg2 n - -> hcat [ + -> line $ hcat [ text "\tclrl", pprFormat fmt, text "i ", @@ -907,7 +907,7 @@ pprInstr platform instr = case instr of ] CLRRI fmt reg1 reg2 n - -> hcat [ + -> line $ hcat [ text "\tclrr", pprFormat fmt, text "i ", @@ -937,7 +937,7 @@ pprInstr platform instr = case instr of -> pprUnary (text "fneg") reg1 reg2 FCMP reg1 reg2 - -> hcat [ + -> line $ hcat [ char '\t', text "fcmpu\t0, ", -- Note: we're using fcmpu, not fcmpo @@ -965,7 +965,7 @@ pprInstr platform instr = case instr of -> pprUnary (text "frsp") reg1 reg2 CRNOR dst src1 src2 - -> hcat [ + -> line $ hcat [ text "\tcrnor\t", int dst, text ", ", @@ -975,7 +975,7 @@ pprInstr platform instr = case instr of ] MFCR reg - -> hcat [ + -> line $ hcat [ char '\t', text "mfcr", char '\t', @@ -983,7 +983,7 @@ pprInstr platform instr = case instr of ] MFLR reg - -> hcat [ + -> line $ hcat [ char '\t', text "mflr", char '\t', @@ -991,25 +991,25 @@ pprInstr platform instr = case instr of ] FETCHPC reg - -> vcat [ + -> lines_ [ text "\tbcl\t20,31,1f", hcat [ text "1:\tmflr\t", pprReg reg ] ] HWSYNC - -> text "\tsync" + -> line $ text "\tsync" ISYNC - -> text "\tisync" + -> line $ text "\tisync" LWSYNC - -> text "\tlwsync" + -> line $ text "\tlwsync" NOP - -> text "\tnop" + -> line $ text "\tnop" -pprLogic :: Platform -> SDoc -> Reg -> Reg -> RI -> SDoc -pprLogic platform op reg1 reg2 ri = hcat [ +pprLogic :: IsDoc doc => Platform -> Line doc -> Reg -> Reg -> RI -> doc +pprLogic platform op reg1 reg2 ri = line $ hcat [ char '\t', op, case ri of @@ -1024,8 +1024,8 @@ pprLogic platform op reg1 reg2 ri = hcat [ ] -pprMul :: Platform -> Format -> Reg -> Reg -> RI -> SDoc -pprMul platform fmt reg1 reg2 ri = hcat [ +pprMul :: IsDoc doc => Platform -> Format -> Reg -> Reg -> RI -> doc +pprMul platform fmt reg1 reg2 ri = line $ hcat [ char '\t', text "mull", case ri of @@ -1043,8 +1043,8 @@ pprMul platform fmt reg1 reg2 ri = hcat [ ] -pprDiv :: Format -> Bool -> Reg -> Reg -> Reg -> SDoc -pprDiv fmt sgn reg1 reg2 reg3 = hcat [ +pprDiv :: IsDoc doc => Format -> Bool -> Reg -> Reg -> Reg -> doc +pprDiv fmt sgn reg1 reg2 reg3 = line $ hcat [ char '\t', text "div", case fmt of @@ -1061,8 +1061,8 @@ pprDiv fmt sgn reg1 reg2 reg3 = hcat [ ] -pprUnary :: SDoc -> Reg -> Reg -> SDoc -pprUnary op reg1 reg2 = hcat [ +pprUnary :: IsDoc doc => Line doc -> Reg -> Reg -> doc +pprUnary op reg1 reg2 = line $ hcat [ char '\t', op, char '\t', @@ -1072,8 +1072,8 @@ pprUnary op reg1 reg2 = hcat [ ] -pprBinaryF :: SDoc -> Format -> Reg -> Reg -> Reg -> SDoc -pprBinaryF op fmt reg1 reg2 reg3 = hcat [ +pprBinaryF :: IsDoc doc => Line doc -> Format -> Reg -> Reg -> Reg -> doc +pprBinaryF op fmt reg1 reg2 reg3 = line $ hcat [ char '\t', op, pprFFormat fmt, @@ -1085,12 +1085,12 @@ pprBinaryF op fmt reg1 reg2 reg3 = hcat [ pprReg reg3 ] -pprRI :: Platform -> RI -> SDoc +pprRI :: IsLine doc => Platform -> RI -> doc pprRI _ (RIReg r) = pprReg r pprRI platform (RIImm r) = pprImm platform r -pprFFormat :: Format -> SDoc +pprFFormat :: IsLine doc => Format -> doc pprFFormat FF64 = empty pprFFormat FF32 = char 's' pprFFormat _ = panic "PPC.Ppr.pprFFormat: no match" diff --git a/compiler/GHC/CmmToAsm/Ppr.hs b/compiler/GHC/CmmToAsm/Ppr.hs index c54ce8f906..7959db8d69 100644 --- a/compiler/GHC/CmmToAsm/Ppr.hs +++ b/compiler/GHC/CmmToAsm/Ppr.hs @@ -27,7 +27,6 @@ import GHC.Cmm.CLabel import GHC.Cmm import GHC.CmmToAsm.Config import GHC.Utils.Outputable as SDoc -import qualified GHC.Utils.Ppr as Pretty import GHC.Utils.Panic import GHC.Platform @@ -89,7 +88,7 @@ doubleToBytes d = runST $ do -- Print as a string and escape non-printable characters. -- This is similar to charToC in GHC.Utils.Misc -pprASCII :: ByteString -> SDoc +pprASCII :: forall doc. IsLine doc => ByteString -> doc pprASCII str -- Transform this given literal bytestring to escaped string and construct -- the literal SDoc directly. @@ -98,19 +97,19 @@ pprASCII str -- -- We work with a `Doc` instead of an `SDoc` because there is no need to carry -- an `SDocContext` that we don't use. It leads to nicer (STG) code. - = docToSDoc (BS.foldr f Pretty.empty str) + = BS.foldr f empty str where - f :: Word8 -> Pretty.Doc -> Pretty.Doc - f w s = do1 w Pretty.<> s - - do1 :: Word8 -> Pretty.Doc - do1 w | 0x09 == w = Pretty.text "\\t" - | 0x0A == w = Pretty.text "\\n" - | 0x22 == w = Pretty.text "\\\"" - | 0x5C == w = Pretty.text "\\\\" + f :: Word8 -> doc -> doc + f w s = do1 w <> s + + do1 :: Word8 -> doc + do1 w | 0x09 == w = text "\\t" + | 0x0A == w = text "\\n" + | 0x22 == w = text "\\\"" + | 0x5C == w = text "\\\\" -- ASCII printable characters range - | w >= 0x20 && w <= 0x7E = Pretty.char (chr' w) - | otherwise = Pretty.sizedText 4 xs + | w >= 0x20 && w <= 0x7E = char (chr' w) + | otherwise = text xs where !xs = [ '\\', x0, x1, x2] -- octal !x0 = chr' (ord0 + (w `unsafeShiftR` 6) .&. 0x07) @@ -122,20 +121,25 @@ pprASCII str -- so we bypass the check in "chr" chr' :: Word8 -> Char chr' (W8# w#) = C# (chr# (word2Int# (word8ToWord# w#))) - +{-# SPECIALIZE pprASCII :: ByteString -> SDoc #-} +{-# SPECIALIZE pprASCII :: ByteString -> HLine #-} -- see Note [SPECIALIZE to HDoc] in GHC.Utils.Outputable -- | Emit a ".string" directive -pprString :: ByteString -> SDoc +pprString :: IsLine doc => ByteString -> doc pprString bs = text "\t.string " <> doubleQuotes (pprASCII bs) +{-# SPECIALIZE pprString :: ByteString -> SDoc #-} +{-# SPECIALIZE pprString :: ByteString -> HLine #-} -- see Note [SPECIALIZE to HDoc] in GHC.Utils.Outputable -- | Emit a ".incbin" directive -- -- A NULL byte is added after the binary data. -pprFileEmbed :: FilePath -> SDoc +pprFileEmbed :: IsLine doc => FilePath -> doc pprFileEmbed path = text "\t.incbin " <> pprFilePathString path -- proper escape (see #16389) <> text "\n\t.byte 0" +{-# SPECIALIZE pprFileEmbed :: FilePath -> SDoc #-} +{-# SPECIALIZE pprFileEmbed :: FilePath -> HLine #-} -- see Note [SPECIALIZE to HDoc] in GHC.Utils.Outputable {- Note [Embedding large binary blobs] @@ -193,14 +197,16 @@ string in source code. See #14741 for profiling results. -- identical strings in the linker. With -split-sections each string also gets -- a unique section to allow strings from unused code to be GC'd. -pprSectionHeader :: NCGConfig -> Section -> SDoc +pprSectionHeader :: IsLine doc => NCGConfig -> Section -> doc pprSectionHeader config (Section t suffix) = case platformOS (ncgPlatform config) of OSAIX -> pprXcoffSectionHeader t OSDarwin -> pprDarwinSectionHeader t _ -> pprGNUSectionHeader config t suffix +{-# SPECIALIZE pprSectionHeader :: NCGConfig -> Section -> SDoc #-} +{-# SPECIALIZE pprSectionHeader :: NCGConfig -> Section -> HLine #-} -- see Note [SPECIALIZE to HDoc] in GHC.Utils.Outputable -pprGNUSectionHeader :: NCGConfig -> SectionType -> CLabel -> SDoc +pprGNUSectionHeader :: IsLine doc => NCGConfig -> SectionType -> CLabel -> doc pprGNUSectionHeader config t suffix = hcat [text ".section ", header, subsection, flags] where @@ -244,10 +250,12 @@ pprGNUSectionHeader config t suffix = -> empty | otherwise -> text ",\"aMS\"," <> sectionType platform "progbits" <> text ",1" _ -> empty +{-# SPECIALIZE pprGNUSectionHeader :: NCGConfig -> SectionType -> CLabel -> SDoc #-} +{-# SPECIALIZE pprGNUSectionHeader :: NCGConfig -> SectionType -> CLabel -> HLine #-} -- see Note [SPECIALIZE to HDoc] in GHC.Utils.Outputable -- XCOFF doesn't support relocating label-differences, so we place all -- RO sections into .text[PR] sections -pprXcoffSectionHeader :: SectionType -> SDoc +pprXcoffSectionHeader :: IsLine doc => SectionType -> doc pprXcoffSectionHeader t = case t of Text -> text ".csect .text[PR]" Data -> text ".csect .data[RW]" @@ -256,8 +264,10 @@ pprXcoffSectionHeader t = case t of CString -> text ".csect .text[PR] # CString" UninitialisedData -> text ".csect .data[BS]" _ -> panic "pprXcoffSectionHeader: unknown section type" +{-# SPECIALIZE pprXcoffSectionHeader :: SectionType -> SDoc #-} +{-# SPECIALIZE pprXcoffSectionHeader :: SectionType -> HLine #-} -- see Note [SPECIALIZE to HDoc] in GHC.Utils.Outputable -pprDarwinSectionHeader :: SectionType -> SDoc +pprDarwinSectionHeader :: IsLine doc => SectionType -> doc pprDarwinSectionHeader t = case t of Text -> text ".text" Data -> text ".data" @@ -268,3 +278,5 @@ pprDarwinSectionHeader t = case t of FiniArray -> panic "pprDarwinSectionHeader: fini not supported" CString -> text ".section\t__TEXT,__cstring,cstring_literals" OtherSection _ -> panic "pprDarwinSectionHeader: unknown section type" +{-# SPECIALIZE pprDarwinSectionHeader :: SectionType -> SDoc #-} +{-# SPECIALIZE pprDarwinSectionHeader :: SectionType -> HLine #-} -- see Note [SPECIALIZE to HDoc] in GHC.Utils.Outputable diff --git a/compiler/GHC/CmmToAsm/X86.hs b/compiler/GHC/CmmToAsm/X86.hs index 91b571f4de..a82674afe8 100644 --- a/compiler/GHC/CmmToAsm/X86.hs +++ b/compiler/GHC/CmmToAsm/X86.hs @@ -33,7 +33,8 @@ ncgX86_64 config = NcgImpl , canShortcut = X86.canShortcut , shortcutStatics = X86.shortcutStatics , shortcutJump = X86.shortcutJump - , pprNatCmmDecl = X86.pprNatCmmDecl config + , pprNatCmmDeclS = X86.pprNatCmmDecl config + , pprNatCmmDeclH = X86.pprNatCmmDecl config , maxSpillSlots = X86.maxSpillSlots config , allocatableRegs = X86.allocatableRegs platform , ncgAllocMoreStack = X86.allocMoreStack platform diff --git a/compiler/GHC/CmmToAsm/X86/CodeGen.hs b/compiler/GHC/CmmToAsm/X86/CodeGen.hs index fd85ae6154..67c5504295 100644 --- a/compiler/GHC/CmmToAsm/X86/CodeGen.hs +++ b/compiler/GHC/CmmToAsm/X86/CodeGen.hs @@ -326,7 +326,7 @@ stmtToInstrs bid stmt = do -> genForeignCall target result_regs args bid _ -> (,Nothing) <$> case stmt of - CmmComment s -> return (unitOL (COMMENT $ ftext s)) + CmmComment s -> return (unitOL (COMMENT s)) CmmTick {} -> return nilOL CmmUnwind regs -> do diff --git a/compiler/GHC/CmmToAsm/X86/Instr.hs b/compiler/GHC/CmmToAsm/X86/Instr.hs index 42b9543204..59c4770c9b 100644 --- a/compiler/GHC/CmmToAsm/X86/Instr.hs +++ b/compiler/GHC/CmmToAsm/X86/Instr.hs @@ -67,6 +67,7 @@ import GHC.Types.Basic (Alignment) import GHC.Cmm.DebugBlock (UnwindTable) import Data.Maybe (fromMaybe) +import GHC.Data.FastString (FastString) -- Format of an x86/x86_64 memory address, in bytes. -- @@ -170,7 +171,7 @@ bit precision. data Instr -- comment pseudo-op - = COMMENT SDoc + = COMMENT FastString -- location pseudo-op (file, line, col, name) | LOCATION Int Int Int String diff --git a/compiler/GHC/CmmToAsm/X86/Ppr.hs b/compiler/GHC/CmmToAsm/X86/Ppr.hs index 0b19665857..11c882e547 100644 --- a/compiler/GHC/CmmToAsm/X86/Ppr.hs +++ b/compiler/GHC/CmmToAsm/X86/Ppr.hs @@ -1,5 +1,6 @@ {-# LANGUAGE LambdaCase #-} +{-# LANGUAGE ScopedTypeVariables #-} ----------------------------------------------------------------------------- -- @@ -11,11 +12,7 @@ module GHC.CmmToAsm.X86.Ppr ( pprNatCmmDecl, - pprData, pprInstr, - pprFormat, - pprImm, - pprDataItem, ) where @@ -39,6 +36,7 @@ import GHC.Cmm.Dataflow.Collections import GHC.Cmm.Dataflow.Label import GHC.Cmm.BlockId import GHC.Cmm.CLabel +import GHC.Cmm.DebugBlock (pprUnwindTable) import GHC.Types.Basic (Alignment, mkAlignment, alignmentBytes) import GHC.Types.Unique ( pprUniqueAlways ) @@ -65,12 +63,12 @@ import Data.Word -- .subsections_via_symbols and -dead_strip can be found at -- <https://developer.apple.com/library/mac/documentation/DeveloperTools/Reference/Assembler/040-Assembler_Directives/asm_directives.html#//apple_ref/doc/uid/TP30000823-TPXREF101> -pprProcAlignment :: NCGConfig -> SDoc +pprProcAlignment :: IsDoc doc => NCGConfig -> doc pprProcAlignment config = maybe empty (pprAlign platform . mkAlignment) (ncgProcAlignment config) where platform = ncgPlatform config -pprNatCmmDecl :: NCGConfig -> NatCmmDecl (Alignment, RawCmmStatics) Instr -> SDoc +pprNatCmmDecl :: IsDoc doc => NCGConfig -> NatCmmDecl (Alignment, RawCmmStatics) Instr -> doc pprNatCmmDecl config (CmmData section dats) = pprSectionAlign config section $$ pprDatas config dats @@ -85,7 +83,7 @@ pprNatCmmDecl config proc@(CmmProc top_info lbl _ (ListGraph blocks)) = pprProcLabel config lbl $$ pprLabel platform lbl $$ -- blocks guaranteed not null, so label needed vcat (map (pprBasicBlock config top_info) blocks) $$ - ppWhen (ncgDwarfEnabled config) (pprBlockEndLabel platform lbl $$ pprProcEndLabel platform lbl) $$ + ppWhen (ncgDwarfEnabled config) (line (pprBlockEndLabel platform lbl) $$ line (pprProcEndLabel platform lbl)) $$ pprSizeDecl platform lbl Just (CmmStaticsRaw info_lbl _) -> @@ -93,48 +91,51 @@ pprNatCmmDecl config proc@(CmmProc top_info lbl _ (ListGraph blocks)) = pprProcAlignment config $$ pprProcLabel config lbl $$ (if platformHasSubsectionsViaSymbols platform - then pprAsmLabel platform (mkDeadStripPreventer info_lbl) <> colon + then line (pprAsmLabel platform (mkDeadStripPreventer info_lbl) <> colon) else empty) $$ vcat (map (pprBasicBlock config top_info) blocks) $$ - ppWhen (ncgDwarfEnabled config) (pprProcEndLabel platform info_lbl) $$ + ppWhen (ncgDwarfEnabled config) (line (pprProcEndLabel platform info_lbl)) $$ -- above: Even the first block gets a label, because with branch-chain -- elimination, it might be the target of a goto. (if platformHasSubsectionsViaSymbols platform then -- See Note [Subsections Via Symbols] - text "\t.long " + line + $ text "\t.long " <+> pprAsmLabel platform info_lbl <+> char '-' <+> pprAsmLabel platform (mkDeadStripPreventer info_lbl) else empty) $$ pprSizeDecl platform info_lbl +{-# SPECIALIZE pprNatCmmDecl :: NCGConfig -> NatCmmDecl (Alignment, RawCmmStatics) Instr -> SDoc #-} +{-# SPECIALIZE pprNatCmmDecl :: NCGConfig -> NatCmmDecl (Alignment, RawCmmStatics) Instr -> HDoc #-} -- see Note [SPECIALIZE to HDoc] in GHC.Utils.Outputable -- | Output an internal proc label. See Note [Internal proc labels] in CLabel. -pprProcLabel :: NCGConfig -> CLabel -> SDoc +pprProcLabel :: IsDoc doc => NCGConfig -> CLabel -> doc pprProcLabel config lbl | ncgExposeInternalSymbols config , Just lbl' <- ppInternalProcLabel (ncgThisModule config) lbl - = lbl' <> colon + = line (lbl' <> colon) | otherwise = empty -pprProcEndLabel :: Platform -> CLabel -- ^ Procedure name - -> SDoc +pprProcEndLabel :: IsLine doc => Platform -> CLabel -- ^ Procedure name + -> doc pprProcEndLabel platform lbl = pprAsmLabel platform (mkAsmTempProcEndLabel lbl) <> colon -pprBlockEndLabel :: Platform -> CLabel -- ^ Block name - -> SDoc +pprBlockEndLabel :: IsLine doc => Platform -> CLabel -- ^ Block name + -> doc pprBlockEndLabel platform lbl = pprAsmLabel platform (mkAsmTempEndLabel lbl) <> colon -- | Output the ELF .size directive. -pprSizeDecl :: Platform -> CLabel -> SDoc +pprSizeDecl :: IsDoc doc => Platform -> CLabel -> doc pprSizeDecl platform lbl = if osElfTarget (platformOS platform) - then text "\t.size" <+> pprAsmLabel platform lbl <> text ", .-" <> pprAsmLabel platform lbl + then line (text "\t.size" <+> pprAsmLabel platform lbl <> text ", .-" <> pprAsmLabel platform lbl) else empty -pprBasicBlock :: NCGConfig -> LabelMap RawCmmStatics -> NatBasicBlock Instr -> SDoc +pprBasicBlock :: IsDoc doc => NCGConfig -> LabelMap RawCmmStatics -> NatBasicBlock Instr -> doc pprBasicBlock config info_env (BasicBlock blockid instrs) = maybe_infotable $ pprLabel platform asmLbl $$ @@ -142,8 +143,8 @@ pprBasicBlock config info_env (BasicBlock blockid instrs) ppWhen (ncgDwarfEnabled config) ( -- Emit both end labels since this may end up being a standalone -- top-level block - pprBlockEndLabel platform asmLbl - <> pprProcEndLabel platform asmLbl + line (pprBlockEndLabel platform asmLbl + <> pprProcEndLabel platform asmLbl) ) where asmLbl = blockLbl blockid @@ -156,7 +157,7 @@ pprBasicBlock config info_env (BasicBlock blockid instrs) vcat (map (pprData config) info) $$ pprLabel platform infoLbl $$ c $$ - ppWhen (ncgDwarfEnabled config) (pprAsmLabel platform (mkAsmTempEndLabel infoLbl) <> colon) + ppWhen (ncgDwarfEnabled config) (line (pprAsmLabel platform (mkAsmTempEndLabel infoLbl) <> colon)) -- Make sure the info table has the right .loc for the block -- coming right after it. See Note [Info Offset] @@ -165,7 +166,7 @@ pprBasicBlock config info_env (BasicBlock blockid instrs) _other -> empty -pprDatas :: NCGConfig -> (Alignment, RawCmmStatics) -> SDoc +pprDatas :: IsDoc doc => NCGConfig -> (Alignment, RawCmmStatics) -> doc -- See Note [emit-time elimination of static indirections] in "GHC.Cmm.CLabel". pprDatas config (_, CmmStaticsRaw alias [CmmStaticLit (CmmLabel lbl), CmmStaticLit ind, _, _]) | lbl == mkIndStaticInfoLabel @@ -175,31 +176,32 @@ pprDatas config (_, CmmStaticsRaw alias [CmmStaticLit (CmmLabel lbl), CmmStaticL , Just ind' <- labelInd ind , alias `mayRedirectTo` ind' = pprGloblDecl (ncgPlatform config) alias - $$ text ".equiv" <+> pprAsmLabel (ncgPlatform config) alias <> comma <> pprAsmLabel (ncgPlatform config) ind' + $$ line (text ".equiv" <+> pprAsmLabel (ncgPlatform config) alias <> comma <> pprAsmLabel (ncgPlatform config) ind') pprDatas config (align, (CmmStaticsRaw lbl dats)) = vcat (pprAlign platform align : pprLabel platform lbl : map (pprData config) dats) where platform = ncgPlatform config -pprData :: NCGConfig -> CmmStatic -> SDoc -pprData _config (CmmString str) = pprString str -pprData _config (CmmFileEmbed path) = pprFileEmbed path +pprData :: IsDoc doc => NCGConfig -> CmmStatic -> doc +pprData _config (CmmString str) = line (pprString str) +pprData _config (CmmFileEmbed path) = line (pprFileEmbed path) pprData config (CmmUninitialised bytes) - = let platform = ncgPlatform config + = line + $ let platform = ncgPlatform config in if platformOS platform == OSDarwin then text ".space " <> int bytes else text ".skip " <> int bytes pprData config (CmmStaticLit lit) = pprDataItem config lit -pprGloblDecl :: Platform -> CLabel -> SDoc +pprGloblDecl :: IsDoc doc => Platform -> CLabel -> doc pprGloblDecl platform lbl | not (externallyVisibleCLabel lbl) = empty - | otherwise = text ".globl " <> pprAsmLabel platform lbl + | otherwise = line (text ".globl " <> pprAsmLabel platform lbl) -pprLabelType' :: Platform -> CLabel -> SDoc +pprLabelType' :: IsLine doc => Platform -> CLabel -> doc pprLabelType' platform lbl = if isCFunctionLabel lbl || functionOkInfoTable then text "@function" @@ -257,21 +259,21 @@ pprLabelType' platform lbl = isInfoTableLabel lbl && not (isCmmInfoTableLabel lbl) && not (isConInfoTableLabel lbl) -pprTypeDecl :: Platform -> CLabel -> SDoc +pprTypeDecl :: IsDoc doc => Platform -> CLabel -> doc pprTypeDecl platform lbl = if osElfTarget (platformOS platform) && externallyVisibleCLabel lbl - then text ".type " <> pprAsmLabel platform lbl <> text ", " <> pprLabelType' platform lbl + then line (text ".type " <> pprAsmLabel platform lbl <> text ", " <> pprLabelType' platform lbl) else empty -pprLabel :: Platform -> CLabel -> SDoc +pprLabel :: IsDoc doc => Platform -> CLabel -> doc pprLabel platform lbl = pprGloblDecl platform lbl $$ pprTypeDecl platform lbl - $$ (pprAsmLabel platform lbl <> colon) + $$ line (pprAsmLabel platform lbl <> colon) -pprAlign :: Platform -> Alignment -> SDoc +pprAlign :: IsDoc doc => Platform -> Alignment -> doc pprAlign platform alignment - = text ".align " <> int (alignmentOn platform) + = line $ text ".align " <> int (alignmentOn platform) where bytes = alignmentBytes alignment alignmentOn platform = if platformOS platform == OSDarwin @@ -285,7 +287,7 @@ pprAlign platform alignment log2 8 = 3 log2 n = 1 + log2 (n `quot` 2) -pprReg :: Platform -> Format -> Reg -> SDoc +pprReg :: forall doc. IsLine doc => Platform -> Format -> Reg -> doc pprReg platform f r = case r of RegReal (RealRegSingle i) -> @@ -297,7 +299,7 @@ pprReg platform f r RegVirtual (VirtualRegD u) -> text "%vD_" <> pprUniqueAlways u where - ppr32_reg_no :: Format -> Int -> SDoc + ppr32_reg_no :: Format -> Int -> doc ppr32_reg_no II8 = ppr32_reg_byte ppr32_reg_no II16 = ppr32_reg_word ppr32_reg_no _ = ppr32_reg_long @@ -327,7 +329,7 @@ pprReg platform f r _ -> ppr_reg_float i } - ppr64_reg_no :: Format -> Int -> SDoc + ppr64_reg_no :: Format -> Int -> doc ppr64_reg_no II8 = ppr64_reg_byte ppr64_reg_no II16 = ppr64_reg_word ppr64_reg_no II32 = ppr64_reg_long @@ -385,7 +387,7 @@ pprReg platform f r _ -> ppr_reg_float i } -ppr_reg_float :: Int -> SDoc +ppr_reg_float :: IsLine doc => Int -> doc ppr_reg_float i = case i of 16 -> text "%xmm0" ; 17 -> text "%xmm1" 18 -> text "%xmm2" ; 19 -> text "%xmm3" @@ -397,7 +399,7 @@ ppr_reg_float i = case i of 30 -> text "%xmm14"; 31 -> text "%xmm15" _ -> text "very naughty x86 register" -pprFormat :: Format -> SDoc +pprFormat :: IsLine doc => Format -> doc pprFormat x = case x of II8 -> text "b" II16 -> text "w" @@ -406,14 +408,14 @@ pprFormat x = case x of FF32 -> text "ss" -- "scalar single-precision float" (SSE2) FF64 -> text "sd" -- "scalar double-precision float" (SSE2) -pprFormat_x87 :: Format -> SDoc +pprFormat_x87 :: IsLine doc => Format -> doc pprFormat_x87 x = case x of FF32 -> text "s" FF64 -> text "l" _ -> panic "X86.Ppr.pprFormat_x87" -pprCond :: Cond -> SDoc +pprCond :: IsLine doc => Cond -> doc pprCond c = case c of { GEU -> text "ae"; LU -> text "b"; EQQ -> text "e"; GTT -> text "g"; @@ -426,7 +428,7 @@ pprCond c = case c of { ALWAYS -> text "mp"} -pprImm :: Platform -> Imm -> SDoc +pprImm :: IsLine doc => Platform -> Imm -> doc pprImm platform = \case ImmInt i -> int i ImmInteger i -> integer i @@ -440,7 +442,7 @@ pprImm platform = \case -pprAddr :: Platform -> AddrMode -> SDoc +pprAddr :: IsLine doc => Platform -> AddrMode -> doc pprAddr platform (ImmAddr imm off) = let pp_imm = pprImm platform imm in @@ -471,16 +473,16 @@ pprAddr platform (AddrBaseIndex base index displacement) ppr_disp imm = pprImm platform imm -- | Print section header and appropriate alignment for that section. -pprSectionAlign :: NCGConfig -> Section -> SDoc +pprSectionAlign :: IsDoc doc => NCGConfig -> Section -> doc pprSectionAlign _config (Section (OtherSection _) _) = panic "X86.Ppr.pprSectionAlign: unknown section" pprSectionAlign config sec@(Section seg _) = - pprSectionHeader config sec $$ + line (pprSectionHeader config sec) $$ pprAlignForSection (ncgPlatform config) seg -- | Print appropriate alignment for the given section type. -pprAlignForSection :: Platform -> SectionType -> SDoc -pprAlignForSection platform seg = +pprAlignForSection :: IsDoc doc => Platform -> SectionType -> doc +pprAlignForSection platform seg = line $ text ".align " <> case platformOS platform of -- Darwin: alignments are given as shifts. @@ -505,9 +507,9 @@ pprAlignForSection platform seg = CString -> int 1 _ -> int 8 -pprDataItem :: NCGConfig -> CmmLit -> SDoc +pprDataItem :: IsDoc doc => NCGConfig -> CmmLit -> doc pprDataItem config lit - = vcat (ppr_item (cmmTypeFormat $ cmmLitType platform lit) lit) + = lines_ (ppr_item (cmmTypeFormat $ cmmLitType platform lit) lit) where platform = ncgPlatform config imm = litToImm lit @@ -557,26 +559,26 @@ pprDataItem config lit [text "\t.quad\t" <> pprImm platform imm] -asmComment :: SDoc -> SDoc +asmComment :: IsLine doc => doc -> doc asmComment c = whenPprDebug $ text "# " <> c -pprInstr :: Platform -> Instr -> SDoc +pprInstr :: forall doc. IsDoc doc => Platform -> Instr -> doc pprInstr platform i = case i of COMMENT s - -> asmComment s + -> line (asmComment (ftext s)) - LOCATION file line col _name - -> text "\t.loc " <> ppr file <+> ppr line <+> ppr col + LOCATION file line' col _name + -> line (text "\t.loc " <> int file <+> int line' <+> int col) DELTA d - -> asmComment $ text ("\tdelta = " ++ show d) + -> line (asmComment $ text ("\tdelta = " ++ show d)) NEWBLOCK _ -> panic "pprInstr: NEWBLOCK" UNWIND lbl d - -> asmComment (text "\tunwind = " <> pdoc platform d) - $$ pprAsmLabel platform lbl <> colon + -> line (asmComment (text "\tunwind = " <> pprUnwindTable platform d)) + $$ line (pprAsmLabel platform lbl <> colon) LDATA _ _ -> panic "pprInstr: LDATA" @@ -794,19 +796,19 @@ pprInstr platform i = case i of -- POPA -> text "\tpopal" NOP - -> text "\tnop" + -> line $ text "\tnop" CLTD II8 - -> text "\tcbtw" + -> line $ text "\tcbtw" CLTD II16 - -> text "\tcwtd" + -> line $ text "\tcwtd" CLTD II32 - -> text "\tcltd" + -> line $ text "\tcltd" CLTD II64 - -> text "\tcqto" + -> line $ text "\tcqto" CLTD x -> panic $ "pprInstr: CLTD " ++ show x @@ -825,19 +827,19 @@ pprInstr platform i = case i of -> pprCondInstr (text "j") cond (pprImm platform imm) JMP (OpImm imm) _ - -> text "\tjmp " <> pprImm platform imm + -> line $ text "\tjmp " <> pprImm platform imm JMP op _ - -> text "\tjmp *" <> pprOperand platform (archWordFormat (target32Bit platform)) op + -> line $ text "\tjmp *" <> pprOperand platform (archWordFormat (target32Bit platform)) op JMP_TBL op _ _ _ -> pprInstr platform (JMP op []) CALL (Left imm) _ - -> text "\tcall " <> pprImm platform imm + -> line $ text "\tcall " <> pprImm platform imm CALL (Right reg) _ - -> text "\tcall *" <> pprReg platform (archWordFormat (target32Bit platform)) reg + -> line $ text "\tcall *" <> pprReg platform (archWordFormat (target32Bit platform)) reg IDIV fmt op -> pprFormatOp (text "idiv") fmt op @@ -881,20 +883,20 @@ pprInstr platform i = case i of -- FETCHGOT for PIC on ELF platforms FETCHGOT reg - -> vcat [ text "\tcall 1f", - hcat [ text "1:\tpopl\t", pprReg platform II32 reg ], - hcat [ text "\taddl\t$_GLOBAL_OFFSET_TABLE_+(.-1b), ", - pprReg platform II32 reg ] - ] + -> lines_ [ text "\tcall 1f", + hcat [ text "1:\tpopl\t", pprReg platform II32 reg ], + hcat [ text "\taddl\t$_GLOBAL_OFFSET_TABLE_+(.-1b), ", + pprReg platform II32 reg ] + ] -- FETCHPC for PIC on Darwin/x86 -- get the instruction pointer into a register -- (Terminology note: the IP is called Program Counter on PPC, -- and it's a good thing to use the same name on both platforms) FETCHPC reg - -> vcat [ text "\tcall 1f", - hcat [ text "1:\tpopl\t", pprReg platform II32 reg ] - ] + -> lines_ [ text "\tcall 1f", + hcat [ text "1:\tpopl\t", pprReg platform II32 reg ] + ] -- the -- GST fmt src addr ==> FLD dst ; FSTPsz addr @@ -903,10 +905,10 @@ pprInstr platform i = case i of -- Atomics LOCK i - -> text "\tlock" $$ pprInstr platform i + -> line (text "\tlock") $$ pprInstr platform i MFENCE - -> text "\tmfence" + -> line $ text "\tmfence" XADD format src dst -> pprFormatOpOp (text "xadd") format src dst @@ -916,46 +918,46 @@ pprInstr platform i = case i of where - gtab :: SDoc + gtab :: Line doc gtab = char '\t' - gsp :: SDoc + gsp :: Line doc gsp = char ' ' - pprX87 :: Instr -> SDoc -> SDoc + pprX87 :: Instr -> Line doc -> doc pprX87 fake actual - = (char '#' <> pprX87Instr fake) $$ actual + = line (char '#' <> pprX87Instr fake) $$ line actual - pprX87Instr :: Instr -> SDoc + pprX87Instr :: Instr -> Line doc pprX87Instr (X87Store fmt dst) = pprFormatAddr (text "gst") fmt dst pprX87Instr _ = panic "X86.Ppr.pprX87Instr: no match" - pprDollImm :: Imm -> SDoc + pprDollImm :: Imm -> Line doc pprDollImm i = text "$" <> pprImm platform i - pprOperand :: Platform -> Format -> Operand -> SDoc + pprOperand :: Platform -> Format -> Operand -> Line doc pprOperand platform f op = case op of OpReg r -> pprReg platform f r OpImm i -> pprDollImm i OpAddr ea -> pprAddr platform ea - pprMnemonic_ :: SDoc -> SDoc + pprMnemonic_ :: Line doc -> Line doc pprMnemonic_ name = char '\t' <> name <> space - pprMnemonic :: SDoc -> Format -> SDoc + pprMnemonic :: Line doc -> Format -> Line doc pprMnemonic name format = char '\t' <> name <> pprFormat format <> space - pprFormatImmOp :: SDoc -> Format -> Imm -> Operand -> SDoc + pprFormatImmOp :: Line doc -> Format -> Imm -> Operand -> doc pprFormatImmOp name format imm op1 - = hcat [ + = line $ hcat [ pprMnemonic name format, char '$', pprImm platform imm, @@ -964,24 +966,24 @@ pprInstr platform i = case i of ] - pprFormatOp_ :: SDoc -> Format -> Operand -> SDoc + pprFormatOp_ :: Line doc -> Format -> Operand -> doc pprFormatOp_ name format op1 - = hcat [ + = line $ hcat [ pprMnemonic_ name , pprOperand platform format op1 ] - pprFormatOp :: SDoc -> Format -> Operand -> SDoc + pprFormatOp :: Line doc -> Format -> Operand -> doc pprFormatOp name format op1 - = hcat [ + = line $ hcat [ pprMnemonic name format, pprOperand platform format op1 ] - pprFormatOpOp :: SDoc -> Format -> Operand -> Operand -> SDoc + pprFormatOpOp :: Line doc -> Format -> Operand -> Operand -> doc pprFormatOpOp name format op1 op2 - = hcat [ + = line $ hcat [ pprMnemonic name format, pprOperand platform format op1, comma, @@ -989,18 +991,18 @@ pprInstr platform i = case i of ] - pprOpOp :: SDoc -> Format -> Operand -> Operand -> SDoc + pprOpOp :: Line doc -> Format -> Operand -> Operand -> doc pprOpOp name format op1 op2 - = hcat [ + = line $ hcat [ pprMnemonic_ name, pprOperand platform format op1, comma, pprOperand platform format op2 ] - pprRegReg :: SDoc -> Reg -> Reg -> SDoc + pprRegReg :: Line doc -> Reg -> Reg -> doc pprRegReg name reg1 reg2 - = hcat [ + = line $ hcat [ pprMnemonic_ name, pprReg platform (archWordFormat (target32Bit platform)) reg1, comma, @@ -1008,18 +1010,18 @@ pprInstr platform i = case i of ] - pprFormatOpReg :: SDoc -> Format -> Operand -> Reg -> SDoc + pprFormatOpReg :: Line doc -> Format -> Operand -> Reg -> doc pprFormatOpReg name format op1 reg2 - = hcat [ + = line $ hcat [ pprMnemonic name format, pprOperand platform format op1, comma, pprReg platform (archWordFormat (target32Bit platform)) reg2 ] - pprCondOpReg :: SDoc -> Format -> Cond -> Operand -> Reg -> SDoc + pprCondOpReg :: Line doc -> Format -> Cond -> Operand -> Reg -> doc pprCondOpReg name format cond op1 reg2 - = hcat [ + = line $ hcat [ char '\t', name, pprCond cond, @@ -1029,18 +1031,18 @@ pprInstr platform i = case i of pprReg platform format reg2 ] - pprFormatFormatOpReg :: SDoc -> Format -> Format -> Operand -> Reg -> SDoc + pprFormatFormatOpReg :: Line doc -> Format -> Format -> Operand -> Reg -> doc pprFormatFormatOpReg name format1 format2 op1 reg2 - = hcat [ + = line $ hcat [ pprMnemonic name format2, pprOperand platform format1 op1, comma, pprReg platform format2 reg2 ] - pprFormatOpOpReg :: SDoc -> Format -> Operand -> Operand -> Reg -> SDoc + pprFormatOpOpReg :: Line doc -> Format -> Operand -> Operand -> Reg -> doc pprFormatOpOpReg name format op1 op2 reg3 - = hcat [ + = line $ hcat [ pprMnemonic name format, pprOperand platform format op1, comma, @@ -1051,7 +1053,7 @@ pprInstr platform i = case i of - pprFormatAddr :: SDoc -> Format -> AddrMode -> SDoc + pprFormatAddr :: Line doc -> Format -> AddrMode -> Line doc pprFormatAddr name format op = hcat [ pprMnemonic name format, @@ -1059,9 +1061,9 @@ pprInstr platform i = case i of pprAddr platform op ] - pprShift :: SDoc -> Format -> Operand -> Operand -> SDoc + pprShift :: Line doc -> Format -> Operand -> Operand -> doc pprShift name format src dest - = hcat [ + = line $ hcat [ pprMnemonic name format, pprOperand platform II8 src, -- src is 8-bit sized comma, @@ -1069,15 +1071,15 @@ pprInstr platform i = case i of ] - pprFormatOpOpCoerce :: SDoc -> Format -> Format -> Operand -> Operand -> SDoc + pprFormatOpOpCoerce :: Line doc -> Format -> Format -> Operand -> Operand -> doc pprFormatOpOpCoerce name format1 format2 op1 op2 - = hcat [ char '\t', name, pprFormat format1, pprFormat format2, space, + = line $ hcat [ char '\t', name, pprFormat format1, pprFormat format2, space, pprOperand platform format1 op1, comma, pprOperand platform format2 op2 ] - pprCondInstr :: SDoc -> Cond -> SDoc -> SDoc + pprCondInstr :: Line doc -> Cond -> Line doc -> doc pprCondInstr name cond arg - = hcat [ char '\t', name, pprCond cond, space, arg] + = line $ hcat [ char '\t', name, pprCond cond, space, arg] |