summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorSylvain Henry <sylvain@haskus.fr>2020-03-01 16:37:59 +0100
committerMarge Bot <ben+marge-bot@smart-cactus.org>2020-03-15 10:57:10 -0400
commit2e82465fff5851f00449131fdc8bacd3ca95f90f (patch)
treecb8c8f57b1c1bf9950c514d91286b3a5463778f4
parentdd6ffe6be742cf3ec98406704fef53ad86cc1560 (diff)
downloadhaskell-2e82465fff5851f00449131fdc8bacd3ca95f90f.tar.gz
Refactor CmmToAsm (disentangle DynFlags)
This patch disentangles a bit more DynFlags from the native code generator (CmmToAsm). In more details: - add a new NCGConfig datatype in GHC.CmmToAsm.Config which contains the configuration of a native code generation session - explicitly pass NCGConfig/Platform arguments when necessary - as a consequence `sdocWithPlatform` is gone and there are only a few `sdocWithDynFlags` left - remove the use of `unsafeGlobalDynFlags` from GHC.CmmToAsm.CFG - remove `sdocDebugLevel` (now we pass the debug level via NCGConfig) There are still some places where DynFlags is used, especially because of pretty-printing (CLabel), because of Cmm helpers (such as `cmmExprType`) and because of `Outputable` instance for the instructions. These are left for future refactoring as this patch is already big.
-rw-r--r--compiler/GHC/Cmm/CLabel.hs8
-rw-r--r--compiler/GHC/CmmToAsm.hs64
-rw-r--r--compiler/GHC/CmmToAsm/BlockLayout.hs16
-rw-r--r--compiler/GHC/CmmToAsm/CFG.hs12
-rw-r--r--compiler/GHC/CmmToAsm/Config.hs32
-rw-r--r--compiler/GHC/CmmToAsm/Dwarf.hs41
-rw-r--r--compiler/GHC/CmmToAsm/Dwarf/Constants.hs24
-rw-r--r--compiler/GHC/CmmToAsm/Dwarf/Types.hs143
-rw-r--r--compiler/GHC/CmmToAsm/Instr.hs9
-rw-r--r--compiler/GHC/CmmToAsm/Monad.hs49
-rw-r--r--compiler/GHC/CmmToAsm/PIC.hs298
-rw-r--r--compiler/GHC/CmmToAsm/PPC/CodeGen.hs96
-rw-r--r--compiler/GHC/CmmToAsm/PPC/Instr.hs40
-rw-r--r--compiler/GHC/CmmToAsm/PPC/Ppr.hs1231
-rw-r--r--compiler/GHC/CmmToAsm/PPC/Regs.hs5
-rw-r--r--compiler/GHC/CmmToAsm/Ppr.hs44
-rw-r--r--compiler/GHC/CmmToAsm/Reg/Graph.hs44
-rw-r--r--compiler/GHC/CmmToAsm/Reg/Graph/Stats.hs36
-rw-r--r--compiler/GHC/CmmToAsm/Reg/Linear.hs49
-rw-r--r--compiler/GHC/CmmToAsm/Reg/Linear/Base.hs6
-rw-r--r--compiler/GHC/CmmToAsm/Reg/Linear/FreeRegs.hs36
-rw-r--r--compiler/GHC/CmmToAsm/Reg/Linear/JoinToTargets.hs14
-rw-r--r--compiler/GHC/CmmToAsm/Reg/Linear/StackMap.hs5
-rw-r--r--compiler/GHC/CmmToAsm/Reg/Linear/State.hs31
-rw-r--r--compiler/GHC/CmmToAsm/Reg/Liveness.hs18
-rw-r--r--compiler/GHC/CmmToAsm/SPARC/Base.hs7
-rw-r--r--compiler/GHC/CmmToAsm/SPARC/CodeGen/Gen64.hs11
-rw-r--r--compiler/GHC/CmmToAsm/SPARC/Instr.hs18
-rw-r--r--compiler/GHC/CmmToAsm/SPARC/Ppr.hs59
-rw-r--r--compiler/GHC/CmmToAsm/SPARC/Stack.hs16
-rw-r--r--compiler/GHC/CmmToAsm/X86/CodeGen.hs202
-rw-r--r--compiler/GHC/CmmToAsm/X86/Instr.hs37
-rw-r--r--compiler/GHC/CmmToAsm/X86/Ppr.hs978
-rw-r--r--compiler/GHC/CmmToAsm/X86/Regs.hs7
-rw-r--r--compiler/GHC/CmmToC.hs9
-rw-r--r--compiler/GHC/Driver/Session.hs9
-rw-r--r--compiler/ghc.cabal.in1
-rw-r--r--compiler/main/Elf.hs7
-rw-r--r--compiler/main/SysTools/ExtraObj.hs9
-rw-r--r--compiler/utils/AsmUtils.hs7
-rw-r--r--compiler/utils/Outputable.hs9
-rw-r--r--testsuite/tests/regalloc/regalloc_unit_tests.hs2
42 files changed, 2001 insertions, 1738 deletions
diff --git a/compiler/GHC/Cmm/CLabel.hs b/compiler/GHC/Cmm/CLabel.hs
index 34217d317f..eea71d0ce9 100644
--- a/compiler/GHC/Cmm/CLabel.hs
+++ b/compiler/GHC/Cmm/CLabel.hs
@@ -1355,18 +1355,18 @@ instance Outputable ForeignLabelSource where
internalNamePrefix :: Name -> SDoc
internalNamePrefix name = getPprStyle $ \ sty ->
if asmStyle sty && isRandomGenerated then
- sdocWithPlatform $ \platform ->
- ptext (asmTempLabelPrefix platform)
+ sdocWithDynFlags $ \dflags ->
+ ptext (asmTempLabelPrefix (targetPlatform dflags))
else
empty
where
isRandomGenerated = not $ isExternalName name
tempLabelPrefixOrUnderscore :: SDoc
-tempLabelPrefixOrUnderscore = sdocWithPlatform $ \platform ->
+tempLabelPrefixOrUnderscore = sdocWithDynFlags $ \dflags ->
getPprStyle $ \ sty ->
if asmStyle sty then
- ptext (asmTempLabelPrefix platform)
+ ptext (asmTempLabelPrefix (targetPlatform dflags))
else
char '_'
diff --git a/compiler/GHC/CmmToAsm.hs b/compiler/GHC/CmmToAsm.hs
index 8dc9b61198..82519db084 100644
--- a/compiler/GHC/CmmToAsm.hs
+++ b/compiler/GHC/CmmToAsm.hs
@@ -69,6 +69,7 @@ import GHC.Platform.Reg
import GHC.CmmToAsm.Monad
import GHC.CmmToAsm.CFG
import GHC.CmmToAsm.Dwarf
+import GHC.CmmToAsm.Config
import GHC.Cmm.DebugBlock
import GHC.Cmm.BlockId
@@ -191,14 +192,15 @@ x86_64NcgImpl :: DynFlags -> NcgImpl (Alignment, RawCmmStatics)
X86.Instr.Instr X86.Instr.JumpDest
x86_64NcgImpl dflags
= NcgImpl {
- cmmTopCodeGen = X86.CodeGen.cmmTopCodeGen
- ,generateJumpTableForInstr = X86.CodeGen.generateJumpTableForInstr dflags
+ ncgConfig = config
+ ,cmmTopCodeGen = X86.CodeGen.cmmTopCodeGen
+ ,generateJumpTableForInstr = X86.CodeGen.generateJumpTableForInstr config
,getJumpDestBlockId = X86.Instr.getJumpDestBlockId
,canShortcut = X86.Instr.canShortcut
,shortcutStatics = X86.Instr.shortcutStatics
,shortcutJump = X86.Instr.shortcutJump
- ,pprNatCmmDecl = X86.Ppr.pprNatCmmDecl
- ,maxSpillSlots = X86.Instr.maxSpillSlots dflags
+ ,pprNatCmmDecl = X86.Ppr.pprNatCmmDecl config
+ ,maxSpillSlots = X86.Instr.maxSpillSlots config
,allocatableRegs = X86.Regs.allocatableRegs platform
,ncgAllocMoreStack = X86.Instr.allocMoreStack platform
,ncgExpandTop = id
@@ -206,19 +208,22 @@ x86_64NcgImpl dflags
,extractUnwindPoints = X86.CodeGen.extractUnwindPoints
,invertCondBranches = X86.CodeGen.invertCondBranches
}
- where platform = targetPlatform dflags
+ where
+ config = initConfig dflags
+ platform = ncgPlatform config
ppcNcgImpl :: DynFlags -> NcgImpl RawCmmStatics PPC.Instr.Instr PPC.RegInfo.JumpDest
ppcNcgImpl dflags
= NcgImpl {
- cmmTopCodeGen = PPC.CodeGen.cmmTopCodeGen
- ,generateJumpTableForInstr = PPC.CodeGen.generateJumpTableForInstr dflags
+ ncgConfig = config
+ ,cmmTopCodeGen = PPC.CodeGen.cmmTopCodeGen
+ ,generateJumpTableForInstr = PPC.CodeGen.generateJumpTableForInstr config
,getJumpDestBlockId = PPC.RegInfo.getJumpDestBlockId
,canShortcut = PPC.RegInfo.canShortcut
,shortcutStatics = PPC.RegInfo.shortcutStatics
,shortcutJump = PPC.RegInfo.shortcutJump
- ,pprNatCmmDecl = PPC.Ppr.pprNatCmmDecl
- ,maxSpillSlots = PPC.Instr.maxSpillSlots dflags
+ ,pprNatCmmDecl = PPC.Ppr.pprNatCmmDecl config
+ ,maxSpillSlots = PPC.Instr.maxSpillSlots config
,allocatableRegs = PPC.Regs.allocatableRegs platform
,ncgAllocMoreStack = PPC.Instr.allocMoreStack platform
,ncgExpandTop = id
@@ -226,19 +231,22 @@ ppcNcgImpl dflags
,extractUnwindPoints = const []
,invertCondBranches = \_ _ -> id
}
- where platform = targetPlatform dflags
+ where
+ config = initConfig dflags
+ platform = ncgPlatform config
sparcNcgImpl :: DynFlags -> NcgImpl RawCmmStatics SPARC.Instr.Instr SPARC.ShortcutJump.JumpDest
sparcNcgImpl dflags
= NcgImpl {
- cmmTopCodeGen = SPARC.CodeGen.cmmTopCodeGen
+ ncgConfig = config
+ ,cmmTopCodeGen = SPARC.CodeGen.cmmTopCodeGen
,generateJumpTableForInstr = SPARC.CodeGen.generateJumpTableForInstr dflags
,getJumpDestBlockId = SPARC.ShortcutJump.getJumpDestBlockId
,canShortcut = SPARC.ShortcutJump.canShortcut
,shortcutStatics = SPARC.ShortcutJump.shortcutStatics
,shortcutJump = SPARC.ShortcutJump.shortcutJump
- ,pprNatCmmDecl = SPARC.Ppr.pprNatCmmDecl
- ,maxSpillSlots = SPARC.Instr.maxSpillSlots dflags
+ ,pprNatCmmDecl = SPARC.Ppr.pprNatCmmDecl config
+ ,maxSpillSlots = SPARC.Instr.maxSpillSlots config
,allocatableRegs = SPARC.Regs.allocatableRegs
,ncgAllocMoreStack = noAllocMoreStack
,ncgExpandTop = map SPARC.CodeGen.Expand.expandTop
@@ -246,6 +254,8 @@ sparcNcgImpl dflags
,extractUnwindPoints = const []
,invertCondBranches = \_ _ -> id
}
+ where
+ config = initConfig dflags
--
-- Allocating more stack space for spilling is currently only
@@ -538,7 +548,8 @@ cmmNativeGen
cmmNativeGen dflags this_mod modLoc ncgImpl us fileIds dbgMap cmm count
= do
- let platform = targetPlatform dflags
+ let config = ncgConfig ncgImpl
+ let platform = ncgPlatform config
let proc_name = case cmm of
(CmmProc _ entry_label _ _) -> ppr entry_label
@@ -577,7 +588,7 @@ cmmNativeGen dflags this_mod modLoc ncgImpl us fileIds dbgMap cmm count
-- tag instructions with register liveness information
-- also drops dead code. We don't keep the cfg in sync on
-- some backends, so don't use it there.
- let livenessCfg = if (backendMaintainsCfg dflags)
+ let livenessCfg = if backendMaintainsCfg platform
then Just nativeCfgWeights
else Nothing
let (withLiveness, usLive) =
@@ -607,7 +618,7 @@ cmmNativeGen dflags this_mod modLoc ncgImpl us fileIds dbgMap cmm count
= {-# SCC "RegAlloc-color" #-}
initUs usLive
$ Color.regAlloc
- dflags
+ config
alloc_regs
(mkUniqSet [0 .. maxSpillSlots ncgImpl])
(maxSpillSlots ncgImpl)
@@ -655,7 +666,7 @@ cmmNativeGen dflags this_mod modLoc ncgImpl us fileIds dbgMap cmm count
-- do linear register allocation
let reg_alloc proc = do
(alloced, maybe_more_stack, ra_stats) <-
- Linear.regAlloc dflags proc
+ Linear.regAlloc config proc
case maybe_more_stack of
Nothing -> return ( alloced, ra_stats, [] )
Just amount -> do
@@ -691,11 +702,11 @@ cmmNativeGen dflags this_mod modLoc ncgImpl us fileIds dbgMap cmm count
cfgRegAllocUpdates = (concatMap Linear.ra_fixupList raStats)
let cfgWithFixupBlks =
- (\cfg -> addNodesBetween cfg cfgRegAllocUpdates) <$> livenessCfg
+ (\cfg -> addNodesBetween dflags cfg cfgRegAllocUpdates) <$> livenessCfg
-- Insert stack update blocks
let postRegCFG =
- pure (foldl' (\m (from,to) -> addImmediateSuccessor from to m ))
+ pure (foldl' (\m (from,to) -> addImmediateSuccessor dflags from to m ))
<*> cfgWithFixupBlks
<*> pure stack_updt_blks
@@ -725,7 +736,7 @@ cmmNativeGen dflags this_mod modLoc ncgImpl us fileIds dbgMap cmm count
let getBlks (CmmProc _info _lbl _live (ListGraph blocks)) = blocks
getBlks _ = []
- when ( backendMaintainsCfg dflags &&
+ when ( backendMaintainsCfg platform &&
(gopt Opt_DoAsmLinting dflags || debugIsOn )) $ do
let blocks = concatMap getBlks shorted
let labels = setFromList $ fmap blockId blocks :: LabelSet
@@ -854,7 +865,7 @@ makeImportsDoc dflags imports
-- security. GHC generated code does not need an executable
-- stack so add the note in:
(if platformHasGnuNonexecStack platform
- then text ".section .note.GNU-stack,\"\"," <> sectionType "progbits"
+ then text ".section .note.GNU-stack,\"\"," <> sectionType platform "progbits"
else Outputable.empty)
$$
-- And just because every other compiler does, let's stick in
@@ -865,9 +876,8 @@ makeImportsDoc dflags imports
else Outputable.empty)
where
- platform = targetPlatform dflags
- arch = platformArch platform
- os = platformOS platform
+ config = initConfig dflags
+ platform = ncgPlatform config
-- Generate "symbol stubs" for all external symbols that might
-- come from a dynamic library.
@@ -877,10 +887,10 @@ makeImportsDoc dflags imports
-- (Hack) sometimes two Labels pretty-print the same, but have
-- different uniques; so we compare their text versions...
dyld_stubs imps
- | needImportedSymbols dflags arch os
+ | needImportedSymbols config
= vcat $
- (pprGotDeclaration dflags arch os :) $
- map ( pprImportedSymbol dflags platform . fst . head) $
+ (pprGotDeclaration config :) $
+ map ( pprImportedSymbol dflags config . fst . head) $
groupBy (\(_,a) (_,b) -> a == b) $
sortBy (\(_,a) (_,b) -> compare a b) $
map doPpr $
diff --git a/compiler/GHC/CmmToAsm/BlockLayout.hs b/compiler/GHC/CmmToAsm/BlockLayout.hs
index 01a1388b5f..0665e71433 100644
--- a/compiler/GHC/CmmToAsm/BlockLayout.hs
+++ b/compiler/GHC/CmmToAsm/BlockLayout.hs
@@ -10,7 +10,7 @@
{-# LANGUAGE FlexibleContexts #-}
module GHC.CmmToAsm.BlockLayout
- ( sequenceTop )
+ ( sequenceTop, backendMaintainsCfg)
where
#include "HsVersions.h"
@@ -25,7 +25,8 @@ import GHC.Cmm
import GHC.Cmm.Dataflow.Collections
import GHC.Cmm.Dataflow.Label
-import GHC.Driver.Session (gopt, GeneralFlag(..), DynFlags, backendMaintainsCfg)
+import GHC.Platform
+import GHC.Driver.Session (gopt, GeneralFlag(..), DynFlags, targetPlatform)
import UniqFM
import Util
import Unique
@@ -785,7 +786,7 @@ sequenceTop
sequenceTop _ _ _ top@(CmmData _ _) = top
sequenceTop dflags ncgImpl edgeWeights
(CmmProc info lbl live (ListGraph blocks))
- | (gopt Opt_CfgBlocklayout dflags) && backendMaintainsCfg dflags
+ | (gopt Opt_CfgBlocklayout dflags) && backendMaintainsCfg (targetPlatform dflags)
--Use chain based algorithm
, Just cfg <- edgeWeights
= CmmProc info lbl live ( ListGraph $ ncgMakeFarBranches ncgImpl info $
@@ -799,7 +800,7 @@ sequenceTop dflags ncgImpl edgeWeights
sequenceBlocks cfg info blocks)
where
dontUseCfg = gopt Opt_WeightlessBlocklayout dflags ||
- (not $ backendMaintainsCfg dflags)
+ (not $ backendMaintainsCfg (targetPlatform dflags))
-- The old algorithm:
-- It is very simple (and stupid): We make a graph out of
@@ -893,3 +894,10 @@ lookupDeleteUFM :: Uniquable key => UniqFM elt -> key
lookupDeleteUFM m k = do -- Maybe monad
v <- lookupUFM m k
return (v, delFromUFM m k)
+
+backendMaintainsCfg :: Platform -> Bool
+backendMaintainsCfg platform = case platformArch platform of
+ -- ArchX86 -- Should work but not tested so disabled currently.
+ ArchX86_64 -> True
+ _otherwise -> False
+
diff --git a/compiler/GHC/CmmToAsm/CFG.hs b/compiler/GHC/CmmToAsm/CFG.hs
index f52ff514b1..0995ecab61 100644
--- a/compiler/GHC/CmmToAsm/CFG.hs
+++ b/compiler/GHC/CmmToAsm/CFG.hs
@@ -328,12 +328,12 @@ shortcutWeightMap cuts cfg =
-- \ \
-- -> C => -> C
--
-addImmediateSuccessor :: BlockId -> BlockId -> CFG -> CFG
-addImmediateSuccessor node follower cfg
+addImmediateSuccessor :: D.DynFlags -> BlockId -> BlockId -> CFG -> CFG
+addImmediateSuccessor dflags node follower cfg
= updateEdges . addWeightEdge node follower uncondWeight $ cfg
where
uncondWeight = fromIntegral . D.uncondWeight .
- D.cfgWeightInfo $ D.unsafeGlobalDynFlags
+ D.cfgWeightInfo $ dflags
targets = getSuccessorEdges cfg node
successors = map fst targets :: [BlockId]
updateEdges = addNewSuccs . remOldSuccs
@@ -508,13 +508,13 @@ mapWeights f cfg =
-- these cases.
-- We assign the old edge info to the edge A -> B and assign B -> C the
-- weight of an unconditional jump.
-addNodesBetween :: CFG -> [(BlockId,BlockId,BlockId)] -> CFG
-addNodesBetween m updates =
+addNodesBetween :: D.DynFlags -> CFG -> [(BlockId,BlockId,BlockId)] -> CFG
+addNodesBetween dflags m updates =
foldl' updateWeight m .
weightUpdates $ updates
where
weight = fromIntegral . D.uncondWeight .
- D.cfgWeightInfo $ D.unsafeGlobalDynFlags
+ D.cfgWeightInfo $ dflags
-- We might add two blocks for different jumps along a single
-- edge. So we end up with edges: A -> B -> C , A -> D -> C
-- in this case after applying the first update the weight for A -> C
diff --git a/compiler/GHC/CmmToAsm/Config.hs b/compiler/GHC/CmmToAsm/Config.hs
new file mode 100644
index 0000000000..2df3655948
--- /dev/null
+++ b/compiler/GHC/CmmToAsm/Config.hs
@@ -0,0 +1,32 @@
+-- | Native code generator configuration
+module GHC.CmmToAsm.Config
+ ( NCGConfig(..)
+ , ncgWordWidth
+ )
+where
+
+import GhcPrelude
+import GHC.Platform
+import GHC.Cmm.Type (Width(..))
+
+-- | Native code generator configuration
+data NCGConfig = NCGConfig
+ { ncgPlatform :: !Platform -- ^ Target platform
+ , ncgProcAlignment :: !(Maybe Int) -- ^ Mandatory proc alignment
+ , ncgDebugLevel :: !Int -- ^ Debug level
+ , ncgExternalDynamicRefs :: !Bool -- ^ Generate code to link against dynamic libraries
+ , ncgPIC :: !Bool -- ^ Enable Position-Independent Code
+ , ncgSplitSections :: !Bool -- ^ Split sections
+ , ncgSpillPreallocSize :: !Int -- ^ Size in bytes of the pre-allocated spill space on the C stack
+ , ncgRegsIterative :: !Bool
+ , ncgAsmLinting :: !Bool -- ^ Perform ASM linting pass
+ , ncgDumpRegAllocStages :: !Bool
+ , ncgDumpAsmStats :: !Bool
+ , ncgDumpAsmConflicts :: !Bool
+ }
+
+-- | Return Word size
+ncgWordWidth :: NCGConfig -> Width
+ncgWordWidth config = case platformWordSize (ncgPlatform config) of
+ PW4 -> W32
+ PW8 -> W64
diff --git a/compiler/GHC/CmmToAsm/Dwarf.hs b/compiler/GHC/CmmToAsm/Dwarf.hs
index cdbbb9885a..9270a308a8 100644
--- a/compiler/GHC/CmmToAsm/Dwarf.hs
+++ b/compiler/GHC/CmmToAsm/Dwarf.hs
@@ -36,6 +36,7 @@ dwarfGen :: DynFlags -> ModLocation -> UniqSupply -> [DebugBlock]
-> IO (SDoc, UniqSupply)
dwarfGen _ _ us [] = return (empty, us)
dwarfGen df modLoc us blocks = do
+ let platform = targetPlatform df
-- Convert debug data structures to DWARF info records
-- We strip out block information when running with -g0 or -g1.
@@ -64,33 +65,33 @@ dwarfGen df modLoc us blocks = do
haveSrc = any haveSrcIn procs
-- .debug_abbrev section: Declare the format we're using
- let abbrevSct = pprAbbrevDecls haveSrc
+ let abbrevSct = pprAbbrevDecls platform haveSrc
-- .debug_info section: Information records on procedures and blocks
let -- unique to identify start and end compilation unit .debug_inf
(unitU, us') = takeUniqFromSupply us
infoSct = vcat [ ptext dwarfInfoLabel <> colon
- , dwarfInfoSection
- , compileUnitHeader unitU
- , pprDwarfInfo haveSrc dwarfUnit
+ , dwarfInfoSection platform
+ , compileUnitHeader platform unitU
+ , pprDwarfInfo platform haveSrc dwarfUnit
, compileUnitFooter unitU
]
-- .debug_line section: Generated mainly by the assembler, but we
-- need to label it
- let lineSct = dwarfLineSection $$
+ let lineSct = dwarfLineSection platform $$
ptext dwarfLineLabel <> colon
-- .debug_frame section: Information about the layout of the GHC stack
let (framesU, us'') = takeUniqFromSupply us'
- frameSct = dwarfFrameSection $$
+ frameSct = dwarfFrameSection platform $$
ptext dwarfFrameLabel <> colon $$
- pprDwarfFrame (debugFrame framesU procs)
+ pprDwarfFrame platform (debugFrame framesU procs)
-- .aranges section: Information about the bounds of compilation units
let aranges' | gopt Opt_SplitSections df = map mkDwarfARange procs
| otherwise = [DwarfARange lowLabel highLabel]
- let aranges = dwarfARangesSection $$ pprDwarfARanges aranges' unitU
+ let aranges = dwarfARangesSection platform $$ pprDwarfARanges platform aranges' unitU
return (infoSct $$ abbrevSct $$ lineSct $$ frameSct $$ aranges, us'')
@@ -106,17 +107,17 @@ mkDwarfARange proc = DwarfARange start end
-- | Header for a compilation unit, establishing global format
-- parameters
-compileUnitHeader :: Unique -> SDoc
-compileUnitHeader unitU = sdocWithPlatform $ \plat ->
+compileUnitHeader :: Platform -> Unique -> SDoc
+compileUnitHeader platform unitU =
let cuLabel = mkAsmTempLabel unitU -- sits right before initialLength field
length = ppr (mkAsmTempEndLabel cuLabel) <> char '-' <> ppr cuLabel
<> text "-4" -- length of initialLength field
in vcat [ ppr cuLabel <> colon
, text "\t.long " <> length -- compilation unit size
, pprHalf 3 -- DWARF version
- , sectionOffset (ptext dwarfAbbrevLabel) (ptext dwarfAbbrevLabel)
+ , sectionOffset platform (ptext dwarfAbbrevLabel) (ptext dwarfAbbrevLabel)
-- abbrevs offset
- , text "\t.byte " <> ppr (platformWordSizeInBytes plat) -- word size
+ , text "\t.byte " <> ppr (platformWordSizeInBytes platform) -- word size
]
-- | Compilation unit footer, mainly establishing size of debug sections
@@ -176,7 +177,7 @@ parent, B.
-- | Generate DWARF info for a procedure debug block
procToDwarf :: DynFlags -> DebugBlock -> DwarfInfo
procToDwarf df prc
- = DwarfSubprogram { dwChildren = map (blockToDwarf df) (dblBlocks prc)
+ = DwarfSubprogram { dwChildren = map blockToDwarf (dblBlocks prc)
, dwName = case dblSourceTick prc of
Just s@SourceNote{} -> sourceName s
_otherwise -> showSDocDump df $ ppr $ dblLabel prc
@@ -195,10 +196,10 @@ procToDwarf df prc
goodParent _ = True
-- | Generate DWARF info for a block
-blockToDwarf :: DynFlags -> DebugBlock -> DwarfInfo
-blockToDwarf df blk
- = DwarfBlock { dwChildren = concatMap (tickToDwarf df) (dblTicks blk)
- ++ map (blockToDwarf df) (dblBlocks blk)
+blockToDwarf :: DebugBlock -> DwarfInfo
+blockToDwarf blk
+ = DwarfBlock { dwChildren = concatMap tickToDwarf (dblTicks blk)
+ ++ map blockToDwarf (dblBlocks blk)
, dwLabel = dblCLabel blk
, dwMarker = marker
}
@@ -207,9 +208,9 @@ blockToDwarf df blk
| Just _ <- dblPosition blk = Just $ mkAsmTempLabel $ dblLabel blk
| otherwise = Nothing -- block was optimized out
-tickToDwarf :: DynFlags -> Tickish () -> [DwarfInfo]
-tickToDwarf _ (SourceNote ss _) = [DwarfSrcNote ss]
-tickToDwarf _ _ = []
+tickToDwarf :: Tickish () -> [DwarfInfo]
+tickToDwarf (SourceNote ss _) = [DwarfSrcNote ss]
+tickToDwarf _ = []
-- | Generates the data for the debug frame section, which encodes the
-- desired stack unwind behaviour for the debugger
diff --git a/compiler/GHC/CmmToAsm/Dwarf/Constants.hs b/compiler/GHC/CmmToAsm/Dwarf/Constants.hs
index 4ab54b6629..16bdded699 100644
--- a/compiler/GHC/CmmToAsm/Dwarf/Constants.hs
+++ b/compiler/GHC/CmmToAsm/Dwarf/Constants.hs
@@ -144,20 +144,20 @@ dW_OP_call_frame_cfa = 0x9c
-- * Dwarf section declarations
dwarfInfoSection, dwarfAbbrevSection, dwarfLineSection,
- dwarfFrameSection, dwarfGhcSection, dwarfARangesSection :: SDoc
-dwarfInfoSection = dwarfSection "info"
-dwarfAbbrevSection = dwarfSection "abbrev"
-dwarfLineSection = dwarfSection "line"
-dwarfFrameSection = dwarfSection "frame"
-dwarfGhcSection = dwarfSection "ghc"
-dwarfARangesSection = dwarfSection "aranges"
-
-dwarfSection :: String -> SDoc
-dwarfSection name = sdocWithPlatform $ \plat ->
- case platformOS plat of
+ dwarfFrameSection, dwarfGhcSection, dwarfARangesSection :: Platform -> SDoc
+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"
+
+dwarfSection :: Platform -> String -> SDoc
+dwarfSection platform name =
+ case platformOS platform of
os | osElfTarget os
-> text "\t.section .debug_" <> text name <> text ",\"\","
- <> sectionType "progbits"
+ <> sectionType platform "progbits"
| osMachOTarget os
-> text "\t.section __DWARF,__debug_" <> text name <> text ",regular,debug"
| otherwise
diff --git a/compiler/GHC/CmmToAsm/Dwarf/Types.hs b/compiler/GHC/CmmToAsm/Dwarf/Types.hs
index 5eda37a653..c54815aff7 100644
--- a/compiler/GHC/CmmToAsm/Dwarf/Types.hs
+++ b/compiler/GHC/CmmToAsm/Dwarf/Types.hs
@@ -90,8 +90,8 @@ 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 :: Bool -> SDoc
-pprAbbrevDecls haveDebugLine =
+pprAbbrevDecls :: Platform -> Bool -> SDoc
+pprAbbrevDecls platform haveDebugLine =
let mkAbbrev abbr tag chld flds =
let fld (tag, form) = pprLEBWord tag $$ pprLEBWord form
in pprAbbrev abbr $$ pprLEBWord tag $$ pprByte chld $$
@@ -106,7 +106,7 @@ pprAbbrevDecls haveDebugLine =
, (dW_AT_high_pc, dW_FORM_addr)
, (dW_AT_frame_base, dW_FORM_block1)
]
- in dwarfAbbrevSection $$
+ in dwarfAbbrevSection platform $$
ptext dwarfAbbrevLabel <> colon $$
mkAbbrev DwAbbrCompileUnit dW_TAG_compile_unit dW_CHILDREN_yes
([(dW_AT_name, dW_FORM_string)
@@ -142,8 +142,8 @@ pprAbbrevDecls haveDebugLine =
pprByte 0
-- | Generate assembly for DWARF data
-pprDwarfInfo :: Bool -> DwarfInfo -> SDoc
-pprDwarfInfo haveSrc d
+pprDwarfInfo :: Platform -> Bool -> DwarfInfo -> SDoc
+pprDwarfInfo platform haveSrc d
= case d of
DwarfCompileUnit {} -> hasChildren
DwarfSubprogram {} -> hasChildren
@@ -151,36 +151,36 @@ pprDwarfInfo haveSrc d
DwarfSrcNote {} -> noChildren
where
hasChildren =
- pprDwarfInfoOpen haveSrc d $$
- vcat (map (pprDwarfInfo haveSrc) (dwChildren d)) $$
+ pprDwarfInfoOpen platform haveSrc d $$
+ vcat (map (pprDwarfInfo platform haveSrc) (dwChildren d)) $$
pprDwarfInfoClose
- noChildren = pprDwarfInfoOpen haveSrc d
+ noChildren = pprDwarfInfoOpen platform haveSrc d
-- | 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 :: Bool -> DwarfInfo -> SDoc
-pprDwarfInfoOpen haveSrc (DwarfCompileUnit _ name producer compDir lowLabel
+pprDwarfInfoOpen :: Platform -> Bool -> DwarfInfo -> SDoc
+pprDwarfInfoOpen platform haveSrc (DwarfCompileUnit _ name producer compDir lowLabel
highLabel lineLbl) =
pprAbbrev DwAbbrCompileUnit
$$ pprString name
$$ pprString producer
$$ pprData4 dW_LANG_Haskell
$$ pprString compDir
- $$ pprWord (ppr lowLabel)
- $$ pprWord (ppr highLabel)
+ $$ pprWord platform (ppr lowLabel)
+ $$ pprWord platform (ppr highLabel)
$$ if haveSrc
- then sectionOffset (ptext lineLbl) (ptext dwarfLineLabel)
+ then sectionOffset platform (ptext lineLbl) (ptext dwarfLineLabel)
else empty
-pprDwarfInfoOpen _ (DwarfSubprogram _ name label
+pprDwarfInfoOpen platform _ (DwarfSubprogram _ name label
parent) = sdocWithDynFlags $ \df ->
ppr (mkAsmTempDieLabel label) <> colon
$$ pprAbbrev abbrev
$$ pprString name
$$ pprString (renderWithStyle (initSDocContext df (mkCodeStyle CStyle)) (ppr label))
$$ pprFlag (externallyVisibleCLabel label)
- $$ pprWord (ppr label)
- $$ pprWord (ppr $ mkAsmTempEndLabel label)
+ $$ pprWord platform (ppr label)
+ $$ pprWord platform (ppr $ mkAsmTempEndLabel label)
$$ pprByte 1
$$ pprByte dW_OP_call_frame_cfa
$$ parentValue
@@ -188,18 +188,18 @@ pprDwarfInfoOpen _ (DwarfSubprogram _ name label
abbrev = case parent of Nothing -> DwAbbrSubprogram
Just _ -> DwAbbrSubprogramWithParent
parentValue = maybe empty pprParentDie parent
- pprParentDie sym = sectionOffset (ppr sym) (ptext dwarfInfoLabel)
-pprDwarfInfoOpen _ (DwarfBlock _ label Nothing) = sdocWithDynFlags $ \df ->
+ pprParentDie sym = sectionOffset platform (ppr sym) (ptext dwarfInfoLabel)
+pprDwarfInfoOpen _ _ (DwarfBlock _ label Nothing) = sdocWithDynFlags $ \df ->
ppr (mkAsmTempDieLabel label) <> colon
$$ pprAbbrev DwAbbrBlockWithoutCode
$$ pprString (renderWithStyle (initSDocContext df (mkCodeStyle CStyle)) (ppr label))
-pprDwarfInfoOpen _ (DwarfBlock _ label (Just marker)) = sdocWithDynFlags $ \df ->
+pprDwarfInfoOpen platform _ (DwarfBlock _ label (Just marker)) = sdocWithDynFlags $ \df ->
ppr (mkAsmTempDieLabel label) <> colon
$$ pprAbbrev DwAbbrBlock
$$ pprString (renderWithStyle (initSDocContext df (mkCodeStyle CStyle)) (ppr label))
- $$ pprWord (ppr marker)
- $$ pprWord (ppr $ mkAsmTempEndLabel marker)
-pprDwarfInfoOpen _ (DwarfSrcNote ss) =
+ $$ pprWord platform (ppr marker)
+ $$ pprWord platform (ppr $ mkAsmTempEndLabel marker)
+pprDwarfInfoOpen _ _ (DwarfSrcNote ss) =
pprAbbrev DwAbbrGhcSrcNote
$$ pprString' (ftext $ srcSpanFile ss)
$$ pprData4 (fromIntegral $ srcSpanStartLine ss)
@@ -222,9 +222,9 @@ data DwarfARange
-- | Print assembler directives corresponding to a DWARF @.debug_aranges@
-- address table entry.
-pprDwarfARanges :: [DwarfARange] -> Unique -> SDoc
-pprDwarfARanges arngs unitU = sdocWithPlatform $ \plat ->
- let wordSize = platformWordSizeInBytes plat
+pprDwarfARanges :: Platform -> [DwarfARange] -> Unique -> SDoc
+pprDwarfARanges platform arngs unitU =
+ let wordSize = platformWordSizeInBytes platform
paddingSize = 4 :: Int
-- header is 12 bytes long.
-- entry is 8 bytes (32-bit platform) or 16 bytes (64-bit platform).
@@ -234,19 +234,19 @@ pprDwarfARanges arngs unitU = sdocWithPlatform $ \plat ->
initialLength = 8 + paddingSize + (1 + length arngs) * 2 * wordSize
in pprDwWord (ppr initialLength)
$$ pprHalf 2
- $$ sectionOffset (ppr $ mkAsmTempLabel $ unitU)
- (ptext dwarfInfoLabel)
+ $$ sectionOffset platform (ppr $ mkAsmTempLabel $ unitU)
+ (ptext dwarfInfoLabel)
$$ pprByte (fromIntegral wordSize)
$$ pprByte 0
$$ pad paddingSize
-- body
- $$ vcat (map pprDwarfARange arngs)
+ $$ vcat (map (pprDwarfARange platform) arngs)
-- terminus
- $$ pprWord (char '0')
- $$ pprWord (char '0')
+ $$ pprWord platform (char '0')
+ $$ pprWord platform (char '0')
-pprDwarfARange :: DwarfARange -> SDoc
-pprDwarfARange arng = pprWord (ppr $ dwArngStartLabel arng) $$ pprWord length
+pprDwarfARange :: Platform -> DwarfARange -> SDoc
+pprDwarfARange platform arng = pprWord platform (ppr $ dwArngStartLabel arng) $$ pprWord platform length
where
length = ppr (dwArngEndLabel arng)
<> char '-' <> ppr (dwArngStartLabel arng)
@@ -286,21 +286,20 @@ instance Outputable 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 :: DwarfFrame -> SDoc
-pprDwarfFrame DwarfFrame{dwCieLabel=cieLabel,dwCieInit=cieInit,dwCieProcs=procs}
- = sdocWithPlatform $ \plat ->
- let cieStartLabel= mkAsmTempDerivedLabel cieLabel (fsLit "_start")
+pprDwarfFrame :: Platform -> DwarfFrame -> SDoc
+pprDwarfFrame platform DwarfFrame{dwCieLabel=cieLabel,dwCieInit=cieInit,dwCieProcs=procs}
+ = let cieStartLabel= mkAsmTempDerivedLabel cieLabel (fsLit "_start")
cieEndLabel = mkAsmTempEndLabel cieLabel
length = ppr cieEndLabel <> char '-' <> ppr cieStartLabel
- spReg = dwarfGlobalRegNo plat Sp
- retReg = dwarfReturnRegNo plat
- wordSize = platformWordSizeInBytes plat
+ spReg = dwarfGlobalRegNo platform Sp
+ retReg = dwarfReturnRegNo platform
+ wordSize = platformWordSizeInBytes platform
pprInit :: (GlobalReg, Maybe UnwindExpr) -> SDoc
- pprInit (g, uw) = pprSetUnwind plat g (Nothing, uw)
+ pprInit (g, uw) = pprSetUnwind platform g (Nothing, uw)
-- Preserve C stack pointer: This necessary to override that default
-- unwinding behavior of setting $sp = CFA.
- preserveSp = case platformArch plat of
+ preserveSp = case platformArch platform of
ArchX86 -> pprByte dW_CFA_same_value $$ pprLEBWord 4
ArchX86_64 -> pprByte dW_CFA_same_value $$ pprLEBWord 7
_ -> empty
@@ -333,16 +332,16 @@ pprDwarfFrame DwarfFrame{dwCieLabel=cieLabel,dwCieInit=cieInit,dwCieProcs=procs}
, pprLEBWord (fromIntegral spReg)
, pprLEBWord 0
] $$
- wordAlign $$
+ wordAlign platform $$
ppr cieEndLabel <> colon $$
-- Procedure unwind tables
- vcat (map (pprFrameProc cieLabel cieInit) procs)
+ vcat (map (pprFrameProc platform cieLabel cieInit) procs)
-- | 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 :: CLabel -> UnwindTable -> DwarfFrameProc -> SDoc
-pprFrameProc frameLbl initUw (DwarfFrameProc procLbl hasInfo blocks)
+pprFrameProc :: Platform -> CLabel -> UnwindTable -> DwarfFrameProc -> SDoc
+pprFrameProc platform frameLbl initUw (DwarfFrameProc procLbl hasInfo blocks)
= let fdeLabel = mkAsmTempDerivedLabel procLbl (fsLit "_fde")
fdeEndLabel = mkAsmTempDerivedLabel procLbl (fsLit "_fde_end")
procEnd = mkAsmTempEndLabel procLbl
@@ -353,20 +352,20 @@ pprFrameProc frameLbl initUw (DwarfFrameProc procLbl hasInfo blocks)
, ppr fdeLabel <> colon
, pprData4' (ppr frameLbl <> char '-' <>
ptext dwarfFrameLabel) -- Reference to CIE
- , pprWord (ppr procLbl <> ifInfo "-1") -- Code pointer
- , pprWord (ppr procEnd <> char '-' <>
- ppr procLbl <> ifInfo "+1") -- Block byte length
+ , pprWord platform (ppr procLbl <> ifInfo "-1") -- Code pointer
+ , pprWord platform (ppr procEnd <> char '-' <>
+ ppr procLbl <> ifInfo "+1") -- Block byte length
] $$
- vcat (S.evalState (mapM pprFrameBlock blocks) initUw) $$
- wordAlign $$
+ vcat (S.evalState (mapM (pprFrameBlock platform) blocks) initUw) $$
+ wordAlign platform $$
ppr 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 :: DwarfFrameBlock -> S.State UnwindTable SDoc
-pprFrameBlock (DwarfFrameBlock hasInfo uws0) =
+pprFrameBlock :: Platform -> DwarfFrameBlock -> S.State UnwindTable SDoc
+pprFrameBlock platform (DwarfFrameBlock hasInfo uws0) =
vcat <$> zipWithM pprFrameDecl (True : repeat False) uws0
where
pprFrameDecl :: Bool -> UnwindPoint -> S.State UnwindTable SDoc
@@ -393,9 +392,8 @@ pprFrameBlock (DwarfFrameBlock hasInfo uws0) =
needsOffset = firstDecl && hasInfo
lblDoc = ppr lbl <>
if needsOffset then text "-1" else empty
- doc = sdocWithPlatform $ \plat ->
- pprByte dW_CFA_set_loc $$ pprWord lblDoc $$
- vcat (map (uncurry $ pprSetUnwind plat) changed)
+ doc = pprByte dW_CFA_set_loc $$ pprWord platform lblDoc $$
+ vcat (map (uncurry $ pprSetUnwind platform) changed)
in (doc, uws)
-- Note [Info Offset]
@@ -452,8 +450,8 @@ pprSetUnwind plat Sp (_, Just (UwReg s' o'))
else pprByte dW_CFA_def_cfa_sf $$
pprLEBRegNo plat s' $$
pprLEBInt o'
-pprSetUnwind _ Sp (_, Just uw)
- = pprByte dW_CFA_def_cfa_expression $$ pprUnwindExpr False uw
+pprSetUnwind plat Sp (_, Just uw)
+ = pprByte dW_CFA_def_cfa_expression $$ pprUnwindExpr plat False uw
pprSetUnwind plat g (_, Just (UwDeref (UwReg Sp o)))
| o < 0 && ((-o) `mod` platformWordSizeInBytes plat) == 0 -- expected case
= pprByte (dW_CFA_offset + dwarfGlobalRegNo plat g) $$
@@ -465,7 +463,7 @@ pprSetUnwind plat g (_, Just (UwDeref (UwReg Sp o)))
pprSetUnwind plat g (_, Just (UwDeref uw))
= pprByte dW_CFA_expression $$
pprLEBRegNo plat g $$
- pprUnwindExpr True uw
+ pprUnwindExpr plat True uw
pprSetUnwind plat g (_, Just (UwReg g' 0))
| g == g'
= pprByte dW_CFA_same_value $$
@@ -473,7 +471,7 @@ pprSetUnwind plat g (_, Just (UwReg g' 0))
pprSetUnwind plat g (_, Just uw)
= pprByte dW_CFA_val_expression $$
pprLEBRegNo plat g $$
- pprUnwindExpr True uw
+ pprUnwindExpr plat True uw
-- | Print the register number of the given 'GlobalReg' as an unsigned LEB128
-- encoded number.
@@ -483,20 +481,19 @@ 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 :: Bool -> UnwindExpr -> SDoc
-pprUnwindExpr spIsCFA expr
- = sdocWithPlatform $ \plat ->
- let pprE (UwConst i)
+pprUnwindExpr :: Platform -> Bool -> UnwindExpr -> SDoc
+pprUnwindExpr platform spIsCFA expr
+ = let pprE (UwConst i)
| i >= 0 && i < 32 = pprByte (dW_OP_lit0 + fromIntegral i)
| otherwise = pprByte dW_OP_consts $$ pprLEBInt i -- lazy...
pprE (UwReg Sp i) | spIsCFA
= if i == 0
then pprByte dW_OP_call_frame_cfa
else pprE (UwPlus (UwReg Sp 0) (UwConst i))
- pprE (UwReg g i) = pprByte (dW_OP_breg0+dwarfGlobalRegNo plat g) $$
+ pprE (UwReg g i) = pprByte (dW_OP_breg0+dwarfGlobalRegNo platform g) $$
pprLEBInt i
pprE (UwDeref u) = pprE u $$ pprByte dW_OP_deref
- pprE (UwLabel l) = pprByte dW_OP_addr $$ pprWord (ppr l)
+ pprE (UwLabel l) = pprByte dW_OP_addr $$ pprWord platform (ppr l)
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
@@ -514,8 +511,8 @@ pprUndefUnwind plat g = pprByte dW_CFA_undefined $$
-- | Align assembly at (machine) word boundary
-wordAlign :: SDoc
-wordAlign = sdocWithPlatform $ \plat ->
+wordAlign :: Platform -> SDoc
+wordAlign plat =
text "\t.align " <> case platformOS plat of
OSDarwin -> case platformWordSize plat of
PW8 -> char '3'
@@ -549,11 +546,11 @@ pprDwWord = pprData4'
-- | Assembly for a machine word of dynamic data. Depends on the
-- architecture we are currently generating code for.
-pprWord :: SDoc -> SDoc
-pprWord s = (<> s) . sdocWithPlatform $ \plat ->
+pprWord :: Platform -> SDoc -> SDoc
+pprWord plat s =
case platformWordSize plat of
- PW4 -> text "\t.long "
- PW8 -> text "\t.quad "
+ PW4 -> text "\t.long " <> s
+ PW8 -> text "\t.quad " <> s
-- | Prints a number in "little endian base 128" format. The idea is
-- to optimize for small numbers by stopping once all further bytes
@@ -604,8 +601,8 @@ 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 :: SDoc -> SDoc -> SDoc
-sectionOffset target section = sdocWithPlatform $ \plat ->
+sectionOffset :: Platform -> SDoc -> SDoc -> SDoc
+sectionOffset plat target section =
case platformOS plat of
OSDarwin -> pprDwWord (target <> char '-' <> section)
OSMinGW32 -> text "\t.secrel32 " <> target
diff --git a/compiler/GHC/CmmToAsm/Instr.hs b/compiler/GHC/CmmToAsm/Instr.hs
index 44fa9b7cc9..01f703340b 100644
--- a/compiler/GHC/CmmToAsm/Instr.hs
+++ b/compiler/GHC/CmmToAsm/Instr.hs
@@ -16,14 +16,15 @@ where
import GhcPrelude
+import GHC.Platform
import GHC.Platform.Reg
import GHC.Cmm.BlockId
import GHC.Cmm.Dataflow.Collections
import GHC.Cmm.Dataflow.Label
-import GHC.Driver.Session
import GHC.Cmm hiding (topInfoTable)
-import GHC.Platform
+
+import GHC.CmmToAsm.Config
-- | Holds a list of source and destination registers used by a
-- particular instruction.
@@ -132,7 +133,7 @@ class Instruction instr where
-- | An instruction to spill a register into a spill slot.
mkSpillInstr
- :: DynFlags
+ :: NCGConfig
-> Reg -- ^ the reg to spill
-> Int -- ^ the current stack delta
-> Int -- ^ spill slot to use
@@ -141,7 +142,7 @@ class Instruction instr where
-- | An instruction to reload a register from a spill slot.
mkLoadInstr
- :: DynFlags
+ :: NCGConfig
-> Reg -- ^ the reg to reload.
-> Int -- ^ the current stack delta
-> Int -- ^ the spill slot to use
diff --git a/compiler/GHC/CmmToAsm/Monad.hs b/compiler/GHC/CmmToAsm/Monad.hs
index c9414a2eee..89e64d5e79 100644
--- a/compiler/GHC/CmmToAsm/Monad.hs
+++ b/compiler/GHC/CmmToAsm/Monad.hs
@@ -16,6 +16,7 @@ module GHC.CmmToAsm.Monad (
NatM, -- instance Monad
initNat,
+ initConfig,
addImportNat,
addNodeBetweenNat,
addImmediateSuccessorNat,
@@ -23,6 +24,8 @@ module GHC.CmmToAsm.Monad (
getUniqueNat,
mapAccumLNat,
setDeltaNat,
+ getConfig,
+ getPlatform,
getDeltaNat,
getThisModuleNat,
getBlockIdNat,
@@ -45,9 +48,11 @@ where
import GhcPrelude
+import GHC.Platform
import GHC.Platform.Reg
import GHC.CmmToAsm.Format
import GHC.CmmToAsm.Reg.Target
+import GHC.CmmToAsm.Config
import GHC.Cmm.BlockId
import GHC.Cmm.Dataflow.Collections
@@ -69,6 +74,7 @@ import GHC.Cmm (RawCmmDecl, RawCmmStatics)
import GHC.CmmToAsm.CFG
data NcgImpl statics instr jumpDest = NcgImpl {
+ ncgConfig :: !NCGConfig,
cmmTopCodeGen :: RawCmmDecl -> NatM [NatCmmDecl statics instr],
generateJumpTableForInstr :: instr -> Maybe (NatCmmDecl statics instr),
getJumpDestBlockId :: jumpDest -> Maybe BlockId,
@@ -102,6 +108,7 @@ data NatM_State
natm_imports :: [(CLabel)],
natm_pic :: Maybe Reg,
natm_dflags :: DynFlags,
+ natm_config :: NCGConfig,
natm_this_module :: Module,
natm_modloc :: ModLocation,
natm_fileid :: DwarfFiles,
@@ -130,6 +137,7 @@ mkNatM_State us delta dflags this_mod
, natm_imports = []
, natm_pic = Nothing
, natm_dflags = dflags
+ , natm_config = initConfig dflags
, natm_this_module = this_mod
, natm_modloc = loc
, natm_fileid = dwf
@@ -137,6 +145,24 @@ mkNatM_State us delta dflags this_mod
, natm_cfg = cfg
}
+-- | Initialize the native code generator configuration from the DynFlags
+initConfig :: DynFlags -> NCGConfig
+initConfig dflags = NCGConfig
+ { ncgPlatform = targetPlatform dflags
+ , ncgProcAlignment = cmmProcAlignment dflags
+ , ncgDebugLevel = debugLevel dflags
+ , ncgExternalDynamicRefs = gopt Opt_ExternalDynamicRefs dflags
+ , ncgPIC = positionIndependent dflags
+ , ncgSplitSections = gopt Opt_SplitSections dflags
+ , ncgSpillPreallocSize = rESERVED_C_STACK_BYTES dflags
+ , ncgRegsIterative = gopt Opt_RegsIterative dflags
+ , ncgAsmLinting = gopt Opt_DoAsmLinting dflags
+ , ncgDumpRegAllocStages = dopt Opt_D_dump_asm_regalloc_stages dflags
+ , ncgDumpAsmStats = dopt Opt_D_dump_asm_stats dflags
+ , ncgDumpAsmConflicts = dopt Opt_D_dump_asm_conflicts dflags
+ }
+
+
initNat :: NatM_State -> NatM a -> (a, NatM_State)
initNat init_st m
= case unNat m init_st of { (r,st) -> (r,st) }
@@ -232,8 +258,9 @@ addNodeBetweenNat from between to
-- | Place `succ` after `block` and change any edges
-- block -> X to `succ` -> X
addImmediateSuccessorNat :: BlockId -> BlockId -> NatM ()
-addImmediateSuccessorNat block succ
- = updateCfgNat (addImmediateSuccessor block succ)
+addImmediateSuccessorNat block succ = do
+ dflags <- getDynFlags
+ updateCfgNat (addImmediateSuccessor dflags block succ)
getBlockIdNat :: NatM BlockId
getBlockIdNat
@@ -249,16 +276,16 @@ getNewLabelNat
getNewRegNat :: Format -> NatM Reg
getNewRegNat rep
= do u <- getUniqueNat
- dflags <- getDynFlags
- return (RegVirtual $ targetMkVirtualReg (targetPlatform dflags) u rep)
+ platform <- getPlatform
+ return (RegVirtual $ targetMkVirtualReg platform u rep)
getNewRegPairNat :: Format -> NatM (Reg,Reg)
getNewRegPairNat rep
= do u <- getUniqueNat
- dflags <- getDynFlags
- let vLo = targetMkVirtualReg (targetPlatform dflags) u rep
- let lo = RegVirtual $ targetMkVirtualReg (targetPlatform dflags) u rep
+ platform <- getPlatform
+ let vLo = targetMkVirtualReg platform u rep
+ let lo = RegVirtual $ targetMkVirtualReg platform u rep
let hi = RegVirtual $ getHiVirtualRegFromLo vLo
return (lo, hi)
@@ -282,6 +309,14 @@ getModLoc :: NatM ModLocation
getModLoc
= NatM $ \ st -> (natm_modloc st, st)
+-- | Get native code generator configuration
+getConfig :: NatM NCGConfig
+getConfig = NatM $ \st -> (natm_config st, st)
+
+-- | Get target platform from native code generator configuration
+getPlatform :: NatM Platform
+getPlatform = ncgPlatform <$> getConfig
+
getFileId :: FastString -> NatM Int
getFileId f = NatM $ \st ->
case lookupUFM (natm_fileid st) f of
diff --git a/compiler/GHC/CmmToAsm/PIC.hs b/compiler/GHC/CmmToAsm/PIC.hs
index 323d93d173..d4d8b55e7e 100644
--- a/compiler/GHC/CmmToAsm/PIC.hs
+++ b/compiler/GHC/CmmToAsm/PIC.hs
@@ -57,6 +57,7 @@ import GHC.Platform
import GHC.CmmToAsm.Instr
import GHC.Platform.Reg
import GHC.CmmToAsm.Monad
+import GHC.CmmToAsm.Config
import GHC.Cmm.Dataflow.Collections
@@ -163,7 +164,7 @@ cmmMakePicReference dflags lbl
| OSAIX <- platformOS $ targetPlatform dflags
= CmmMachOp (MO_Add W32)
[ CmmReg (CmmGlobal PicBaseReg)
- , CmmLit $ picRelative dflags
+ , CmmLit $ picRelative (wordWidth dflags)
(platformArch $ targetPlatform dflags)
(platformOS $ targetPlatform dflags)
lbl ]
@@ -172,7 +173,7 @@ cmmMakePicReference dflags lbl
| ArchPPC_64 _ <- platformArch $ targetPlatform dflags
= CmmMachOp (MO_Add W32) -- code model medium
[ CmmReg (CmmGlobal PicBaseReg)
- , CmmLit $ picRelative dflags
+ , CmmLit $ picRelative (wordWidth dflags)
(platformArch $ targetPlatform dflags)
(platformOS $ targetPlatform dflags)
lbl ]
@@ -181,7 +182,7 @@ cmmMakePicReference dflags lbl
&& absoluteLabel lbl
= CmmMachOp (MO_Add (wordWidth dflags))
[ CmmReg (CmmGlobal PicBaseReg)
- , CmmLit $ picRelative dflags
+ , CmmLit $ picRelative (wordWidth dflags)
(platformArch $ targetPlatform dflags)
(platformOS $ targetPlatform dflags)
lbl ]
@@ -404,7 +405,7 @@ howToAccessLabel dflags _ _ _ _ _
-- | Says what we have to add to our 'PIC base register' in order to
-- get the address of a label.
-picRelative :: DynFlags -> Arch -> OS -> CLabel -> CmmLit
+picRelative :: Width -> Arch -> OS -> CLabel -> CmmLit
-- Darwin, but not x86_64:
-- The PIC base register points to the PIC base label at the beginning
@@ -413,15 +414,15 @@ picRelative :: DynFlags -> Arch -> OS -> CLabel -> CmmLit
-- We have already made sure that all labels that are not from the current
-- module are accessed indirectly ('as' can't calculate differences between
-- undefined labels).
-picRelative dflags arch OSDarwin lbl
+picRelative width arch OSDarwin lbl
| arch /= ArchX86_64
- = CmmLabelDiffOff lbl mkPicBaseLabel 0 (wordWidth dflags)
+ = CmmLabelDiffOff lbl mkPicBaseLabel 0 width
-- On AIX we use an indirect local TOC anchored by 'gotLabel'.
-- This way we use up only one global TOC entry per compilation-unit
-- (this is quite similar to GCC's @-mminimal-toc@ compilation mode)
-picRelative dflags _ OSAIX lbl
- = CmmLabelDiffOff lbl gotLabel 0 (wordWidth dflags)
+picRelative width _ OSAIX lbl
+ = CmmLabelDiffOff lbl gotLabel 0 width
-- PowerPC Linux:
-- The PIC base register points to our fake GOT. Use a label difference
@@ -429,9 +430,9 @@ picRelative dflags _ OSAIX lbl
-- We have made sure that *everything* is accessed indirectly, so this
-- is only used for offsets from the GOT to symbol pointers inside the
-- GOT.
-picRelative dflags ArchPPC os lbl
+picRelative width ArchPPC os lbl
| osElfTarget os
- = CmmLabelDiffOff lbl gotLabel 0 (wordWidth dflags)
+ = CmmLabelDiffOff lbl gotLabel 0 width
-- Most Linux versions:
@@ -453,14 +454,14 @@ picRelative _ arch os lbl
in result
picRelative _ _ _ _
- = panic "PositionIndependentCode.picRelative undefined for this platform"
+ = panic "GHC.CmmToAsm.PIC.picRelative undefined for this platform"
--------------------------------------------------------------------------------
-needImportedSymbols :: DynFlags -> Arch -> OS -> Bool
-needImportedSymbols dflags arch os
+needImportedSymbols :: NCGConfig -> Bool
+needImportedSymbols config
| os == OSDarwin
, arch /= ArchX86_64
= True
@@ -471,7 +472,7 @@ needImportedSymbols dflags arch os
-- PowerPC Linux: -fPIC or -dynamic
| osElfTarget os
, arch == ArchPPC
- = positionIndependent dflags || gopt Opt_ExternalDynamicRefs dflags
+ = ncgPIC config || ncgExternalDynamicRefs config
-- PowerPC 64 Linux: always
| osElfTarget os
@@ -481,11 +482,15 @@ needImportedSymbols dflags arch os
-- i386 (and others?): -dynamic but not -fPIC
| osElfTarget os
, arch /= ArchPPC_64 ELF_V1 && arch /= ArchPPC_64 ELF_V2
- = gopt Opt_ExternalDynamicRefs dflags &&
- not (positionIndependent dflags)
+ = ncgExternalDynamicRefs config &&
+ not (ncgPIC config)
| otherwise
= False
+ where
+ platform = ncgPlatform config
+ arch = platformArch platform
+ os = platformOS platform
-- gotLabel
-- The label used to refer to our "fake GOT" from
@@ -499,13 +504,16 @@ gotLabel
---------------------------------------------------------------------------------
+-- Emit GOT declaration
+-- Output whatever needs to be output once per .s file.
+--
-- We don't need to declare any offset tables.
-- However, for PIC on x86, we need a small helper function.
-pprGotDeclaration :: DynFlags -> Arch -> OS -> SDoc
-pprGotDeclaration dflags ArchX86 OSDarwin
- | positionIndependent dflags
- = vcat [
+pprGotDeclaration :: NCGConfig -> SDoc
+pprGotDeclaration config = case (arch,os) of
+ (ArchX86, OSDarwin)
+ | ncgPIC config
+ -> vcat [
text ".section __TEXT,__textcoal_nt,coalesced,no_toc",
text ".weak_definition ___i686.get_pc_thunk.ax",
text ".private_extern ___i686.get_pc_thunk.ax",
@@ -513,48 +521,49 @@ pprGotDeclaration dflags ArchX86 OSDarwin
text "\tmovl (%esp), %eax",
text "\tret" ]
-pprGotDeclaration _ _ OSDarwin
- = empty
-
--- Emit XCOFF TOC section
-pprGotDeclaration _ _ 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"
- ]
-
-
--- PPC 64 ELF v1 needs a Table Of Contents (TOC)
-pprGotDeclaration _ (ArchPPC_64 ELF_V1) _
- = 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.
-pprGotDeclaration _ (ArchPPC_64 ELF_V2) _
- = vcat [ text ".abiversion 2",
- text ".section \".toc\",\"aw\""
- ]
+ (_, OSDarwin) -> empty
--- Emit GOT declaration
--- Output whatever needs to be output once per .s file.
-pprGotDeclaration dflags arch os
+ -- 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"
+ ]
+
+
+ -- PPC 64 ELF v1 needs a Table Of Contents (TOC)
+ (ArchPPC_64 ELF_V1, _)
+ -> 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\""
+ ]
+
+ (arch, os)
| osElfTarget os
, arch /= ArchPPC_64 ELF_V1 && arch /= ArchPPC_64 ELF_V2
- , not (positionIndependent dflags)
- = empty
+ , not (ncgPIC config)
+ -> empty
| osElfTarget os
, arch /= ArchPPC_64 ELF_V1 && arch /= ArchPPC_64 ELF_V2
- = vcat [
+ -> vcat [
-- See Note [.LCTOC1 in PPC PIC code]
text ".section \".got2\",\"aw\"",
text ".LCTOC1 = .+32768" ]
-pprGotDeclaration _ _ _
- = panic "pprGotDeclaration: no match"
+ _ -> panic "pprGotDeclaration: no match"
+ where
+ platform = ncgPlatform config
+ arch = platformArch platform
+ os = platformOS platform
--------------------------------------------------------------------------------
@@ -563,43 +572,44 @@ pprGotDeclaration _ _ _
-- and one for non-PIC.
--
-pprImportedSymbol :: DynFlags -> Platform -> CLabel -> SDoc
-pprImportedSymbol dflags (Platform { platformMini = PlatformMini { platformMini_arch = ArchX86, platformMini_os = OSDarwin } }) importedLbl
+pprImportedSymbol :: DynFlags -> NCGConfig -> CLabel -> SDoc
+pprImportedSymbol dflags config importedLbl = case (arch,os) of
+ (ArchX86, OSDarwin)
| Just (CodeStub, lbl) <- dynamicLinkerLabelInfo importedLbl
- = case positionIndependent dflags of
- False ->
- vcat [
- text ".symbol_stub",
- text "L" <> pprCLabel dflags lbl <> ptext (sLit "$stub:"),
- text "\t.indirect_symbol" <+> pprCLabel dflags lbl,
- text "\tjmp *L" <> pprCLabel dflags lbl
- <> text "$lazy_ptr",
- text "L" <> pprCLabel dflags lbl
- <> text "$stub_binder:",
- text "\tpushl $L" <> pprCLabel dflags lbl
- <> text "$lazy_ptr",
- text "\tjmp dyld_stub_binding_helper"
- ]
- True ->
- vcat [
- text ".section __TEXT,__picsymbolstub2,"
- <> text "symbol_stubs,pure_instructions,25",
- text "L" <> pprCLabel dflags lbl <> ptext (sLit "$stub:"),
- text "\t.indirect_symbol" <+> pprCLabel dflags lbl,
- text "\tcall ___i686.get_pc_thunk.ax",
- text "1:",
- text "\tmovl L" <> pprCLabel dflags lbl
- <> text "$lazy_ptr-1b(%eax),%edx",
- text "\tjmp *%edx",
- text "L" <> pprCLabel dflags lbl
- <> text "$stub_binder:",
- text "\tlea L" <> pprCLabel dflags lbl
- <> text "$lazy_ptr-1b(%eax),%eax",
- text "\tpushl %eax",
- text "\tjmp dyld_stub_binding_helper"
- ]
- $+$ vcat [ text ".section __DATA, __la_sym_ptr"
- <> (if positionIndependent dflags then int 2 else int 3)
+ -> if not pic
+ then
+ vcat [
+ text ".symbol_stub",
+ text "L" <> pprCLabel dflags lbl <> ptext (sLit "$stub:"),
+ text "\t.indirect_symbol" <+> pprCLabel dflags lbl,
+ text "\tjmp *L" <> pprCLabel dflags lbl
+ <> text "$lazy_ptr",
+ text "L" <> pprCLabel dflags lbl
+ <> text "$stub_binder:",
+ text "\tpushl $L" <> pprCLabel dflags lbl
+ <> text "$lazy_ptr",
+ text "\tjmp dyld_stub_binding_helper"
+ ]
+ else
+ vcat [
+ text ".section __TEXT,__picsymbolstub2,"
+ <> text "symbol_stubs,pure_instructions,25",
+ text "L" <> pprCLabel dflags lbl <> ptext (sLit "$stub:"),
+ text "\t.indirect_symbol" <+> pprCLabel dflags lbl,
+ text "\tcall ___i686.get_pc_thunk.ax",
+ text "1:",
+ text "\tmovl L" <> pprCLabel dflags lbl
+ <> text "$lazy_ptr-1b(%eax),%edx",
+ text "\tjmp *%edx",
+ text "L" <> pprCLabel dflags lbl
+ <> text "$stub_binder:",
+ text "\tlea L" <> pprCLabel dflags lbl
+ <> text "$lazy_ptr-1b(%eax),%eax",
+ text "\tpushl %eax",
+ text "\tjmp dyld_stub_binding_helper"
+ ]
+ $+$ vcat [ text ".section __DATA, __la_sym_ptr"
+ <> (if pic then int 2 else int 3)
<> text ",lazy_symbol_pointers",
text "L" <> pprCLabel dflags lbl <> ptext (sLit "$lazy_ptr:"),
text "\t.indirect_symbol" <+> pprCLabel dflags lbl,
@@ -607,71 +617,68 @@ pprImportedSymbol dflags (Platform { platformMini = PlatformMini { platformMini_
<> text "$stub_binder"]
| Just (SymbolPtr, lbl) <- dynamicLinkerLabelInfo importedLbl
- = vcat [
+ -> vcat [
text ".non_lazy_symbol_pointer",
char 'L' <> pprCLabel dflags lbl <> text "$non_lazy_ptr:",
text "\t.indirect_symbol" <+> pprCLabel dflags lbl,
text "\t.long\t0"]
| otherwise
- = empty
+ -> empty
+ (_, OSDarwin) -> empty
-pprImportedSymbol _ (Platform { platformMini = PlatformMini { platformMini_os = OSDarwin } }) _
- = empty
--- XCOFF / AIX
---
--- Similar to PPC64 ELF v1, there's dedicated TOC register (r2). To
--- workaround the limitation of a global TOC we use an indirect TOC
--- with the label `ghc_toc_table`.
---
--- See also GCC's `-mminimal-toc` compilation mode or
--- http://www.ibm.com/developerworks/rational/library/overview-toc-aix/
---
--- NB: No DSO-support yet
+ -- XCOFF / AIX
+ --
+ -- Similar to PPC64 ELF v1, there's dedicated TOC register (r2). To
+ -- workaround the limitation of a global TOC we use an indirect TOC
+ -- with the label `ghc_toc_table`.
+ --
+ -- See also GCC's `-mminimal-toc` compilation mode or
+ -- http://www.ibm.com/developerworks/rational/library/overview-toc-aix/
+ --
+ -- NB: No DSO-support yet
-pprImportedSymbol dflags (Platform { platformMini = PlatformMini { platformMini_os = OSAIX } }) importedLbl
- = case dynamicLinkerLabelInfo importedLbl of
+ (_, OSAIX) -> case dynamicLinkerLabelInfo importedLbl of
Just (SymbolPtr, lbl)
-> vcat [
text "LC.." <> pprCLabel dflags lbl <> char ':',
text "\t.long" <+> pprCLabel dflags lbl ]
_ -> empty
--- ELF / Linux
---
--- In theory, we don't need to generate any stubs or symbol pointers
--- by hand for Linux.
---
--- Reality differs from this in two areas.
---
--- 1) If we just use a dynamically imported symbol directly in a read-only
--- section of the main executable (as GCC does), ld generates R_*_COPY
--- relocations, which are fundamentally incompatible with reversed info
--- tables. Therefore, we need a table of imported addresses in a writable
--- section.
--- The "official" GOT mechanism (label@got) isn't intended to be used
--- in position dependent code, so we have to create our own "fake GOT"
--- when not Opt_PIC && WayDyn `elem` ways dflags.
---
--- 2) PowerPC Linux is just plain broken.
--- While it's theoretically possible to use GOT offsets larger
--- than 16 bit, the standard crt*.o files don't, which leads to
--- linker errors as soon as the GOT size exceeds 16 bit.
--- Also, the assembler doesn't support @gotoff labels.
--- In order to be able to use a larger GOT, we have to circumvent the
--- entire GOT mechanism and do it ourselves (this is also what GCC does).
-
-
--- When needImportedSymbols is defined,
--- the NCG will keep track of all DynamicLinkerLabels it uses
--- and output each of them using pprImportedSymbol.
-
-pprImportedSymbol dflags platform@(Platform { platformMini = PlatformMini { platformMini_arch = ArchPPC_64 _ } })
- importedLbl
- | osElfTarget (platformOS platform)
- = case dynamicLinkerLabelInfo importedLbl of
+ -- ELF / Linux
+ --
+ -- In theory, we don't need to generate any stubs or symbol pointers
+ -- by hand for Linux.
+ --
+ -- Reality differs from this in two areas.
+ --
+ -- 1) If we just use a dynamically imported symbol directly in a read-only
+ -- section of the main executable (as GCC does), ld generates R_*_COPY
+ -- relocations, which are fundamentally incompatible with reversed info
+ -- tables. Therefore, we need a table of imported addresses in a writable
+ -- section.
+ -- The "official" GOT mechanism (label@got) isn't intended to be used
+ -- in position dependent code, so we have to create our own "fake GOT"
+ -- when not Opt_PIC && WayDyn `elem` ways dflags.
+ --
+ -- 2) PowerPC Linux is just plain broken.
+ -- While it's theoretically possible to use GOT offsets larger
+ -- than 16 bit, the standard crt*.o files don't, which leads to
+ -- linker errors as soon as the GOT size exceeds 16 bit.
+ -- Also, the assembler doesn't support @gotoff labels.
+ -- In order to be able to use a larger GOT, we have to circumvent the
+ -- entire GOT mechanism and do it ourselves (this is also what GCC does).
+
+
+ -- 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 [
text ".section \".toc\", \"aw\"",
@@ -679,11 +686,10 @@ pprImportedSymbol dflags platform@(Platform { platformMini = PlatformMini { plat
text "\t.quad" <+> pprCLabel dflags lbl ]
_ -> empty
-pprImportedSymbol dflags platform importedLbl
- | osElfTarget (platformOS platform)
- = case dynamicLinkerLabelInfo importedLbl of
+ _ | osElfTarget os
+ -> case dynamicLinkerLabelInfo importedLbl of
Just (SymbolPtr, lbl)
- -> let symbolSize = case wordWidth dflags of
+ -> let symbolSize = case ncgWordWidth config of
W32 -> sLit "\t.long"
W64 -> sLit "\t.quad"
_ -> panic "Unknown wordRep in pprImportedSymbol"
@@ -696,8 +702,12 @@ pprImportedSymbol dflags platform importedLbl
-- PLT code stubs are generated automatically by the dynamic linker.
_ -> empty
-pprImportedSymbol _ _ _
- = panic "PIC.pprImportedSymbol: no match"
+ _ -> panic "PIC.pprImportedSymbol: no match"
+ where
+ platform = ncgPlatform config
+ arch = platformArch platform
+ os = platformOS platform
+ pic = ncgPIC config
--------------------------------------------------------------------------------
-- Generate code to calculate the address that should be put in the
diff --git a/compiler/GHC/CmmToAsm/PPC/CodeGen.hs b/compiler/GHC/CmmToAsm/PPC/CodeGen.hs
index 02319171dc..531efdde68 100644
--- a/compiler/GHC/CmmToAsm/PPC/CodeGen.hs
+++ b/compiler/GHC/CmmToAsm/PPC/CodeGen.hs
@@ -33,11 +33,12 @@ import GHC.CmmToAsm.CPrim
import GHC.CmmToAsm.Monad
( NatM, getNewRegNat, getNewLabelNat
, getBlockIdNat, getPicBaseNat, getNewRegPairNat
- , getPicBaseMaybeNat
+ , getPicBaseMaybeNat, getPlatform
)
import GHC.CmmToAsm.Instr
import GHC.CmmToAsm.PIC
import GHC.CmmToAsm.Format
+import GHC.CmmToAsm.Config
import GHC.Platform.Reg.Class
import GHC.Platform.Reg
import GHC.CmmToAsm.Reg.Target
@@ -81,11 +82,11 @@ cmmTopCodeGen
cmmTopCodeGen (CmmProc info lab live graph) = do
let blocks = toBlockListEntryFirst graph
(nat_blocks,statics) <- mapAndUnzipM basicBlockCodeGen blocks
- dflags <- getDynFlags
+ platform <- getPlatform
let proc = CmmProc info lab live (ListGraph $ concat nat_blocks)
tops = proc : concat statics
- os = platformOS $ targetPlatform dflags
- arch = platformArch $ targetPlatform dflags
+ os = platformOS platform
+ arch = platformArch platform
case arch of
ArchPPC | os == OSAIX -> return tops
| otherwise -> do
@@ -149,6 +150,7 @@ stmtsToInstrs stmts
stmtToInstrs :: CmmNode e x -> NatM InstrBlock
stmtToInstrs stmt = do
dflags <- getDynFlags
+ platform <- getPlatform
case stmt of
CmmComment s -> return (unitOL (COMMENT s))
CmmTick {} -> return nilOL
@@ -156,7 +158,7 @@ stmtToInstrs stmt = do
CmmAssign reg src
| isFloatType ty -> assignReg_FltCode format reg src
- | target32Bit (targetPlatform dflags) &&
+ | target32Bit platform &&
isWord64 ty -> assignReg_I64Code reg src
| otherwise -> assignReg_IntCode format reg src
where ty = cmmRegType dflags reg
@@ -164,7 +166,7 @@ stmtToInstrs stmt = do
CmmStore addr src
| isFloatType ty -> assignMem_FltCode format addr src
- | target32Bit (targetPlatform dflags) &&
+ | target32Bit platform &&
isWord64 ty -> assignMem_I64Code addr src
| otherwise -> assignMem_IntCode format addr src
where ty = cmmExprType dflags src
@@ -178,18 +180,14 @@ stmtToInstrs stmt = do
b1 <- genCondJump true arg prediction
b2 <- genBranch false
return (b1 `appOL` b2)
- CmmSwitch arg ids -> do dflags <- getDynFlags
- genSwitch dflags arg ids
+ CmmSwitch arg ids -> genSwitch dflags arg ids
CmmCall { cml_target = arg
- , cml_args_regs = gregs } -> do
- dflags <- getDynFlags
- genJump arg (jumpRegs dflags gregs)
+ , cml_args_regs = gregs } -> genJump arg (jumpRegs platform gregs)
_ ->
panic "stmtToInstrs: statement should have been cps'd away"
-jumpRegs :: DynFlags -> [GlobalReg] -> [Reg]
-jumpRegs dflags gregs = [ RegReal r | Just r <- map (globalRegMaybe platform) gregs ]
- where platform = targetPlatform dflags
+jumpRegs :: Platform -> [GlobalReg] -> [Reg]
+jumpRegs platform gregs = [ RegReal r | Just r <- map (globalRegMaybe platform) gregs ]
--------------------------------------------------------------------------------
-- | 'InstrBlock's are the insn sequences generated by the insn selectors.
@@ -230,8 +228,8 @@ getRegisterReg platform (CmmGlobal mid)
-- platform. Hence ...
-- | Convert a BlockId to some CmmStatic data
-jumpTableEntry :: DynFlags -> Maybe BlockId -> CmmStatic
-jumpTableEntry dflags Nothing = CmmStaticLit (CmmInt 0 (wordWidth dflags))
+jumpTableEntry :: NCGConfig -> Maybe BlockId -> CmmStatic
+jumpTableEntry config Nothing = CmmStaticLit (CmmInt 0 (ncgWordWidth config))
jumpTableEntry _ (Just blockid) = CmmStaticLit (CmmLabel blockLabel)
where blockLabel = blockLbl blockid
@@ -801,11 +799,11 @@ getAmode DS (CmmMachOp (MO_Add W64) [x, CmmLit (CmmInt i _)])
-- (needed for PIC)
getAmode _ (CmmMachOp (MO_Add W32) [x, CmmLit lit])
= do
- dflags <- getDynFlags
+ platform <- getPlatform
(src, srcCode) <- getSomeReg x
let imm = litToImm lit
case () of
- _ | OSAIX <- platformOS (targetPlatform dflags)
+ _ | OSAIX <- platformOS platform
, isCmmLabelType lit ->
-- HA16/LO16 relocations on labels not supported on AIX
return (Amode (AddrRegImm src imm) srcCode)
@@ -821,8 +819,8 @@ getAmode _ (CmmMachOp (MO_Add W32) [x, CmmLit lit])
getAmode _ (CmmLit lit)
= do
- dflags <- getDynFlags
- case platformArch $ targetPlatform dflags of
+ platform <- getPlatform
+ case platformArch platform of
ArchPPC -> do
tmp <- getNewRegNat II32
let imm = litToImm lit
@@ -911,8 +909,8 @@ getCondCode _ = panic "getCondCode(2)(powerpc)"
condIntCode :: Cond -> Width -> CmmExpr -> CmmExpr -> NatM CondCode
condIntCode cond width x y = do
- dflags <- getDynFlags
- condIntCode' (target32Bit (targetPlatform dflags)) cond width x y
+ platform <- getPlatform
+ condIntCode' (target32Bit platform) cond width x y
condIntCode' :: Bool -> Cond -> Width -> CmmExpr -> CmmExpr -> NatM CondCode
@@ -1749,13 +1747,13 @@ genCCall' dflags gcp target dest_regs args
-- TODO: Do not create a new stack frame if delta is too large.
move_sp_down finalStack
- | delta > stackFrameHeaderSize dflags =
+ | delta > stackFrameHeaderSize platform =
toOL [STU spFormat sp (AddrRegImm sp (ImmInt (-delta))),
DELTA (-delta)]
| otherwise = nilOL
where delta = stackDelta finalStack
move_sp_up finalStack
- | delta > stackFrameHeaderSize dflags =
+ | delta > stackFrameHeaderSize platform =
toOL [ADD sp sp (RIImm (ImmInt delta)),
DELTA 0]
| otherwise = nilOL
@@ -2096,19 +2094,18 @@ genSwitch dflags expr targets
return code
where (offset, ids) = switchTargetsToTable targets
-generateJumpTableForInstr :: DynFlags -> Instr
+generateJumpTableForInstr :: NCGConfig -> Instr
-> Maybe (NatCmmDecl RawCmmStatics Instr)
-generateJumpTableForInstr dflags (BCTR ids (Just lbl) _) =
+generateJumpTableForInstr config (BCTR ids (Just lbl) _) =
let jumpTable
- | (positionIndependent dflags)
- || (not $ target32Bit $ targetPlatform dflags)
+ | (ncgPIC config) || (not $ target32Bit $ ncgPlatform config)
= map jumpTableEntryRel ids
- | otherwise = map (jumpTableEntry dflags) ids
+ | otherwise = map (jumpTableEntry config) ids
where jumpTableEntryRel Nothing
- = CmmStaticLit (CmmInt 0 (wordWidth dflags))
+ = CmmStaticLit (CmmInt 0 (ncgWordWidth config))
jumpTableEntryRel (Just blockid)
= CmmStaticLit (CmmLabelDiffOff blockLabel lbl 0
- (wordWidth dflags))
+ (ncgWordWidth config))
where blockLabel = blockLbl blockid
in Just (CmmData (Section ReadOnlyData lbl) (RawCmmStatics lbl jumpTable))
generateJumpTableForInstr _ _ = Nothing
@@ -2124,7 +2121,7 @@ generateJumpTableForInstr _ _ = Nothing
condReg :: NatM CondCode -> NatM Register
condReg getCond = do
CondCode _ cond cond_code <- getCond
- dflags <- getDynFlags
+ platform <- getPlatform
let
code dst = cond_code
`appOL` negate_code
@@ -2151,7 +2148,7 @@ condReg getCond = do
GU -> (1, False)
_ -> panic "PPC.CodeGen.codeReg: no match"
- format = archWordFormat $ target32Bit $ targetPlatform dflags
+ format = archWordFormat $ target32Bit platform
return (Any format code)
condIntReg :: Cond -> Width -> CmmExpr -> CmmExpr -> NatM Register
@@ -2324,8 +2321,8 @@ remainderCode rep sgn reg_q arg_x arg_y = do
coerceInt2FP :: Width -> Width -> CmmExpr -> NatM Register
coerceInt2FP fromRep toRep x = do
- dflags <- getDynFlags
- let arch = platformArch $ targetPlatform dflags
+ platform <- getPlatform
+ let arch = platformArch platform
coerceInt2FP' arch fromRep toRep x
coerceInt2FP' :: Arch -> Width -> Width -> CmmExpr -> NatM Register
@@ -2335,6 +2332,7 @@ coerceInt2FP' ArchPPC fromRep toRep x = do
itmp <- getNewRegNat II32
ftmp <- getNewRegNat FF64
dflags <- getDynFlags
+ platform <- getPlatform
dynRef <- cmmMakeDynamicReference dflags DataReference lbl
Amode addr addr_code <- getAmode D dynRef
let
@@ -2343,10 +2341,10 @@ coerceInt2FP' ArchPPC fromRep toRep x = do
[CmmStaticLit (CmmInt 0x43300000 W32),
CmmStaticLit (CmmInt 0x80000000 W32)],
XORIS itmp src (ImmInt 0x8000),
- ST II32 itmp (spRel dflags 3),
+ ST II32 itmp (spRel platform 3),
LIS itmp (ImmInt 0x4330),
- ST II32 itmp (spRel dflags 2),
- LD FF64 ftmp (spRel dflags 2)
+ ST II32 itmp (spRel platform 2),
+ LD FF64 ftmp (spRel platform 2)
] `appOL` addr_code `appOL` toOL [
LD FF64 dst addr,
FSUB FF64 dst ftmp dst
@@ -2372,11 +2370,11 @@ coerceInt2FP' ArchPPC fromRep toRep x = do
-- So it is fine.
coerceInt2FP' (ArchPPC_64 _) fromRep toRep x = do
(src, code) <- getSomeReg x
- dflags <- getDynFlags
+ platform <- getPlatform
let
code' dst = code `appOL` maybe_exts `appOL` toOL [
- ST II64 src (spRel dflags 3),
- LD FF64 dst (spRel dflags 3),
+ ST II64 src (spRel platform 3),
+ LD FF64 dst (spRel platform 3),
FCFID dst dst
] `appOL` maybe_frsp dst
@@ -2400,13 +2398,13 @@ coerceInt2FP' _ _ _ _ = panic "PPC.CodeGen.coerceInt2FP: unknown arch"
coerceFP2Int :: Width -> Width -> CmmExpr -> NatM Register
coerceFP2Int fromRep toRep x = do
- dflags <- getDynFlags
- let arch = platformArch $ targetPlatform dflags
+ platform <- getPlatform
+ let arch = platformArch platform
coerceFP2Int' arch fromRep toRep x
coerceFP2Int' :: Arch -> Width -> Width -> CmmExpr -> NatM Register
coerceFP2Int' ArchPPC _ toRep x = do
- dflags <- getDynFlags
+ platform <- getPlatform
-- the reps don't really matter: F*->FF64 and II32->I* are no-ops
(src, code) <- getSomeReg x
tmp <- getNewRegNat FF64
@@ -2415,13 +2413,13 @@ coerceFP2Int' ArchPPC _ toRep x = do
-- convert to int in FP reg
FCTIWZ tmp src,
-- store value (64bit) from FP to stack
- ST FF64 tmp (spRel dflags 2),
+ ST FF64 tmp (spRel platform 2),
-- read low word of value (high word is undefined)
- LD II32 dst (spRel dflags 3)]
+ LD II32 dst (spRel platform 3)]
return (Any (intFormat toRep) code')
coerceFP2Int' (ArchPPC_64 _) _ toRep x = do
- dflags <- getDynFlags
+ platform <- getPlatform
-- the reps don't really matter: F*->FF64 and II64->I* are no-ops
(src, code) <- getSomeReg x
tmp <- getNewRegNat FF64
@@ -2430,8 +2428,8 @@ coerceFP2Int' (ArchPPC_64 _) _ toRep x = do
-- convert to int in FP reg
FCTIDZ tmp src,
-- store value (64bit) from FP to compiler word on stack
- ST FF64 tmp (spRel dflags 3),
- LD II64 dst (spRel dflags 3)]
+ ST FF64 tmp (spRel platform 3),
+ LD II64 dst (spRel platform 3)]
return (Any (intFormat toRep) code')
coerceFP2Int' _ _ _ _ = panic "PPC.CodeGen.coerceFP2Int: unknown arch"
diff --git a/compiler/GHC/CmmToAsm/PPC/Instr.hs b/compiler/GHC/CmmToAsm/PPC/Instr.hs
index b92a952340..26742b5a17 100644
--- a/compiler/GHC/CmmToAsm/PPC/Instr.hs
+++ b/compiler/GHC/CmmToAsm/PPC/Instr.hs
@@ -31,6 +31,7 @@ import GHC.CmmToAsm.PPC.Cond
import GHC.CmmToAsm.Instr
import GHC.CmmToAsm.Format
import GHC.CmmToAsm.Reg.Target
+import GHC.CmmToAsm.Config
import GHC.Platform.Reg.Class
import GHC.Platform.Reg
@@ -38,7 +39,6 @@ import GHC.Platform.Regs
import GHC.Cmm.BlockId
import GHC.Cmm.Dataflow.Collections
import GHC.Cmm.Dataflow.Label
-import GHC.Driver.Session
import GHC.Cmm
import GHC.Cmm.Info
import FastString
@@ -534,15 +534,15 @@ ppc_patchJumpInstr insn patchF
-- | An instruction to spill a register into a spill slot.
ppc_mkSpillInstr
- :: DynFlags
+ :: NCGConfig
-> Reg -- register to spill
-> Int -- current stack delta
-> Int -- spill slot to use
-> Instr
-ppc_mkSpillInstr dflags reg delta slot
- = let platform = targetPlatform dflags
- off = spillSlotToOffset dflags slot
+ppc_mkSpillInstr config reg delta slot
+ = let platform = ncgPlatform config
+ off = spillSlotToOffset platform slot
arch = platformArch platform
in
let fmt = case targetClassOfReg platform reg of
@@ -559,15 +559,15 @@ ppc_mkSpillInstr dflags reg delta slot
ppc_mkLoadInstr
- :: DynFlags
+ :: NCGConfig
-> Reg -- register to load
-> Int -- current stack delta
-> Int -- spill slot to use
-> Instr
-ppc_mkLoadInstr dflags reg delta slot
- = let platform = targetPlatform dflags
- off = spillSlotToOffset dflags slot
+ppc_mkLoadInstr config reg delta slot
+ = let platform = ncgPlatform config
+ off = spillSlotToOffset platform slot
arch = platformArch platform
in
let fmt = case targetClassOfReg platform reg of
@@ -585,8 +585,8 @@ ppc_mkLoadInstr dflags reg delta slot
-- | The size of a minimal stackframe header including minimal
-- parameter save area.
-stackFrameHeaderSize :: DynFlags -> Int
-stackFrameHeaderSize dflags
+stackFrameHeaderSize :: Platform -> Int
+stackFrameHeaderSize platform
= case platformOS platform of
OSAIX -> 24 + 8 * 4
_ -> case platformArch platform of
@@ -595,7 +595,6 @@ stackFrameHeaderSize dflags
ArchPPC_64 ELF_V1 -> 48 + 8 * 8
ArchPPC_64 ELF_V2 -> 32 + 8 * 8
_ -> panic "PPC.stackFrameHeaderSize: not defined for this OS"
- where platform = targetPlatform dflags
-- | The maximum number of bytes required to spill a register. PPC32
-- has 32-bit GPRs and 64-bit FPRs, while PPC64 has 64-bit GPRs and
@@ -606,11 +605,12 @@ spillSlotSize :: Int
spillSlotSize = 8
-- | The number of spill slots available without allocating more.
-maxSpillSlots :: DynFlags -> Int
-maxSpillSlots dflags
- = ((rESERVED_C_STACK_BYTES dflags - stackFrameHeaderSize dflags)
- `div` spillSlotSize) - 1
--- = 0 -- useful for testing allocMoreStack
+maxSpillSlots :: NCGConfig -> Int
+maxSpillSlots config
+-- = 0 -- useful for testing allocMoreStack
+ = let platform = ncgPlatform config
+ in ((ncgSpillPreallocSize config - stackFrameHeaderSize platform)
+ `div` spillSlotSize) - 1
-- | The number of bytes that the stack pointer should be aligned
-- to. This is 16 both on PPC32 and PPC64 ELF (see ELF processor
@@ -619,9 +619,9 @@ stackAlign :: Int
stackAlign = 16
-- | Convert a spill slot number to a *byte* offset, with no sign.
-spillSlotToOffset :: DynFlags -> Int -> Int
-spillSlotToOffset dflags slot
- = stackFrameHeaderSize dflags + spillSlotSize * slot
+spillSlotToOffset :: Platform -> Int -> Int
+spillSlotToOffset platform slot
+ = stackFrameHeaderSize platform + spillSlotSize * slot
--------------------------------------------------------------------------------
diff --git a/compiler/GHC/CmmToAsm/PPC/Ppr.hs b/compiler/GHC/CmmToAsm/PPC/Ppr.hs
index 550bd618ef..09f390163f 100644
--- a/compiler/GHC/CmmToAsm/PPC/Ppr.hs
+++ b/compiler/GHC/CmmToAsm/PPC/Ppr.hs
@@ -20,6 +20,7 @@ import GHC.CmmToAsm.Format
import GHC.Platform.Reg
import GHC.Platform.Reg.Class
import GHC.CmmToAsm.Reg.Target
+import GHC.CmmToAsm.Config
import GHC.Cmm hiding (topInfoTable)
import GHC.Cmm.Dataflow.Collections
@@ -33,7 +34,7 @@ import Unique ( pprUniqueAlways, getUnique )
import GHC.Platform
import FastString
import Outputable
-import GHC.Driver.Session
+import GHC.Driver.Session (targetPlatform)
import Data.Word
import Data.Int
@@ -42,30 +43,30 @@ import Data.Bits
-- -----------------------------------------------------------------------------
-- Printing this stuff out
-pprNatCmmDecl :: NatCmmDecl RawCmmStatics Instr -> SDoc
-pprNatCmmDecl (CmmData section dats) =
- pprSectionAlign section $$ pprDatas dats
+pprNatCmmDecl :: NCGConfig -> NatCmmDecl RawCmmStatics Instr -> SDoc
+pprNatCmmDecl config (CmmData section dats) =
+ pprSectionAlign config section
+ $$ pprDatas (ncgPlatform config) dats
-pprNatCmmDecl proc@(CmmProc top_info lbl _ (ListGraph blocks)) =
+pprNatCmmDecl config proc@(CmmProc top_info lbl _ (ListGraph blocks)) =
+ let platform = ncgPlatform config in
case topInfoTable proc of
Nothing ->
- sdocWithPlatform $ \platform ->
-- special case for code without info table:
- pprSectionAlign (Section Text lbl) $$
+ pprSectionAlign config (Section Text lbl) $$
(case platformArch platform of
ArchPPC_64 ELF_V1 -> pprFunctionDescriptor lbl
ArchPPC_64 ELF_V2 -> pprFunctionPrologue lbl
- _ -> pprLabel lbl) $$ -- blocks guaranteed not null,
- -- so label needed
- vcat (map (pprBasicBlock top_info) blocks)
+ _ -> pprLabel platform lbl) $$ -- blocks guaranteed not null,
+ -- so label needed
+ vcat (map (pprBasicBlock platform top_info) blocks)
Just (RawCmmStatics info_lbl _) ->
- sdocWithPlatform $ \platform ->
- pprSectionAlign (Section Text info_lbl) $$
+ pprSectionAlign config (Section Text info_lbl) $$
(if platformHasSubsectionsViaSymbols platform
then ppr (mkDeadStripPreventer info_lbl) <> char ':'
else empty) $$
- vcat (map (pprBasicBlock top_info) blocks) $$
+ vcat (map (pprBasicBlock platform 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
@@ -104,24 +105,24 @@ pprFunctionPrologue lab = pprGloblDecl lab
$$ text "\t.localentry\t" <> ppr lab
<> text ",.-" <> ppr lab
-pprBasicBlock :: LabelMap RawCmmStatics -> NatBasicBlock Instr -> SDoc
-pprBasicBlock info_env (BasicBlock blockid instrs)
+pprBasicBlock :: Platform -> LabelMap RawCmmStatics -> NatBasicBlock Instr -> SDoc
+pprBasicBlock platform info_env (BasicBlock blockid instrs)
= maybe_infotable $$
- pprLabel (blockLbl blockid) $$
- vcat (map pprInstr instrs)
+ pprLabel platform (blockLbl blockid) $$
+ vcat (map (pprInstr platform) instrs)
where
maybe_infotable = case mapLookup blockid info_env of
Nothing -> empty
Just (RawCmmStatics info_lbl info) ->
- pprAlignForSection Text $$
- vcat (map pprData info) $$
- pprLabel info_lbl
+ pprAlignForSection platform Text $$
+ vcat (map (pprData platform) info) $$
+ pprLabel platform info_lbl
-pprDatas :: RawCmmStatics -> SDoc
+pprDatas :: Platform -> RawCmmStatics -> SDoc
-- See note [emit-time elimination of static indirections] in CLabel.
-pprDatas (RawCmmStatics alias [CmmStaticLit (CmmLabel lbl), CmmStaticLit ind, _, _])
+pprDatas _platform (RawCmmStatics alias [CmmStaticLit (CmmLabel lbl), CmmStaticLit ind, _, _])
| lbl == mkIndStaticInfoLabel
, let labelInd (CmmLabelOff l _) = Just l
labelInd (CmmLabel l) = Just l
@@ -130,36 +131,38 @@ pprDatas (RawCmmStatics alias [CmmStaticLit (CmmLabel lbl), CmmStaticLit ind, _,
, alias `mayRedirectTo` ind'
= pprGloblDecl alias
$$ text ".equiv" <+> ppr alias <> comma <> ppr (CmmLabel ind')
-pprDatas (RawCmmStatics lbl dats) = vcat (pprLabel lbl : map pprData dats)
+pprDatas platform (RawCmmStatics lbl dats) = vcat (pprLabel platform lbl : map (pprData platform) dats)
-pprData :: CmmStatic -> SDoc
-pprData (CmmString str) = pprBytes str
-pprData (CmmUninitialised bytes) = text ".space " <> int bytes
-pprData (CmmStaticLit lit) = pprDataItem lit
+pprData :: Platform -> CmmStatic -> SDoc
+pprData platform d = case d of
+ CmmString str -> pprBytes str
+ CmmUninitialised bytes -> text ".space " <> int bytes
+ CmmStaticLit lit -> pprDataItem platform lit
pprGloblDecl :: CLabel -> SDoc
pprGloblDecl lbl
| not (externallyVisibleCLabel lbl) = empty
| otherwise = text ".globl " <> ppr lbl
-pprTypeAndSizeDecl :: CLabel -> SDoc
-pprTypeAndSizeDecl lbl
- = sdocWithPlatform $ \platform ->
- if platformOS platform == OSLinux && externallyVisibleCLabel lbl
+pprTypeAndSizeDecl :: Platform -> CLabel -> SDoc
+pprTypeAndSizeDecl platform lbl
+ = if platformOS platform == OSLinux && externallyVisibleCLabel lbl
then text ".type " <>
ppr lbl <> text ", @object"
else empty
-pprLabel :: CLabel -> SDoc
-pprLabel lbl = pprGloblDecl lbl
- $$ pprTypeAndSizeDecl lbl
- $$ (ppr lbl <> char ':')
+pprLabel :: Platform -> CLabel -> SDoc
+pprLabel platform lbl =
+ pprGloblDecl lbl
+ $$ pprTypeAndSizeDecl platform lbl
+ $$ (ppr lbl <> char ':')
-- -----------------------------------------------------------------------------
-- pprInstr: print an 'Instr'
instance Outputable Instr where
- ppr instr = pprInstr instr
+ ppr instr = sdocWithDynFlags $ \dflags ->
+ pprInstr (targetPlatform dflags) instr
pprReg :: Reg -> SDoc
@@ -258,16 +261,14 @@ pprAddr (AddrRegImm r1 imm)
= hcat [ pprImm imm, char '(', pprReg r1, char ')' ]
-pprSectionAlign :: Section -> SDoc
-pprSectionAlign sec@(Section seg _) =
- sdocWithPlatform $ \platform ->
- pprSectionHeader platform sec $$
- pprAlignForSection seg
+pprSectionAlign :: NCGConfig -> Section -> SDoc
+pprSectionAlign config sec@(Section seg _) =
+ pprSectionHeader config sec $$
+ pprAlignForSection (ncgPlatform config) seg
-- | Print appropriate alignment for the given section type.
-pprAlignForSection :: SectionType -> SDoc
-pprAlignForSection seg =
- sdocWithPlatform $ \platform ->
+pprAlignForSection :: Platform -> SectionType -> SDoc
+pprAlignForSection platform seg =
let ppc64 = not $ target32Bit platform
in ptext $ case seg of
Text -> sLit ".align 2"
@@ -291,199 +292,213 @@ pprAlignForSection seg =
| otherwise -> sLit ".align 2"
OtherSection _ -> panic "PprMach.pprSectionAlign: unknown section"
-pprDataItem :: CmmLit -> SDoc
-pprDataItem lit
+pprDataItem :: Platform -> CmmLit -> SDoc
+pprDataItem platform lit
= sdocWithDynFlags $ \dflags ->
- vcat (ppr_item (cmmTypeFormat $ cmmLitType dflags lit) lit dflags)
+ vcat (ppr_item (cmmTypeFormat $ cmmLitType dflags lit) lit)
where
imm = litToImm lit
- archPPC_64 dflags = not $ target32Bit $ targetPlatform dflags
+ archPPC_64 = not $ target32Bit platform
- ppr_item II8 _ _ = [text "\t.byte\t" <> pprImm imm]
+ ppr_item II8 _ = [text "\t.byte\t" <> pprImm imm]
+ ppr_item II16 _ = [text "\t.short\t" <> pprImm imm]
+ ppr_item II32 _ = [text "\t.long\t" <> pprImm imm]
+ ppr_item II64 _
+ | archPPC_64 = [text "\t.quad\t" <> pprImm imm]
- ppr_item II32 _ _ = [text "\t.long\t" <> pprImm imm]
-
- ppr_item II64 _ dflags
- | archPPC_64 dflags = [text "\t.quad\t" <> pprImm imm]
+ ppr_item II64 (CmmInt x _)
+ | not archPPC_64 =
+ [text "\t.long\t"
+ <> int (fromIntegral
+ (fromIntegral (x `shiftR` 32) :: Word32)),
+ text "\t.long\t"
+ <> int (fromIntegral (fromIntegral x :: Word32))]
- ppr_item FF32 (CmmFloat r _) _
+ ppr_item FF32 (CmmFloat r _)
= let bs = floatToBytes (fromRational r)
in map (\b -> text "\t.byte\t" <> pprImm (ImmInt b)) bs
- ppr_item FF64 (CmmFloat r _) _
+ ppr_item FF64 (CmmFloat r _)
= let bs = doubleToBytes (fromRational r)
in map (\b -> text "\t.byte\t" <> pprImm (ImmInt b)) bs
- ppr_item II16 _ _ = [text "\t.short\t" <> pprImm imm]
+ ppr_item _ _
+ = panic "PPC.Ppr.pprDataItem: no match"
- ppr_item II64 (CmmInt x _) dflags
- | not(archPPC_64 dflags) =
- [text "\t.long\t"
- <> int (fromIntegral
- (fromIntegral (x `shiftR` 32) :: Word32)),
- text "\t.long\t"
- <> int (fromIntegral (fromIntegral x :: Word32))]
- ppr_item _ _ _
- = panic "PPC.Ppr.pprDataItem: no match"
+pprInstr :: Platform -> Instr -> SDoc
+pprInstr platform instr = case instr of
+ COMMENT _
+ -> empty -- nuke 'em
-pprInstr :: Instr -> SDoc
+ -- COMMENT s
+ -- -> if platformOS platform == OSLinux
+ -- then text "# " <> ftext s
+ -- else text "; " <> ftext s
-pprInstr (COMMENT _) = empty -- nuke 'em
-{-
-pprInstr (COMMENT s) =
- if platformOS platform == OSLinux
- then text "# " <> ftext s
- else text "; " <> ftext s
--}
-pprInstr (DELTA d)
- = pprInstr (COMMENT (mkFastString ("\tdelta = " ++ show d)))
+ DELTA d
+ -> pprInstr platform (COMMENT (mkFastString ("\tdelta = " ++ show d)))
-pprInstr (NEWBLOCK _)
- = panic "PprMach.pprInstr: NEWBLOCK"
+ NEWBLOCK _
+ -> panic "PprMach.pprInstr: NEWBLOCK"
-pprInstr (LDATA _ _)
- = panic "PprMach.pprInstr: LDATA"
+ LDATA _ _
+ -> panic "PprMach.pprInstr: LDATA"
{-
-pprInstr (SPILL reg slot)
- = hcat [
- text "\tSPILL",
- char '\t',
- pprReg reg,
- comma,
- text "SLOT" <> parens (int slot)]
-
-pprInstr (RELOAD slot reg)
- = hcat [
- text "\tRELOAD",
- char '\t',
- text "SLOT" <> parens (int slot),
- comma,
- pprReg reg]
+ SPILL reg slot
+ -> hcat [
+ text "\tSPILL",
+ char '\t',
+ pprReg reg,
+ comma,
+ text "SLOT" <> parens (int slot)]
+
+ RELOAD slot reg
+ -> hcat [
+ text "\tRELOAD",
+ char '\t',
+ text "SLOT" <> parens (int slot),
+ comma,
+ pprReg reg]
-}
-pprInstr (LD fmt reg addr) = hcat [
- char '\t',
- text "l",
- ptext (case fmt of
- II8 -> sLit "bz"
- II16 -> sLit "hz"
- II32 -> sLit "wz"
- II64 -> sLit "d"
- FF32 -> sLit "fs"
- FF64 -> sLit "fd"
- ),
- case addr of AddrRegImm _ _ -> empty
- AddrRegReg _ _ -> char 'x',
- char '\t',
- pprReg reg,
- text ", ",
- pprAddr addr
- ]
+ LD fmt reg addr
+ -> hcat [
+ char '\t',
+ text "l",
+ ptext (case fmt of
+ II8 -> sLit "bz"
+ II16 -> sLit "hz"
+ II32 -> sLit "wz"
+ II64 -> sLit "d"
+ FF32 -> sLit "fs"
+ FF64 -> sLit "fd"
+ ),
+ case addr of AddrRegImm _ _ -> empty
+ AddrRegReg _ _ -> char 'x',
+ char '\t',
+ pprReg reg,
+ text ", ",
+ pprAddr addr
+ ]
+
+ LDFAR fmt reg (AddrRegImm source off)
+ -> vcat
+ [ pprInstr platform (ADDIS (tmpReg platform) source (HA off))
+ , pprInstr platform (LD fmt reg (AddrRegImm (tmpReg platform) (LO off)))
+ ]
-pprInstr (LDFAR fmt reg (AddrRegImm source off)) =
- sdocWithPlatform $ \platform -> vcat [
- pprInstr (ADDIS (tmpReg platform) source (HA off)),
- pprInstr (LD fmt reg (AddrRegImm (tmpReg platform) (LO off)))
- ]
-pprInstr (LDFAR _ _ _) =
- panic "PPC.Ppr.pprInstr LDFAR: no match"
-
-pprInstr (LDR fmt reg1 addr) = hcat [
- text "\tl",
- case fmt of
- II32 -> char 'w'
- II64 -> char 'd'
- _ -> panic "PPC.Ppr.Instr LDR: no match",
- text "arx\t",
- pprReg reg1,
- text ", ",
- pprAddr addr
- ]
-
-pprInstr (LA fmt reg addr) = hcat [
- char '\t',
- text "l",
- ptext (case fmt of
- II8 -> sLit "ba"
- II16 -> sLit "ha"
- II32 -> sLit "wa"
- II64 -> sLit "d"
- FF32 -> sLit "fs"
- FF64 -> sLit "fd"
- ),
- case addr of AddrRegImm _ _ -> empty
- AddrRegReg _ _ -> char 'x',
- char '\t',
- pprReg reg,
- text ", ",
- pprAddr addr
- ]
-pprInstr (ST fmt reg addr) = hcat [
- char '\t',
- text "st",
- pprFormat fmt,
- case addr of AddrRegImm _ _ -> empty
- AddrRegReg _ _ -> char 'x',
+ LDFAR _ _ _
+ -> panic "PPC.Ppr.pprInstr LDFAR: no match"
+
+ LDR fmt reg1 addr
+ -> hcat [
+ text "\tl",
+ case fmt of
+ II32 -> char 'w'
+ II64 -> char 'd'
+ _ -> panic "PPC.Ppr.Instr LDR: no match",
+ text "arx\t",
+ pprReg reg1,
+ text ", ",
+ pprAddr addr
+ ]
+
+ LA fmt reg addr
+ -> hcat [
+ char '\t',
+ text "l",
+ ptext (case fmt of
+ II8 -> sLit "ba"
+ II16 -> sLit "ha"
+ II32 -> sLit "wa"
+ II64 -> sLit "d"
+ FF32 -> sLit "fs"
+ FF64 -> sLit "fd"
+ ),
+ case addr of AddrRegImm _ _ -> empty
+ AddrRegReg _ _ -> char 'x',
+ char '\t',
+ pprReg reg,
+ text ", ",
+ pprAddr addr
+ ]
+
+ ST fmt reg addr
+ -> hcat [
+ char '\t',
+ text "st",
+ pprFormat fmt,
+ case addr of AddrRegImm _ _ -> empty
+ AddrRegReg _ _ -> char 'x',
+ char '\t',
+ pprReg reg,
+ text ", ",
+ pprAddr addr
+ ]
+
+ STFAR fmt reg (AddrRegImm source off)
+ -> vcat [ pprInstr platform (ADDIS (tmpReg platform) source (HA off))
+ , pprInstr platform (ST fmt reg (AddrRegImm (tmpReg platform) (LO off)))
+ ]
+
+ STFAR _ _ _
+ -> panic "PPC.Ppr.pprInstr STFAR: no match"
+
+ STU fmt reg addr
+ -> hcat [
+ char '\t',
+ text "st",
+ pprFormat fmt,
+ char 'u',
+ case addr of AddrRegImm _ _ -> empty
+ AddrRegReg _ _ -> char 'x',
+ char '\t',
+ pprReg reg,
+ text ", ",
+ pprAddr addr
+ ]
+
+ STC fmt reg1 addr
+ -> hcat [
+ text "\tst",
+ case fmt of
+ II32 -> char 'w'
+ II64 -> char 'd'
+ _ -> panic "PPC.Ppr.Instr STC: no match",
+ text "cx.\t",
+ pprReg reg1,
+ text ", ",
+ pprAddr addr
+ ]
+
+ LIS reg imm
+ -> hcat [
+ char '\t',
+ text "lis",
+ char '\t',
+ pprReg reg,
+ text ", ",
+ pprImm imm
+ ]
+
+ LI reg imm
+ -> hcat [
+ char '\t',
+ text "li",
+ char '\t',
+ pprReg reg,
+ text ", ",
+ pprImm imm
+ ]
+
+ MR reg1 reg2
+ | reg1 == reg2 -> empty
+ | otherwise -> hcat [
char '\t',
- pprReg reg,
- text ", ",
- pprAddr addr
- ]
-pprInstr (STFAR fmt reg (AddrRegImm source off)) =
- sdocWithPlatform $ \platform -> vcat [
- pprInstr (ADDIS (tmpReg platform) source (HA off)),
- pprInstr (ST fmt reg (AddrRegImm (tmpReg platform) (LO off)))
- ]
-pprInstr (STFAR _ _ _) =
- panic "PPC.Ppr.pprInstr STFAR: no match"
-pprInstr (STU fmt reg addr) = hcat [
- char '\t',
- text "st",
- pprFormat fmt,
- char 'u',
- case addr of AddrRegImm _ _ -> empty
- AddrRegReg _ _ -> char 'x',
- char '\t',
- pprReg reg,
- text ", ",
- pprAddr addr
- ]
-pprInstr (STC fmt reg1 addr) = hcat [
- text "\tst",
- case fmt of
- II32 -> char 'w'
- II64 -> char 'd'
- _ -> panic "PPC.Ppr.Instr STC: no match",
- text "cx.\t",
- pprReg reg1,
- text ", ",
- pprAddr addr
- ]
-pprInstr (LIS reg imm) = hcat [
- char '\t',
- text "lis",
- char '\t',
- pprReg reg,
- text ", ",
- pprImm imm
- ]
-pprInstr (LI reg imm) = hcat [
- char '\t',
- text "li",
- char '\t',
- pprReg reg,
- text ", ",
- pprImm imm
- ]
-pprInstr (MR reg1 reg2)
- | reg1 == reg2 = empty
- | otherwise = hcat [
- char '\t',
- sdocWithPlatform $ \platform ->
case targetClassOfReg platform reg1 of
RcInteger -> text "mr"
_ -> text "fmr",
@@ -491,411 +506,499 @@ pprInstr (MR reg1 reg2)
pprReg reg1,
text ", ",
pprReg reg2
- ]
-pprInstr (CMP fmt reg ri) = hcat [
- char '\t',
- op,
- char '\t',
- pprReg reg,
- text ", ",
- pprRI ri
- ]
- where
- op = hcat [
- text "cmp",
- pprFormat fmt,
- case ri of
- RIReg _ -> empty
- RIImm _ -> char 'i'
- ]
-pprInstr (CMPL fmt reg ri) = hcat [
- char '\t',
- op,
- char '\t',
- pprReg reg,
- text ", ",
- pprRI ri
- ]
- where
- op = hcat [
- text "cmpl",
- pprFormat fmt,
- case ri of
- RIReg _ -> empty
- RIImm _ -> char 'i'
- ]
-pprInstr (BCC cond blockid prediction) = hcat [
- char '\t',
- text "b",
- pprCond cond,
- pprPrediction prediction,
- char '\t',
- ppr lbl
- ]
- where lbl = mkLocalBlockLabel (getUnique blockid)
- pprPrediction p = case p of
- Nothing -> empty
- Just True -> char '+'
- Just False -> char '-'
-
-pprInstr (BCCFAR cond blockid prediction) = vcat [
- hcat [
- text "\tb",
- pprCond (condNegate cond),
- neg_prediction,
- text "\t$+8"
- ],
- hcat [
- text "\tb\t",
- ppr lbl
]
- ]
- where lbl = mkLocalBlockLabel (getUnique blockid)
- neg_prediction = case prediction of
- Nothing -> empty
- Just True -> char '-'
- Just False -> char '+'
-
-pprInstr (JMP lbl _)
- -- 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
- char '\t',
- text "b",
- char '\t',
- ppr lbl
- ]
-pprInstr (MTCTR reg) = hcat [
- char '\t',
- text "mtctr",
- char '\t',
- pprReg reg
- ]
-pprInstr (BCTR _ _ _) = hcat [
- char '\t',
- text "bctr"
- ]
-pprInstr (BL lbl _) = do
- sdocWithPlatform $ \platform -> case platformOS platform of
- OSAIX ->
- -- On AIX, "printf" denotes a function-descriptor (for use
- -- by function pointers), whereas the actual entry-code
- -- address is denoted by the dot-prefixed ".printf" label.
- -- Moreover, the PPC NCG only ever emits a BL instruction
- -- for calling C ABI functions. Most of the time these calls
- -- originate from FFI imports and have a 'ForeignLabel',
- -- but when profiling the codegen inserts calls via
- -- 'emitRtsCallGen' which are 'CmmLabel's even though
- -- they'd technically be more like 'ForeignLabel's.
- hcat [
- text "\tbl\t.",
- ppr lbl
- ]
- _ ->
- hcat [
- text "\tbl\t",
- ppr lbl
+ CMP fmt reg ri
+ -> hcat [
+ char '\t',
+ op,
+ char '\t',
+ pprReg reg,
+ text ", ",
+ pprRI ri
+ ]
+ where
+ op = hcat [
+ text "cmp",
+ pprFormat fmt,
+ case ri of
+ RIReg _ -> empty
+ RIImm _ -> char 'i'
+ ]
+
+ CMPL fmt reg ri
+ -> hcat [
+ char '\t',
+ op,
+ char '\t',
+ pprReg reg,
+ text ", ",
+ pprRI ri
+ ]
+ where
+ op = hcat [
+ text "cmpl",
+ pprFormat fmt,
+ case ri of
+ RIReg _ -> empty
+ RIImm _ -> char 'i'
+ ]
+
+ BCC cond blockid prediction
+ -> hcat [
+ char '\t',
+ text "b",
+ pprCond cond,
+ pprPrediction prediction,
+ char '\t',
+ ppr lbl
+ ]
+ where lbl = mkLocalBlockLabel (getUnique blockid)
+ pprPrediction p = case p of
+ Nothing -> empty
+ Just True -> char '+'
+ Just False -> char '-'
+
+ BCCFAR cond blockid prediction
+ -> vcat [
+ hcat [
+ text "\tb",
+ pprCond (condNegate cond),
+ neg_prediction,
+ text "\t$+8"
+ ],
+ hcat [
+ text "\tb\t",
+ ppr lbl
+ ]
]
-pprInstr (BCTRL _) = hcat [
- char '\t',
- text "bctrl"
- ]
-pprInstr (ADD reg1 reg2 ri) = pprLogic (sLit "add") reg1 reg2 ri
-pprInstr (ADDIS reg1 reg2 imm) = hcat [
- char '\t',
- text "addis",
- char '\t',
- pprReg reg1,
- text ", ",
- pprReg reg2,
- text ", ",
- pprImm imm
- ]
+ where lbl = mkLocalBlockLabel (getUnique blockid)
+ neg_prediction = case prediction of
+ Nothing -> empty
+ Just True -> char '-'
+ Just False -> char '+'
+
+ JMP lbl _
+ -- 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
+ char '\t',
+ text "b",
+ char '\t',
+ ppr lbl
+ ]
+
+ MTCTR reg
+ -> hcat [
+ char '\t',
+ text "mtctr",
+ char '\t',
+ pprReg reg
+ ]
-pprInstr (ADDO reg1 reg2 reg3) = pprLogic (sLit "addo") reg1 reg2 (RIReg reg3)
-pprInstr (ADDC reg1 reg2 reg3) = pprLogic (sLit "addc") reg1 reg2 (RIReg reg3)
-pprInstr (ADDE reg1 reg2 reg3) = pprLogic (sLit "adde") reg1 reg2 (RIReg reg3)
-pprInstr (ADDZE reg1 reg2) = pprUnary (sLit "addze") reg1 reg2
-pprInstr (SUBF reg1 reg2 reg3) = pprLogic (sLit "subf") reg1 reg2 (RIReg reg3)
-pprInstr (SUBFO reg1 reg2 reg3) = pprLogic (sLit "subfo") reg1 reg2 (RIReg reg3)
-pprInstr (SUBFC reg1 reg2 ri) = hcat [
- char '\t',
- text "subf",
- case ri of
- RIReg _ -> empty
- RIImm _ -> char 'i',
- text "c\t",
- pprReg reg1,
- text ", ",
- pprReg reg2,
- text ", ",
- pprRI ri
- ]
-pprInstr (SUBFE reg1 reg2 reg3) = pprLogic (sLit "subfe") reg1 reg2 (RIReg reg3)
-pprInstr (MULL fmt reg1 reg2 ri) = pprMul fmt reg1 reg2 ri
-pprInstr (MULLO fmt reg1 reg2 reg3) = hcat [
- char '\t',
- text "mull",
- case fmt of
- II32 -> char 'w'
- II64 -> char 'd'
- _ -> panic "PPC: illegal format",
- text "o\t",
- pprReg reg1,
- text ", ",
- pprReg reg2,
- text ", ",
- pprReg reg3
- ]
-pprInstr (MFOV fmt reg) = vcat [
- hcat [
- char '\t',
- text "mfxer",
+ BCTR _ _ _
+ -> hcat [
+ char '\t',
+ text "bctr"
+ ]
+
+ BL lbl _
+ -> case platformOS platform of
+ OSAIX ->
+ -- On AIX, "printf" denotes a function-descriptor (for use
+ -- by function pointers), whereas the actual entry-code
+ -- address is denoted by the dot-prefixed ".printf" label.
+ -- Moreover, the PPC NCG only ever emits a BL instruction
+ -- for calling C ABI functions. Most of the time these calls
+ -- originate from FFI imports and have a 'ForeignLabel',
+ -- but when profiling the codegen inserts calls via
+ -- 'emitRtsCallGen' which are 'CmmLabel's even though
+ -- they'd technically be more like 'ForeignLabel's.
+ hcat [
+ text "\tbl\t.",
+ ppr lbl
+ ]
+ _ ->
+ hcat [
+ text "\tbl\t",
+ ppr lbl
+ ]
+
+ BCTRL _
+ -> hcat [
+ char '\t',
+ text "bctrl"
+ ]
+
+ ADD reg1 reg2 ri
+ -> pprLogic (sLit "add") reg1 reg2 ri
+
+ ADDIS reg1 reg2 imm
+ -> hcat [
+ char '\t',
+ text "addis",
+ char '\t',
+ pprReg reg1,
+ text ", ",
+ pprReg reg2,
+ text ", ",
+ pprImm imm
+ ]
+
+ ADDO reg1 reg2 reg3
+ -> pprLogic (sLit "addo") reg1 reg2 (RIReg reg3)
+
+ ADDC reg1 reg2 reg3
+ -> pprLogic (sLit "addc") reg1 reg2 (RIReg reg3)
+
+ ADDE reg1 reg2 reg3
+ -> pprLogic (sLit "adde") reg1 reg2 (RIReg reg3)
+
+ ADDZE reg1 reg2
+ -> pprUnary (sLit "addze") reg1 reg2
+
+ SUBF reg1 reg2 reg3
+ -> pprLogic (sLit "subf") reg1 reg2 (RIReg reg3)
+
+ SUBFO reg1 reg2 reg3
+ -> pprLogic (sLit "subfo") reg1 reg2 (RIReg reg3)
+
+ SUBFC reg1 reg2 ri
+ -> hcat [
+ char '\t',
+ text "subf",
+ case ri of
+ RIReg _ -> empty
+ RIImm _ -> char 'i',
+ text "c\t",
+ pprReg reg1,
+ text ", ",
+ pprReg reg2,
+ text ", ",
+ pprRI ri
+ ]
+
+ SUBFE reg1 reg2 reg3
+ -> pprLogic (sLit "subfe") reg1 reg2 (RIReg reg3)
+
+ MULL fmt reg1 reg2 ri
+ -> pprMul fmt reg1 reg2 ri
+
+ MULLO fmt reg1 reg2 reg3
+ -> hcat [
+ char '\t',
+ text "mull",
+ case fmt of
+ II32 -> char 'w'
+ II64 -> char 'd'
+ _ -> panic "PPC: illegal format",
+ text "o\t",
+ pprReg reg1,
+ text ", ",
+ pprReg reg2,
+ text ", ",
+ pprReg reg3
+ ]
+
+ MFOV fmt reg
+ -> vcat [
+ hcat [
+ char '\t',
+ text "mfxer",
+ char '\t',
+ pprReg reg
+ ],
+ hcat [
+ char '\t',
+ text "extr",
+ case fmt of
+ II32 -> char 'w'
+ II64 -> char 'd'
+ _ -> panic "PPC: illegal format",
+ text "i\t",
+ pprReg reg,
+ text ", ",
+ pprReg reg,
+ text ", 1, ",
+ case fmt of
+ II32 -> text "1"
+ II64 -> text "33"
+ _ -> panic "PPC: illegal format"
+ ]
+ ]
+
+ MULHU fmt reg1 reg2 reg3
+ -> hcat [
char '\t',
- pprReg reg
- ],
- hcat [
- char '\t',
- text "extr",
+ text "mulh",
case fmt of
II32 -> char 'w'
II64 -> char 'd'
_ -> panic "PPC: illegal format",
- text "i\t",
- pprReg reg,
+ text "u\t",
+ pprReg reg1,
text ", ",
- pprReg reg,
- text ", 1, ",
- case fmt of
- II32 -> text "1"
- II64 -> text "33"
- _ -> panic "PPC: illegal format"
- ]
+ pprReg reg2,
+ text ", ",
+ pprReg reg3
]
-pprInstr (MULHU fmt reg1 reg2 reg3) = hcat [
- char '\t',
- text "mulh",
- case fmt of
- II32 -> char 'w'
- II64 -> char 'd'
- _ -> panic "PPC: illegal format",
- text "u\t",
- pprReg reg1,
- text ", ",
- pprReg reg2,
- text ", ",
- pprReg reg3
- ]
-
-pprInstr (DIV fmt sgn reg1 reg2 reg3) = pprDiv fmt sgn reg1 reg2 reg3
+ DIV fmt sgn reg1 reg2 reg3
+ -> pprDiv fmt sgn reg1 reg2 reg3
-- for some reason, "andi" doesn't exist.
-- we'll use "andi." instead.
-pprInstr (AND reg1 reg2 (RIImm imm)) = hcat [
- char '\t',
- text "andi.",
- char '\t',
- pprReg reg1,
- text ", ",
- pprReg reg2,
- text ", ",
- pprImm imm
- ]
-pprInstr (AND reg1 reg2 ri) = pprLogic (sLit "and") reg1 reg2 ri
-pprInstr (ANDC reg1 reg2 reg3) = pprLogic (sLit "andc") reg1 reg2 (RIReg reg3)
-pprInstr (NAND reg1 reg2 reg3) = pprLogic (sLit "nand") reg1 reg2 (RIReg reg3)
+ AND reg1 reg2 (RIImm imm)
+ -> hcat [
+ char '\t',
+ text "andi.",
+ char '\t',
+ pprReg reg1,
+ text ", ",
+ pprReg reg2,
+ text ", ",
+ pprImm imm
+ ]
-pprInstr (OR reg1 reg2 ri) = pprLogic (sLit "or") reg1 reg2 ri
-pprInstr (XOR reg1 reg2 ri) = pprLogic (sLit "xor") reg1 reg2 ri
+ AND reg1 reg2 ri
+ -> pprLogic (sLit "and") reg1 reg2 ri
-pprInstr (ORIS reg1 reg2 imm) = hcat [
- char '\t',
- text "oris",
- char '\t',
- pprReg reg1,
- text ", ",
- pprReg reg2,
- text ", ",
- pprImm imm
- ]
+ ANDC reg1 reg2 reg3
+ -> pprLogic (sLit "andc") reg1 reg2 (RIReg reg3)
-pprInstr (XORIS reg1 reg2 imm) = hcat [
- char '\t',
- text "xoris",
- char '\t',
- pprReg reg1,
- text ", ",
- pprReg reg2,
- text ", ",
- pprImm imm
- ]
+ NAND reg1 reg2 reg3
+ -> pprLogic (sLit "nand") reg1 reg2 (RIReg reg3)
-pprInstr (EXTS fmt reg1 reg2) = hcat [
- char '\t',
- text "exts",
- pprFormat fmt,
- char '\t',
- pprReg reg1,
- text ", ",
- pprReg reg2
- ]
-pprInstr (CNTLZ fmt reg1 reg2) = hcat [
- char '\t',
- text "cntlz",
- case fmt of
- II32 -> char 'w'
- II64 -> char 'd'
- _ -> panic "PPC: illegal format",
- char '\t',
- pprReg reg1,
- text ", ",
- pprReg reg2
- ]
+ OR reg1 reg2 ri
+ -> pprLogic (sLit "or") reg1 reg2 ri
-pprInstr (NEG reg1 reg2) = pprUnary (sLit "neg") reg1 reg2
-pprInstr (NOT reg1 reg2) = pprUnary (sLit "not") reg1 reg2
+ XOR reg1 reg2 ri
+ -> pprLogic (sLit "xor") reg1 reg2 ri
-pprInstr (SR II32 reg1 reg2 (RIImm (ImmInt i))) | i < 0 || i > 31 =
+ ORIS reg1 reg2 imm
+ -> hcat [
+ char '\t',
+ text "oris",
+ char '\t',
+ pprReg reg1,
+ text ", ",
+ pprReg reg2,
+ text ", ",
+ pprImm imm
+ ]
+
+ XORIS reg1 reg2 imm
+ -> hcat [
+ char '\t',
+ text "xoris",
+ char '\t',
+ pprReg reg1,
+ text ", ",
+ pprReg reg2,
+ text ", ",
+ pprImm imm
+ ]
+
+ EXTS fmt reg1 reg2
+ -> hcat [
+ char '\t',
+ text "exts",
+ pprFormat fmt,
+ char '\t',
+ pprReg reg1,
+ text ", ",
+ pprReg reg2
+ ]
+
+ CNTLZ fmt reg1 reg2
+ -> hcat [
+ char '\t',
+ text "cntlz",
+ case fmt of
+ II32 -> char 'w'
+ II64 -> char 'd'
+ _ -> panic "PPC: illegal format",
+ char '\t',
+ pprReg reg1,
+ text ", ",
+ pprReg reg2
+ ]
+
+ NEG reg1 reg2
+ -> pprUnary (sLit "neg") reg1 reg2
+
+ NOT reg1 reg2
+ -> pprUnary (sLit "not") reg1 reg2
+
+ SR II32 reg1 reg2 (RIImm (ImmInt i))
-- Handle the case where we are asked to shift a 32 bit register by
-- less than zero or more than 31 bits. We convert this into a clear
-- of the destination register.
-- Fixes ticket https://gitlab.haskell.org/ghc/ghc/issues/5900
- pprInstr (XOR reg1 reg2 (RIReg reg2))
+ | i < 0 || i > 31 -> pprInstr platform (XOR reg1 reg2 (RIReg reg2))
-pprInstr (SL II32 reg1 reg2 (RIImm (ImmInt i))) | i < 0 || i > 31 =
+ SL II32 reg1 reg2 (RIImm (ImmInt i))
-- As above for SR, but for left shifts.
-- Fixes ticket https://gitlab.haskell.org/ghc/ghc/issues/10870
- pprInstr (XOR reg1 reg2 (RIReg reg2))
+ | i < 0 || i > 31 -> pprInstr platform (XOR reg1 reg2 (RIReg reg2))
-pprInstr (SRA II32 reg1 reg2 (RIImm (ImmInt i))) | i > 31 =
+ SRA II32 reg1 reg2 (RIImm (ImmInt i))
-- PT: I don't know what to do for negative shift amounts:
-- For now just panic.
--
-- For shift amounts greater than 31 set all bit to the
-- value of the sign bit, this also what sraw does.
- pprInstr (SRA II32 reg1 reg2 (RIImm (ImmInt 31)))
+ | i > 31 -> pprInstr platform (SRA II32 reg1 reg2 (RIImm (ImmInt 31)))
-pprInstr (SL fmt reg1 reg2 ri) =
- let op = case fmt of
+ SL fmt reg1 reg2 ri
+ -> let op = case fmt of
II32 -> "slw"
II64 -> "sld"
_ -> panic "PPC.Ppr.pprInstr: shift illegal size"
in pprLogic (sLit op) reg1 reg2 (limitShiftRI fmt ri)
-pprInstr (SR fmt reg1 reg2 ri) =
- let op = case fmt of
+ SR fmt reg1 reg2 ri
+ -> let op = case fmt of
II32 -> "srw"
II64 -> "srd"
_ -> panic "PPC.Ppr.pprInstr: shift illegal size"
in pprLogic (sLit op) reg1 reg2 (limitShiftRI fmt ri)
-pprInstr (SRA fmt reg1 reg2 ri) =
- let op = case fmt of
+ SRA fmt reg1 reg2 ri
+ -> let op = case fmt of
II32 -> "sraw"
II64 -> "srad"
_ -> panic "PPC.Ppr.pprInstr: shift illegal size"
in pprLogic (sLit op) reg1 reg2 (limitShiftRI fmt ri)
-pprInstr (RLWINM reg1 reg2 sh mb me) = hcat [
- text "\trlwinm\t",
- pprReg reg1,
- text ", ",
- pprReg reg2,
- text ", ",
- int sh,
- text ", ",
- int mb,
- text ", ",
- int me
- ]
-
-pprInstr (CLRLI fmt reg1 reg2 n) = hcat [
- text "\tclrl",
- pprFormat fmt,
- text "i ",
- pprReg reg1,
- text ", ",
- pprReg reg2,
- text ", ",
- int n
- ]
-pprInstr (CLRRI fmt reg1 reg2 n) = hcat [
- text "\tclrr",
- pprFormat fmt,
- text "i ",
- pprReg reg1,
- text ", ",
- pprReg reg2,
- text ", ",
- int n
- ]
-
-pprInstr (FADD fmt reg1 reg2 reg3) = pprBinaryF (sLit "fadd") fmt reg1 reg2 reg3
-pprInstr (FSUB fmt reg1 reg2 reg3) = pprBinaryF (sLit "fsub") fmt reg1 reg2 reg3
-pprInstr (FMUL fmt reg1 reg2 reg3) = pprBinaryF (sLit "fmul") fmt reg1 reg2 reg3
-pprInstr (FDIV fmt reg1 reg2 reg3) = pprBinaryF (sLit "fdiv") fmt reg1 reg2 reg3
-pprInstr (FABS reg1 reg2) = pprUnary (sLit "fabs") reg1 reg2
-pprInstr (FNEG reg1 reg2) = pprUnary (sLit "fneg") reg1 reg2
-
-pprInstr (FCMP reg1 reg2) = hcat [
- char '\t',
- text "fcmpu\t0, ",
- -- Note: we're using fcmpu, not fcmpo
- -- The difference is with fcmpo, compare with NaN is an invalid operation.
- -- We don't handle invalid fp ops, so we don't care.
- -- Moreover, we use `fcmpu 0, ...` rather than `fcmpu cr0, ...` for
- -- better portability since some non-GNU assembler (such as
- -- IBM's `as`) tend not to support the symbolic register name cr0.
- -- This matches the syntax that GCC seems to emit for PPC targets.
- pprReg reg1,
- text ", ",
- pprReg reg2
- ]
-
-pprInstr (FCTIWZ reg1 reg2) = pprUnary (sLit "fctiwz") reg1 reg2
-pprInstr (FCTIDZ reg1 reg2) = pprUnary (sLit "fctidz") reg1 reg2
-pprInstr (FCFID reg1 reg2) = pprUnary (sLit "fcfid") reg1 reg2
-pprInstr (FRSP reg1 reg2) = pprUnary (sLit "frsp") reg1 reg2
-
-pprInstr (CRNOR dst src1 src2) = hcat [
- text "\tcrnor\t",
- int dst,
- text ", ",
- int src1,
- text ", ",
- int src2
- ]
-
-pprInstr (MFCR reg) = hcat [
- char '\t',
- text "mfcr",
- char '\t',
- pprReg reg
- ]
-
-pprInstr (MFLR reg) = hcat [
- char '\t',
- text "mflr",
- char '\t',
- pprReg reg
- ]
-
-pprInstr (FETCHPC reg) = vcat [
- text "\tbcl\t20,31,1f",
- hcat [ text "1:\tmflr\t", pprReg reg ]
- ]
-
-pprInstr HWSYNC = text "\tsync"
-
-pprInstr ISYNC = text "\tisync"
-
-pprInstr LWSYNC = text "\tlwsync"
+ RLWINM reg1 reg2 sh mb me
+ -> hcat [
+ text "\trlwinm\t",
+ pprReg reg1,
+ text ", ",
+ pprReg reg2,
+ text ", ",
+ int sh,
+ text ", ",
+ int mb,
+ text ", ",
+ int me
+ ]
+
+ CLRLI fmt reg1 reg2 n
+ -> hcat [
+ text "\tclrl",
+ pprFormat fmt,
+ text "i ",
+ pprReg reg1,
+ text ", ",
+ pprReg reg2,
+ text ", ",
+ int n
+ ]
-pprInstr NOP = text "\tnop"
+ CLRRI fmt reg1 reg2 n
+ -> hcat [
+ text "\tclrr",
+ pprFormat fmt,
+ text "i ",
+ pprReg reg1,
+ text ", ",
+ pprReg reg2,
+ text ", ",
+ int n
+ ]
+ FADD fmt reg1 reg2 reg3
+ -> pprBinaryF (sLit "fadd") fmt reg1 reg2 reg3
+
+ FSUB fmt reg1 reg2 reg3
+ -> pprBinaryF (sLit "fsub") fmt reg1 reg2 reg3
+
+ FMUL fmt reg1 reg2 reg3
+ -> pprBinaryF (sLit "fmul") fmt reg1 reg2 reg3
+
+ FDIV fmt reg1 reg2 reg3
+ -> pprBinaryF (sLit "fdiv") fmt reg1 reg2 reg3
+
+ FABS reg1 reg2
+ -> pprUnary (sLit "fabs") reg1 reg2
+
+ FNEG reg1 reg2
+ -> pprUnary (sLit "fneg") reg1 reg2
+
+ FCMP reg1 reg2
+ -> hcat [
+ char '\t',
+ text "fcmpu\t0, ",
+ -- Note: we're using fcmpu, not fcmpo
+ -- The difference is with fcmpo, compare with NaN is an invalid operation.
+ -- We don't handle invalid fp ops, so we don't care.
+ -- Moreover, we use `fcmpu 0, ...` rather than `fcmpu cr0, ...` for
+ -- better portability since some non-GNU assembler (such as
+ -- IBM's `as`) tend not to support the symbolic register name cr0.
+ -- This matches the syntax that GCC seems to emit for PPC targets.
+ pprReg reg1,
+ text ", ",
+ pprReg reg2
+ ]
+
+ FCTIWZ reg1 reg2
+ -> pprUnary (sLit "fctiwz") reg1 reg2
+
+ FCTIDZ reg1 reg2
+ -> pprUnary (sLit "fctidz") reg1 reg2
+
+ FCFID reg1 reg2
+ -> pprUnary (sLit "fcfid") reg1 reg2
+
+ FRSP reg1 reg2
+ -> pprUnary (sLit "frsp") reg1 reg2
+
+ CRNOR dst src1 src2
+ -> hcat [
+ text "\tcrnor\t",
+ int dst,
+ text ", ",
+ int src1,
+ text ", ",
+ int src2
+ ]
+
+ MFCR reg
+ -> hcat [
+ char '\t',
+ text "mfcr",
+ char '\t',
+ pprReg reg
+ ]
+
+ MFLR reg
+ -> hcat [
+ char '\t',
+ text "mflr",
+ char '\t',
+ pprReg reg
+ ]
+
+ FETCHPC reg
+ -> vcat [
+ text "\tbcl\t20,31,1f",
+ hcat [ text "1:\tmflr\t", pprReg reg ]
+ ]
+
+ HWSYNC
+ -> text "\tsync"
+
+ ISYNC
+ -> text "\tisync"
+
+ LWSYNC
+ -> text "\tlwsync"
+
+ NOP
+ -> text "\tnop"
pprLogic :: PtrString -> Reg -> Reg -> RI -> SDoc
pprLogic op reg1 reg2 ri = hcat [
diff --git a/compiler/GHC/CmmToAsm/PPC/Regs.hs b/compiler/GHC/CmmToAsm/PPC/Regs.hs
index 8a9a859665..90f8a62ab7 100644
--- a/compiler/GHC/CmmToAsm/PPC/Regs.hs
+++ b/compiler/GHC/CmmToAsm/PPC/Regs.hs
@@ -60,7 +60,6 @@ import GHC.Cmm.CLabel ( CLabel )
import Unique
import GHC.Platform.Regs
-import GHC.Driver.Session
import Outputable
import GHC.Platform
@@ -199,11 +198,11 @@ addrOffset addr off
-- temporaries and for excess call arguments. @fpRel@, where
-- applicable, is the same but for the frame pointer.
-spRel :: DynFlags
+spRel :: Platform
-> Int -- desired stack offset in words, positive or negative
-> AddrMode
-spRel dflags n = AddrRegImm sp (ImmInt (n * wORD_SIZE dflags))
+spRel platform n = AddrRegImm sp (ImmInt (n * platformWordSizeInBytes platform))
-- argRegs is the set of regs which are read for an n-argument call to C.
diff --git a/compiler/GHC/CmmToAsm/Ppr.hs b/compiler/GHC/CmmToAsm/Ppr.hs
index 636d2e4e3a..324bad63c4 100644
--- a/compiler/GHC/CmmToAsm/Ppr.hs
+++ b/compiler/GHC/CmmToAsm/Ppr.hs
@@ -25,6 +25,7 @@ import GhcPrelude
import AsmUtils
import GHC.Cmm.CLabel
import GHC.Cmm
+import GHC.CmmToAsm.Config
import GHC.Driver.Session
import FastString
import Outputable
@@ -203,48 +204,49 @@ 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 :: Platform -> Section -> SDoc
-pprSectionHeader platform (Section t suffix) =
- case platformOS platform of
+pprSectionHeader :: NCGConfig -> Section -> SDoc
+pprSectionHeader config (Section t suffix) =
+ case platformOS (ncgPlatform config) of
OSAIX -> pprXcoffSectionHeader t
OSDarwin -> pprDarwinSectionHeader t
- OSMinGW32 -> pprGNUSectionHeader (char '$') t suffix
- _ -> pprGNUSectionHeader (char '.') t suffix
-
-pprGNUSectionHeader :: SDoc -> SectionType -> CLabel -> SDoc
-pprGNUSectionHeader sep t suffix = sdocWithDynFlags $ \dflags ->
- let splitSections = gopt Opt_SplitSections dflags
- subsection | splitSections = sep <> ppr suffix
- | otherwise = empty
- in text ".section " <> ptext (header dflags) <> subsection <>
- flags dflags
+ OSMinGW32 -> pprGNUSectionHeader config (char '$') t suffix
+ _ -> pprGNUSectionHeader config (char '.') t suffix
+
+pprGNUSectionHeader :: NCGConfig -> SDoc -> SectionType -> CLabel -> SDoc
+pprGNUSectionHeader config sep t suffix =
+ text ".section " <> ptext header <> subsection <> flags
where
- header dflags = case t of
+ platform = ncgPlatform config
+ splitSections = ncgSplitSections config
+ subsection
+ | splitSections = sep <> ppr suffix
+ | otherwise = empty
+ header = case t of
Text -> sLit ".text"
Data -> sLit ".data"
- ReadOnlyData | OSMinGW32 <- platformOS (targetPlatform dflags)
+ ReadOnlyData | OSMinGW32 <- platformOS platform
-> sLit ".rdata"
| otherwise -> sLit ".rodata"
- RelocatableReadOnlyData | OSMinGW32 <- platformOS (targetPlatform dflags)
+ RelocatableReadOnlyData | OSMinGW32 <- platformOS platform
-- Concept does not exist on Windows,
-- So map these to R/O data.
-> sLit ".rdata$rel.ro"
| otherwise -> sLit ".data.rel.ro"
UninitialisedData -> sLit ".bss"
- ReadOnlyData16 | OSMinGW32 <- platformOS (targetPlatform dflags)
+ ReadOnlyData16 | OSMinGW32 <- platformOS platform
-> sLit ".rdata$cst16"
| otherwise -> sLit ".rodata.cst16"
CString
- | OSMinGW32 <- platformOS (targetPlatform dflags)
+ | OSMinGW32 <- platformOS platform
-> sLit ".rdata"
| otherwise -> sLit ".rodata.str"
OtherSection _ ->
panic "PprBase.pprGNUSectionHeader: unknown section type"
- flags dflags = case t of
+ flags = case t of
CString
- | OSMinGW32 <- platformOS (targetPlatform dflags)
+ | OSMinGW32 <- platformOS platform
-> empty
- | otherwise -> text ",\"aMS\"," <> sectionType "progbits" <> text ",1"
+ | otherwise -> text ",\"aMS\"," <> sectionType platform "progbits" <> text ",1"
_ -> empty
-- XCOFF doesn't support relocating label-differences, so we place all
diff --git a/compiler/GHC/CmmToAsm/Reg/Graph.hs b/compiler/GHC/CmmToAsm/Reg/Graph.hs
index 6dfe84cf95..7f0cacfcb4 100644
--- a/compiler/GHC/CmmToAsm/Reg/Graph.hs
+++ b/compiler/GHC/CmmToAsm/Reg/Graph.hs
@@ -16,11 +16,11 @@ import GHC.CmmToAsm.Reg.Graph.Stats
import GHC.CmmToAsm.Reg.Graph.TrivColorable
import GHC.CmmToAsm.Instr
import GHC.CmmToAsm.Reg.Target
+import GHC.CmmToAsm.Config
import GHC.Platform.Reg.Class
import GHC.Platform.Reg
import Bag
-import GHC.Driver.Session
import Outputable
import GHC.Platform
import UniqFM
@@ -45,7 +45,7 @@ maxSpinCount = 10
-- | The top level of the graph coloring register allocator.
regAlloc
:: (Outputable statics, Outputable instr, Instruction instr)
- => DynFlags
+ => NCGConfig
-> UniqFM (UniqSet RealReg) -- ^ registers we can use for allocation
-> UniqSet Int -- ^ set of available spill slots.
-> Int -- ^ current number of spill slots
@@ -56,18 +56,15 @@ regAlloc
-- ^ code with registers allocated, additional stacks required
-- and stats for each stage of allocation
-regAlloc dflags regsFree slotsFree slotsCount code cfg
+regAlloc config regsFree slotsFree slotsCount code cfg
= do
- -- TODO: the regClass function is currently hard coded to the default
- -- target architecture. Would prefer to determine this from dflags.
- -- There are other uses of targetRegClass later in this module.
- let platform = targetPlatform dflags
+ let platform = ncgPlatform config
triv = trivColorable platform
(targetVirtualRegSqueeze platform)
(targetRealRegSqueeze platform)
(code_final, debug_codeGraphs, slotsCount', _)
- <- regAlloc_spin dflags 0
+ <- regAlloc_spin config 0
triv
regsFree slotsFree slotsCount [] code cfg
@@ -94,7 +91,7 @@ regAlloc_spin
(Instruction instr,
Outputable instr,
Outputable statics)
- => DynFlags
+ => NCGConfig
-> Int -- ^ Number of solver iterations we've already performed.
-> Color.Triv VirtualReg RegClass RealReg
-- ^ Function for calculating whether a register is trivially
@@ -110,17 +107,18 @@ regAlloc_spin
, Int -- Slots in use
, Color.Graph VirtualReg RegClass RealReg)
-regAlloc_spin dflags spinCount triv regsFree slotsFree slotsCount debug_codeGraphs code cfg
+regAlloc_spin config spinCount triv regsFree slotsFree slotsCount debug_codeGraphs code cfg
= do
- let platform = targetPlatform dflags
+ let platform = ncgPlatform config
-- If any of these dump flags are turned on we want to hang on to
-- intermediate structures in the allocator - otherwise tell the
-- allocator to ditch them early so we don't end up creating space leaks.
let dump = or
- [ dopt Opt_D_dump_asm_regalloc_stages dflags
- , dopt Opt_D_dump_asm_stats dflags
- , dopt Opt_D_dump_asm_conflicts dflags ]
+ [ ncgDumpRegAllocStages config
+ , ncgDumpAsmStats config
+ , ncgDumpAsmConflicts config
+ ]
-- Check that we're not running off down the garden path.
when (spinCount > maxSpinCount)
@@ -161,14 +159,16 @@ regAlloc_spin dflags spinCount triv regsFree slotsFree slotsCount debug_codeGrap
then Just $ RegAllocStatsStart
{ raLiveCmm = code
, raGraph = graph
- , raSpillCosts = spillCosts }
+ , raSpillCosts = spillCosts
+ , raPlatform = platform
+ }
else Nothing
-- Try and color the graph.
let (graph_colored, rsSpill, rmCoalesce)
= {-# SCC "ColorGraph" #-}
Color.colorGraph
- (gopt Opt_RegsIterative dflags)
+ (ncgRegsIterative config)
spinCount
regsFree triv spill graph
@@ -193,7 +193,7 @@ regAlloc_spin dflags spinCount triv regsFree slotsFree slotsCount debug_codeGrap
-- if -fasm-lint is turned on then validate the graph.
-- This checks for bugs in the graph allocator itself.
let graph_colored_lint =
- if gopt Opt_DoAsmLinting dflags
+ if ncgAsmLinting config
then Color.validateGraph (text "")
True -- Require all nodes to be colored.
graph_colored
@@ -215,7 +215,7 @@ regAlloc_spin dflags spinCount triv regsFree slotsFree slotsCount debug_codeGrap
-- Also rewrite SPILL/RELOAD meta instructions into real machine
-- instructions along the way
let code_final
- = map (stripLive dflags) code_spillclean
+ = map (stripLive config) code_spillclean
-- Record what happened in this stage for debugging
let stat
@@ -229,7 +229,9 @@ regAlloc_spin dflags spinCount triv regsFree slotsFree slotsCount debug_codeGrap
, raSpillClean = code_spillclean
, raFinal = code_final
, raSRMs = foldl' addSRM (0, 0, 0)
- $ map countSRMs code_spillclean }
+ $ map countSRMs code_spillclean
+ , raPlatform = platform
+ }
-- Bundle up all the register allocator statistics.
-- .. but make sure to drop them on the floor if they're not
@@ -251,7 +253,7 @@ regAlloc_spin dflags spinCount triv regsFree slotsFree slotsCount debug_codeGrap
else do
-- if -fasm-lint is turned on then validate the graph
let graph_colored_lint =
- if gopt Opt_DoAsmLinting dflags
+ if ncgAsmLinting config
then Color.validateGraph (text "")
False -- don't require nodes to be colored
graph_colored
@@ -289,7 +291,7 @@ regAlloc_spin dflags spinCount triv regsFree slotsFree slotsCount debug_codeGrap
-- Ensure all the statistics are evaluated, to avoid space leaks.
seqList statList (return ())
- regAlloc_spin dflags (spinCount + 1) triv regsFree slotsFree'
+ regAlloc_spin config (spinCount + 1) triv regsFree slotsFree'
slotsCount' statList code_relive cfg
diff --git a/compiler/GHC/CmmToAsm/Reg/Graph/Stats.hs b/compiler/GHC/CmmToAsm/Reg/Graph/Stats.hs
index 05d2e814af..2285d3e908 100644
--- a/compiler/GHC/CmmToAsm/Reg/Graph/Stats.hs
+++ b/compiler/GHC/CmmToAsm/Reg/Graph/Stats.hs
@@ -27,6 +27,7 @@ import GHC.CmmToAsm.Instr
import GHC.Platform.Reg.Class
import GHC.Platform.Reg
import GHC.CmmToAsm.Reg.Target
+import GHC.Platform
import Outputable
import UniqFM
@@ -45,7 +46,11 @@ data RegAllocStats statics instr
, raGraph :: Color.Graph VirtualReg RegClass RealReg
-- | Information to help choose which regs to spill.
- , raSpillCosts :: SpillCostInfo }
+ , raSpillCosts :: SpillCostInfo
+
+ -- | Target platform
+ , raPlatform :: !Platform
+ }
-- Information about an intermediate graph.
@@ -98,23 +103,27 @@ data RegAllocStats statics instr
, raFinal :: [NatCmmDecl statics instr]
-- | Spill\/reload\/reg-reg moves present in this code.
- , raSRMs :: (Int, Int, Int) }
+ , raSRMs :: (Int, Int, Int)
+
+ -- | Target platform
+ , raPlatform :: !Platform
+ }
instance (Outputable statics, Outputable instr)
=> Outputable (RegAllocStats statics instr) where
- ppr (s@RegAllocStatsStart{}) = sdocWithPlatform $ \platform ->
- text "# Start"
+ ppr (s@RegAllocStatsStart{})
+ = text "# Start"
$$ text "# Native code with liveness information."
$$ ppr (raLiveCmm s)
$$ text ""
$$ text "# Initial register conflict graph."
$$ Color.dotGraph
- (targetRegDotColor platform)
- (trivColorable platform
- (targetVirtualRegSqueeze platform)
- (targetRealRegSqueeze platform))
+ (targetRegDotColor (raPlatform s))
+ (trivColorable (raPlatform s)
+ (targetVirtualRegSqueeze (raPlatform s))
+ (targetRealRegSqueeze (raPlatform s)))
(raGraph s)
@@ -140,8 +149,7 @@ instance (Outputable statics, Outputable instr)
ppr (s@RegAllocStatsColored { raSRMs = (spills, reloads, moves) })
- = sdocWithPlatform $ \platform ->
- text "# Colored"
+ = text "# Colored"
$$ text "# Code with liveness information."
$$ ppr (raCode s)
@@ -149,10 +157,10 @@ instance (Outputable statics, Outputable instr)
$$ text "# Register conflict graph (colored)."
$$ Color.dotGraph
- (targetRegDotColor platform)
- (trivColorable platform
- (targetVirtualRegSqueeze platform)
- (targetRealRegSqueeze platform))
+ (targetRegDotColor (raPlatform s))
+ (trivColorable (raPlatform s)
+ (targetVirtualRegSqueeze (raPlatform s))
+ (targetRealRegSqueeze (raPlatform s)))
(raGraphColored s)
$$ text ""
diff --git a/compiler/GHC/CmmToAsm/Reg/Linear.hs b/compiler/GHC/CmmToAsm/Reg/Linear.hs
index 9b263889d8..155d67c2c2 100644
--- a/compiler/GHC/CmmToAsm/Reg/Linear.hs
+++ b/compiler/GHC/CmmToAsm/Reg/Linear.hs
@@ -119,6 +119,7 @@ import qualified GHC.CmmToAsm.Reg.Linear.X86_64 as X86_64
import GHC.CmmToAsm.Reg.Target
import GHC.CmmToAsm.Reg.Liveness
import GHC.CmmToAsm.Instr
+import GHC.CmmToAsm.Config
import GHC.Platform.Reg
import GHC.Cmm.BlockId
@@ -126,7 +127,6 @@ import GHC.Cmm.Dataflow.Collections
import GHC.Cmm hiding (RegSet)
import Digraph
-import GHC.Driver.Session
import Unique
import UniqSet
import UniqFM
@@ -144,7 +144,7 @@ import Control.Monad
-- Allocate registers
regAlloc
:: (Outputable instr, Instruction instr)
- => DynFlags
+ => NCGConfig
-> LiveCmmDecl statics instr
-> UniqSM ( NatCmmDecl statics instr
, Maybe Int -- number of extra stack slots required,
@@ -163,19 +163,19 @@ regAlloc _ (CmmProc (LiveInfo info _ _ _) lbl live [])
, Nothing
, Nothing )
-regAlloc dflags (CmmProc static lbl live sccs)
+regAlloc config (CmmProc static lbl live sccs)
| LiveInfo info entry_ids@(first_id:_) block_live _ <- static
= do
-- do register allocation on each component.
(final_blocks, stats, stack_use)
- <- linearRegAlloc dflags entry_ids block_live sccs
+ <- linearRegAlloc config entry_ids block_live sccs
-- make sure the block that was first in the input list
-- stays at the front of the output
let ((first':_), rest')
= partition ((== first_id) . blockId) final_blocks
- let max_spill_slots = maxSpillSlots dflags
+ let max_spill_slots = maxSpillSlots config
extra_stack
| stack_use > max_spill_slots
= Just (stack_use - max_spill_slots)
@@ -201,7 +201,7 @@ regAlloc _ (CmmProc _ _ _ _)
--
linearRegAlloc
:: (Outputable instr, Instruction instr)
- => DynFlags
+ => NCGConfig
-> [BlockId] -- ^ entry points
-> BlockMap RegSet
-- ^ live regs on entry to each basic block
@@ -209,7 +209,7 @@ linearRegAlloc
-- ^ instructions annotated with "deaths"
-> UniqSM ([NatBasicBlock instr], RegAllocStats, Int)
-linearRegAlloc dflags entry_ids block_live sccs
+linearRegAlloc config entry_ids block_live sccs
= case platformArch platform of
ArchX86 -> go $ (frInitFreeRegs platform :: X86.FreeRegs)
ArchX86_64 -> go $ (frInitFreeRegs platform :: X86_64.FreeRegs)
@@ -226,22 +226,22 @@ linearRegAlloc dflags entry_ids block_live sccs
ArchJavaScript -> panic "linearRegAlloc ArchJavaScript"
ArchUnknown -> panic "linearRegAlloc ArchUnknown"
where
- go f = linearRegAlloc' dflags f entry_ids block_live sccs
- platform = targetPlatform dflags
+ go f = linearRegAlloc' config f entry_ids block_live sccs
+ platform = ncgPlatform config
linearRegAlloc'
:: (FR freeRegs, Outputable instr, Instruction instr)
- => DynFlags
+ => NCGConfig
-> freeRegs
-> [BlockId] -- ^ entry points
-> BlockMap RegSet -- ^ live regs on entry to each basic block
-> [SCC (LiveBasicBlock instr)] -- ^ instructions annotated with "deaths"
-> UniqSM ([NatBasicBlock instr], RegAllocStats, Int)
-linearRegAlloc' dflags initFreeRegs entry_ids block_live sccs
+linearRegAlloc' config initFreeRegs entry_ids block_live sccs
= do us <- getUniqueSupplyM
let (_, stack, stats, blocks) =
- runR dflags mapEmpty initFreeRegs emptyRegMap (emptyStackMap dflags) us
+ runR config mapEmpty initFreeRegs emptyRegMap emptyStackMap us
$ linearRA_SCCs entry_ids block_live [] sccs
return (blocks, stats, getStackUse stack)
@@ -342,9 +342,8 @@ processBlock block_live (BasicBlock id instrs)
initBlock :: FR freeRegs
=> BlockId -> BlockMap RegSet -> RegM freeRegs ()
initBlock id block_live
- = do dflags <- getDynFlags
- let platform = targetPlatform dflags
- block_assig <- getBlockAssigR
+ = do platform <- getPlatform
+ block_assig <- getBlockAssigR
case mapLookup id block_assig of
-- no prior info about this block: we must consider
-- any fixed regs to be allocated, but we can ignore
@@ -487,8 +486,7 @@ genRaInsn :: (FR freeRegs, Instruction instr, Outputable instr)
-> RegM freeRegs ([instr], [NatBasicBlock instr])
genRaInsn block_live new_instrs block_id instr r_dying w_dying = do
- dflags <- getDynFlags
- let platform = targetPlatform dflags
+ platform <- getPlatform
case regUsageOfInstr platform instr of { RU read written ->
do
let real_written = [ rr | (RegReal rr) <- written ]
@@ -590,8 +588,7 @@ genRaInsn block_live new_instrs block_id instr r_dying w_dying = do
releaseRegs :: FR freeRegs => [Reg] -> RegM freeRegs ()
releaseRegs regs = do
- dflags <- getDynFlags
- let platform = targetPlatform dflags
+ platform <- getPlatform
assig <- getAssigR
free <- getFreeRegsR
let loop assig !free [] = do setAssigR assig; setFreeRegsR free; return ()
@@ -651,8 +648,7 @@ saveClobberedTemps clobbered dying
= return (instrs, assig)
clobber assig instrs ((temp, reg) : rest)
- = do dflags <- getDynFlags
- let platform = targetPlatform dflags
+ = do platform <- getPlatform
freeRegs <- getFreeRegsR
let regclass = targetClassOfRealReg platform reg
@@ -693,10 +689,8 @@ clobberRegs []
= return ()
clobberRegs clobbered
- = do dflags <- getDynFlags
- let platform = targetPlatform dflags
-
- freeregs <- getFreeRegsR
+ = do platform <- getPlatform
+ freeregs <- getFreeRegsR
setFreeRegsR $! foldl' (flip $ frAllocateReg platform) freeregs clobbered
assig <- getAssigR
@@ -799,9 +793,8 @@ allocRegsAndSpill_spill :: (FR freeRegs, Instruction instr, Outputable instr)
-> SpillLoc
-> RegM freeRegs ([instr], [RealReg])
allocRegsAndSpill_spill reading keep spills alloc r rs assig spill_loc
- = do dflags <- getDynFlags
- let platform = targetPlatform dflags
- freeRegs <- getFreeRegsR
+ = do platform <- getPlatform
+ freeRegs <- getFreeRegsR
let freeRegs_thisClass = frGetFreeRegs platform (classOfVirtualReg r) freeRegs
case freeRegs_thisClass of
diff --git a/compiler/GHC/CmmToAsm/Reg/Linear/Base.hs b/compiler/GHC/CmmToAsm/Reg/Linear/Base.hs
index 43dbab843b..92b3ee19a3 100644
--- a/compiler/GHC/CmmToAsm/Reg/Linear/Base.hs
+++ b/compiler/GHC/CmmToAsm/Reg/Linear/Base.hs
@@ -21,9 +21,9 @@ import GhcPrelude
import GHC.CmmToAsm.Reg.Linear.StackMap
import GHC.CmmToAsm.Reg.Liveness
+import GHC.CmmToAsm.Config
import GHC.Platform.Reg
-import GHC.Driver.Session
import Outputable
import Unique
import UniqFM
@@ -133,7 +133,9 @@ data RA_State freeRegs
-- Just keep a list here instead of a map of regs -> reasons.
-- We don't want to slow down the allocator if we're not going to emit the stats.
, ra_spills :: [SpillReason]
- , ra_DynFlags :: DynFlags
+
+ -- | Native code generator configuration
+ , ra_config :: !NCGConfig
-- | (from,fixup,to) : We inserted fixup code between from and to
, ra_fixups :: [(BlockId,BlockId,BlockId)] }
diff --git a/compiler/GHC/CmmToAsm/Reg/Linear/FreeRegs.hs b/compiler/GHC/CmmToAsm/Reg/Linear/FreeRegs.hs
index 0d72d8b6e9..e340dcf5c6 100644
--- a/compiler/GHC/CmmToAsm/Reg/Linear/FreeRegs.hs
+++ b/compiler/GHC/CmmToAsm/Reg/Linear/FreeRegs.hs
@@ -14,7 +14,7 @@ import GhcPrelude
import GHC.Platform.Reg
import GHC.Platform.Reg.Class
-import GHC.Driver.Session
+import GHC.CmmToAsm.Config
import Panic
import GHC.Platform
@@ -69,21 +69,19 @@ instance FR SPARC.FreeRegs where
frInitFreeRegs = SPARC.initFreeRegs
frReleaseReg = SPARC.releaseReg
-maxSpillSlots :: DynFlags -> Int
-maxSpillSlots dflags
- = case platformArch (targetPlatform dflags) of
- ArchX86 -> X86.Instr.maxSpillSlots dflags
- ArchX86_64 -> X86.Instr.maxSpillSlots dflags
- ArchPPC -> PPC.Instr.maxSpillSlots dflags
- ArchS390X -> panic "maxSpillSlots ArchS390X"
- ArchSPARC -> SPARC.Instr.maxSpillSlots dflags
- ArchSPARC64 -> panic "maxSpillSlots ArchSPARC64"
- ArchARM _ _ _ -> panic "maxSpillSlots ArchARM"
- ArchARM64 -> panic "maxSpillSlots ArchARM64"
- ArchPPC_64 _ -> PPC.Instr.maxSpillSlots dflags
- ArchAlpha -> panic "maxSpillSlots ArchAlpha"
- ArchMipseb -> panic "maxSpillSlots ArchMipseb"
- ArchMipsel -> panic "maxSpillSlots ArchMipsel"
- ArchJavaScript-> panic "maxSpillSlots ArchJavaScript"
- ArchUnknown -> panic "maxSpillSlots ArchUnknown"
-
+maxSpillSlots :: NCGConfig -> Int
+maxSpillSlots config = case platformArch (ncgPlatform config) of
+ ArchX86 -> X86.Instr.maxSpillSlots config
+ ArchX86_64 -> X86.Instr.maxSpillSlots config
+ ArchPPC -> PPC.Instr.maxSpillSlots config
+ ArchS390X -> panic "maxSpillSlots ArchS390X"
+ ArchSPARC -> SPARC.Instr.maxSpillSlots config
+ ArchSPARC64 -> panic "maxSpillSlots ArchSPARC64"
+ ArchARM _ _ _ -> panic "maxSpillSlots ArchARM"
+ ArchARM64 -> panic "maxSpillSlots ArchARM64"
+ ArchPPC_64 _ -> PPC.Instr.maxSpillSlots config
+ ArchAlpha -> panic "maxSpillSlots ArchAlpha"
+ ArchMipseb -> panic "maxSpillSlots ArchMipseb"
+ ArchMipsel -> panic "maxSpillSlots ArchMipsel"
+ ArchJavaScript-> panic "maxSpillSlots ArchJavaScript"
+ ArchUnknown -> panic "maxSpillSlots ArchUnknown"
diff --git a/compiler/GHC/CmmToAsm/Reg/Linear/JoinToTargets.hs b/compiler/GHC/CmmToAsm/Reg/Linear/JoinToTargets.hs
index b4ad1b948c..0874cd0dbf 100644
--- a/compiler/GHC/CmmToAsm/Reg/Linear/JoinToTargets.hs
+++ b/compiler/GHC/CmmToAsm/Reg/Linear/JoinToTargets.hs
@@ -17,12 +17,12 @@ import GHC.CmmToAsm.Reg.Linear.Base
import GHC.CmmToAsm.Reg.Linear.FreeRegs
import GHC.CmmToAsm.Reg.Liveness
import GHC.CmmToAsm.Instr
+import GHC.CmmToAsm.Config
import GHC.Platform.Reg
import GHC.Cmm.BlockId
import GHC.Cmm.Dataflow.Collections
import Digraph
-import GHC.Driver.Session
import Outputable
import Unique
import UniqFM
@@ -125,8 +125,8 @@ joinToTargets_first block_live new_blocks block_id instr dest dests
block_assig src_assig
to_free
- = do dflags <- getDynFlags
- let platform = targetPlatform dflags
+ = do config <- getConfig
+ let platform = ncgPlatform config
-- free up the regs that are not live on entry to this block.
freeregs <- getFreeRegsR
@@ -355,8 +355,8 @@ makeMove
-> RegM freeRegs instr -- ^ move instruction.
makeMove delta vreg src dst
- = do dflags <- getDynFlags
- let platform = targetPlatform dflags
+ = do config <- getConfig
+ let platform = ncgPlatform config
case (src, dst) of
(InReg s, InReg d) ->
@@ -364,10 +364,10 @@ makeMove delta vreg src dst
return $ mkRegRegMoveInstr platform (RegReal s) (RegReal d)
(InMem s, InReg d) ->
do recordSpill (SpillJoinRM vreg)
- return $ mkLoadInstr dflags (RegReal d) delta s
+ return $ mkLoadInstr config (RegReal d) delta s
(InReg s, InMem d) ->
do recordSpill (SpillJoinRM vreg)
- return $ mkSpillInstr dflags (RegReal s) delta d
+ return $ mkSpillInstr config (RegReal s) delta d
_ ->
-- we don't handle memory to memory moves.
-- they shouldn't happen because we don't share
diff --git a/compiler/GHC/CmmToAsm/Reg/Linear/StackMap.hs b/compiler/GHC/CmmToAsm/Reg/Linear/StackMap.hs
index 630b101fc7..00fcfd91c8 100644
--- a/compiler/GHC/CmmToAsm/Reg/Linear/StackMap.hs
+++ b/compiler/GHC/CmmToAsm/Reg/Linear/StackMap.hs
@@ -22,7 +22,6 @@ where
import GhcPrelude
-import GHC.Driver.Session
import UniqFM
import Unique
@@ -40,8 +39,8 @@ data StackMap
-- | An empty stack map, with all slots available.
-emptyStackMap :: DynFlags -> StackMap
-emptyStackMap _ = StackMap 0 emptyUFM
+emptyStackMap :: StackMap
+emptyStackMap = StackMap 0 emptyUFM
-- | If this vreg unique already has a stack assignment then return the slot number,
diff --git a/compiler/GHC/CmmToAsm/Reg/Linear/State.hs b/compiler/GHC/CmmToAsm/Reg/Linear/State.hs
index a167cc7e00..5a1e3a4c3f 100644
--- a/compiler/GHC/CmmToAsm/Reg/Linear/State.hs
+++ b/compiler/GHC/CmmToAsm/Reg/Linear/State.hs
@@ -30,6 +30,8 @@ module GHC.CmmToAsm.Reg.Linear.State (
getDeltaR,
getUniqueR,
+ getConfig,
+ getPlatform,
recordSpill,
recordFixupBlock
@@ -43,10 +45,11 @@ import GHC.CmmToAsm.Reg.Linear.StackMap
import GHC.CmmToAsm.Reg.Linear.Base
import GHC.CmmToAsm.Reg.Liveness
import GHC.CmmToAsm.Instr
+import GHC.CmmToAsm.Config
import GHC.Platform.Reg
import GHC.Cmm.BlockId
-import GHC.Driver.Session
+import GHC.Platform
import Unique
import UniqSupply
@@ -79,12 +82,16 @@ instance Applicative (RegM freeRegs) where
instance Monad (RegM freeRegs) where
m >>= k = RegM $ \s -> case unReg m s of { RA_Result s a -> unReg (k a) s }
-instance HasDynFlags (RegM a) where
- getDynFlags = RegM $ \s -> RA_Result s (ra_DynFlags s)
+-- | Get native code generator configuration
+getConfig :: RegM a NCGConfig
+getConfig = RegM $ \s -> RA_Result s (ra_config s)
+-- | Get target platform from native code generator configuration
+getPlatform :: RegM a Platform
+getPlatform = ncgPlatform <$> getConfig
-- | Run a computation in the RegM register allocator monad.
-runR :: DynFlags
+runR :: NCGConfig
-> BlockAssignment freeRegs
-> freeRegs
-> RegMap Loc
@@ -93,7 +100,7 @@ runR :: DynFlags
-> RegM freeRegs a
-> (BlockAssignment freeRegs, StackMap, RegAllocStats, a)
-runR dflags block_assig freeregs assig stack us thing =
+runR config block_assig freeregs assig stack us thing =
case unReg thing
(RA_State
{ ra_blockassig = block_assig
@@ -103,7 +110,7 @@ runR dflags block_assig freeregs assig stack us thing =
, ra_stack = stack
, ra_us = us
, ra_spills = []
- , ra_DynFlags = dflags
+ , ra_config = config
, ra_fixups = [] })
of
RA_Result state returned_thing
@@ -121,10 +128,9 @@ makeRAStats state
spillR :: Instruction instr
=> Reg -> Unique -> RegM freeRegs (instr, Int)
-spillR reg temp = RegM $ \ s@RA_State{ra_delta=delta, ra_stack=stack0} ->
- let dflags = ra_DynFlags s
- (stack1,slot) = getStackSlotFor stack0 temp
- instr = mkSpillInstr dflags reg delta slot
+spillR reg temp = RegM $ \s ->
+ let (stack1,slot) = getStackSlotFor (ra_stack s) temp
+ instr = mkSpillInstr (ra_config s) reg (ra_delta s) slot
in
RA_Result s{ra_stack=stack1} (instr,slot)
@@ -132,9 +138,8 @@ spillR reg temp = RegM $ \ s@RA_State{ra_delta=delta, ra_stack=stack0} ->
loadR :: Instruction instr
=> Reg -> Int -> RegM freeRegs instr
-loadR reg slot = RegM $ \ s@RA_State{ra_delta=delta} ->
- let dflags = ra_DynFlags s
- in RA_Result s (mkLoadInstr dflags reg delta slot)
+loadR reg slot = RegM $ \s ->
+ RA_Result s (mkLoadInstr (ra_config s) reg (ra_delta s) slot)
getFreeRegsR :: RegM freeRegs freeRegs
getFreeRegsR = RegM $ \ s@RA_State{ra_freeregs = freeregs} ->
diff --git a/compiler/GHC/CmmToAsm/Reg/Liveness.hs b/compiler/GHC/CmmToAsm/Reg/Liveness.hs
index 03b8123f93..d1c4c8f498 100644
--- a/compiler/GHC/CmmToAsm/Reg/Liveness.hs
+++ b/compiler/GHC/CmmToAsm/Reg/Liveness.hs
@@ -41,15 +41,15 @@ import GhcPrelude
import GHC.Platform.Reg
import GHC.CmmToAsm.Instr
+import GHC.CmmToAsm.CFG
+import GHC.CmmToAsm.Config
import GHC.Cmm.BlockId
-import GHC.CmmToAsm.CFG
import GHC.Cmm.Dataflow.Collections
import GHC.Cmm.Dataflow.Label
import GHC.Cmm hiding (RegSet, emptyRegSet)
import Digraph
-import GHC.Driver.Session
import MonadUtils
import Outputable
import GHC.Platform
@@ -483,11 +483,11 @@ slurpReloadCoalesce live
-- | Strip away liveness information, yielding NatCmmDecl
stripLive
:: (Outputable statics, Outputable instr, Instruction instr)
- => DynFlags
+ => NCGConfig
-> LiveCmmDecl statics instr
-> NatCmmDecl statics instr
-stripLive dflags live
+stripLive config live
= stripCmm live
where stripCmm :: (Outputable statics, Outputable instr, Instruction instr)
@@ -503,7 +503,7 @@ stripLive dflags live
= partition ((== first_id) . blockId) final_blocks
in CmmProc info label live
- (ListGraph $ map (stripLiveBlock dflags) $ first' : rest')
+ (ListGraph $ map (stripLiveBlock config) $ first' : rest')
-- If the proc has blocks but we don't know what the first one was, then we're dead.
stripCmm proc
@@ -514,11 +514,11 @@ stripLive dflags live
stripLiveBlock
:: Instruction instr
- => DynFlags
+ => NCGConfig
-> LiveBasicBlock instr
-> NatBasicBlock instr
-stripLiveBlock dflags (BasicBlock i lis)
+stripLiveBlock config (BasicBlock i lis)
= BasicBlock i instrs'
where (instrs', _)
@@ -529,11 +529,11 @@ stripLiveBlock dflags (BasicBlock i lis)
spillNat acc (LiveInstr (SPILL reg slot) _ : instrs)
= do delta <- get
- spillNat (mkSpillInstr dflags reg delta slot : acc) instrs
+ spillNat (mkSpillInstr config reg delta slot : acc) instrs
spillNat acc (LiveInstr (RELOAD slot reg) _ : instrs)
= do delta <- get
- spillNat (mkLoadInstr dflags reg delta slot : acc) instrs
+ spillNat (mkLoadInstr config reg delta slot : acc) instrs
spillNat acc (LiveInstr (Instr instr) _ : instrs)
| Just i <- takeDeltaInstr instr
diff --git a/compiler/GHC/CmmToAsm/SPARC/Base.hs b/compiler/GHC/CmmToAsm/SPARC/Base.hs
index 86a897dacb..85b1de9ef3 100644
--- a/compiler/GHC/CmmToAsm/SPARC/Base.hs
+++ b/compiler/GHC/CmmToAsm/SPARC/Base.hs
@@ -8,7 +8,6 @@
module GHC.CmmToAsm.SPARC.Base (
wordLength,
wordLengthInBits,
- spillAreaLength,
spillSlotSize,
extraStackArgsHere,
fits13Bits,
@@ -20,7 +19,6 @@ where
import GhcPrelude
-import GHC.Driver.Session
import Panic
import Data.Int
@@ -34,11 +32,6 @@ wordLengthInBits :: Int
wordLengthInBits
= wordLength * 8
--- Size of the available spill area
-spillAreaLength :: DynFlags -> Int
-spillAreaLength
- = rESERVED_C_STACK_BYTES
-
-- | We need 8 bytes because our largest registers are 64 bit.
spillSlotSize :: Int
spillSlotSize = 8
diff --git a/compiler/GHC/CmmToAsm/SPARC/CodeGen/Gen64.hs b/compiler/GHC/CmmToAsm/SPARC/CodeGen/Gen64.hs
index 43807ec027..18b22b2a1e 100644
--- a/compiler/GHC/CmmToAsm/SPARC/CodeGen/Gen64.hs
+++ b/compiler/GHC/CmmToAsm/SPARC/CodeGen/Gen64.hs
@@ -24,7 +24,6 @@ import GHC.Platform.Reg
import GHC.Cmm
-import GHC.Driver.Session
import OrdList
import Outputable
@@ -184,9 +183,8 @@ iselExpr64 (CmmMachOp (MO_UU_Conv _ W64) [expr])
-- compute expr and load it into r_dst_lo
(a_reg, a_code) <- getSomeReg expr
- dflags <- getDynFlags
- let platform = targetPlatform dflags
- code = a_code
+ platform <- getPlatform
+ let code = a_code
`appOL` toOL
[ mkRegRegMoveInstr platform g0 r_dst_hi -- clear high 32 bits
, mkRegRegMoveInstr platform a_reg r_dst_lo ]
@@ -202,9 +200,8 @@ iselExpr64 (CmmMachOp (MO_SS_Conv W32 W64) [expr])
-- compute expr and load it into r_dst_lo
(a_reg, a_code) <- getSomeReg expr
- dflags <- getDynFlags
- let platform = targetPlatform dflags
- code = a_code
+ platform <- getPlatform
+ let code = a_code
`appOL` toOL
[ SRA a_reg (RIImm (ImmInt 31)) r_dst_hi
, mkRegRegMoveInstr platform a_reg r_dst_lo ]
diff --git a/compiler/GHC/CmmToAsm/SPARC/Instr.hs b/compiler/GHC/CmmToAsm/SPARC/Instr.hs
index ec74d3723b..a1f890bc6d 100644
--- a/compiler/GHC/CmmToAsm/SPARC/Instr.hs
+++ b/compiler/GHC/CmmToAsm/SPARC/Instr.hs
@@ -37,11 +37,11 @@ import GHC.CmmToAsm.Instr
import GHC.Platform.Reg.Class
import GHC.Platform.Reg
import GHC.CmmToAsm.Format
+import GHC.CmmToAsm.Config
import GHC.Cmm.CLabel
import GHC.Platform.Regs
import GHC.Cmm.BlockId
-import GHC.Driver.Session
import GHC.Cmm
import FastString
import Outputable
@@ -369,15 +369,15 @@ sparc_patchJumpInstr insn patchF
-- | Make a spill instruction.
-- On SPARC we spill below frame pointer leaving 2 words/spill
sparc_mkSpillInstr
- :: DynFlags
+ :: NCGConfig
-> Reg -- ^ register to spill
-> Int -- ^ current stack delta
-> Int -- ^ spill slot to use
-> Instr
-sparc_mkSpillInstr dflags reg _ slot
- = let platform = targetPlatform dflags
- off = spillSlotToOffset dflags slot
+sparc_mkSpillInstr config reg _ slot
+ = let platform = ncgPlatform config
+ off = spillSlotToOffset config slot
off_w = 1 + (off `div` 4)
fmt = case targetClassOfReg platform reg of
RcInteger -> II32
@@ -389,15 +389,15 @@ sparc_mkSpillInstr dflags reg _ slot
-- | Make a spill reload instruction.
sparc_mkLoadInstr
- :: DynFlags
+ :: NCGConfig
-> Reg -- ^ register to load into
-> Int -- ^ current stack delta
-> Int -- ^ spill slot to use
-> Instr
-sparc_mkLoadInstr dflags reg _ slot
- = let platform = targetPlatform dflags
- off = spillSlotToOffset dflags slot
+sparc_mkLoadInstr config reg _ slot
+ = let platform = ncgPlatform config
+ off = spillSlotToOffset config slot
off_w = 1 + (off `div` 4)
fmt = case targetClassOfReg platform reg of
RcInteger -> II32
diff --git a/compiler/GHC/CmmToAsm/SPARC/Ppr.hs b/compiler/GHC/CmmToAsm/SPARC/Ppr.hs
index 2f3ea778f7..fc382a5c10 100644
--- a/compiler/GHC/CmmToAsm/SPARC/Ppr.hs
+++ b/compiler/GHC/CmmToAsm/SPARC/Ppr.hs
@@ -36,6 +36,7 @@ import GHC.CmmToAsm.Instr
import GHC.Platform.Reg
import GHC.CmmToAsm.Format
import GHC.CmmToAsm.Ppr
+import GHC.CmmToAsm.Config
import GHC.Cmm hiding (topInfoTable)
import GHC.Cmm.Ppr() -- For Outputable instances
@@ -52,25 +53,26 @@ import FastString
-- -----------------------------------------------------------------------------
-- Printing this stuff out
-pprNatCmmDecl :: NatCmmDecl RawCmmStatics Instr -> SDoc
-pprNatCmmDecl (CmmData section dats) =
- pprSectionAlign section $$ pprDatas dats
+pprNatCmmDecl :: NCGConfig -> NatCmmDecl RawCmmStatics Instr -> SDoc
+pprNatCmmDecl config (CmmData section dats) =
+ pprSectionAlign config section
+ $$ pprDatas (ncgPlatform config) dats
-pprNatCmmDecl proc@(CmmProc top_info lbl _ (ListGraph blocks)) =
+pprNatCmmDecl config proc@(CmmProc top_info lbl _ (ListGraph blocks)) =
+ let platform = ncgPlatform config in
case topInfoTable proc of
Nothing ->
-- special case for code without info table:
- pprSectionAlign (Section Text lbl) $$
- pprLabel lbl $$ -- blocks guaranteed not null, so label needed
- vcat (map (pprBasicBlock top_info) blocks)
+ pprSectionAlign config (Section Text lbl) $$
+ pprLabel platform lbl $$ -- blocks guaranteed not null, so label needed
+ vcat (map (pprBasicBlock platform top_info) blocks)
Just (RawCmmStatics info_lbl _) ->
- sdocWithPlatform $ \platform ->
(if platformHasSubsectionsViaSymbols platform
- then pprSectionAlign dspSection $$
+ then pprSectionAlign config dspSection $$
ppr (mkDeadStripPreventer info_lbl) <> char ':'
else empty) $$
- vcat (map (pprBasicBlock top_info) blocks) $$
+ vcat (map (pprBasicBlock platform 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
@@ -86,10 +88,10 @@ dspSection :: Section
dspSection = Section Text $
panic "subsections-via-symbols doesn't combine with split-sections"
-pprBasicBlock :: LabelMap RawCmmStatics -> NatBasicBlock Instr -> SDoc
-pprBasicBlock info_env (BasicBlock blockid instrs)
+pprBasicBlock :: Platform -> LabelMap RawCmmStatics -> NatBasicBlock Instr -> SDoc
+pprBasicBlock platform info_env (BasicBlock blockid instrs)
= maybe_infotable $$
- pprLabel (blockLbl blockid) $$
+ pprLabel platform (blockLbl blockid) $$
vcat (map pprInstr instrs)
where
maybe_infotable = case mapLookup blockid info_env of
@@ -97,12 +99,12 @@ pprBasicBlock info_env (BasicBlock blockid instrs)
Just (RawCmmStatics info_lbl info) ->
pprAlignForSection Text $$
vcat (map pprData info) $$
- pprLabel info_lbl
+ pprLabel platform info_lbl
-pprDatas :: RawCmmStatics -> SDoc
+pprDatas :: Platform -> RawCmmStatics -> SDoc
-- See note [emit-time elimination of static indirections] in CLabel.
-pprDatas (RawCmmStatics alias [CmmStaticLit (CmmLabel lbl), CmmStaticLit ind, _, _])
+pprDatas _platform (RawCmmStatics alias [CmmStaticLit (CmmLabel lbl), CmmStaticLit ind, _, _])
| lbl == mkIndStaticInfoLabel
, let labelInd (CmmLabelOff l _) = Just l
labelInd (CmmLabel l) = Just l
@@ -111,7 +113,7 @@ pprDatas (RawCmmStatics alias [CmmStaticLit (CmmLabel lbl), CmmStaticLit ind, _,
, alias `mayRedirectTo` ind'
= pprGloblDecl alias
$$ text ".equiv" <+> ppr alias <> comma <> ppr (CmmLabel ind')
-pprDatas (RawCmmStatics lbl dats) = vcat (pprLabel lbl : map pprData dats)
+pprDatas platform (RawCmmStatics lbl dats) = vcat (pprLabel platform lbl : map pprData dats)
pprData :: CmmStatic -> SDoc
pprData (CmmString str) = pprBytes str
@@ -123,17 +125,17 @@ pprGloblDecl lbl
| not (externallyVisibleCLabel lbl) = empty
| otherwise = text ".global " <> ppr lbl
-pprTypeAndSizeDecl :: CLabel -> SDoc
-pprTypeAndSizeDecl lbl
- = sdocWithPlatform $ \platform ->
- if platformOS platform == OSLinux && externallyVisibleCLabel lbl
+pprTypeAndSizeDecl :: Platform -> CLabel -> SDoc
+pprTypeAndSizeDecl platform lbl
+ = if platformOS platform == OSLinux && externallyVisibleCLabel lbl
then text ".type " <> ppr lbl <> ptext (sLit ", @object")
else empty
-pprLabel :: CLabel -> SDoc
-pprLabel lbl = pprGloblDecl lbl
- $$ pprTypeAndSizeDecl lbl
- $$ (ppr lbl <> char ':')
+pprLabel :: Platform -> CLabel -> SDoc
+pprLabel platform lbl =
+ pprGloblDecl lbl
+ $$ pprTypeAndSizeDecl platform lbl
+ $$ (ppr lbl <> char ':')
-- -----------------------------------------------------------------------------
-- pprInstr: print an 'Instr'
@@ -321,10 +323,9 @@ pprImm imm
-- On SPARC all the data sections must be at least 8 byte aligned
-- incase we store doubles in them.
--
-pprSectionAlign :: Section -> SDoc
-pprSectionAlign sec@(Section seg _) =
- sdocWithPlatform $ \platform ->
- pprSectionHeader platform sec $$
+pprSectionAlign :: NCGConfig -> Section -> SDoc
+pprSectionAlign config sec@(Section seg _) =
+ pprSectionHeader config sec $$
pprAlignForSection seg
-- | Print appropriate alignment for the given section type.
diff --git a/compiler/GHC/CmmToAsm/SPARC/Stack.hs b/compiler/GHC/CmmToAsm/SPARC/Stack.hs
index d9a0ffd7cf..861d1ad691 100644
--- a/compiler/GHC/CmmToAsm/SPARC/Stack.hs
+++ b/compiler/GHC/CmmToAsm/SPARC/Stack.hs
@@ -13,8 +13,8 @@ import GHC.CmmToAsm.SPARC.AddrMode
import GHC.CmmToAsm.SPARC.Regs
import GHC.CmmToAsm.SPARC.Base
import GHC.CmmToAsm.SPARC.Imm
+import GHC.CmmToAsm.Config
-import GHC.Driver.Session
import Outputable
-- | Get an AddrMode relative to the address in sp.
@@ -37,15 +37,15 @@ fpRel n
-- | Convert a spill slot number to a *byte* offset, with no sign.
--
-spillSlotToOffset :: DynFlags -> Int -> Int
-spillSlotToOffset dflags slot
- | slot >= 0 && slot < maxSpillSlots dflags
+spillSlotToOffset :: NCGConfig -> Int -> Int
+spillSlotToOffset config slot
+ | slot >= 0 && slot < maxSpillSlots config
= 64 + spillSlotSize * slot
| otherwise
= pprPanic "spillSlotToOffset:"
( text "invalid spill location: " <> int slot
- $$ text "maxSpillSlots: " <> int (maxSpillSlots dflags))
+ $$ text "maxSpillSlots: " <> int (maxSpillSlots config))
-- | The maximum number of spill slots available on the C stack.
@@ -54,6 +54,6 @@ spillSlotToOffset dflags slot
-- Why do we reserve 64 bytes, instead of using the whole thing??
-- -- BL 2009/02/15
--
-maxSpillSlots :: DynFlags -> Int
-maxSpillSlots dflags
- = ((spillAreaLength dflags - 64) `div` spillSlotSize) - 1
+maxSpillSlots :: NCGConfig -> Int
+maxSpillSlots config
+ = ((ncgSpillPreallocSize config - 64) `div` spillSlotSize) - 1
diff --git a/compiler/GHC/CmmToAsm/X86/CodeGen.hs b/compiler/GHC/CmmToAsm/X86/CodeGen.hs
index 4b1dd31cf1..17e246366b 100644
--- a/compiler/GHC/CmmToAsm/X86/CodeGen.hs
+++ b/compiler/GHC/CmmToAsm/X86/CodeGen.hs
@@ -41,7 +41,7 @@ import GhcPrelude
import GHC.CmmToAsm.X86.Instr
import GHC.CmmToAsm.X86.Cond
import GHC.CmmToAsm.X86.Regs
-import GHC.CmmToAsm.X86.Ppr ( )
+import GHC.CmmToAsm.X86.Ppr
import GHC.CmmToAsm.X86.RegInfo
import GHC.Platform.Regs
@@ -56,10 +56,11 @@ import GHC.CmmToAsm.Monad
( NatM, getNewRegNat, getNewLabelNat, setDeltaNat
, getDeltaNat, getBlockIdNat, getPicBaseNat, getNewRegPairNat
, getPicBaseMaybeNat, getDebugBlock, getFileId
- , addImmediateSuccessorNat, updateCfgNat
+ , addImmediateSuccessorNat, updateCfgNat, getConfig, getPlatform
)
import GHC.CmmToAsm.CFG
import GHC.CmmToAsm.Format
+import GHC.CmmToAsm.Config
import GHC.Platform.Reg
import GHC.Platform
@@ -98,13 +99,13 @@ import qualified Data.Map as M
is32BitPlatform :: NatM Bool
is32BitPlatform = do
- dflags <- getDynFlags
- return $ target32Bit (targetPlatform dflags)
+ platform <- getPlatform
+ return $ target32Bit platform
sse2Enabled :: NatM Bool
sse2Enabled = do
- dflags <- getDynFlags
- case platformArch (targetPlatform dflags) of
+ platform <- getPlatform
+ case platformArch platform of
-- We Assume SSE1 and SSE2 operations are available on both
-- x86 and x86_64. Historically we didn't default to SSE2 and
-- SSE1 on x86, which results in defacto nondeterminism for how
@@ -132,10 +133,10 @@ cmmTopCodeGen (CmmProc info lab live graph) = do
let blocks = toBlockListEntryFirst graph
(nat_blocks,statics) <- mapAndUnzipM basicBlockCodeGen blocks
picBaseMb <- getPicBaseMaybeNat
- dflags <- getDynFlags
+ platform <- getPlatform
let proc = CmmProc info lab live (ListGraph $ concat nat_blocks)
tops = proc : concat statics
- os = platformOS $ targetPlatform dflags
+ os = platformOS platform
case picBaseMb of
Just picBase -> initializePicBase_x86 ArchX86 os picBase tops
@@ -172,8 +173,8 @@ cmmTopCodeGen (CmmData sec dat) = do
-}
-- Verifying basic blocks is cheap, but not cheap enough to enable it unconditionally.
-verifyBasicBlock :: [Instr] -> ()
-verifyBasicBlock instrs
+verifyBasicBlock :: Platform -> [Instr] -> ()
+verifyBasicBlock platform instrs
| debugIsOn = go False instrs
| otherwise = ()
where
@@ -193,7 +194,7 @@ verifyBasicBlock instrs
else faultyBlockWith i
faultyBlockWith i
= pprPanic "Non control flow instructions after end of basic block."
- (ppr i <+> text "in:" $$ vcat (map ppr instrs))
+ (pprInstr platform i <+> text "in:" $$ vcat (map (pprInstr platform) instrs))
basicBlockCodeGen
:: CmmBlock
@@ -215,7 +216,8 @@ basicBlockCodeGen block = do
(mid_instrs,mid_bid) <- stmtsToInstrs id stmts
(!tail_instrs,_) <- stmtToInstrs mid_bid tail
let instrs = loc_instrs `appOL` mid_instrs `appOL` tail_instrs
- return $! verifyBasicBlock (fromOL instrs)
+ platform <- getPlatform
+ return $! verifyBasicBlock platform (fromOL instrs)
instrs' <- fold <$> traverse addSpUnwindings instrs
-- code generation may introduce new basic block boundaries, which
-- are indicated by the NEWBLOCK instruction. We must split up the
@@ -237,8 +239,8 @@ basicBlockCodeGen block = do
-- for details.
addSpUnwindings :: Instr -> NatM (OrdList Instr)
addSpUnwindings instr@(DELTA d) = do
- dflags <- getDynFlags
- if debugLevel dflags >= 1
+ config <- getConfig
+ if ncgDebugLevel config >= 1
then do lbl <- mkAsmTempLabel <$> getUniqueM
let unwind = M.singleton MachSp (Just $ UwReg MachSp $ negate d)
return $ toOL [ instr, UNWIND lbl unwind ]
@@ -332,9 +334,10 @@ stmtToInstrs :: BlockId -- ^ Basic block this statement will start to be placed
stmtToInstrs bid stmt = do
dflags <- getDynFlags
is32Bit <- is32BitPlatform
+ platform <- getPlatform
case stmt of
CmmUnsafeForeignCall target result_regs args
- -> genCCall dflags is32Bit target result_regs args bid
+ -> genCCall is32Bit target result_regs args bid
_ -> (,Nothing) <$> case stmt of
CmmComment s -> return (unitOL (COMMENT s))
@@ -368,19 +371,15 @@ stmtToInstrs bid stmt = do
--We try to arrange blocks such that the likely branch is the fallthrough
--in GHC.Cmm.ContFlowOpt. So we can assume the condition is likely false here.
CmmCondBranch arg true false _ -> genCondBranch bid true false arg
- CmmSwitch arg ids -> do dflags <- getDynFlags
- genSwitch dflags arg ids
+ CmmSwitch arg ids -> genSwitch arg ids
CmmCall { cml_target = arg
- , cml_args_regs = gregs } -> do
- dflags <- getDynFlags
- genJump arg (jumpRegs dflags gregs)
+ , cml_args_regs = gregs } -> genJump arg (jumpRegs platform gregs)
_ ->
panic "stmtToInstrs: statement should have been cps'd away"
-jumpRegs :: DynFlags -> [GlobalReg] -> [Reg]
-jumpRegs dflags gregs = [ RegReal r | Just r <- map (globalRegMaybe platform) gregs ]
- where platform = targetPlatform dflags
+jumpRegs :: Platform -> [GlobalReg] -> [Reg]
+jumpRegs platform gregs = [ RegReal r | Just r <- map (globalRegMaybe platform) gregs ]
--------------------------------------------------------------------------------
-- | 'InstrBlock's are the insn sequences generated by the insn selectors.
@@ -477,8 +476,8 @@ is32BitInteger i = i64 <= 0x7fffffff && i64 >= -0x80000000
-- | Convert a BlockId to some CmmStatic data
-jumpTableEntry :: DynFlags -> Maybe BlockId -> CmmStatic
-jumpTableEntry dflags Nothing = CmmStaticLit (CmmInt 0 (wordWidth dflags))
+jumpTableEntry :: NCGConfig -> Maybe BlockId -> CmmStatic
+jumpTableEntry config Nothing = CmmStaticLit (CmmInt 0 (ncgWordWidth config))
jumpTableEntry _ (Just blockid) = CmmStaticLit (CmmLabel blockLabel)
where blockLabel = blockLbl blockid
@@ -659,9 +658,9 @@ getRegister' dflags is32Bit (CmmReg reg)
fmt = cmmTypeFormat (cmmRegType dflags reg)
format = fmt
--
- let platform = targetPlatform dflags
+ platform <- ncgPlatform <$> getConfig
return (Fixed format
- (getRegisterReg platform reg)
+ (getRegisterReg platform reg)
nilOL)
@@ -1236,15 +1235,15 @@ getByteReg expr = do
-- be modified by code to evaluate an arbitrary expression.
getNonClobberedReg :: CmmExpr -> NatM (Reg, InstrBlock)
getNonClobberedReg expr = do
- dflags <- getDynFlags
r <- getRegister expr
+ platform <- ncgPlatform <$> getConfig
case r of
Any rep code -> do
tmp <- getNewRegNat rep
return (tmp, code tmp)
Fixed rep reg code
-- only certain regs can be clobbered
- | reg `elem` instrClobberedRegs (targetPlatform dflags)
+ | reg `elem` instrClobberedRegs platform
-> do
tmp <- getNewRegNat rep
return (tmp, code `snocOL` reg2reg rep reg tmp)
@@ -1326,11 +1325,12 @@ getAmode' _ expr = do
-- (i.e. no index register). This stops us from running out of
-- registers on x86 when using instructions such as cmpxchg, which can
-- use up to three virtual registers and one fixed register.
-getSimpleAmode :: DynFlags -> Bool -> CmmExpr -> NatM Amode
-getSimpleAmode dflags is32Bit addr
+getSimpleAmode :: Bool -> CmmExpr -> NatM Amode
+getSimpleAmode is32Bit addr
| is32Bit = do
addr_code <- getAnyReg addr
- addr_r <- getNewRegNat (intFormat (wordWidth dflags))
+ config <- getConfig
+ addr_r <- getNewRegNat (intFormat (ncgWordWidth config))
let amode = AddrBaseIndex (EABaseReg addr_r) EAIndexNone (ImmInt 0)
return $! Amode amode (addr_code addr_r)
| otherwise = getAmode addr
@@ -1383,8 +1383,7 @@ getNonClobberedOperand (CmmLoad mem pk) = do
-- or if 64bit
-- this could use some eyeballs or i'll need to stare at it more later
then do
- dflags <- getDynFlags
- let platform = targetPlatform dflags
+ platform <- ncgPlatform <$> getConfig
Amode src mem_code <- getAmode mem
(src',save_code) <-
if (amodeCouldBeClobbered platform src)
@@ -1477,7 +1476,8 @@ memConstant align lit = do
lbl <- getNewLabelNat
let rosection = Section ReadOnlyData lbl
dflags <- getDynFlags
- (addr, addr_code) <- if target32Bit (targetPlatform dflags)
+ platform <- getPlatform
+ (addr, addr_code) <- if target32Bit platform
then do dynRef <- cmmMakeDynamicReference
dflags
DataReference
@@ -1742,14 +1742,12 @@ assignMem_IntCode pk addr src = do
-- Assign; dst is a reg, rhs is mem
assignReg_IntCode pk reg (CmmLoad src _) = do
load_code <- intLoadCode (MOV pk) src
- dflags <- getDynFlags
- let platform = targetPlatform dflags
+ platform <- ncgPlatform <$> getConfig
return (load_code (getRegisterReg platform reg))
-- dst is a reg, but src could be anything
assignReg_IntCode _ reg src = do
- dflags <- getDynFlags
- let platform = targetPlatform dflags
+ platform <- ncgPlatform <$> getConfig
code <- getAnyReg src
return (code (getRegisterReg platform reg))
@@ -1768,9 +1766,8 @@ assignMem_FltCode pk addr src = do
-- Floating point assignment to a register/temporary
assignReg_FltCode _ reg src = do
src_code <- getAnyReg src
- dflags <- getDynFlags
- let platform = targetPlatform dflags
- return (src_code (getRegisterReg platform reg))
+ platform <- ncgPlatform <$> getConfig
+ return (src_code (getRegisterReg platform reg))
genJump :: CmmExpr{-the branch target-} -> [Reg] -> NatM InstrBlock
@@ -1997,8 +1994,7 @@ genCondBranch' _ bid id false bool = do
-- to take/return a block id.
genCCall
- :: DynFlags
- -> Bool -- 32 bit platform?
+ :: Bool -- 32 bit platform?
-> ForeignTarget -- function to call
-> [CmmFormal] -- where to put the result
-> [CmmActual] -- arguments (of mixed type)
@@ -2007,16 +2003,16 @@ genCCall
-- First we deal with cases which might introduce new blocks in the stream.
-genCCall dflags is32Bit (PrimTarget (MO_AtomicRMW width amop))
+genCCall is32Bit (PrimTarget (MO_AtomicRMW width amop))
[dst] [addr, n] bid = do
Amode amode addr_code <-
if amop `elem` [AMO_Add, AMO_Sub]
then getAmode addr
- else getSimpleAmode dflags is32Bit addr -- See genCCall for MO_Cmpxchg
+ else getSimpleAmode is32Bit addr -- See genCCall for MO_Cmpxchg
arg <- getNewRegNat format
arg_code <- getAnyReg n
- let platform = targetPlatform dflags
- dst_r = getRegisterReg platform (CmmLocal dst)
+ platform <- ncgPlatform <$> getConfig
+ let dst_r = getRegisterReg platform (CmmLocal dst)
(code, lbl) <- op_code dst_r arg amode
return (addr_code `appOL` arg_code arg `appOL` code, Just lbl)
where
@@ -2080,9 +2076,10 @@ genCCall dflags is32Bit (PrimTarget (MO_AtomicRMW width amop))
lbl2)
format = intFormat width
-genCCall dflags is32Bit (PrimTarget (MO_Ctz width)) [dst] [src] bid
+genCCall is32Bit (PrimTarget (MO_Ctz width)) [dst] [src] bid
| is32Bit, width == W64 = do
ChildCode64 vcode rlo <- iselExpr64 src
+ platform <- ncgPlatform <$> getConfig
let rhi = getHiVRegFromLo rlo
dst_r = getRegisterReg platform (CmmLocal dst)
lbl1 <- getBlockIdNat
@@ -2094,9 +2091,10 @@ genCCall dflags is32Bit (PrimTarget (MO_Ctz width)) [dst] [src] bid
-- bid -> lbl2
-- bid -> lbl1 -> lbl2
-- We also changes edges originating at bid to start at lbl2 instead.
+ dflags <- getDynFlags
updateCfgNat (addWeightEdge bid lbl1 110 .
addWeightEdge lbl1 lbl2 110 .
- addImmediateSuccessor bid lbl2)
+ addImmediateSuccessor dflags bid lbl2)
-- The following instruction sequence corresponds to the pseudo-code
--
@@ -2125,8 +2123,9 @@ genCCall dflags is32Bit (PrimTarget (MO_Ctz width)) [dst] [src] bid
| otherwise = do
code_src <- getAnyReg src
+ platform <- ncgPlatform <$> getConfig
let dst_r = getRegisterReg platform (CmmLocal dst)
-
+ dflags <- getDynFlags
if isBmi2Enabled dflags
then do
src_r <- getNewRegNat (intFormat width)
@@ -2158,9 +2157,9 @@ genCCall dflags is32Bit (PrimTarget (MO_Ctz width)) [dst] [src] bid
return (instrs, Nothing)
where
bw = widthInBits width
- platform = targetPlatform dflags
-genCCall dflags bits mop dst args bid = do
+genCCall bits mop dst args bid = do
+ dflags <- getDynFlags
instr <- genCCall' dflags bits mop dst args bid
return (instr, Nothing)
@@ -2326,8 +2325,8 @@ genCCall' _ is32bit (PrimTarget (MO_Prefetch_Data n )) _ [src] _ =
((AddrBaseIndex (EABaseReg src_r ) EAIndexNone (ImmInt 0)))) ))
-- prefetch always takes an address
-genCCall' dflags is32Bit (PrimTarget (MO_BSwap width)) [dst] [src] _ = do
- let platform = targetPlatform dflags
+genCCall' _ is32Bit (PrimTarget (MO_BSwap width)) [dst] [src] _ = do
+ platform <- ncgPlatform <$> getConfig
let dst_r = getRegisterReg platform (CmmLocal dst)
case width of
W64 | is32Bit -> do
@@ -2351,7 +2350,7 @@ genCCall' dflags is32Bit (PrimTarget (MO_BSwap width)) [dst] [src] _ = do
genCCall' dflags is32Bit (PrimTarget (MO_PopCnt width)) dest_regs@[dst]
args@[src] bid = do
sse4_2 <- sse4_2Enabled
- let platform = targetPlatform dflags
+ platform <- ncgPlatform <$> getConfig
if sse4_2
then do code_src <- getAnyReg src
src_r <- getNewRegNat format
@@ -2381,7 +2380,7 @@ genCCall' dflags is32Bit (PrimTarget (MO_PopCnt width)) dest_regs@[dst]
genCCall' dflags is32Bit (PrimTarget (MO_Pdep width)) dest_regs@[dst]
args@[src, mask] bid = do
- let platform = targetPlatform dflags
+ platform <- ncgPlatform <$> getConfig
if isBmi2Enabled dflags
then do code_src <- getAnyReg src
code_mask <- getAnyReg mask
@@ -2414,7 +2413,7 @@ genCCall' dflags is32Bit (PrimTarget (MO_Pdep width)) dest_regs@[dst]
genCCall' dflags is32Bit (PrimTarget (MO_Pext width)) dest_regs@[dst]
args@[src, mask] bid = do
- let platform = targetPlatform dflags
+ platform <- ncgPlatform <$> getConfig
if isBmi2Enabled dflags
then do code_src <- getAnyReg src
code_mask <- getAnyReg mask
@@ -2456,6 +2455,7 @@ genCCall' dflags is32Bit (PrimTarget (MO_Clz width)) dest_regs@[dst] args@[src]
| otherwise = do
code_src <- getAnyReg src
+ platform <- ncgPlatform <$> getConfig
let dst_r = getRegisterReg platform (CmmLocal dst)
if isBmi2Enabled dflags
then do
@@ -2486,7 +2486,6 @@ genCCall' dflags is32Bit (PrimTarget (MO_Clz width)) dest_regs@[dst] args@[src]
-- took care of implicitly clearing the upper bits
where
bw = widthInBits width
- platform = targetPlatform dflags
lbl = mkCmmCodeLabel primUnitId (fsLit (clzLabel width))
genCCall' dflags is32Bit (PrimTarget (MO_UF_Conv width)) dest_regs args bid = do
@@ -2499,9 +2498,9 @@ genCCall' dflags is32Bit (PrimTarget (MO_UF_Conv width)) dest_regs args bid = do
where
lbl = mkCmmCodeLabel primUnitId (fsLit (word2FloatLabel width))
-genCCall' dflags _ (PrimTarget (MO_AtomicRead width)) [dst] [addr] _ = do
+genCCall' _ _ (PrimTarget (MO_AtomicRead width)) [dst] [addr] _ = do
load_code <- intLoadCode (MOV (intFormat width)) addr
- let platform = targetPlatform dflags
+ platform <- ncgPlatform <$> getConfig
return (load_code (getRegisterReg platform (CmmLocal dst)))
@@ -2509,17 +2508,17 @@ genCCall' _ _ (PrimTarget (MO_AtomicWrite width)) [] [addr, val] _ = do
code <- assignMem_IntCode (intFormat width) addr val
return $ code `snocOL` MFENCE
-genCCall' dflags is32Bit (PrimTarget (MO_Cmpxchg width)) [dst] [addr, old, new] _ = do
+genCCall' _ is32Bit (PrimTarget (MO_Cmpxchg width)) [dst] [addr, old, new] _ = do
-- On x86 we don't have enough registers to use cmpxchg with a
-- complicated addressing mode, so on that architecture we
-- pre-compute the address first.
- Amode amode addr_code <- getSimpleAmode dflags is32Bit addr
+ Amode amode addr_code <- getSimpleAmode is32Bit addr
newval <- getNewRegNat format
newval_code <- getAnyReg new
oldval <- getNewRegNat format
oldval_code <- getAnyReg old
- let platform = targetPlatform dflags
- dst_r = getRegisterReg platform (CmmLocal dst)
+ platform <- getPlatform
+ let dst_r = getRegisterReg platform (CmmLocal dst)
code = toOL
[ MOV format (OpReg oldval) (OpReg eax)
, LOCK (CMPXCHG format (OpReg newval) (OpAddr amode))
@@ -2530,9 +2529,8 @@ genCCall' dflags is32Bit (PrimTarget (MO_Cmpxchg width)) [dst] [addr, old, new]
where
format = intFormat width
-genCCall' _ is32Bit target dest_regs args bid = do
- dflags <- getDynFlags
- let platform = targetPlatform dflags
+genCCall' dflags is32Bit target dest_regs args bid = do
+ platform <- ncgPlatform <$> getConfig
case (target, dest_regs) of
-- void return type prim op
(PrimTarget op, []) ->
@@ -2785,8 +2783,7 @@ genCCall32' dflags target dest_regs args = do
)
setDeltaNat delta0
- dflags <- getDynFlags
- let platform = targetPlatform dflags
+ platform <- getPlatform
let
-- assign the results, if necessary
@@ -2889,6 +2886,8 @@ genCCall64' :: DynFlags
-> [CmmActual] -- arguments (of mixed type)
-> NatM InstrBlock
genCCall64' dflags target dest_regs args = do
+ config <- getConfig
+ let platform = ncgPlatform config
-- load up the register arguments
let prom_args = map (maybePromoteCArg dflags W32) args
@@ -2921,15 +2920,16 @@ genCCall64' dflags target dest_regs args = do
-- Align stack to 16n for calls, assuming a starting stack
-- alignment of 16n - word_size on procedure entry. Which we
-- maintain. See Note [rts/StgCRun.c : Stack Alignment on X86]
+ let word_size = platformWordSizeInBytes platform
(real_size, adjust_rsp) <-
- if (tot_arg_size + wORD_SIZE dflags) `rem` 16 == 0
+ if (tot_arg_size + word_size) `rem` 16 == 0
then return (tot_arg_size, nilOL)
else do -- we need to adjust...
delta <- getDeltaNat
- setDeltaNat (delta - wORD_SIZE dflags)
- return (tot_arg_size + wORD_SIZE dflags, toOL [
- SUB II64 (OpImm (ImmInt (wORD_SIZE dflags))) (OpReg rsp),
- DELTA (delta - wORD_SIZE dflags) ])
+ setDeltaNat (delta - word_size)
+ return (tot_arg_size + word_size, toOL [
+ SUB II64 (OpImm (ImmInt word_size)) (OpReg rsp),
+ DELTA (delta - word_size) ])
-- push the stack args, right to left
push_code <- push_args (reverse stack_args) nilOL
@@ -2971,7 +2971,7 @@ genCCall64' dflags target dest_regs args = do
-- stdcall has callee do it, but is not supported on
-- x86_64 target (see #3336)
(if real_size==0 then [] else
- [ADD (intFormat (wordWidth dflags)) (OpImm (ImmInt real_size)) (OpReg esp)])
+ [ADD (intFormat (ncgWordWidth config)) (OpImm (ImmInt real_size)) (OpReg esp)])
++
[DELTA (delta + real_size)]
)
@@ -3003,8 +3003,7 @@ genCCall64' dflags target dest_regs args = do
call `appOL`
assign_code dest_regs)
- where platform = targetPlatform dflags
- arg_size = 8 -- always, at the mo
+ where arg_size = 8 -- always, at the mo
load_args :: [CmmExpr]
@@ -3107,7 +3106,7 @@ genCCall64' dflags target dest_regs args = do
let code' = code `appOL` arg_code `appOL` toOL [
SUB (intFormat (wordWidth dflags)) (OpImm (ImmInt arg_size)) (OpReg rsp),
DELTA (delta-arg_size),
- MOV (floatFormat width) (OpReg arg_reg) (OpAddr (spRel dflags 0))]
+ MOV (floatFormat width) (OpReg arg_reg) (OpAddr (spRel (targetPlatform dflags) 0))]
push_args rest code'
| otherwise = do
@@ -3250,17 +3249,19 @@ outOfLineCmmOp bid mop res args
-- -----------------------------------------------------------------------------
-- Generating a table-branch
-genSwitch :: DynFlags -> CmmExpr -> SwitchTargets -> NatM InstrBlock
+genSwitch :: CmmExpr -> SwitchTargets -> NatM InstrBlock
-genSwitch dflags expr targets
- | positionIndependent dflags
- = do
+genSwitch expr targets = do
+ config <- getConfig
+ dflags <- getDynFlags
+ let platform = ncgPlatform config
+ if ncgPIC config
+ then do
(reg,e_code) <- getNonClobberedReg (cmmOffset dflags expr offset)
-- getNonClobberedReg because it needs to survive across t_code
lbl <- getNewLabelNat
- dflags <- getDynFlags
- let is32bit = target32Bit (targetPlatform dflags)
- os = platformOS (targetPlatform dflags)
+ let is32bit = target32Bit platform
+ os = platformOS platform
-- Might want to use .rodata.<function we're in> instead, but as
-- long as it's something unique it'll work out since the
-- references to the jump table are in the appropriate section.
@@ -3275,12 +3276,12 @@ genSwitch dflags expr targets
dynRef <- cmmMakeDynamicReference dflags DataReference lbl
(tableReg,t_code) <- getSomeReg $ dynRef
let op = OpAddr (AddrBaseIndex (EABaseReg tableReg)
- (EAIndex reg (wORD_SIZE dflags)) (ImmInt 0))
+ (EAIndex reg (platformWordSizeInBytes platform)) (ImmInt 0))
- offsetReg <- getNewRegNat (intFormat (wordWidth dflags))
+ offsetReg <- getNewRegNat (intFormat (ncgWordWidth config))
return $ if is32bit || os == OSDarwin
then e_code `appOL` t_code `appOL` toOL [
- ADD (intFormat (wordWidth dflags)) op (OpReg tableReg),
+ ADD (intFormat (ncgWordWidth config)) op (OpReg tableReg),
JMP_TBL (OpReg tableReg) ids rosection lbl
]
else -- HACK: On x86_64 binutils<2.17 is only able to generate
@@ -3291,16 +3292,15 @@ genSwitch dflags expr targets
-- PprMach.hs/pprDataItem once binutils 2.17 is standard.
e_code `appOL` t_code `appOL` toOL [
MOVSxL II32 op (OpReg offsetReg),
- ADD (intFormat (wordWidth dflags))
+ ADD (intFormat (ncgWordWidth config))
(OpReg offsetReg)
(OpReg tableReg),
JMP_TBL (OpReg tableReg) ids rosection lbl
]
- | otherwise
- = do
+ else do
(reg,e_code) <- getSomeReg (cmmOffset dflags expr offset)
lbl <- getNewLabelNat
- let op = OpAddr (AddrBaseIndex EABaseNone (EAIndex reg (wORD_SIZE dflags)) (ImmCLbl lbl))
+ let op = OpAddr (AddrBaseIndex EABaseNone (EAIndex reg (platformWordSizeInBytes platform)) (ImmCLbl lbl))
code = e_code `appOL` toOL [
JMP_TBL op ids (Section ReadOnlyData lbl) lbl
]
@@ -3309,27 +3309,27 @@ genSwitch dflags expr targets
(offset, blockIds) = switchTargetsToTable targets
ids = map (fmap DestBlockId) blockIds
-generateJumpTableForInstr :: DynFlags -> Instr -> Maybe (NatCmmDecl (Alignment, RawCmmStatics) Instr)
-generateJumpTableForInstr dflags (JMP_TBL _ ids section lbl)
+generateJumpTableForInstr :: NCGConfig -> Instr -> Maybe (NatCmmDecl (Alignment, RawCmmStatics) Instr)
+generateJumpTableForInstr config (JMP_TBL _ ids section lbl)
= let getBlockId (DestBlockId id) = id
getBlockId _ = panic "Non-Label target in Jump Table"
blockIds = map (fmap getBlockId) ids
- in Just (createJumpTable dflags blockIds section lbl)
+ in Just (createJumpTable config blockIds section lbl)
generateJumpTableForInstr _ _ = Nothing
-createJumpTable :: DynFlags -> [Maybe BlockId] -> Section -> CLabel
+createJumpTable :: NCGConfig -> [Maybe BlockId] -> Section -> CLabel
-> GenCmmDecl (Alignment, RawCmmStatics) h g
-createJumpTable dflags ids section lbl
+createJumpTable config ids section lbl
= let jumpTable
- | positionIndependent dflags =
- let ww = wordWidth dflags
+ | ncgPIC config =
+ let ww = ncgWordWidth config
jumpTableEntryRel Nothing
= CmmStaticLit (CmmInt 0 ww)
jumpTableEntryRel (Just blockid)
= CmmStaticLit (CmmLabelDiffOff blockLabel lbl 0 ww)
where blockLabel = blockLbl blockid
in map jumpTableEntryRel ids
- | otherwise = map (jumpTableEntry dflags) ids
+ | otherwise = map (jumpTableEntry config) ids
in CmmData section (mkAlignment 1, RawCmmStatics lbl jumpTable)
extractUnwindPoints :: [Instr] -> [UnwindPoint]
diff --git a/compiler/GHC/CmmToAsm/X86/Instr.hs b/compiler/GHC/CmmToAsm/X86/Instr.hs
index 4171806695..71ee322516 100644
--- a/compiler/GHC/CmmToAsm/X86/Instr.hs
+++ b/compiler/GHC/CmmToAsm/X86/Instr.hs
@@ -27,6 +27,7 @@ import GHC.CmmToAsm.Format
import GHC.Platform.Reg.Class
import GHC.Platform.Reg
import GHC.CmmToAsm.Reg.Target
+import GHC.CmmToAsm.Config
import GHC.Cmm.BlockId
import GHC.Cmm.Dataflow.Collections
@@ -39,7 +40,6 @@ import GHC.Platform
import BasicTypes (Alignment)
import GHC.Cmm.CLabel
-import GHC.Driver.Session
import UniqSet
import Unique
import UniqSupply
@@ -660,50 +660,51 @@ x86_patchJumpInstr insn patchF
-- -----------------------------------------------------------------------------
-- | Make a spill instruction.
x86_mkSpillInstr
- :: DynFlags
+ :: NCGConfig
-> Reg -- register to spill
-> Int -- current stack delta
-> Int -- spill slot to use
-> Instr
-x86_mkSpillInstr dflags reg delta slot
+x86_mkSpillInstr config reg delta slot
= let off = spillSlotToOffset platform slot - delta
in
case targetClassOfReg platform reg of
RcInteger -> MOV (archWordFormat is32Bit)
- (OpReg reg) (OpAddr (spRel dflags off))
- RcDouble -> MOV FF64 (OpReg reg) (OpAddr (spRel dflags off))
+ (OpReg reg) (OpAddr (spRel platform off))
+ RcDouble -> MOV FF64 (OpReg reg) (OpAddr (spRel platform off))
_ -> panic "X86.mkSpillInstr: no match"
- where platform = targetPlatform dflags
+ where platform = ncgPlatform config
is32Bit = target32Bit platform
-- | Make a spill reload instruction.
x86_mkLoadInstr
- :: DynFlags
+ :: NCGConfig
-> Reg -- register to load
-> Int -- current stack delta
-> Int -- spill slot to use
-> Instr
-x86_mkLoadInstr dflags reg delta slot
+x86_mkLoadInstr config reg delta slot
= let off = spillSlotToOffset platform slot - delta
in
case targetClassOfReg platform reg of
RcInteger -> MOV (archWordFormat is32Bit)
- (OpAddr (spRel dflags off)) (OpReg reg)
- RcDouble -> MOV FF64 (OpAddr (spRel dflags off)) (OpReg reg)
+ (OpAddr (spRel platform off)) (OpReg reg)
+ RcDouble -> MOV FF64 (OpAddr (spRel platform off)) (OpReg reg)
_ -> panic "X86.x86_mkLoadInstr"
- where platform = targetPlatform dflags
+ where platform = ncgPlatform config
is32Bit = target32Bit platform
spillSlotSize :: Platform -> Int
-spillSlotSize dflags = if is32Bit then 12 else 8
- where is32Bit = target32Bit dflags
-
-maxSpillSlots :: DynFlags -> Int
-maxSpillSlots dflags
- = ((rESERVED_C_STACK_BYTES dflags - 64) `div` spillSlotSize (targetPlatform dflags)) - 1
--- = 0 -- useful for testing allocMoreStack
+spillSlotSize platform
+ | target32Bit platform = 12
+ | otherwise = 8
+
+maxSpillSlots :: NCGConfig -> Int
+maxSpillSlots config
+ = ((ncgSpillPreallocSize config - 64) `div` spillSlotSize (ncgPlatform config)) - 1
+-- = 0 -- useful for testing allocMoreStack
-- number of bytes that the stack pointer should be aligned to
stackAlign :: Int
diff --git a/compiler/GHC/CmmToAsm/X86/Ppr.hs b/compiler/GHC/CmmToAsm/X86/Ppr.hs
index a5b9041974..5aa216f6ba 100644
--- a/compiler/GHC/CmmToAsm/X86/Ppr.hs
+++ b/compiler/GHC/CmmToAsm/X86/Ppr.hs
@@ -28,6 +28,7 @@ import GHC.CmmToAsm.X86.Regs
import GHC.CmmToAsm.X86.Instr
import GHC.CmmToAsm.X86.Cond
import GHC.CmmToAsm.Instr
+import GHC.CmmToAsm.Config
import GHC.CmmToAsm.Format
import GHC.Platform.Reg
import GHC.CmmToAsm.Ppr
@@ -69,36 +70,36 @@ import Data.Bits
-- .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 :: SDoc
-pprProcAlignment = sdocWithDynFlags $ \dflags ->
- (maybe empty (pprAlign . mkAlignment) (cmmProcAlignment dflags))
+pprProcAlignment :: NCGConfig -> SDoc
+pprProcAlignment config = maybe empty (pprAlign platform . mkAlignment) (ncgProcAlignment config)
+ where
+ platform = ncgPlatform config
-pprNatCmmDecl :: NatCmmDecl (Alignment, RawCmmStatics) Instr -> SDoc
-pprNatCmmDecl (CmmData section dats) =
- pprSectionAlign section $$ pprDatas dats
+pprNatCmmDecl :: NCGConfig -> NatCmmDecl (Alignment, RawCmmStatics) Instr -> SDoc
+pprNatCmmDecl config (CmmData section dats) =
+ pprSectionAlign config section $$ pprDatas config dats
-pprNatCmmDecl proc@(CmmProc top_info lbl _ (ListGraph blocks)) =
- sdocWithDynFlags $ \dflags ->
- pprProcAlignment $$
+pprNatCmmDecl config proc@(CmmProc top_info lbl _ (ListGraph blocks)) =
+ let platform = ncgPlatform config in
+ pprProcAlignment config $$
case topInfoTable proc of
Nothing ->
-- special case for code without info table:
- pprSectionAlign (Section Text lbl) $$
- pprProcAlignment $$
- pprLabel lbl $$ -- blocks guaranteed not null, so label needed
- vcat (map (pprBasicBlock top_info) blocks) $$
- (if debugLevel dflags > 0
+ pprSectionAlign config (Section Text lbl) $$
+ pprProcAlignment config $$
+ pprLabel platform lbl $$ -- blocks guaranteed not null, so label needed
+ vcat (map (pprBasicBlock config top_info) blocks) $$
+ (if ncgDebugLevel config > 0
then ppr (mkAsmTempEndLabel lbl) <> char ':' else empty) $$
- pprSizeDecl lbl
+ pprSizeDecl platform lbl
Just (RawCmmStatics info_lbl _) ->
- sdocWithPlatform $ \platform ->
- pprSectionAlign (Section Text info_lbl) $$
- pprProcAlignment $$
+ pprSectionAlign config (Section Text info_lbl) $$
+ pprProcAlignment config $$
(if platformHasSubsectionsViaSymbols platform
then ppr (mkDeadStripPreventer info_lbl) <> char ':'
else empty) $$
- vcat (map (pprBasicBlock top_info) blocks) $$
+ 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
@@ -108,51 +109,49 @@ pprNatCmmDecl proc@(CmmProc top_info lbl _ (ListGraph blocks)) =
<+> char '-'
<+> ppr (mkDeadStripPreventer info_lbl)
else empty) $$
- pprSizeDecl info_lbl
+ pprSizeDecl platform info_lbl
-- | Output the ELF .size directive.
-pprSizeDecl :: CLabel -> SDoc
-pprSizeDecl lbl
- = sdocWithPlatform $ \platform ->
- if osElfTarget (platformOS platform)
+pprSizeDecl :: Platform -> CLabel -> SDoc
+pprSizeDecl platform lbl
+ = if osElfTarget (platformOS platform)
then text "\t.size" <+> ppr lbl <> ptext (sLit ", .-") <> ppr lbl
else empty
-pprBasicBlock :: LabelMap RawCmmStatics -> NatBasicBlock Instr -> SDoc
-pprBasicBlock info_env (BasicBlock blockid instrs)
+pprBasicBlock :: NCGConfig -> LabelMap RawCmmStatics -> NatBasicBlock Instr -> SDoc
+pprBasicBlock config info_env (BasicBlock blockid instrs)
= maybe_infotable $
- pprLabel asmLbl $$
- vcat (map pprInstr instrs) $$
- (sdocOption sdocDebugLevel $ \level ->
- if level > 0
- then ppr (mkAsmTempEndLabel asmLbl) <> char ':'
- else empty
+ pprLabel platform asmLbl $$
+ vcat (map (pprInstr platform) instrs) $$
+ (if ncgDebugLevel config > 0
+ then ppr (mkAsmTempEndLabel asmLbl) <> char ':'
+ else empty
)
where
asmLbl = blockLbl blockid
+ platform = ncgPlatform config
maybe_infotable c = case mapLookup blockid info_env of
Nothing -> c
Just (RawCmmStatics infoLbl info) ->
- pprAlignForSection Text $$
+ pprAlignForSection platform Text $$
infoTableLoc $$
- vcat (map pprData info) $$
- pprLabel infoLbl $$
+ vcat (map (pprData config) info) $$
+ pprLabel platform infoLbl $$
c $$
- (sdocOption sdocDebugLevel $ \level ->
- if level > 0
- then ppr (mkAsmTempEndLabel infoLbl) <> char ':'
- else empty
+ (if ncgDebugLevel config > 0
+ then ppr (mkAsmTempEndLabel infoLbl) <> char ':'
+ else empty
)
-- Make sure the info table has the right .loc for the block
-- coming right after it. See [Note: Info Offset]
infoTableLoc = case instrs of
- (l@LOCATION{} : _) -> pprInstr l
+ (l@LOCATION{} : _) -> pprInstr platform l
_other -> empty
-pprDatas :: (Alignment, RawCmmStatics) -> SDoc
+pprDatas :: NCGConfig -> (Alignment, RawCmmStatics) -> SDoc
-- See note [emit-time elimination of static indirections] in CLabel.
-pprDatas (_, RawCmmStatics alias [CmmStaticLit (CmmLabel lbl), CmmStaticLit ind, _, _])
+pprDatas _config (_, RawCmmStatics alias [CmmStaticLit (CmmLabel lbl), CmmStaticLit ind, _, _])
| lbl == mkIndStaticInfoLabel
, let labelInd (CmmLabelOff l _) = Just l
labelInd (CmmLabel l) = Just l
@@ -162,18 +161,21 @@ pprDatas (_, RawCmmStatics alias [CmmStaticLit (CmmLabel lbl), CmmStaticLit ind,
= pprGloblDecl alias
$$ text ".equiv" <+> ppr alias <> comma <> ppr (CmmLabel ind')
-pprDatas (align, (RawCmmStatics lbl dats))
- = vcat (pprAlign align : pprLabel lbl : map pprData dats)
+pprDatas config (align, (RawCmmStatics lbl dats))
+ = vcat (pprAlign platform align : pprLabel platform lbl : map (pprData config) dats)
+ where
+ platform = ncgPlatform config
-pprData :: CmmStatic -> SDoc
-pprData (CmmString str) = pprBytes str
+pprData :: NCGConfig -> CmmStatic -> SDoc
+pprData _config (CmmString str) = pprBytes str
-pprData (CmmUninitialised bytes)
- = sdocWithPlatform $ \platform ->
- if platformOS platform == OSDarwin then text ".space " <> int bytes
- else text ".skip " <> int bytes
+pprData config (CmmUninitialised bytes)
+ = let platform = ncgPlatform config
+ in if platformOS platform == OSDarwin
+ then text ".space " <> int bytes
+ else text ".skip " <> int bytes
-pprData (CmmStaticLit lit) = pprDataItem lit
+pprData config (CmmStaticLit lit) = pprDataItem config lit
pprGloblDecl :: CLabel -> SDoc
pprGloblDecl lbl
@@ -238,24 +240,23 @@ pprLabelType' dflags lbl =
isInfoTableLabel lbl && not (isConInfoTableLabel lbl)
-pprTypeDecl :: CLabel -> SDoc
-pprTypeDecl lbl
- = sdocWithPlatform $ \platform ->
- if osElfTarget (platformOS platform) && externallyVisibleCLabel lbl
+pprTypeDecl :: Platform -> CLabel -> SDoc
+pprTypeDecl platform lbl
+ = if osElfTarget (platformOS platform) && externallyVisibleCLabel lbl
then
sdocWithDynFlags $ \df ->
text ".type " <> ppr lbl <> ptext (sLit ", ") <> pprLabelType' df lbl
else empty
-pprLabel :: CLabel -> SDoc
-pprLabel lbl = pprGloblDecl lbl
- $$ pprTypeDecl lbl
- $$ (ppr lbl <> char ':')
+pprLabel :: Platform -> CLabel -> SDoc
+pprLabel platform lbl =
+ pprGloblDecl lbl
+ $$ pprTypeDecl platform lbl
+ $$ (ppr lbl <> char ':')
-pprAlign :: Alignment -> SDoc
-pprAlign alignment
- = sdocWithPlatform $ \platform ->
- text ".align " <> int (alignmentOn platform)
+pprAlign :: Platform -> Alignment -> SDoc
+pprAlign platform alignment
+ = text ".align " <> int (alignmentOn platform)
where
bytes = alignmentBytes alignment
alignmentOn platform = if platformOS platform == OSDarwin
@@ -269,18 +270,15 @@ pprAlign alignment
log2 8 = 3
log2 n = 1 + log2 (n `quot` 2)
--- -----------------------------------------------------------------------------
--- pprInstr: print an 'Instr'
-
instance Outputable Instr where
- ppr instr = pprInstr instr
+ ppr instr = sdocWithDynFlags $ \dflags ->
+ pprInstr (targetPlatform dflags) instr
-pprReg :: Format -> Reg -> SDoc
-pprReg f r
+pprReg :: Platform -> Format -> Reg -> SDoc
+pprReg platform f r
= case r of
RegReal (RealRegSingle i) ->
- sdocWithPlatform $ \platform ->
if target32Bit platform then ppr32_reg_no f i
else ppr64_reg_no f i
RegReal (RealRegPair _ _) -> panic "X86.Ppr: no reg pairs on this arch"
@@ -439,8 +437,8 @@ pprImm (ImmConstantDiff a b) = pprImm a <> char '-'
-pprAddr :: AddrMode -> SDoc
-pprAddr (ImmAddr imm off)
+pprAddr :: Platform -> AddrMode -> SDoc
+pprAddr _platform (ImmAddr imm off)
= let pp_imm = pprImm imm
in
if (off == 0) then
@@ -450,12 +448,11 @@ pprAddr (ImmAddr imm off)
else
pp_imm <> char '+' <> int off
-pprAddr (AddrBaseIndex base index displacement)
- = sdocWithPlatform $ \platform ->
- let
+pprAddr platform (AddrBaseIndex base index displacement)
+ = let
pp_disp = ppr_disp displacement
pp_off p = pp_disp <> char '(' <> p <> char ')'
- pp_reg r = pprReg (archWordFormat (target32Bit platform)) r
+ pp_reg r = pprReg platform (archWordFormat (target32Bit platform)) r
in
case (base, index) of
(EABaseNone, EAIndexNone) -> pp_disp
@@ -471,18 +468,16 @@ pprAddr (AddrBaseIndex base index displacement)
ppr_disp imm = pprImm imm
-- | Print section header and appropriate alignment for that section.
-pprSectionAlign :: Section -> SDoc
-pprSectionAlign (Section (OtherSection _) _) =
+pprSectionAlign :: NCGConfig -> Section -> SDoc
+pprSectionAlign _config (Section (OtherSection _) _) =
panic "X86.Ppr.pprSectionAlign: unknown section"
-pprSectionAlign sec@(Section seg _) =
- sdocWithPlatform $ \platform ->
- pprSectionHeader platform sec $$
- pprAlignForSection seg
+pprSectionAlign config sec@(Section seg _) =
+ pprSectionHeader config sec $$
+ pprAlignForSection (ncgPlatform config) seg
-- | Print appropriate alignment for the given section type.
-pprAlignForSection :: SectionType -> SDoc
-pprAlignForSection seg =
- sdocWithPlatform $ \platform ->
+pprAlignForSection :: Platform -> SectionType -> SDoc
+pprAlignForSection platform seg =
text ".align " <>
case platformOS platform of
-- Darwin: alignments are given as shifts.
@@ -511,14 +506,14 @@ pprAlignForSection seg =
CString -> int 1
_ -> int 8
-pprDataItem :: CmmLit -> SDoc
-pprDataItem lit = sdocWithDynFlags $ \dflags -> pprDataItem' dflags lit
+pprDataItem :: NCGConfig -> CmmLit -> SDoc
+pprDataItem config lit = sdocWithDynFlags $ \dflags -> pprDataItem' dflags config lit
-pprDataItem' :: DynFlags -> CmmLit -> SDoc
-pprDataItem' dflags lit
+pprDataItem' :: DynFlags -> NCGConfig -> CmmLit -> SDoc
+pprDataItem' dflags config lit
= vcat (ppr_item (cmmTypeFormat $ cmmLitType dflags lit) lit)
where
- platform = targetPlatform dflags
+ platform = ncgPlatform config
imm = litToImm lit
-- These seem to be common:
@@ -577,38 +572,38 @@ pprDataItem' dflags lit
asmComment :: SDoc -> SDoc
asmComment c = whenPprDebug $ text "# " <> c
-pprInstr :: Instr -> SDoc
+pprInstr :: Platform -> Instr -> SDoc
+pprInstr platform i = case i of
+ COMMENT s
+ -> asmComment (ftext s)
-pprInstr (COMMENT s)
- = asmComment (ftext s)
+ LOCATION file line col _name
+ -> text "\t.loc " <> ppr file <+> ppr line <+> ppr col
-pprInstr (LOCATION file line col _name)
- = text "\t.loc " <> ppr file <+> ppr line <+> ppr col
+ DELTA d
+ -> asmComment $ text ("\tdelta = " ++ show d)
-pprInstr (DELTA d)
- = asmComment $ text ("\tdelta = " ++ show d)
+ NEWBLOCK _
+ -> panic "pprInstr: NEWBLOCK"
-pprInstr (NEWBLOCK _)
- = panic "PprMach.pprInstr: NEWBLOCK"
+ UNWIND lbl d
+ -> asmComment (text "\tunwind = " <> ppr d)
+ $$ ppr lbl <> colon
-pprInstr (UNWIND lbl d)
- = asmComment (text "\tunwind = " <> ppr d)
- $$ ppr lbl <> colon
-
-pprInstr (LDATA _ _)
- = panic "PprMach.pprInstr: LDATA"
+ LDATA _ _
+ -> panic "pprInstr: LDATA"
{-
-pprInstr (SPILL reg slot)
- = hcat [
- text "\tSPILL",
- char ' ',
- pprUserReg reg,
- comma,
- text "SLOT" <> parens (int slot)]
-
-pprInstr (RELOAD slot reg)
- = hcat [
+ SPILL reg slot
+ -> hcat [
+ text "\tSPILL",
+ char ' ',
+ pprUserReg reg,
+ comma,
+ text "SLOT" <> parens (int slot)]
+
+ RELOAD slot reg
+ -> hcat [
text "\tRELOAD",
char ' ',
text "SLOT" <> parens (int slot),
@@ -616,120 +611,170 @@ pprInstr (RELOAD slot reg)
pprUserReg reg]
-}
--- Replace 'mov $0x0,%reg' by 'xor %reg,%reg', which is smaller and cheaper.
--- The code generator catches most of these already, but not all.
-pprInstr (MOV format (OpImm (ImmInt 0)) dst@(OpReg _))
- = pprInstr (XOR format' dst dst)
- where format' = case format of
- II64 -> II32 -- 32-bit version is equivalent, and smaller
- _ -> format
-pprInstr (MOV format src dst)
- = pprFormatOpOp (sLit "mov") format src dst
+ -- Replace 'mov $0x0,%reg' by 'xor %reg,%reg', which is smaller and cheaper.
+ -- The code generator catches most of these already, but not all.
+ MOV format (OpImm (ImmInt 0)) dst@(OpReg _)
+ -> pprInstr platform (XOR format' dst dst)
+ where format' = case format of
+ II64 -> II32 -- 32-bit version is equivalent, and smaller
+ _ -> format
+
+ MOV format src dst
+ -> pprFormatOpOp (sLit "mov") format src dst
-pprInstr (CMOV cc format src dst)
- = pprCondOpReg (sLit "cmov") format cc src dst
+ CMOV cc format src dst
+ -> pprCondOpReg (sLit "cmov") format cc src dst
-pprInstr (MOVZxL II32 src dst) = pprFormatOpOp (sLit "mov") II32 src dst
+ MOVZxL II32 src dst
+ -> pprFormatOpOp (sLit "mov") II32 src dst
-- 32-to-64 bit zero extension on x86_64 is accomplished by a simple
-- movl. But we represent it as a MOVZxL instruction, because
-- the reg alloc would tend to throw away a plain reg-to-reg
-- move, and we still want it to do that.
-pprInstr (MOVZxL formats src dst)
- = pprFormatOpOpCoerce (sLit "movz") formats II32 src dst
+ MOVZxL formats src dst
+ -> pprFormatOpOpCoerce (sLit "movz") formats II32 src dst
-- zero-extension only needs to extend to 32 bits: on x86_64,
-- the remaining zero-extension to 64 bits is automatic, and the 32-bit
-- instruction is shorter.
-pprInstr (MOVSxL formats src dst)
- = sdocWithPlatform $ \platform ->
- pprFormatOpOpCoerce (sLit "movs") formats (archWordFormat (target32Bit platform)) src dst
-
--- here we do some patching, since the physical registers are only set late
--- in the code generation.
-pprInstr (LEA format (OpAddr (AddrBaseIndex (EABaseReg reg1) (EAIndex reg2 1) (ImmInt 0))) dst@(OpReg reg3))
- | reg1 == reg3
- = pprFormatOpOp (sLit "add") format (OpReg reg2) dst
-
-pprInstr (LEA format (OpAddr (AddrBaseIndex (EABaseReg reg1) (EAIndex reg2 1) (ImmInt 0))) dst@(OpReg reg3))
- | reg2 == reg3
- = pprFormatOpOp (sLit "add") format (OpReg reg1) dst
-
-pprInstr (LEA format (OpAddr (AddrBaseIndex (EABaseReg reg1) EAIndexNone displ)) dst@(OpReg reg3))
- | reg1 == reg3
- = pprInstr (ADD format (OpImm displ) dst)
-
-pprInstr (LEA format src dst) = pprFormatOpOp (sLit "lea") format src dst
-
-pprInstr (ADD format (OpImm (ImmInt (-1))) dst)
- = pprFormatOp (sLit "dec") format dst
-pprInstr (ADD format (OpImm (ImmInt 1)) dst)
- = pprFormatOp (sLit "inc") format dst
-pprInstr (ADD format src dst) = pprFormatOpOp (sLit "add") format src dst
-pprInstr (ADC format src dst) = pprFormatOpOp (sLit "adc") format src dst
-pprInstr (SUB format src dst) = pprFormatOpOp (sLit "sub") format src dst
-pprInstr (SBB format src dst) = pprFormatOpOp (sLit "sbb") format src dst
-pprInstr (IMUL format op1 op2) = pprFormatOpOp (sLit "imul") format op1 op2
-
-pprInstr (ADD_CC format src dst)
- = pprFormatOpOp (sLit "add") format src dst
-pprInstr (SUB_CC format src dst)
- = pprFormatOpOp (sLit "sub") format src dst
-
-{- A hack. The Intel documentation says that "The two and three
- operand forms [of IMUL] may also be used with unsigned operands
- because the lower half of the product is the same regardless if
- (sic) the operands are signed or unsigned. The CF and OF flags,
- however, cannot be used to determine if the upper half of the
- result is non-zero." So there.
--}
+ MOVSxL formats src dst
+ -> pprFormatOpOpCoerce (sLit "movs") formats (archWordFormat (target32Bit platform)) src dst
+
+ -- here we do some patching, since the physical registers are only set late
+ -- in the code generation.
+ LEA format (OpAddr (AddrBaseIndex (EABaseReg reg1) (EAIndex reg2 1) (ImmInt 0))) dst@(OpReg reg3)
+ | reg1 == reg3
+ -> pprFormatOpOp (sLit "add") format (OpReg reg2) dst
+
+ LEA format (OpAddr (AddrBaseIndex (EABaseReg reg1) (EAIndex reg2 1) (ImmInt 0))) dst@(OpReg reg3)
+ | reg2 == reg3
+ -> pprFormatOpOp (sLit "add") format (OpReg reg1) dst
+
+ LEA format (OpAddr (AddrBaseIndex (EABaseReg reg1) EAIndexNone displ)) dst@(OpReg reg3)
+ | reg1 == reg3
+ -> pprInstr platform (ADD format (OpImm displ) dst)
+
+ LEA format src dst
+ -> pprFormatOpOp (sLit "lea") format src dst
+
+ ADD format (OpImm (ImmInt (-1))) dst
+ -> pprFormatOp (sLit "dec") format dst
+
+ ADD format (OpImm (ImmInt 1)) dst
+ -> pprFormatOp (sLit "inc") format dst
+
+ ADD format src dst
+ -> pprFormatOpOp (sLit "add") format src dst
+
+ ADC format src dst
+ -> pprFormatOpOp (sLit "adc") format src dst
+
+ SUB format src dst
+ -> pprFormatOpOp (sLit "sub") format src dst
+
+ SBB format src dst
+ -> pprFormatOpOp (sLit "sbb") format src dst
+
+ IMUL format op1 op2
+ -> pprFormatOpOp (sLit "imul") format op1 op2
+
+ ADD_CC format src dst
+ -> pprFormatOpOp (sLit "add") format src dst
+
+ SUB_CC format src dst
+ -> pprFormatOpOp (sLit "sub") format src dst
+
+ -- Use a 32-bit instruction when possible as it saves a byte.
+ -- Notably, extracting the tag bits of a pointer has this form.
+ -- TODO: we could save a byte in a subsequent CMP instruction too,
+ -- but need something like a peephole pass for this
+ AND II64 src@(OpImm (ImmInteger mask)) dst
+ | 0 <= mask && mask < 0xffffffff
+ -> pprInstr platform (AND II32 src dst)
+
+ AND FF32 src dst
+ -> pprOpOp (sLit "andps") FF32 src dst
+
+ AND FF64 src dst
+ -> pprOpOp (sLit "andpd") FF64 src dst
+
+ AND format src dst
+ -> pprFormatOpOp (sLit "and") format src dst
+
+ OR format src dst
+ -> pprFormatOpOp (sLit "or") format src dst
+
+ XOR FF32 src dst
+ -> pprOpOp (sLit "xorps") FF32 src dst
+
+ XOR FF64 src dst
+ -> pprOpOp (sLit "xorpd") FF64 src dst
+
+ XOR format src dst
+ -> pprFormatOpOp (sLit "xor") format src dst
+
+ POPCNT format src dst
+ -> pprOpOp (sLit "popcnt") format src (OpReg dst)
+
+ LZCNT format src dst
+ -> pprOpOp (sLit "lzcnt") format src (OpReg dst)
+
+ TZCNT format src dst
+ -> pprOpOp (sLit "tzcnt") format src (OpReg dst)
+
+ BSF format src dst
+ -> pprOpOp (sLit "bsf") format src (OpReg dst)
+
+ BSR format src dst
+ -> pprOpOp (sLit "bsr") format src (OpReg dst)
+
+ PDEP format src mask dst
+ -> pprFormatOpOpReg (sLit "pdep") format src mask dst
+
+ PEXT format src mask dst
+ -> pprFormatOpOpReg (sLit "pext") format src mask dst
+
+ PREFETCH NTA format src
+ -> pprFormatOp_ (sLit "prefetchnta") format src
+
+ PREFETCH Lvl0 format src
+ -> pprFormatOp_ (sLit "prefetcht0") format src
--- Use a 32-bit instruction when possible as it saves a byte.
--- Notably, extracting the tag bits of a pointer has this form.
--- TODO: we could save a byte in a subsequent CMP instruction too,
--- but need something like a peephole pass for this
-pprInstr (AND II64 src@(OpImm (ImmInteger mask)) dst)
- | 0 <= mask && mask < 0xffffffff
- = pprInstr (AND II32 src dst)
-pprInstr (AND FF32 src dst) = pprOpOp (sLit "andps") FF32 src dst
-pprInstr (AND FF64 src dst) = pprOpOp (sLit "andpd") FF64 src dst
-pprInstr (AND format src dst) = pprFormatOpOp (sLit "and") format src dst
-pprInstr (OR format src dst) = pprFormatOpOp (sLit "or") format src dst
-
-pprInstr (XOR FF32 src dst) = pprOpOp (sLit "xorps") FF32 src dst
-pprInstr (XOR FF64 src dst) = pprOpOp (sLit "xorpd") FF64 src dst
-pprInstr (XOR format src dst) = pprFormatOpOp (sLit "xor") format src dst
-
-pprInstr (POPCNT format src dst) = pprOpOp (sLit "popcnt") format src (OpReg dst)
-pprInstr (LZCNT format src dst) = pprOpOp (sLit "lzcnt") format src (OpReg dst)
-pprInstr (TZCNT format src dst) = pprOpOp (sLit "tzcnt") format src (OpReg dst)
-pprInstr (BSF format src dst) = pprOpOp (sLit "bsf") format src (OpReg dst)
-pprInstr (BSR format src dst) = pprOpOp (sLit "bsr") format src (OpReg dst)
-
-pprInstr (PDEP format src mask dst) = pprFormatOpOpReg (sLit "pdep") format src mask dst
-pprInstr (PEXT format src mask dst) = pprFormatOpOpReg (sLit "pext") format src mask dst
-
-pprInstr (PREFETCH NTA format src ) = pprFormatOp_ (sLit "prefetchnta") format src
-pprInstr (PREFETCH Lvl0 format src) = pprFormatOp_ (sLit "prefetcht0") format src
-pprInstr (PREFETCH Lvl1 format src) = pprFormatOp_ (sLit "prefetcht1") format src
-pprInstr (PREFETCH Lvl2 format src) = pprFormatOp_ (sLit "prefetcht2") format src
-
-pprInstr (NOT format op) = pprFormatOp (sLit "not") format op
-pprInstr (BSWAP format op) = pprFormatOp (sLit "bswap") format (OpReg op)
-pprInstr (NEGI format op) = pprFormatOp (sLit "neg") format op
-
-pprInstr (SHL format src dst) = pprShift (sLit "shl") format src dst
-pprInstr (SAR format src dst) = pprShift (sLit "sar") format src dst
-pprInstr (SHR format src dst) = pprShift (sLit "shr") format src dst
-
-pprInstr (BT format imm src) = pprFormatImmOp (sLit "bt") format imm src
-
-pprInstr (CMP format src dst)
- | isFloatFormat format = pprFormatOpOp (sLit "ucomi") format src dst -- SSE2
- | otherwise = pprFormatOpOp (sLit "cmp") format src dst
-
-pprInstr (TEST format src dst) = sdocWithPlatform $ \platform ->
- let format' = case (src,dst) of
+ PREFETCH Lvl1 format src
+ -> pprFormatOp_ (sLit "prefetcht1") format src
+
+ PREFETCH Lvl2 format src
+ -> pprFormatOp_ (sLit "prefetcht2") format src
+
+ NOT format op
+ -> pprFormatOp (sLit "not") format op
+
+ BSWAP format op
+ -> pprFormatOp (sLit "bswap") format (OpReg op)
+
+ NEGI format op
+ -> pprFormatOp (sLit "neg") format op
+
+ SHL format src dst
+ -> pprShift (sLit "shl") format src dst
+
+ SAR format src dst
+ -> pprShift (sLit "sar") format src dst
+
+ SHR format src dst
+ -> pprShift (sLit "shr") format src dst
+
+ BT format imm src
+ -> pprFormatImmOp (sLit "bt") format imm src
+
+ CMP format src dst
+ | isFloatFormat format -> pprFormatOpOp (sLit "ucomi") format src dst -- SSE2
+ | otherwise -> pprFormatOpOp (sLit "cmp") format src dst
+
+ TEST format src dst
+ -> pprFormatOpOp (sLit "test") format' src dst
+ where
-- Match instructions like 'test $0x3,%esi' or 'test $0x7,%rbx'.
-- We can replace them by equivalent, but smaller instructions
-- by reducing the size of the immediate operand as far as possible.
@@ -740,275 +785,308 @@ pprInstr (TEST format src dst) = sdocWithPlatform $ \platform ->
-- to be completely equivalent to the original; in particular so
-- that the signed comparison condition bits are the same as they
-- would be if doing a full word comparison. See #13425.
- (OpImm (ImmInteger mask), OpReg dstReg)
- | 0 <= mask && mask < 128 -> minSizeOfReg platform dstReg
- _ -> format
- in pprFormatOpOp (sLit "test") format' src dst
- where
- minSizeOfReg platform (RegReal (RealRegSingle i))
- | target32Bit platform && i <= 3 = II8 -- al, bl, cl, dl
- | target32Bit platform && i <= 7 = II16 -- si, di, bp, sp
- | not (target32Bit platform) && i <= 15 = II8 -- al .. r15b
- minSizeOfReg _ _ = format -- other
-
-pprInstr (PUSH format op) = pprFormatOp (sLit "push") format op
-pprInstr (POP format op) = pprFormatOp (sLit "pop") format op
+ format' = case (src,dst) of
+ (OpImm (ImmInteger mask), OpReg dstReg)
+ | 0 <= mask && mask < 128 -> minSizeOfReg platform dstReg
+ _ -> format
+ minSizeOfReg platform (RegReal (RealRegSingle i))
+ | target32Bit platform && i <= 3 = II8 -- al, bl, cl, dl
+ | target32Bit platform && i <= 7 = II16 -- si, di, bp, sp
+ | not (target32Bit platform) && i <= 15 = II8 -- al .. r15b
+ minSizeOfReg _ _ = format -- other
+
+ PUSH format op
+ -> pprFormatOp (sLit "push") format op
+
+ POP format op
+ -> pprFormatOp (sLit "pop") format op
-- both unused (SDM):
--- pprInstr PUSHA = text "\tpushal"
--- pprInstr POPA = text "\tpopal"
-
-pprInstr NOP = text "\tnop"
-pprInstr (CLTD II8) = text "\tcbtw"
-pprInstr (CLTD II16) = text "\tcwtd"
-pprInstr (CLTD II32) = text "\tcltd"
-pprInstr (CLTD II64) = text "\tcqto"
-pprInstr (CLTD x) = panic $ "pprInstr: " ++ show x
-
-pprInstr (SETCC cond op) = pprCondInstr (sLit "set") cond (pprOperand II8 op)
-
-pprInstr (JXX cond blockid)
- = pprCondInstr (sLit "j") cond (ppr lab)
- where lab = blockLbl blockid
-
-pprInstr (JXX_GBL cond imm) = pprCondInstr (sLit "j") cond (pprImm imm)
-
-pprInstr (JMP (OpImm imm) _) = text "\tjmp " <> pprImm imm
-pprInstr (JMP op _) = sdocWithPlatform $ \platform ->
- text "\tjmp *"
- <> pprOperand (archWordFormat (target32Bit platform)) op
-pprInstr (JMP_TBL op _ _ _) = pprInstr (JMP op [])
-pprInstr (CALL (Left imm) _) = text "\tcall " <> pprImm imm
-pprInstr (CALL (Right reg) _) = sdocWithPlatform $ \platform ->
- text "\tcall *"
- <> pprReg (archWordFormat (target32Bit platform)) reg
-
-pprInstr (IDIV fmt op) = pprFormatOp (sLit "idiv") fmt op
-pprInstr (DIV fmt op) = pprFormatOp (sLit "div") fmt op
-pprInstr (IMUL2 fmt op) = pprFormatOp (sLit "imul") fmt op
-
--- x86_64 only
-pprInstr (MUL format op1 op2) = pprFormatOpOp (sLit "mul") format op1 op2
-pprInstr (MUL2 format op) = pprFormatOp (sLit "mul") format op
-
-pprInstr (FDIV format op1 op2) = pprFormatOpOp (sLit "div") format op1 op2
-pprInstr (SQRT format op1 op2) = pprFormatOpReg (sLit "sqrt") format op1 op2
-
-pprInstr (CVTSS2SD from to) = pprRegReg (sLit "cvtss2sd") from to
-pprInstr (CVTSD2SS from to) = pprRegReg (sLit "cvtsd2ss") from to
-pprInstr (CVTTSS2SIQ fmt from to) = pprFormatFormatOpReg (sLit "cvttss2si") FF32 fmt from to
-pprInstr (CVTTSD2SIQ fmt from to) = pprFormatFormatOpReg (sLit "cvttsd2si") FF64 fmt from to
-pprInstr (CVTSI2SS fmt from to) = pprFormatOpReg (sLit "cvtsi2ss") fmt from to
-pprInstr (CVTSI2SD fmt from to) = pprFormatOpReg (sLit "cvtsi2sd") fmt from to
-
- -- FETCHGOT for PIC on ELF platforms
-pprInstr (FETCHGOT reg)
- = vcat [ text "\tcall 1f",
- hcat [ text "1:\tpopl\t", pprReg II32 reg ],
- hcat [ text "\taddl\t$_GLOBAL_OFFSET_TABLE_+(.-1b), ",
- pprReg 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)
-pprInstr (FETCHPC reg)
- = vcat [ text "\tcall 1f",
- hcat [ text "1:\tpopl\t", pprReg II32 reg ]
- ]
-
+-- PUSHA -> text "\tpushal"
+-- POPA -> text "\tpopal"
--- the
--- GST fmt src addr ==> FLD dst ; FSTPsz addr
-pprInstr g@(X87Store fmt addr)
- = pprX87 g (hcat [gtab,
- text "fstp", pprFormat_x87 fmt, gsp, pprAddr addr])
+ NOP
+ -> text "\tnop"
+ CLTD II8
+ -> text "\tcbtw"
--- Atomics
+ CLTD II16
+ -> text "\tcwtd"
-pprInstr (LOCK i) = text "\tlock" $$ pprInstr i
+ CLTD II32
+ -> text "\tcltd"
-pprInstr MFENCE = text "\tmfence"
+ CLTD II64
+ -> text "\tcqto"
-pprInstr (XADD format src dst) = pprFormatOpOp (sLit "xadd") format src dst
+ CLTD x
+ -> panic $ "pprInstr: CLTD " ++ show x
-pprInstr (CMPXCHG format src dst)
- = pprFormatOpOp (sLit "cmpxchg") format src dst
+ SETCC cond op
+ -> pprCondInstr (sLit "set") cond (pprOperand platform II8 op)
+ JXX cond blockid
+ -> pprCondInstr (sLit "j") cond (ppr lab)
+ where lab = blockLbl blockid
+ JXX_GBL cond imm
+ -> pprCondInstr (sLit "j") cond (pprImm imm)
---------------------------
--- some left over
+ JMP (OpImm imm) _
+ -> text "\tjmp " <> pprImm imm
+ JMP op _
+ -> text "\tjmp *" <> pprOperand platform (archWordFormat (target32Bit platform)) op
+ JMP_TBL op _ _ _
+ -> pprInstr platform (JMP op [])
-gtab :: SDoc
-gtab = char '\t'
+ CALL (Left imm) _
+ -> text "\tcall " <> pprImm imm
-gsp :: SDoc
-gsp = char ' '
+ CALL (Right reg) _
+ -> text "\tcall *" <> pprReg platform (archWordFormat (target32Bit platform)) reg
+ IDIV fmt op
+ -> pprFormatOp (sLit "idiv") fmt op
+ DIV fmt op
+ -> pprFormatOp (sLit "div") fmt op
-pprX87 :: Instr -> SDoc -> SDoc
-pprX87 fake actual
- = (char '#' <> pprX87Instr fake) $$ actual
+ IMUL2 fmt op
+ -> pprFormatOp (sLit "imul") fmt op
-pprX87Instr :: Instr -> SDoc
-pprX87Instr (X87Store fmt dst) = pprFormatAddr (sLit "gst") fmt dst
-pprX87Instr _ = panic "X86.Ppr.pprX87Instr: no match"
+ -- x86_64 only
+ MUL format op1 op2
+ -> pprFormatOpOp (sLit "mul") format op1 op2
-pprDollImm :: Imm -> SDoc
-pprDollImm i = text "$" <> pprImm i
+ MUL2 format op
+ -> pprFormatOp (sLit "mul") format op
+ FDIV format op1 op2
+ -> pprFormatOpOp (sLit "div") format op1 op2
-pprOperand :: Format -> Operand -> SDoc
-pprOperand f (OpReg r) = pprReg f r
-pprOperand _ (OpImm i) = pprDollImm i
-pprOperand _ (OpAddr ea) = pprAddr ea
+ SQRT format op1 op2
+ -> pprFormatOpReg (sLit "sqrt") format op1 op2
+ CVTSS2SD from to
+ -> pprRegReg (sLit "cvtss2sd") from to
-pprMnemonic_ :: PtrString -> SDoc
-pprMnemonic_ name =
- char '\t' <> ptext name <> space
+ CVTSD2SS from to
+ -> pprRegReg (sLit "cvtsd2ss") from to
+ CVTTSS2SIQ fmt from to
+ -> pprFormatFormatOpReg (sLit "cvttss2si") FF32 fmt from to
-pprMnemonic :: PtrString -> Format -> SDoc
-pprMnemonic name format =
- char '\t' <> ptext name <> pprFormat format <> space
+ CVTTSD2SIQ fmt from to
+ -> pprFormatFormatOpReg (sLit "cvttsd2si") FF64 fmt from to
+ CVTSI2SS fmt from to
+ -> pprFormatOpReg (sLit "cvtsi2ss") fmt from to
-pprFormatImmOp :: PtrString -> Format -> Imm -> Operand -> SDoc
-pprFormatImmOp name format imm op1
- = hcat [
- pprMnemonic name format,
- char '$',
- pprImm imm,
- comma,
- pprOperand format op1
- ]
-
-
-pprFormatOp_ :: PtrString -> Format -> Operand -> SDoc
-pprFormatOp_ name format op1
- = hcat [
- pprMnemonic_ name ,
- pprOperand format op1
- ]
-
-pprFormatOp :: PtrString -> Format -> Operand -> SDoc
-pprFormatOp name format op1
- = hcat [
- pprMnemonic name format,
- pprOperand format op1
- ]
-
-
-pprFormatOpOp :: PtrString -> Format -> Operand -> Operand -> SDoc
-pprFormatOpOp name format op1 op2
- = hcat [
- pprMnemonic name format,
- pprOperand format op1,
- comma,
- pprOperand format op2
- ]
+ CVTSI2SD fmt from to
+ -> pprFormatOpReg (sLit "cvtsi2sd") fmt from to
+ -- 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 ]
+ ]
-pprOpOp :: PtrString -> Format -> Operand -> Operand -> SDoc
-pprOpOp name format op1 op2
- = hcat [
- pprMnemonic_ name,
- pprOperand format op1,
- comma,
- pprOperand format op2
- ]
+ -- 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 ]
+ ]
+ -- the
+ -- GST fmt src addr ==> FLD dst ; FSTPsz addr
+ g@(X87Store fmt addr)
+ -> pprX87 g (hcat [gtab, text "fstp", pprFormat_x87 fmt, gsp, pprAddr platform addr])
+ -- Atomics
+ LOCK i
+ -> text "\tlock" $$ pprInstr platform i
-pprRegReg :: PtrString -> Reg -> Reg -> SDoc
-pprRegReg name reg1 reg2
- = sdocWithPlatform $ \platform ->
- hcat [
- pprMnemonic_ name,
- pprReg (archWordFormat (target32Bit platform)) reg1,
- comma,
- pprReg (archWordFormat (target32Bit platform)) reg2
- ]
-
-
-pprFormatOpReg :: PtrString -> Format -> Operand -> Reg -> SDoc
-pprFormatOpReg name format op1 reg2
- = sdocWithPlatform $ \platform ->
- hcat [
- pprMnemonic name format,
- pprOperand format op1,
- comma,
- pprReg (archWordFormat (target32Bit platform)) reg2
- ]
-
-pprCondOpReg :: PtrString -> Format -> Cond -> Operand -> Reg -> SDoc
-pprCondOpReg name format cond op1 reg2
- = hcat [
- char '\t',
- ptext name,
- pprCond cond,
- space,
- pprOperand format op1,
- comma,
- pprReg format reg2
- ]
-
-pprFormatFormatOpReg :: PtrString -> Format -> Format -> Operand -> Reg -> SDoc
-pprFormatFormatOpReg name format1 format2 op1 reg2
- = hcat [
- pprMnemonic name format2,
- pprOperand format1 op1,
- comma,
- pprReg format2 reg2
- ]
-
-pprFormatOpOpReg :: PtrString -> Format -> Operand -> Operand -> Reg -> SDoc
-pprFormatOpOpReg name format op1 op2 reg3
- = hcat [
- pprMnemonic name format,
- pprOperand format op1,
- comma,
- pprOperand format op2,
- comma,
- pprReg format reg3
- ]
+ MFENCE
+ -> text "\tmfence"
+ XADD format src dst
+ -> pprFormatOpOp (sLit "xadd") format src dst
+ CMPXCHG format src dst
+ -> pprFormatOpOp (sLit "cmpxchg") format src dst
-pprFormatAddr :: PtrString -> Format -> AddrMode -> SDoc
-pprFormatAddr name format op
- = hcat [
- pprMnemonic name format,
- comma,
- pprAddr op
- ]
-
-pprShift :: PtrString -> Format -> Operand -> Operand -> SDoc
-pprShift name format src dest
- = hcat [
- pprMnemonic name format,
- pprOperand II8 src, -- src is 8-bit sized
- comma,
- pprOperand format dest
- ]
-
-
-pprFormatOpOpCoerce :: PtrString -> Format -> Format -> Operand -> Operand -> SDoc
-pprFormatOpOpCoerce name format1 format2 op1 op2
- = hcat [ char '\t', ptext name, pprFormat format1, pprFormat format2, space,
- pprOperand format1 op1,
- comma,
- pprOperand format2 op2
- ]
+ where
+ gtab :: SDoc
+ gtab = char '\t'
-pprCondInstr :: PtrString -> Cond -> SDoc -> SDoc
-pprCondInstr name cond arg
- = hcat [ char '\t', ptext name, pprCond cond, space, arg]
+ gsp :: SDoc
+ gsp = char ' '
+
+
+
+ pprX87 :: Instr -> SDoc -> SDoc
+ pprX87 fake actual
+ = (char '#' <> pprX87Instr fake) $$ actual
+
+ pprX87Instr :: Instr -> SDoc
+ pprX87Instr (X87Store fmt dst) = pprFormatAddr (sLit "gst") fmt dst
+ pprX87Instr _ = panic "X86.Ppr.pprX87Instr: no match"
+
+ pprDollImm :: Imm -> SDoc
+ pprDollImm i = text "$" <> pprImm i
+
+
+ pprOperand :: Platform -> Format -> Operand -> SDoc
+ pprOperand platform f op = case op of
+ OpReg r -> pprReg platform f r
+ OpImm i -> pprDollImm i
+ OpAddr ea -> pprAddr platform ea
+
+
+ pprMnemonic_ :: PtrString -> SDoc
+ pprMnemonic_ name =
+ char '\t' <> ptext name <> space
+
+
+ pprMnemonic :: PtrString -> Format -> SDoc
+ pprMnemonic name format =
+ char '\t' <> ptext name <> pprFormat format <> space
+
+
+ pprFormatImmOp :: PtrString -> Format -> Imm -> Operand -> SDoc
+ pprFormatImmOp name format imm op1
+ = hcat [
+ pprMnemonic name format,
+ char '$',
+ pprImm imm,
+ comma,
+ pprOperand platform format op1
+ ]
+
+
+ pprFormatOp_ :: PtrString -> Format -> Operand -> SDoc
+ pprFormatOp_ name format op1
+ = hcat [
+ pprMnemonic_ name ,
+ pprOperand platform format op1
+ ]
+
+ pprFormatOp :: PtrString -> Format -> Operand -> SDoc
+ pprFormatOp name format op1
+ = hcat [
+ pprMnemonic name format,
+ pprOperand platform format op1
+ ]
+
+
+ pprFormatOpOp :: PtrString -> Format -> Operand -> Operand -> SDoc
+ pprFormatOpOp name format op1 op2
+ = hcat [
+ pprMnemonic name format,
+ pprOperand platform format op1,
+ comma,
+ pprOperand platform format op2
+ ]
+
+
+ pprOpOp :: PtrString -> Format -> Operand -> Operand -> SDoc
+ pprOpOp name format op1 op2
+ = hcat [
+ pprMnemonic_ name,
+ pprOperand platform format op1,
+ comma,
+ pprOperand platform format op2
+ ]
+
+ pprRegReg :: PtrString -> Reg -> Reg -> SDoc
+ pprRegReg name reg1 reg2
+ = hcat [
+ pprMnemonic_ name,
+ pprReg platform (archWordFormat (target32Bit platform)) reg1,
+ comma,
+ pprReg platform (archWordFormat (target32Bit platform)) reg2
+ ]
+
+
+ pprFormatOpReg :: PtrString -> Format -> Operand -> Reg -> SDoc
+ pprFormatOpReg name format op1 reg2
+ = hcat [
+ pprMnemonic name format,
+ pprOperand platform format op1,
+ comma,
+ pprReg platform (archWordFormat (target32Bit platform)) reg2
+ ]
+
+ pprCondOpReg :: PtrString -> Format -> Cond -> Operand -> Reg -> SDoc
+ pprCondOpReg name format cond op1 reg2
+ = hcat [
+ char '\t',
+ ptext name,
+ pprCond cond,
+ space,
+ pprOperand platform format op1,
+ comma,
+ pprReg platform format reg2
+ ]
+
+ pprFormatFormatOpReg :: PtrString -> Format -> Format -> Operand -> Reg -> SDoc
+ pprFormatFormatOpReg name format1 format2 op1 reg2
+ = hcat [
+ pprMnemonic name format2,
+ pprOperand platform format1 op1,
+ comma,
+ pprReg platform format2 reg2
+ ]
+
+ pprFormatOpOpReg :: PtrString -> Format -> Operand -> Operand -> Reg -> SDoc
+ pprFormatOpOpReg name format op1 op2 reg3
+ = hcat [
+ pprMnemonic name format,
+ pprOperand platform format op1,
+ comma,
+ pprOperand platform format op2,
+ comma,
+ pprReg platform format reg3
+ ]
+
+
+
+ pprFormatAddr :: PtrString -> Format -> AddrMode -> SDoc
+ pprFormatAddr name format op
+ = hcat [
+ pprMnemonic name format,
+ comma,
+ pprAddr platform op
+ ]
+
+ pprShift :: PtrString -> Format -> Operand -> Operand -> SDoc
+ pprShift name format src dest
+ = hcat [
+ pprMnemonic name format,
+ pprOperand platform II8 src, -- src is 8-bit sized
+ comma,
+ pprOperand platform format dest
+ ]
+
+
+ pprFormatOpOpCoerce :: PtrString -> Format -> Format -> Operand -> Operand -> SDoc
+ pprFormatOpOpCoerce name format1 format2 op1 op2
+ = hcat [ char '\t', ptext name, pprFormat format1, pprFormat format2, space,
+ pprOperand platform format1 op1,
+ comma,
+ pprOperand platform format2 op2
+ ]
+
+
+ pprCondInstr :: PtrString -> Cond -> SDoc -> SDoc
+ pprCondInstr name cond arg
+ = hcat [ char '\t', ptext name, pprCond cond, space, arg]
diff --git a/compiler/GHC/CmmToAsm/X86/Regs.hs b/compiler/GHC/CmmToAsm/X86/Regs.hs
index 87e31a1428..ab8e6d3b4f 100644
--- a/compiler/GHC/CmmToAsm/X86/Regs.hs
+++ b/compiler/GHC/CmmToAsm/X86/Regs.hs
@@ -57,7 +57,6 @@ import GHC.Platform.Reg.Class
import GHC.Cmm
import GHC.Cmm.CLabel ( CLabel )
-import GHC.Driver.Session
import Outputable
import GHC.Platform
@@ -188,11 +187,11 @@ addrModeRegs _ = []
-- applicable, is the same but for the frame pointer.
-spRel :: DynFlags
+spRel :: Platform
-> Int -- ^ desired stack offset in bytes, positive or negative
-> AddrMode
-spRel dflags n
- | target32Bit (targetPlatform dflags)
+spRel platform n
+ | target32Bit platform
= AddrBaseIndex (EABaseReg esp) EAIndexNone (ImmInt n)
| otherwise
= AddrBaseIndex (EABaseReg rsp) EAIndexNone (ImmInt n)
diff --git a/compiler/GHC/CmmToC.hs b/compiler/GHC/CmmToC.hs
index 6e6f58ba7d..7944f6a0fc 100644
--- a/compiler/GHC/CmmToC.hs
+++ b/compiler/GHC/CmmToC.hs
@@ -406,7 +406,7 @@ pprLoad dflags e ty
-- (For tagging to work, I had to avoid unaligned loads. --ARY)
-> pprAsPtrReg r <> brackets (ppr (off `shiftR` wordShift dflags))
- _other -> cLoad e ty
+ _other -> cLoad (targetPlatform dflags) e ty
where
width = typeWidth ty
@@ -1145,10 +1145,9 @@ te_Reg _ = return ()
cCast :: SDoc -> CmmExpr -> SDoc
cCast ty expr = parens ty <> pprExpr1 expr
-cLoad :: CmmExpr -> CmmType -> SDoc
-cLoad expr rep
- = sdocWithPlatform $ \platform ->
- if bewareLoadStoreAlignment (platformArch platform)
+cLoad :: Platform -> CmmExpr -> CmmType -> SDoc
+cLoad platform expr rep
+ = if bewareLoadStoreAlignment (platformArch platform)
then let decl = machRepCType rep <+> text "x" <> semi
struct = text "struct" <+> braces (decl)
packed_attr = text "__attribute__((packed))"
diff --git a/compiler/GHC/Driver/Session.hs b/compiler/GHC/Driver/Session.hs
index 97dd1a6f07..ac0bbbd286 100644
--- a/compiler/GHC/Driver/Session.hs
+++ b/compiler/GHC/Driver/Session.hs
@@ -235,7 +235,7 @@ module GHC.Driver.Session (
initSDocContext,
-- * Make use of the Cmm CFG
- CfgWeights(..), backendMaintainsCfg
+ CfgWeights(..)
) where
#include "HsVersions.h"
@@ -852,12 +852,6 @@ parseCfgWeights s oldWeights =
",likelyCondWeight=900,unlikelyCondWeight=300" ++
",infoTablePenalty=300,backEdgeBonus=400"
-backendMaintainsCfg :: DynFlags -> Bool
-backendMaintainsCfg dflags = case (platformArch $ targetPlatform dflags) of
- -- ArchX86 -- Should work but not tested so disabled currently.
- ArchX86_64 -> True
- _otherwise -> False
-
class HasDynFlags m where
getDynFlags :: m DynFlags
@@ -5226,7 +5220,6 @@ initSDocContext dflags style = SDC
, sdocLineLength = pprCols dflags
, sdocCanUseUnicode = useUnicode dflags
, sdocHexWordLiterals = gopt Opt_HexWordLiterals dflags
- , sdocDebugLevel = debugLevel dflags
, sdocPprDebug = dopt Opt_D_ppr_debug dflags
, sdocPrintUnicodeSyntax = gopt Opt_PrintUnicodeSyntax dflags
, sdocPrintCaseAsLet = gopt Opt_PprCaseAsLet dflags
diff --git a/compiler/ghc.cabal.in b/compiler/ghc.cabal.in
index 0cc41b65c0..7a2fd82342 100644
--- a/compiler/ghc.cabal.in
+++ b/compiler/ghc.cabal.in
@@ -269,6 +269,7 @@ Library
FileSettings
GHC.Cmm.Graph
GHC.CmmToAsm.Ppr
+ GHC.CmmToAsm.Config
GHC.CmmToC
GHC.Cmm.Ppr
GHC.Cmm.Ppr.Decl
diff --git a/compiler/main/Elf.hs b/compiler/main/Elf.hs
index e9c80d7d81..4d3b06e731 100644
--- a/compiler/main/Elf.hs
+++ b/compiler/main/Elf.hs
@@ -19,6 +19,7 @@ import GhcPrelude
import AsmUtils
import Exception
import GHC.Driver.Session
+import GHC.Platform
import ErrUtils
import Maybes (MaybeT(..),runMaybeT)
import Util (charToC)
@@ -408,12 +409,12 @@ readElfNoteAsString dflags path sectionName noteId = action `catchIO` \_ -> do
-- | Generate the GAS code to create a Note section
--
-- Header fields for notes are 32-bit long (see Note [ELF specification]).
-makeElfNote :: String -> String -> Word32 -> String -> SDoc
-makeElfNote sectionName noteName typ contents = hcat [
+makeElfNote :: Platform -> String -> String -> Word32 -> String -> SDoc
+makeElfNote platform sectionName noteName typ contents = hcat [
text "\t.section ",
text sectionName,
text ",\"\",",
- sectionType "note",
+ sectionType platform "note",
text "\n",
text "\t.balign 4\n",
diff --git a/compiler/main/SysTools/ExtraObj.hs b/compiler/main/SysTools/ExtraObj.hs
index 9ff428f9ca..73b28a368f 100644
--- a/compiler/main/SysTools/ExtraObj.hs
+++ b/compiler/main/SysTools/ExtraObj.hs
@@ -143,22 +143,23 @@ mkNoteObjsToLinkIntoBinary :: DynFlags -> [InstalledUnitId] -> IO [FilePath]
mkNoteObjsToLinkIntoBinary dflags dep_packages = do
link_info <- getLinkInfo dflags dep_packages
- if (platformSupportsSavingLinkOpts (platformOS (targetPlatform dflags)))
+ if (platformSupportsSavingLinkOpts (platformOS platform ))
then fmap (:[]) $ mkExtraObj dflags "s" (showSDoc dflags (link_opts link_info))
else return []
where
+ platform = targetPlatform dflags
link_opts info = hcat [
-- "link info" section (see Note [LinkInfo section])
- makeElfNote ghcLinkInfoSectionName ghcLinkInfoNoteName 0 info,
+ makeElfNote platform ghcLinkInfoSectionName ghcLinkInfoNoteName 0 info,
-- ALL generated assembly must have this section to disable
-- executable stacks. See also
-- compiler/nativeGen/AsmCodeGen.hs for another instance
-- where we need to do this.
- if platformHasGnuNonexecStack (targetPlatform dflags)
+ if platformHasGnuNonexecStack platform
then text ".section .note.GNU-stack,\"\","
- <> sectionType "progbits" <> char '\n'
+ <> sectionType platform "progbits" <> char '\n'
else Outputable.empty
]
diff --git a/compiler/utils/AsmUtils.hs b/compiler/utils/AsmUtils.hs
index 591b53dc31..d3393d71e2 100644
--- a/compiler/utils/AsmUtils.hs
+++ b/compiler/utils/AsmUtils.hs
@@ -12,9 +12,10 @@ import GHC.Platform
import Outputable
-- | Generate a section type (e.g. @\@progbits@). See #13937.
-sectionType :: String -- ^ section type
- -> SDoc -- ^ pretty assembler fragment
-sectionType ty = sdocWithPlatform $ \platform ->
+sectionType :: Platform -- ^ Target platform
+ -> String -- ^ section type
+ -> SDoc -- ^ pretty assembler fragment
+sectionType platform ty =
case platformArch platform of
ArchARM{} -> char '%' <> text ty
_ -> char '@' <> text ty
diff --git a/compiler/utils/Outputable.hs b/compiler/utils/Outputable.hs
index 7133951d67..6f6a335ed7 100644
--- a/compiler/utils/Outputable.hs
+++ b/compiler/utils/Outputable.hs
@@ -71,7 +71,7 @@ module Outputable (
neverQualify, neverQualifyNames, neverQualifyModules,
alwaysQualifyPackages, neverQualifyPackages,
QualifyName(..), queryQual,
- sdocWithDynFlags, sdocWithPlatform, sdocOption,
+ sdocWithDynFlags, sdocOption,
updSDocContext,
SDocContext (..), sdocWithContext,
getPprStyle, withPprStyle, setStyleColoured,
@@ -96,7 +96,7 @@ import GhcPrelude
import {-# SOURCE #-} GHC.Driver.Session
( DynFlags, hasPprDebug, hasNoDebugOutput
- , targetPlatform, pprUserLength, pprCols
+ , pprUserLength, pprCols
, unsafeGlobalDynFlags, initSDocContext
)
import {-# SOURCE #-} Module( UnitId, Module, ModuleName, moduleName )
@@ -106,7 +106,6 @@ import BufWrite (BufHandle)
import FastString
import qualified Pretty
import Util
-import GHC.Platform
import qualified PprColour as Col
import Pretty ( Doc, Mode(..) )
import Panic
@@ -346,7 +345,6 @@ data SDocContext = SDC
-- ^ True if Unicode encoding is supported
-- and not disable by GHC_NO_UNICODE environment variable
, sdocHexWordLiterals :: !Bool
- , sdocDebugLevel :: !Int
, sdocPprDebug :: !Bool
, sdocPrintUnicodeSyntax :: !Bool
, sdocPrintCaseAsLet :: !Bool
@@ -422,9 +420,6 @@ getPprStyle df = SDoc $ \ctx -> runSDoc (df (sdocStyle ctx)) ctx
sdocWithDynFlags :: (DynFlags -> SDoc) -> SDoc
sdocWithDynFlags f = SDoc $ \ctx -> runSDoc (f (sdocDynFlags ctx)) ctx
-sdocWithPlatform :: (Platform -> SDoc) -> SDoc
-sdocWithPlatform f = sdocWithDynFlags (f . targetPlatform)
-
sdocWithContext :: (SDocContext -> SDoc) -> SDoc
sdocWithContext f = SDoc $ \ctx -> runSDoc (f ctx) ctx
diff --git a/testsuite/tests/regalloc/regalloc_unit_tests.hs b/testsuite/tests/regalloc/regalloc_unit_tests.hs
index f9ccd1f703..2b018fc0e1 100644
--- a/testsuite/tests/regalloc/regalloc_unit_tests.hs
+++ b/testsuite/tests/regalloc/regalloc_unit_tests.hs
@@ -200,7 +200,7 @@ testGraphNoSpills dflags' path us = do
-- discard irrelevant stats
extractSRMs x = case x of
Color.RegAllocStatsColored _ _ _ _ _ _ _ _
- rSrms -> Just rSrms
+ rSrms _ -> Just rSrms
_ -> Nothing
matchesExpected (a, b, c) = a == 0 && b == 0