| From 7e00046772e053c63ac93630a60b0f396e32a2d7 Mon Sep 17 00:00:00 2001 |
| From: Sergei Trofimovich <slyfox@gentoo.org> |
| Date: Sun, 16 Apr 2017 10:43:38 +0100 |
| Subject: [PATCH] compiler/cmm/PprC.hs: constify labels in .rodata |
| |
| Summary: |
| Consider one-line module |
| module B (v) where v = "hello" |
| in -fvia-C mode it generates code like |
| static char gibberish_str[] = "hello"; |
| |
| It resides in data section (precious resource on ia64!). |
| The patch switches genrator to emit: |
| static const char gibberish_str[] = "hello"; |
| |
| Other types if symbols that gained 'const' qualifier are: |
| |
| - info tables (from haskell and CMM) |
| - static reference tables (from haskell and CMM) |
| |
| Cleanups along the way: |
| |
| - fixed info tables defined in .cmm to reside in .rodata |
| - split out closure declaration into 'IC_' / 'EC_' |
| - added label declaration (based on label type) right before |
| each label definition (based on section type) so that C |
| compiler could check if declaration and definition matches |
| at definition site. |
| |
| Signed-off-by: Sergei Trofimovich <slyfox@gentoo.org> |
| |
| Test Plan: ran testsuite on unregisterised x86_64 compiler |
| |
| Reviewers: simonmar, ezyang, austin, bgamari, erikd |
| |
| Subscribers: rwbarton, thomie |
| |
| GHC Trac Issues: #8996 |
| |
| Differential Revision: https://phabricator.haskell.org/D3481 |
| --- |
| compiler/cmm/CLabel.hs | 24 ++++++++++++++ |
| compiler/cmm/Cmm.hs | 13 ++++++++ |
| compiler/cmm/CmmInfo.hs | 2 +- |
| compiler/cmm/PprC.hs | 62 +++++++++++++++++++++++------------- |
| compiler/llvmGen/LlvmCodeGen/Data.hs | 12 ------- |
| includes/Stg.h | 22 +++++++++---- |
| includes/rts/storage/InfoTables.h | 2 +- |
| includes/stg/MiscClosures.h | 14 ++++---- |
| 8 files changed, 102 insertions(+), 49 deletions(-) |
| |
| diff --git a/compiler/cmm/CLabel.hs b/compiler/cmm/CLabel.hs |
| index 3ba4f7647a..62c8037e9c 100644 |
| --- a/compiler/cmm/CLabel.hs |
| +++ b/compiler/cmm/CLabel.hs |
| @@ -89,6 +89,8 @@ module CLabel ( |
| foreignLabelStdcallInfo, |
| isBytesLabel, |
| isForeignLabel, |
| + isSomeRODataLabel, |
| + isStaticClosureLabel, |
| mkCCLabel, mkCCSLabel, |
| |
| DynamicLinkerLabelInfo(..), |
| @@ -575,6 +577,28 @@ isForeignLabel :: CLabel -> Bool |
| isForeignLabel (ForeignLabel _ _ _ _) = True |
| isForeignLabel _lbl = False |
| |
| +-- | Whether label is a static closure label (can come from haskell or cmm) |
| +isStaticClosureLabel :: CLabel -> Bool |
| +-- Closure defined in haskell (.hs) |
| +isStaticClosureLabel (IdLabel _ _ Closure) = True |
| +-- Closure defined in cmm |
| +isStaticClosureLabel (CmmLabel _ _ CmmClosure) = True |
| +isStaticClosureLabel _lbl = False |
| + |
| +-- | Whether label is a .rodata label |
| +isSomeRODataLabel :: CLabel -> Bool |
| +-- info table defined in haskell (.hs) |
| +isSomeRODataLabel (IdLabel _ _ ClosureTable) = True |
| +isSomeRODataLabel (IdLabel _ _ ConInfoTable) = True |
| +isSomeRODataLabel (IdLabel _ _ InfoTable) = True |
| +isSomeRODataLabel (IdLabel _ _ LocalInfoTable) = True |
| +-- static reference tables defined in haskell (.hs) |
| +isSomeRODataLabel (IdLabel _ _ SRT) = True |
| +isSomeRODataLabel (SRTLabel _) = True |
| +-- info table defined in cmm (.cmm) |
| +isSomeRODataLabel (CmmLabel _ _ CmmInfo) = True |
| +isSomeRODataLabel _lbl = False |
| + |
| -- | Get the label size field from a ForeignLabel |
| foreignLabelStdcallInfo :: CLabel -> Maybe Int |
| foreignLabelStdcallInfo (ForeignLabel _ info _ _) = info |
| diff --git a/compiler/cmm/Cmm.hs b/compiler/cmm/Cmm.hs |
| index d2ee531686..bab20f3fdd 100644 |
| --- a/compiler/cmm/Cmm.hs |
| +++ b/compiler/cmm/Cmm.hs |
| @@ -9,6 +9,7 @@ module Cmm ( |
| CmmBlock, |
| RawCmmDecl, RawCmmGroup, |
| Section(..), SectionType(..), CmmStatics(..), CmmStatic(..), |
| + isSecConstant, |
| |
| -- ** Blocks containing lists |
| GenBasicBlock(..), blockId, |
| @@ -167,6 +168,18 @@ data SectionType |
| | OtherSection String |
| deriving (Show) |
| |
| +-- | Should a data in this section be considered constant |
| +isSecConstant :: Section -> Bool |
| +isSecConstant (Section t _) = case t of |
| + Text -> True |
| + ReadOnlyData -> True |
| + RelocatableReadOnlyData -> True |
| + ReadOnlyData16 -> True |
| + CString -> True |
| + Data -> False |
| + UninitialisedData -> False |
| + (OtherSection _) -> False |
| + |
| data Section = Section SectionType CLabel |
| |
| data CmmStatic |
| diff --git a/compiler/cmm/CmmInfo.hs b/compiler/cmm/CmmInfo.hs |
| index b5e800a977..35e3a1888d 100644 |
| --- a/compiler/cmm/CmmInfo.hs |
| +++ b/compiler/cmm/CmmInfo.hs |
| @@ -133,7 +133,7 @@ mkInfoTable dflags proc@(CmmProc infos entry_lbl live blocks) |
| -- |
| return (top_decls ++ |
| [CmmProc mapEmpty entry_lbl live blocks, |
| - mkDataLits (Section Data info_lbl) info_lbl |
| + mkRODataLits info_lbl |
| (CmmLabel entry_lbl : rel_std_info ++ rel_extra_bits)]) |
| |
| -- |
| diff --git a/compiler/cmm/PprC.hs b/compiler/cmm/PprC.hs |
| index 56de94079f..21ed6f6516 100644 |
| --- a/compiler/cmm/PprC.hs |
| +++ b/compiler/cmm/PprC.hs |
| @@ -83,12 +83,13 @@ pprC tops = vcat $ intersperse blankLine $ map pprTop tops |
| -- top level procs |
| -- |
| pprTop :: RawCmmDecl -> SDoc |
| -pprTop (CmmProc infos clbl _ graph) = |
| +pprTop (CmmProc infos clbl _in_live_regs graph) = |
| |
| (case mapLookup (g_entry graph) infos of |
| Nothing -> empty |
| - Just (Statics info_clbl info_dat) -> pprDataExterns info_dat $$ |
| - pprWordArray info_clbl info_dat) $$ |
| + Just (Statics info_clbl info_dat) -> |
| + pprDataExterns info_dat $$ |
| + pprWordArray info_is_in_rodata info_clbl info_dat) $$ |
| (vcat [ |
| blankLine, |
| extern_decls, |
| @@ -99,6 +100,8 @@ pprTop (CmmProc infos clbl _ graph) = |
| rbrace ] |
| ) |
| where |
| + -- info tables are always in .rodata |
| + info_is_in_rodata = True |
| blocks = toBlockListEntryFirst graph |
| (temp_decls, extern_decls) = pprTempAndExternDecls blocks |
| |
| @@ -107,21 +110,23 @@ pprTop (CmmProc infos clbl _ graph) = |
| |
| -- We only handle (a) arrays of word-sized things and (b) strings. |
| |
| -pprTop (CmmData _section (Statics lbl [CmmString str])) = |
| +pprTop (CmmData section (Statics lbl [CmmString str])) = |
| + pprExternDecl lbl $$ |
| hcat [ |
| - pprLocalness lbl, text "char ", ppr lbl, |
| + pprLocalness lbl, pprConstness (isSecConstant section), text "char ", ppr lbl, |
| text "[] = ", pprStringInCStyle str, semi |
| ] |
| |
| -pprTop (CmmData _section (Statics lbl [CmmUninitialised size])) = |
| +pprTop (CmmData section (Statics lbl [CmmUninitialised size])) = |
| + pprExternDecl lbl $$ |
| hcat [ |
| - pprLocalness lbl, text "char ", ppr lbl, |
| + pprLocalness lbl, pprConstness (isSecConstant section), text "char ", ppr lbl, |
| brackets (int size), semi |
| ] |
| |
| -pprTop (CmmData _section (Statics lbl lits)) = |
| +pprTop (CmmData section (Statics lbl lits)) = |
| pprDataExterns lits $$ |
| - pprWordArray lbl lits |
| + pprWordArray (isSecConstant section) lbl lits |
| |
| -- -------------------------------------------------------------------------- |
| -- BasicBlocks are self-contained entities: they always end in a jump. |
| @@ -141,10 +146,12 @@ pprBBlock block = |
| -- Info tables. Just arrays of words. |
| -- See codeGen/ClosureInfo, and nativeGen/PprMach |
| |
| -pprWordArray :: CLabel -> [CmmStatic] -> SDoc |
| -pprWordArray lbl ds |
| +pprWordArray :: Bool -> CLabel -> [CmmStatic] -> SDoc |
| +pprWordArray is_ro lbl ds |
| = sdocWithDynFlags $ \dflags -> |
| - hcat [ pprLocalness lbl, text "StgWord" |
| + -- TODO: align closures only |
| + pprExternDecl lbl $$ |
| + hcat [ pprLocalness lbl, pprConstness is_ro, text "StgWord" |
| , space, ppr lbl, text "[]" |
| -- See Note [StgWord alignment] |
| , pprAlignment (wordWidth dflags) |
| @@ -180,6 +187,10 @@ pprLocalness :: CLabel -> SDoc |
| pprLocalness lbl | not $ externallyVisibleCLabel lbl = text "static " |
| | otherwise = empty |
| |
| +pprConstness :: Bool -> SDoc |
| +pprConstness is_ro | is_ro = text "const " |
| + | otherwise = empty |
| + |
| -- -------------------------------------------------------------------------- |
| -- Statements. |
| -- |
| @@ -984,31 +995,38 @@ is_cishCC JavaScriptCallConv = False |
| pprTempAndExternDecls :: [CmmBlock] -> (SDoc{-temps-}, SDoc{-externs-}) |
| pprTempAndExternDecls stmts |
| = (pprUFM (getUniqSet temps) (vcat . map pprTempDecl), |
| - vcat (map (pprExternDecl False{-ToDo-}) (Map.keys lbls))) |
| + vcat (map pprExternDecl (Map.keys lbls))) |
| where (temps, lbls) = runTE (mapM_ te_BB stmts) |
| |
| pprDataExterns :: [CmmStatic] -> SDoc |
| pprDataExterns statics |
| - = vcat (map (pprExternDecl False{-ToDo-}) (Map.keys lbls)) |
| + = vcat (map pprExternDecl (Map.keys lbls)) |
| where (_, lbls) = runTE (mapM_ te_Static statics) |
| |
| pprTempDecl :: LocalReg -> SDoc |
| pprTempDecl l@(LocalReg _ rep) |
| = hcat [ machRepCType rep, space, pprLocalReg l, semi ] |
| |
| -pprExternDecl :: Bool -> CLabel -> SDoc |
| -pprExternDecl _in_srt lbl |
| +pprExternDecl :: CLabel -> SDoc |
| +pprExternDecl lbl |
| -- do not print anything for "known external" things |
| | not (needsCDecl lbl) = empty |
| | Just sz <- foreignLabelStdcallInfo lbl = stdcall_decl sz |
| | otherwise = |
| - hcat [ visibility, label_type lbl, |
| - lparen, ppr lbl, text ");" ] |
| + hcat [ visibility, label_type lbl , lparen, ppr lbl, text ");" |
| + -- occasionally useful to see label type |
| + -- , text "/* ", pprDebugCLabel lbl, text " */" |
| + ] |
| where |
| - label_type lbl | isBytesLabel lbl = text "B_" |
| - | isForeignLabel lbl && isCFunctionLabel lbl = text "FF_" |
| - | isCFunctionLabel lbl = text "F_" |
| - | otherwise = text "I_" |
| + label_type lbl | isBytesLabel lbl = text "B_" |
| + | isForeignLabel lbl && isCFunctionLabel lbl |
| + = text "FF_" |
| + | isCFunctionLabel lbl = text "F_" |
| + | isStaticClosureLabel lbl = text "C_" |
| + -- generic .rodata labels |
| + | isSomeRODataLabel lbl = text "RO_" |
| + -- generic .data labels (common case) |
| + | otherwise = text "RW_" |
| |
| visibility |
| | externallyVisibleCLabel lbl = char 'E' |
| diff --git a/compiler/llvmGen/LlvmCodeGen/Data.hs b/compiler/llvmGen/LlvmCodeGen/Data.hs |
| index 9bb5a75bda..adb86d312d 100644 |
| --- a/compiler/llvmGen/LlvmCodeGen/Data.hs |
| +++ b/compiler/llvmGen/LlvmCodeGen/Data.hs |
| @@ -56,18 +56,6 @@ genLlvmData (sec, Statics lbl xs) = do |
| |
| return ([globDef], [tyAlias]) |
| |
| --- | Should a data in this section be considered constant |
| -isSecConstant :: Section -> Bool |
| -isSecConstant (Section t _) = case t of |
| - Text -> True |
| - ReadOnlyData -> True |
| - RelocatableReadOnlyData -> True |
| - ReadOnlyData16 -> True |
| - CString -> True |
| - Data -> False |
| - UninitialisedData -> False |
| - (OtherSection _) -> False |
| - |
| -- | Format the section type part of a Cmm Section |
| llvmSectionType :: Platform -> SectionType -> FastString |
| llvmSectionType p t = case t of |
| diff --git a/includes/Stg.h b/includes/Stg.h |
| index 619984d8e5..b1b3190307 100644 |
| --- a/includes/Stg.h |
| +++ b/includes/Stg.h |
| @@ -223,13 +223,23 @@ typedef StgInt I_; |
| typedef StgWord StgWordArray[]; |
| typedef StgFunPtr F_; |
| |
| -#define EB_(X) extern char X[] |
| -#define IB_(X) static char X[] |
| -#define EI_(X) extern StgWordArray (X) GNU_ATTRIBUTE(aligned (8)) |
| -#define II_(X) static StgWordArray (X) GNU_ATTRIBUTE(aligned (8)) |
| +/* byte arrays (and strings): */ |
| +#define EB_(X) extern const char X[] |
| +#define IB_(X) static const char X[] |
| +/* static (non-heap) closures (requires alignment for pointer tagging): */ |
| +#define EC_(X) extern StgWordArray (X) GNU_ATTRIBUTE(aligned (8)) |
| +#define IC_(X) static StgWordArray (X) GNU_ATTRIBUTE(aligned (8)) |
| +/* writable data (does not require alignment): */ |
| +#define ERW_(X) extern StgWordArray (X) |
| +#define IRW_(X) static StgWordArray (X) |
| +/* read-only data (does not require alignment): */ |
| +#define ERO_(X) extern const StgWordArray (X) |
| +#define IRO_(X) static const StgWordArray (X) |
| +/* stg-native functions: */ |
| #define IF_(f) static StgFunPtr GNUC3_ATTRIBUTE(used) f(void) |
| -#define FN_(f) StgFunPtr f(void) |
| -#define EF_(f) StgFunPtr f(void) /* External Cmm functions */ |
| +#define FN_(f) StgFunPtr f(void) |
| +#define EF_(f) StgFunPtr f(void) /* External Cmm functions */ |
| +/* foreign functions: */ |
| #define EFF_(f) void f() /* See Note [External function prototypes] */ |
| |
| /* Note [External function prototypes] See Trac #8965, #11395 |
| diff --git a/includes/rts/storage/InfoTables.h b/includes/rts/storage/InfoTables.h |
| index 307aac371c..163f1d1c87 100644 |
| --- a/includes/rts/storage/InfoTables.h |
| +++ b/includes/rts/storage/InfoTables.h |
| @@ -266,7 +266,7 @@ typedef struct { |
| } StgFunInfoTable; |
| |
| // canned bitmap for each arg type, indexed by constants in FunTypes.h |
| -extern StgWord stg_arg_bitmaps[]; |
| +extern const StgWord stg_arg_bitmaps[]; |
| |
| /* ----------------------------------------------------------------------------- |
| Return info tables |
| diff --git a/includes/stg/MiscClosures.h b/includes/stg/MiscClosures.h |
| index 9d907ab3ba..b604f1c42b 100644 |
| --- a/includes/stg/MiscClosures.h |
| +++ b/includes/stg/MiscClosures.h |
| @@ -21,10 +21,10 @@ |
| #define STGMISCCLOSURES_H |
| |
| #if IN_STG_CODE |
| -# define RTS_RET_INFO(i) extern W_(i)[] |
| -# define RTS_FUN_INFO(i) extern W_(i)[] |
| -# define RTS_THUNK_INFO(i) extern W_(i)[] |
| -# define RTS_INFO(i) extern W_(i)[] |
| +# define RTS_RET_INFO(i) extern const W_(i)[] |
| +# define RTS_FUN_INFO(i) extern const W_(i)[] |
| +# define RTS_THUNK_INFO(i) extern const W_(i)[] |
| +# define RTS_INFO(i) extern const W_(i)[] |
| # define RTS_CLOSURE(i) extern W_(i)[] |
| # define RTS_FUN_DECL(f) extern DLL_IMPORT_RTS StgFunPtr f(void) |
| #else |
| @@ -489,9 +489,9 @@ extern StgWord RTS_VAR(sched_mutex); |
| |
| // Apply.cmm |
| // canned bitmap for each arg type |
| -extern StgWord stg_arg_bitmaps[]; |
| -extern StgWord stg_ap_stack_entries[]; |
| -extern StgWord stg_stack_save_entries[]; |
| +extern const StgWord stg_arg_bitmaps[]; |
| +extern const StgWord stg_ap_stack_entries[]; |
| +extern const StgWord stg_stack_save_entries[]; |
| |
| // Storage.c |
| extern unsigned int RTS_VAR(g0); |
| -- |
| 2.12.2 |
| |