summaryrefslogtreecommitdiff
path: root/compiler/llvmGen
diff options
context:
space:
mode:
authorSimon Brenner <olsner@gmail.com>2015-11-12 11:10:54 +0100
committerBen Gamari <ben@smart-cactus.org>2015-11-12 11:10:54 +0100
commit4a32bf925b8aba7885d9c745769fe84a10979a53 (patch)
tree73869f4df99cdb434e7fdd10f67cc9ea96022f4c /compiler/llvmGen
parent9bea234dbe3b36957acc42f74f0d54ddc05ad139 (diff)
downloadhaskell-4a32bf925b8aba7885d9c745769fe84a10979a53.tar.gz
Implement function-sections for Haskell code, #8405
This adds a flag -split-sections that does similar things to -split-objs, but using sections in single object files instead of relying on the Satanic Splitter and other abominations. This is very similar to the GCC flags -ffunction-sections and -fdata-sections. The --gc-sections linker flag, which allows unused sections to actually be removed, is added to all link commands (if the linker supports it) so that space savings from having base compiled with sections can be realized. Supported both in LLVM and the native code-gen, in theory for all architectures, but really tested on x86 only. In the GHC build, a new SplitSections variable enables -split-sections for relevant parts of the build. Test Plan: validate with both settings of SplitSections Reviewers: dterei, Phyx, austin, simonmar, thomie, bgamari Reviewed By: simonmar, thomie, bgamari Subscribers: hsyl20, erikd, kgardas, thomie Differential Revision: https://phabricator.haskell.org/D1242 GHC Trac Issues: #8405
Diffstat (limited to 'compiler/llvmGen')
-rw-r--r--compiler/llvmGen/LlvmCodeGen/Base.hs8
-rw-r--r--compiler/llvmGen/LlvmCodeGen/CodeGen.hs4
-rw-r--r--compiler/llvmGen/LlvmCodeGen/Data.hs42
-rw-r--r--compiler/llvmGen/LlvmCodeGen/Ppr.hs4
4 files changed, 46 insertions, 12 deletions
diff --git a/compiler/llvmGen/LlvmCodeGen/Base.hs b/compiler/llvmGen/LlvmCodeGen/Base.hs
index 7a673b8ec3..3367cdaf45 100644
--- a/compiler/llvmGen/LlvmCodeGen/Base.hs
+++ b/compiler/llvmGen/LlvmCodeGen/Base.hs
@@ -26,7 +26,7 @@ module LlvmCodeGen.Base (
cmmToLlvmType, widthToLlvmFloat, widthToLlvmInt, llvmFunTy,
llvmFunSig, llvmFunArgs, llvmStdFunAttrs, llvmFunAlign, llvmInfAlign,
- llvmPtrBits, tysToParams,
+ llvmPtrBits, tysToParams, llvmFunSection,
strCLabel_llvm, strDisplayName_llvm, strProcedureName_llvm,
getGlobalPtr, generateExternDecls,
@@ -140,6 +140,12 @@ llvmFunAlign dflags = Just (wORD_SIZE dflags)
llvmInfAlign :: DynFlags -> LMAlign
llvmInfAlign dflags = Just (wORD_SIZE dflags)
+-- | Section to use for a function
+llvmFunSection :: DynFlags -> LMString -> LMSection
+llvmFunSection dflags lbl
+ | gopt Opt_SplitSections dflags = Just (concatFS [fsLit ".text.", lbl])
+ | otherwise = Nothing
+
-- | A Function's arguments
llvmFunArgs :: DynFlags -> LiveGlobalRegs -> [LlvmVar]
llvmFunArgs dflags live =
diff --git a/compiler/llvmGen/LlvmCodeGen/CodeGen.hs b/compiler/llvmGen/LlvmCodeGen/CodeGen.hs
index aa3a0c3f1e..fb79a9d973 100644
--- a/compiler/llvmGen/LlvmCodeGen/CodeGen.hs
+++ b/compiler/llvmGen/LlvmCodeGen/CodeGen.hs
@@ -144,7 +144,9 @@ getInstrinct2 fname fty@(LMFunction funSig) = do
return []
Nothing -> do
funInsert fname fty
- return [CmmData Data [([],[fty])]]
+ un <- runUs getUniqueM
+ let lbl = mkAsmTempLabel un
+ return [CmmData (Section Data lbl) [([],[fty])]]
return (fv, nilOL, tops)
diff --git a/compiler/llvmGen/LlvmCodeGen/Data.hs b/compiler/llvmGen/LlvmCodeGen/Data.hs
index b306748d23..3c1af4f587 100644
--- a/compiler/llvmGen/LlvmCodeGen/Data.hs
+++ b/compiler/llvmGen/LlvmCodeGen/Data.hs
@@ -15,6 +15,7 @@ import LlvmCodeGen.Base
import BlockId
import CLabel
import Cmm
+import DynFlags
import FastString
import Outputable
@@ -36,6 +37,7 @@ genLlvmData :: (Section, CmmStatics) -> LlvmM LlvmData
genLlvmData (sec, Statics lbl xs) = do
label <- strCLabel_llvm lbl
static <- mapM genData xs
+ lmsec <- llvmSection sec
let types = map getStatType static
strucTy = LMStruct types
@@ -45,21 +47,43 @@ genLlvmData (sec, Statics lbl xs) = do
link = if (externallyVisibleCLabel lbl)
then ExternallyVisible else Internal
const = if isSecConstant sec then Constant else Global
- varDef = LMGlobalVar label tyAlias link Nothing Nothing const
+ varDef = LMGlobalVar label tyAlias link lmsec Nothing const
globDef = LMGlobal varDef struct
return ([globDef], [tyAlias])
-- | Should a data in this section be considered constant
isSecConstant :: Section -> Bool
-isSecConstant Text = True
-isSecConstant ReadOnlyData = True
-isSecConstant RelocatableReadOnlyData = True
-isSecConstant ReadOnlyData16 = True
-isSecConstant Data = False
-isSecConstant UninitialisedData = False
-isSecConstant (OtherSection _) = False
-
+isSecConstant (Section t _) = case t of
+ Text -> True
+ ReadOnlyData -> True
+ RelocatableReadOnlyData -> True
+ ReadOnlyData16 -> True
+ Data -> False
+ UninitialisedData -> False
+ (OtherSection _) -> False
+
+-- | Format the section type part of a Cmm Section
+llvmSectionType :: SectionType -> FastString
+llvmSectionType t = case t of
+ Text -> fsLit ".text"
+ ReadOnlyData -> fsLit ".rodata"
+ RelocatableReadOnlyData -> fsLit ".data.rel.ro"
+ ReadOnlyData16 -> fsLit ".rodata.cst16"
+ Data -> fsLit ".data"
+ UninitialisedData -> fsLit ".bss"
+ (OtherSection _) -> panic "llvmSectionType: unknown section type"
+
+-- | Format a Cmm Section into a LLVM section name
+llvmSection :: Section -> LlvmM LMSection
+llvmSection (Section t suffix) = do
+ dflags <- getDynFlags
+ let splitSect = gopt Opt_SplitSections dflags
+ if not splitSect
+ then return Nothing
+ else do
+ lmsuffix <- strCLabel_llvm suffix
+ return (Just (concatFS [llvmSectionType t, fsLit ".", lmsuffix]))
-- ----------------------------------------------------------------------------
-- * Generate static data
diff --git a/compiler/llvmGen/LlvmCodeGen/Ppr.hs b/compiler/llvmGen/LlvmCodeGen/Ppr.hs
index d7ddf804f2..1de630ef10 100644
--- a/compiler/llvmGen/LlvmCodeGen/Ppr.hs
+++ b/compiler/llvmGen/LlvmCodeGen/Ppr.hs
@@ -114,6 +114,7 @@ pprLlvmCmmDecl (CmmProc mb_info entry_lbl live (ListGraph blks))
dflags <- getDynFlags
let buildArg = fsLit . showSDoc dflags . ppPlainName
funArgs = map buildArg (llvmFunArgs dflags live)
+ funSect = llvmFunSection dflags (decName funDec)
-- generate the info table
prefix <- case mb_info of
@@ -123,7 +124,8 @@ pprLlvmCmmDecl (CmmProc mb_info entry_lbl live (ListGraph blks))
let infoTy = LMStruct $ map getStatType infoStatics
return $ Just $ LMStaticStruc infoStatics infoTy
- let fun = LlvmFunction funDec funArgs llvmStdFunAttrs Nothing
+
+ let fun = LlvmFunction funDec funArgs llvmStdFunAttrs funSect
prefix lmblocks
name = decName $ funcDecl fun
defName = name `appendFS` fsLit "$def"