Marge Bot pushed to branch wip/marge_bot_batch_merge_job at Glasgow Haskell Compiler / GHC

Commits:

8 changed files:

Changes:

  • compiler/GHC/StgToJS/Linker/Linker.hs
    ... ... @@ -2,6 +2,7 @@
    2 2
     {-# LANGUAGE TupleSections     #-}
    
    3 3
     {-# LANGUAGE LambdaCase        #-}
    
    4 4
     {-# LANGUAGE BlockArguments    #-}
    
    5
    +{-# LANGUAGE MultiWayIf        #-}
    
    5 6
     
    
    6 7
     -----------------------------------------------------------------------------
    
    7 8
     -- |
    
    ... ... @@ -666,12 +667,19 @@ renderLinkerStats s =
    666 667
     
    
    667 668
     
    
    668 669
     getPackageArchives :: StgToJSConfig -> UnitEnv -> [UnitId] -> IO [FilePath]
    
    669
    -getPackageArchives cfg unit_env units =
    
    670
    -  filterM doesFileExist [ ST.unpack p </> "lib" ++ ST.unpack l ++ profSuff <.> "a"
    
    671
    -                        | u <- units
    
    672
    -                        , p <- getInstalledPackageLibDirs ue_state u
    
    673
    -                        , l <- getInstalledPackageHsLibs  ue_state u
    
    674
    -                        ]
    
    670
    +getPackageArchives cfg unit_env units = do
    
    671
    +  fmap concat $ forM units $ \u -> do
    
    672
    +    let archives = [ ST.unpack p </> "lib" ++ ST.unpack l ++ profSuff <.> "a"
    
    673
    +                   | p <- getInstalledPackageLibDirs ue_state u
    
    674
    +                   , l <- getInstalledPackageHsLibs  ue_state u
    
    675
    +                   ]
    
    676
    +    foundArchives <- filterM doesFileExist archives
    
    677
    +    if | not (null archives)
    
    678
    +       , null foundArchives
    
    679
    +       -> do
    
    680
    +         throwGhcExceptionIO (InstallationError $ "Could not find any library archives for unit-id: " <> (renderWithContext (csContext cfg) $ ppr u))
    
    681
    +       | otherwise
    
    682
    +       -> pure foundArchives
    
    675 683
       where
    
    676 684
         ue_state = ue_homeUnitState unit_env
    
    677 685
     
    

  • hadrian/src/Rules/Gmp.hs
    ... ... @@ -11,7 +11,7 @@ import Target
    11 11
     import Utilities
    
    12 12
     import Hadrian.BuildPath
    
    13 13
     import Hadrian.Expression
    
    14
    -import Settings.Builders.Common (cArgs, getStagedCCFlags)
    
    14
    +import Settings.Builders.Common (getStagedCCFlags)
    
    15 15
     
    
    16 16
     -- | Build in-tree GMP library objects (if GmpInTree flag is set) and return
    
    17 17
     -- their paths.
    
    ... ... @@ -125,8 +125,7 @@ gmpRules = do
    125 125
                 cFlags <-
    
    126 126
                     interpretInContext ctx $
    
    127 127
                     mconcat
    
    128
    -                    [ cArgs
    
    129
    -                    , getStagedCCFlags
    
    128
    +                    [ getStagedCCFlags
    
    130 129
                         -- gmp symbols are only used by bignum logic in
    
    131 130
                         -- ghc-internal and shouldn't be exported by the
    
    132 131
                         -- ghc-internal shared library.
    

  • hadrian/src/Rules/Libffi.hs
    ... ... @@ -130,17 +130,14 @@ fixLibffiMakefile top =
    130 130
     configureEnvironment :: Stage -> Action [CmdOption]
    
    131 131
     configureEnvironment stage = do
    
    132 132
         context <- libffiContext stage
    
    133
    -    cFlags  <- interpretInContext context $ mconcat
    
    134
    -               [ cArgs
    
    135
    -               , getStagedCCFlags ]
    
    136
    -    ldFlags <- interpretInContext context ldArgs
    
    133
    +    cFlags  <- interpretInContext context getStagedCCFlags
    
    137 134
         sequence [ builderEnvironment "CC" $ Cc CompileC stage
    
    138 135
                  , builderEnvironment "CXX" $ Cc CompileC stage
    
    139
    -             , builderEnvironment "AR" (Ar Unpack stage)
    
    136
    +             , builderEnvironment "AR" $ Ar Unpack stage
    
    140 137
                  , builderEnvironment "NM" Nm
    
    141 138
                  , builderEnvironment "RANLIB" Ranlib
    
    142 139
                  , return . AddEnv  "CFLAGS" $ unwords  cFlags ++ " -w"
    
    143
    -             , return . AddEnv "LDFLAGS" $ unwords ldFlags ++ " -w" ]
    
    140
    +             , return . AddEnv "LDFLAGS" $ "-w" ]
    
    144 141
     
    
    145 142
     -- Need the libffi archive and `trackAllow` all files in the build directory.
    
    146 143
     -- See [Libffi indicating inputs].
    

  • hadrian/src/Settings/Builders/Cabal.hs
    ... ... @@ -188,18 +188,16 @@ configureArgs cFlags' ldFlags' = do
    188 188
                 values <- unwords <$> expr
    
    189 189
                 not (null values) ?
    
    190 190
                     arg ("--configure-option=" ++ key ++ "=" ++ values)
    
    191
    -        cFlags   = mconcat [ remove ["-Werror"] cArgs
    
    192
    -                           , getStagedCCFlags
    
    191
    +        cFlags   = mconcat [ getStagedCCFlags
    
    193 192
                                -- See https://github.com/snowleopard/hadrian/issues/523
    
    194 193
                                , arg $ "-iquote"
    
    195 194
     
    
    196 195
                                , arg $ top -/- pkgPath pkg
    
    197 196
                                , cFlags'
    
    198 197
                                ]
    
    199
    -        ldFlags  = ldArgs <> ldFlags'
    
    200 198
         mconcat
    
    201 199
             [ conf "CFLAGS"   cFlags
    
    202
    -        , conf "LDFLAGS"  ldFlags
    
    200
    +        , conf "LDFLAGS"  ldFlags'
    
    203 201
             , conf "--with-iconv-includes"    $ arg =<< getSetting IconvIncludeDir
    
    204 202
             , conf "--with-iconv-libraries"   $ arg =<< getSetting IconvLibDir
    
    205 203
             , conf "--with-gmp-includes"      $ arg =<< getSetting GmpIncludeDir
    

  • hadrian/src/Settings/Builders/Common.hs
    ... ... @@ -5,7 +5,7 @@ module Settings.Builders.Common (
    5 5
         module Oracles.Setting,
    
    6 6
         module Settings,
    
    7 7
         module UserSettings,
    
    8
    -    cIncludeArgs, ldArgs, cArgs, cppArgs, cWarnings,
    
    8
    +    cIncludeArgs, cWarnings,
    
    9 9
         packageDatabaseArgs, bootPackageDatabaseArgs,
    
    10 10
         getStagedCCFlags, wayCcArgs
    
    11 11
         ) where
    
    ... ... @@ -38,15 +38,6 @@ cIncludeArgs = do
    38 38
                 , pure [ "-I" ++ pkgPath pkg -/- dir | dir <- incDirs ]
    
    39 39
                 , pure [ "-I" ++       unifyPath dir | dir <- depDirs ] ]
    
    40 40
     
    
    41
    -ldArgs :: Args
    
    42
    -ldArgs = mempty
    
    43
    -
    
    44
    -cArgs :: Args
    
    45
    -cArgs = mempty
    
    46
    -
    
    47
    -cppArgs :: Args
    
    48
    -cppArgs = mempty
    
    49
    -
    
    50 41
     -- TODO: should be in a different file
    
    51 42
     cWarnings :: Args
    
    52 43
     cWarnings = mconcat
    

  • hadrian/src/Settings/Builders/DeriveConstants.hs
    ... ... @@ -40,8 +40,7 @@ includeCcArgs :: Args
    40 40
     includeCcArgs = do
    
    41 41
         stage <- getStage
    
    42 42
         rtsPath <- expr $ rtsBuildPath stage
    
    43
    -    mconcat [ cArgs
    
    44
    -            , cWarnings
    
    43
    +    mconcat [ cWarnings
    
    45 44
                 , prgFlags . ccProgram . tgtCCompiler <$> expr (targetStage Stage1)
    
    46 45
                 , queryTargetTarget tgtUnregisterised ? arg "-DUSE_MINIINTERPRETER"
    
    47 46
                 , arg "-Irts"
    

  • hadrian/src/Settings/Builders/Hsc2Hs.hs
    ... ... @@ -50,7 +50,7 @@ getCFlags = do
    50 50
         autogen <- expr $ autogenPath context
    
    51 51
         let cabalMacros = autogen -/- "cabal_macros.h"
    
    52 52
         expr $ need [cabalMacros]
    
    53
    -    mconcat [ remove ["-O"] (cArgs <> getStagedCCFlags)
    
    53
    +    mconcat [ remove ["-O"] getStagedCCFlags
    
    54 54
                 -- Either "-E" is not part of the configured cpp args, or we can't add those args to invocations of things like this
    
    55 55
                 -- ROMES:TODO: , prgFlags . cppProgram . tgtCPreprocessor <$> getStagedTargetConfig
    
    56 56
                 , cIncludeArgs
    
    ... ... @@ -64,6 +64,5 @@ getCFlags = do
    64 64
     getLFlags :: Expr [String]
    
    65 65
     getLFlags =
    
    66 66
         mconcat [ prgFlags . ccLinkProgram . tgtCCompilerLink <$> getStagedTarget
    
    67
    -            , ldArgs
    
    68 67
                 , getContextData ldOpts
    
    69 68
                 , getContextData depLdOpts ]

  • utils/jsffi/dyld.mjs
    ... ... @@ -670,7 +670,25 @@ class DyLD {
    670 670
     
    
    671 671
       // Wasm memory & table
    
    672 672
       #memory = new WebAssembly.Memory({ initial: 1 });
    
    673
    +
    
    673 674
       #table = new WebAssembly.Table({ element: "anyfunc", initial: 1 });
    
    675
    +  // First free slot, might be invalid when it advances to #table.length
    
    676
    +  #tableFree = 1;
    
    677
    +  // See Note [The evil wasm table grower]
    
    678
    +  #tableGrowInstance = new WebAssembly.Instance(
    
    679
    +    new WebAssembly.Module(
    
    680
    +      new Uint8Array([
    
    681
    +        0, 97, 115, 109, 1, 0, 0, 0, 1, 6, 1, 96, 1, 127, 1, 127, 2, 35, 1, 3,
    
    682
    +        101, 110, 118, 25, 95, 95, 105, 110, 100, 105, 114, 101, 99, 116, 95,
    
    683
    +        102, 117, 110, 99, 116, 105, 111, 110, 95, 116, 97, 98, 108, 101, 1,
    
    684
    +        112, 0, 0, 3, 2, 1, 0, 7, 31, 1, 27, 95, 95, 103, 104, 99, 95, 119, 97,
    
    685
    +        115, 109, 95, 106, 115, 102, 102, 105, 95, 116, 97, 98, 108, 101, 95,
    
    686
    +        103, 114, 111, 119, 0, 0, 10, 11, 1, 9, 0, 208, 112, 32, 0, 252, 15, 0,
    
    687
    +        11,
    
    688
    +      ])
    
    689
    +    ),
    
    690
    +    { env: { __indirect_function_table: this.#table } }
    
    691
    +  );
    
    674 692
     
    
    675 693
       // __stack_pointer
    
    676 694
       #sp = new WebAssembly.Global(
    
    ... ... @@ -715,6 +733,82 @@ class DyLD {
    715 733
       // Global STG registers
    
    716 734
       #regs = {};
    
    717 735
     
    
    736
    +  // Note [The evil wasm table grower]
    
    737
    +  // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    
    738
    +  // We need to grow the wasm table as we load shared libraries in
    
    739
    +  // wasm dyld. We used to directly call the table.grow() JS API,
    
    740
    +  // which works as expected in Firefox/Chrome, but unfortunately,
    
    741
    +  // WebKit's implementation of the table.grow() JS API is broken:
    
    742
    +  // https://bugs.webkit.org/show_bug.cgi?id=290681, which means that
    
    743
    +  // the wasm dyld simply does not work in WebKit-based browsers like
    
    744
    +  // Safari.
    
    745
    +  //
    
    746
    +  // Now, one simple workaround would be to avoid growing the table at
    
    747
    +  // all: just allocate a huge table upfront (current limitation
    
    748
    +  // agreed by all vendors is 10000000). To avoid unnecessary space
    
    749
    +  // waste on non-WebKit platforms, we could additionally check
    
    750
    +  // navigator.userAgent against some regexes and only allocate
    
    751
    +  // fixed-length table when there's no blink/gecko mention. But this
    
    752
    +  // is fragile and gross, and it's better to stick to a uniform code
    
    753
    +  // path for all browsers.
    
    754
    +  //
    
    755
    +  // Fortunately, it turns out the table.grow wasm instruction work as
    
    756
    +  // expected in WebKit! So we can invoke a wasm function that grows
    
    757
    +  // the table for us. But don't open a champagne yet, where would
    
    758
    +  // that wasm function come from? It can't be put into RTS, or even
    
    759
    +  // libc.so, because loading those libraries would require growing
    
    760
    +  // the table in the first place! Or perhaps, reserve a table upfront
    
    761
    +  // that's just large enough to load RTS and then we can access that
    
    762
    +  // function for subsequent table grows? But then we need to
    
    763
    +  // experiment for a reasonable initial size, and add a magic number
    
    764
    +  // here, which is also fragile and gross and not future-proof!
    
    765
    +  //
    
    766
    +  // So this special wasm function needs to live in a single wasm
    
    767
    +  // module, which is loaded before we load anything else. The full
    
    768
    +  // source code for this module is:
    
    769
    +  //
    
    770
    +  // (module
    
    771
    +  //   (type (func (param i32) (result i32)))
    
    772
    +  //   (import "env" "__indirect_function_table" (table 0 funcref))
    
    773
    +  //   (export "__ghc_wasm_jsffi_table_grow" (func 0))
    
    774
    +  //   (func (type 0) (param i32) (result i32)
    
    775
    +  //     ref.null func
    
    776
    +  //     local.get 0
    
    777
    +  //     table.grow 0
    
    778
    +  //   )
    
    779
    +  // )
    
    780
    +  //
    
    781
    +  // This module is 103 bytes so that we can inline its blob in dyld,
    
    782
    +  // and use the usually discouraged synchronous
    
    783
    +  // WebAssembly.Instance/WebAssembly.Module constructors to load it.
    
    784
    +  // On non-WebKit platforms, growing tables this way would introduce
    
    785
    +  // a bit of extra JS/Wasm interop overhead, which can be amplified
    
    786
    +  // as we used to call table.grow(1, foo) for every GOT.func item.
    
    787
    +  // Therefore, unless we're about to exceed the hard limit of table
    
    788
    +  // size, we now grow the table exponentially, and use bump
    
    789
    +  // allocation to calculate the table index to be returned.
    
    790
    +  // Exponential growth is only implemented to minimize the JS/Wasm
    
    791
    +  // interop overhead when calling __ghc_wasm_jsffi_table_grow;
    
    792
    +  // V8/SpiderMonkey/WebKit already do their own exponential growth of
    
    793
    +  // the table's backing buffer in their table growth logic.
    
    794
    +  //
    
    795
    +  // Invariants: n >= 0; when v is non-null, n === 1
    
    796
    +  #tableGrow(n, v) {
    
    797
    +    const prev_free = this.#tableFree;
    
    798
    +    if (prev_free + n > this.#table.length) {
    
    799
    +      const min_delta = prev_free + n - this.#table.length;
    
    800
    +      const delta = Math.max(min_delta, this.#table.length);
    
    801
    +      this.#tableGrowInstance.exports.__ghc_wasm_jsffi_table_grow(
    
    802
    +        this.#table.length + delta <= 10000000 ? delta : min_delta
    
    803
    +      );
    
    804
    +    }
    
    805
    +    if (v) {
    
    806
    +      this.#table.set(prev_free, v);
    
    807
    +    }
    
    808
    +    this.#tableFree += n;
    
    809
    +    return prev_free;
    
    810
    +  }
    
    811
    +
    
    718 812
       constructor({ args, rpc }) {
    
    719 813
         this.#rpc = rpc;
    
    720 814
     
    
    ... ... @@ -878,7 +972,7 @@ class DyLD {
    878 972
     
    
    879 973
           // __memory_base & __table_base, different for each .so
    
    880 974
           let memory_base;
    
    881
    -      let table_base = this.#table.grow(tableSize);
    
    975
    +      let table_base = this.#tableGrow(tableSize);
    
    882 976
           console.assert(tableP2Align === 0);
    
    883 977
     
    
    884 978
           // libc.so is always the first one to be ever loaded and has VIP
    
    ... ... @@ -982,7 +1076,7 @@ class DyLD {
    982 1076
               if (this.exportFuncs[name]) {
    
    983 1077
                 this.#gotFunc[name] = new WebAssembly.Global(
    
    984 1078
                   { value: "i32", mutable: true },
    
    985
    -              this.#table.grow(1, this.exportFuncs[name])
    
    1079
    +              this.#tableGrow(1, this.exportFuncs[name])
    
    986 1080
                 );
    
    987 1081
                 continue;
    
    988 1082
               }
    
    ... ... @@ -1033,7 +1127,7 @@ class DyLD {
    1033 1127
               if (this.#gotFunc[k]) {
    
    1034 1128
                 const got = this.#gotFunc[k];
    
    1035 1129
                 if (got.value === DyLD.#poison) {
    
    1036
    -              const idx = this.#table.grow(1, v);
    
    1130
    +              const idx = this.#tableGrow(1, v);
    
    1037 1131
                   got.value = idx;
    
    1038 1132
                 } else {
    
    1039 1133
                   this.#table.set(got.value, v);
    
    ... ... @@ -1103,7 +1197,7 @@ class DyLD {
    1103 1197
         // Not in GOT.func yet, create the entry on demand
    
    1104 1198
         if (this.exportFuncs[sym]) {
    
    1105 1199
           console.assert(!this.#gotFunc[sym]);
    
    1106
    -      const addr = this.#table.grow(1, this.exportFuncs[sym]);
    
    1200
    +      const addr = this.#tableGrow(1, this.exportFuncs[sym]);
    
    1107 1201
           this.#gotFunc[sym] = new WebAssembly.Global(
    
    1108 1202
             { value: "i32", mutable: true },
    
    1109 1203
             addr