Marge Bot pushed to branch wip/marge_bot_batch_merge_job at Glasgow Haskell Compiler / GHC
Commits:
-
a1de535f
by Luite Stegeman at 2025-09-30T18:40:28-04:00
-
b7e21e49
by Luite Stegeman at 2025-09-30T18:40:28-04:00
-
02a7c18a
by Cheng Shao at 2025-09-30T18:41:27-04:00
-
aa0ca5e3
by Cheng Shao at 2025-09-30T18:41:27-04:00
-
69503668
by Cheng Shao at 2025-09-30T18:41:27-04:00
-
e9445c01
by Matthew Pickering at 2025-09-30T18:42:23-04:00
-
b8307eab
by Cheng Shao at 2025-09-30T18:43:14-04:00
-
9c293544
by Simon Peyton Jones at 2025-10-01T09:36:10+01:00
-
d21638e3
by Rodrigo Mesquita at 2025-10-01T18:03:13-04:00
25 changed files:
- compiler/GHC.hs
- compiler/GHC/Cmm/Parser.y
- compiler/GHC/Core/Unify.hs
- compiler/GHC/Driver/Main.hs
- compiler/GHC/Driver/Make.hs
- compiler/GHC/Driver/Session.hs
- compiler/GHC/Iface/Tidy/StaticPtrTable.hs
- compiler/GHC/Linker/Loader.hs
- compiler/GHC/Runtime/Interpreter/Types.hs
- compiler/Language/Haskell/Syntax/Decls.hs
- configure.ac
- distrib/configure.ac.in
- hadrian/src/Settings/Packages.hs
- libraries/ghci/GHCi/ObjLink.hs
- m4/fp_cmm_cpp_cmd_with_args.m4
- − m4/fp_set_cflags_c99.m4
- rts/Apply.cmm
- rts/ThreadPaused.c
- + testsuite/tests/ghci-wasm/T26431.hs
- + testsuite/tests/ghci-wasm/T26431.stdout
- testsuite/tests/ghci-wasm/all.T
- + testsuite/tests/typecheck/should_compile/T26457.hs
- testsuite/tests/typecheck/should_compile/all.T
- utils/ghc-toolchain/src/GHC/Toolchain/Tools/Cc.hs
- utils/ghc-toolchain/src/GHC/Toolchain/Tools/Cpp.hs
Changes:
| ... | ... | @@ -716,17 +716,14 @@ setTopSessionDynFlags dflags = do |
| 716 | 716 | |
| 717 | 717 | -- see Note [Target code interpreter]
|
| 718 | 718 | interp <- if
|
| 719 | +#if !defined(wasm32_HOST_ARCH)
|
|
| 719 | 720 | -- Wasm dynamic linker
|
| 720 | 721 | | ArchWasm32 <- platformArch $ targetPlatform dflags
|
| 721 | 722 | -> do
|
| 722 | 723 | s <- liftIO $ newMVar InterpPending
|
| 723 | 724 | loader <- liftIO Loader.uninitializedLoader
|
| 724 | 725 | dyld <- liftIO $ makeAbsolute $ topDir dflags </> "dyld.mjs"
|
| 725 | -#if defined(wasm32_HOST_ARCH)
|
|
| 726 | - let libdir = sorry "cannot spawn child process on wasm"
|
|
| 727 | -#else
|
|
| 728 | 726 | libdir <- liftIO $ last <$> Loader.getGccSearchDirectory logger dflags "libraries"
|
| 729 | -#endif
|
|
| 730 | 727 | let profiled = ways dflags `hasWay` WayProf
|
| 731 | 728 | way_tag = if profiled then "_p" else ""
|
| 732 | 729 | let cfg =
|
| ... | ... | @@ -747,6 +744,7 @@ setTopSessionDynFlags dflags = do |
| 747 | 744 | wasmInterpUnitState = ue_homeUnitState $ hsc_unit_env hsc_env
|
| 748 | 745 | }
|
| 749 | 746 | pure $ Just $ Interp (ExternalInterp $ ExtWasm $ ExtInterpState cfg s) loader lookup_cache
|
| 747 | +#endif
|
|
| 750 | 748 | |
| 751 | 749 | -- JavaScript interpreter
|
| 752 | 750 | | ArchJavaScript <- platformArch (targetPlatform dflags)
|
| ... | ... | @@ -1321,6 +1321,7 @@ stmtMacros = listToUFM [ |
| 1321 | 1321 | ( fsLit "PROF_HEADER_CREATE", \[e] -> profHeaderCreate e ),
|
| 1322 | 1322 | |
| 1323 | 1323 | ( fsLit "PUSH_UPD_FRAME", \[sp,e] -> emitPushUpdateFrame sp e ),
|
| 1324 | + ( fsLit "PUSH_BH_UPD_FRAME", \[sp,e] -> emitPushBHUpdateFrame sp e ),
|
|
| 1324 | 1325 | ( fsLit "SET_HDR", \[ptr,info,ccs] ->
|
| 1325 | 1326 | emitSetDynHdr ptr info ccs ),
|
| 1326 | 1327 | ( fsLit "TICK_ALLOC_PRIM", \[hdr,goods,slop] ->
|
| ... | ... | @@ -1336,6 +1337,10 @@ emitPushUpdateFrame :: CmmExpr -> CmmExpr -> FCode () |
| 1336 | 1337 | emitPushUpdateFrame sp e = do
|
| 1337 | 1338 | emitUpdateFrame sp mkUpdInfoLabel e
|
| 1338 | 1339 | |
| 1340 | +emitPushBHUpdateFrame :: CmmExpr -> CmmExpr -> FCode ()
|
|
| 1341 | +emitPushBHUpdateFrame sp e = do
|
|
| 1342 | + emitUpdateFrame sp mkBHUpdInfoLabel e
|
|
| 1343 | + |
|
| 1339 | 1344 | pushStackFrame :: [CmmParse CmmExpr] -> CmmParse () -> CmmParse ()
|
| 1340 | 1345 | pushStackFrame fields body = do
|
| 1341 | 1346 | profile <- getProfile
|
| ... | ... | @@ -288,10 +288,11 @@ Wrinkles |
| 288 | 288 | |
| 289 | 289 | (ATF3) What about foralls? For example, supppose we are unifying
|
| 290 | 290 | (forall a. F a) -> (forall a. F a)
|
| 291 | - Those two (F a) types are unrelated, bound by different foralls.
|
|
| 291 | + against some other type. Those two (F a) types are unrelated, bound by
|
|
| 292 | + different foralls; we cannot extend the um_fam_env with a binding [F a :-> blah]
|
|
| 292 | 293 | |
| 293 | 294 | So to keep things simple, the entire family-substitution machinery is used
|
| 294 | - only if there are no enclosing foralls (see the (um_foralls env)) check in
|
|
| 295 | + only if there are no enclosing foralls (see the `under_forall` check in
|
|
| 295 | 296 | `uSatFamApp`). That's fine, because the apartness business is used only for
|
| 296 | 297 | reducing type-family applications, and class instances, and their arguments
|
| 297 | 298 | can't have foralls anyway.
|
| ... | ... | @@ -329,6 +330,8 @@ Wrinkles |
| 329 | 330 | instance (Generic1 f, Ord (Rep1 f a))
|
| 330 | 331 | => Ord (Generically1 f a) where ...
|
| 331 | 332 | -- The "..." gives rise to [W] Ord (Generically1 f a)
|
| 333 | + where Rep1 is a type family.
|
|
| 334 | + |
|
| 332 | 335 | We must use the instance decl (recursively) to simplify the [W] constraint;
|
| 333 | 336 | we do /not/ want to worry that the `[G] Ord (Rep1 f a)` might be an
|
| 334 | 337 | alternative path. So `noMatchableGivenDicts` must return False;
|
| ... | ... | @@ -336,6 +339,12 @@ Wrinkles |
| 336 | 339 | `DontBindMe`, the unifier must return `SurelyApart`, not `MaybeApart`. See
|
| 337 | 340 | `go` in `uVarOrFam`
|
| 338 | 341 | |
| 342 | + This looks a bit sketchy, because they aren't SurelyApart, but see
|
|
| 343 | + Note [What might equal later?] in GHC.Tc.Utils.Unify, esp "Red Herring".
|
|
| 344 | + |
|
| 345 | + If we are under a forall, we return `MaybeApart`; that seems more conservative,
|
|
| 346 | + and class constraints are on tau-types so it doesn't matter.
|
|
| 347 | + |
|
| 339 | 348 | (ATF6) When /matching/ can we ever have a type-family application on the LHS, in
|
| 340 | 349 | the template? You might think not, because type-class-instance and
|
| 341 | 350 | type-family-instance heads can't include type families. E.g.
|
| ... | ... | @@ -344,12 +353,12 @@ Wrinkles |
| 344 | 353 | But you'd be wrong: even when matching, we can see type families in the LHS template:
|
| 345 | 354 | * In `checkValidClass`, in `check_dm` we check that the default method has the
|
| 346 | 355 | right type, using matching, both ways. And that type may have type-family
|
| 347 | - applications in it. Example in test CoOpt_Singletons.
|
|
| 356 | + applications in it. Examples in test CoOpt_Singletons and T26457.
|
|
| 348 | 357 | |
| 349 | 358 | * In the specialiser: see the call to `tcMatchTy` in
|
| 350 | 359 | `GHC.Core.Opt.Specialise.beats_or_same`
|
| 351 | 360 | |
| 352 | - * With -fpolymorphic-specialsation, we might get a specialiation rule like
|
|
| 361 | + * With -fpolymorphic-specialisation, we might get a specialiation rule like
|
|
| 353 | 362 | RULE forall a (d :: Eq (Maybe (F a))) .
|
| 354 | 363 | f @(Maybe (F a)) d = ...
|
| 355 | 364 | See #25965.
|
| ... | ... | @@ -362,7 +371,7 @@ Wrinkles |
| 362 | 371 | type variables/ that makes the match work. So we simply want to recurse into
|
| 363 | 372 | the arguments of the type family. E.g.
|
| 364 | 373 | Template: forall a. Maybe (F a)
|
| 365 | - Target: Mabybe (F Int)
|
|
| 374 | + Target: Maybe (F Int)
|
|
| 366 | 375 | We want to succeed with substitution [a :-> Int]. See (ATF9).
|
| 367 | 376 | |
| 368 | 377 | Conclusion: where we enter via `tcMatchTy`, `tcMatchTys`, `tc_match_tys`,
|
| ... | ... | @@ -378,10 +387,10 @@ Wrinkles |
| 378 | 387 | type family G6 a = r | r -> a
|
| 379 | 388 | type instance G6 [a] = [G a]
|
| 380 | 389 | type instance G6 Bool = Int
|
| 381 | - and suppose we haev a Wanted constraint
|
|
| 390 | + and suppose we have a Wanted constraint
|
|
| 382 | 391 | [W] G6 alpha ~ [Int]
|
| 383 | -. According to Section 5.2 of "Injective type families for Haskell", we /match/
|
|
| 384 | - the RHS each type instance [Int]. So we try
|
|
| 392 | + According to Section 5.2 of "Injective type families for Haskell", we /match/
|
|
| 393 | + the RHS each of type instance with [Int]. So we try
|
|
| 385 | 394 | Template: [G a] Target: [Int]
|
| 386 | 395 | and we want to succeed with MaybeApart, so that we can generate the improvement
|
| 387 | 396 | constraint
|
| ... | ... | @@ -401,15 +410,21 @@ Wrinkles |
| 401 | 410 | |
| 402 | 411 | (ATF9) Decomposition. Consider unifying
|
| 403 | 412 | F a ~ F Int
|
| 404 | - There is a unifying substitition [a :-> Int], and we want to find it, returning
|
|
| 405 | - Unifiable. (Remember, this is the Core unifier -- we are not doing type inference.)
|
|
| 406 | - So we should decompose to get (a ~ Int)
|
|
| 413 | + when `um_bind_fam_fun` says DontBindMe. There is a unifying substitition [a :-> Int],
|
|
| 414 | + and we want to find it, returning Unifiable. Why?
|
|
| 415 | + - Remember, this is the Core unifier -- we are not doing type inference
|
|
| 416 | + - When we have two equal types, like F a ~ F a, it is ridiculous to say that they
|
|
| 417 | + are MaybeApart. Example: the two-way tcMatchTy in `checkValidClass` and #26457.
|
|
| 407 | 418 | |
| 408 | - But consider unifying
|
|
| 419 | + (ATF9-1) But consider unifying
|
|
| 409 | 420 | F Int ~ F Bool
|
| 410 | - Although Int and Bool are SurelyApart, we must return MaybeApart for the outer
|
|
| 411 | - unification. Hence the use of `don'tBeSoSure` in `go_fam_fam`; it leaves Unifiable
|
|
| 412 | - alone, but weakens `SurelyApart` to `MaybeApart`.
|
|
| 421 | + Although Int and Bool are SurelyApart, we must return MaybeApart for the outer
|
|
| 422 | + unification. Hence the use of `don'tBeSoSure` in `go_fam_fam`; it leaves Unifiable
|
|
| 423 | + alone, but weakens `SurelyApart` to `MaybeApart`.
|
|
| 424 | + |
|
| 425 | + (ATF9-2) We want this decomposition to occur even under a forall (this was #26457).
|
|
| 426 | + E.g. (forall a. F Int) -> Int ~ (forall a. F Int) ~ Int
|
|
| 427 | + |
|
| 413 | 428 | |
| 414 | 429 | (ATF10) Injectivity. Consider (AFT9) where F is known to be injective. Then if we
|
| 415 | 430 | are unifying
|
| ... | ... | @@ -1815,6 +1830,9 @@ uVarOrFam env ty1 ty2 kco |
| 1815 | 1830 | -- , text "fam_env" <+> ppr (um_fam_env substs) ]) $
|
| 1816 | 1831 | ; go NotSwapped substs ty1 ty2 kco }
|
| 1817 | 1832 | where
|
| 1833 | + foralld_tvs = um_foralls env
|
|
| 1834 | + under_forall = not (isEmptyVarSet foralld_tvs)
|
|
| 1835 | + |
|
| 1818 | 1836 | -- `go` takes two bites at the cherry; if the first one fails
|
| 1819 | 1837 | -- it swaps the arguments and tries again; and then it fails.
|
| 1820 | 1838 | -- The SwapFlag argument tells `go` whether it is on the first
|
| ... | ... | @@ -1889,7 +1907,6 @@ uVarOrFam env ty1 ty2 kco |
| 1889 | 1907 | | otherwise
|
| 1890 | 1908 | = False
|
| 1891 | 1909 | |
| 1892 | - foralld_tvs = um_foralls env
|
|
| 1893 | 1910 | occurs_check = um_unif env && uOccursCheck substs foralld_tvs lhs rhs
|
| 1894 | 1911 | -- Occurs check, only when unifying
|
| 1895 | 1912 | -- see Note [Infinitary substitutions]
|
| ... | ... | @@ -1899,14 +1916,11 @@ uVarOrFam env ty1 ty2 kco |
| 1899 | 1916 | -- LHS is a saturated type-family application
|
| 1900 | 1917 | -- Invariant: ty2 is not a TyVarTy
|
| 1901 | 1918 | go swapped substs lhs@(TyFamLHS tc1 tys1) ty2 kco
|
| 1902 | - -- If we are under a forall, just give up and return MaybeApart
|
|
| 1903 | - -- see (ATF3) in Note [Apartness and type families]
|
|
| 1904 | - | not (isEmptyVarSet (um_foralls env))
|
|
| 1905 | - = maybeApart MARTypeFamily
|
|
| 1906 | - |
|
| 1907 | - -- We are not under any foralls, so the RnEnv2 is empty
|
|
| 1908 | 1919 | -- Check if we have an existing substitution for the LHS; if so, recurse
|
| 1909 | - | Just ty1' <- lookupFamEnv (um_fam_env substs) tc1 tys1
|
|
| 1920 | + -- But not under a forall; see (ATF3) in Note [Apartness and type families]
|
|
| 1921 | + -- Hence the RnEnv2 is empty
|
|
| 1922 | + | not under_forall
|
|
| 1923 | + , Just ty1' <- lookupFamEnv (um_fam_env substs) tc1 tys1
|
|
| 1910 | 1924 | = if | um_unif env -> unify_ty env ty1' ty2 kco
|
| 1911 | 1925 | -- Below here we are matching
|
| 1912 | 1926 | -- The return () case deals with:
|
| ... | ... | @@ -1917,11 +1931,19 @@ uVarOrFam env ty1 ty2 kco |
| 1917 | 1931 | | otherwise -> maybeApart MARTypeFamily
|
| 1918 | 1932 | |
| 1919 | 1933 | -- Check for equality F tys1 ~ F tys2
|
| 1934 | + -- Very important that this can happen under a forall, so that we
|
|
| 1935 | + -- successfully match (forall a. F a) ~ (forall b. F b) See (ATF9-2)
|
|
| 1920 | 1936 | | Just (tc2, tys2) <- isSatTyFamApp ty2
|
| 1921 | 1937 | , tc1 == tc2
|
| 1922 | 1938 | = go_fam_fam substs tc1 tys1 tys2 kco
|
| 1923 | 1939 | |
| 1940 | + -- If we are under a forall, just give up
|
|
| 1941 | + -- see (ATF3) and (ATF5) in Note [Apartness and type families]
|
|
| 1942 | + | under_forall
|
|
| 1943 | + = maybeApart MARTypeFamily
|
|
| 1944 | + |
|
| 1924 | 1945 | -- Now check if we can bind the (F tys) to the RHS
|
| 1946 | + -- Again, not under a forall; see (ATF3)
|
|
| 1925 | 1947 | -- This can happen even when matching: see (ATF7)
|
| 1926 | 1948 | | BindMe <- um_bind_fam_fun env tc1 tys1 rhs
|
| 1927 | 1949 | = if uOccursCheck substs emptyVarSet lhs rhs
|
| ... | ... | @@ -1935,6 +1957,7 @@ uVarOrFam env ty1 ty2 kco |
| 1935 | 1957 | -- Maybe um_bind_fam_fun is False of (F a b) but true of (G c d e)
|
| 1936 | 1958 | -- NB: a type family can appear on the template when matching
|
| 1937 | 1959 | -- see (ATF6) in Note [Apartness and type families]
|
| 1960 | + -- (Only worth doing this if we are not under a forall.)
|
|
| 1938 | 1961 | | um_unif env
|
| 1939 | 1962 | , NotSwapped <- swapped
|
| 1940 | 1963 | , Just lhs2 <- canEqLHS_maybe ty2
|
| ... | ... | @@ -1949,7 +1972,6 @@ uVarOrFam env ty1 ty2 kco |
| 1949 | 1972 | -----------------------------
|
| 1950 | 1973 | -- go_fam_fam: LHS and RHS are both saturated type-family applications,
|
| 1951 | 1974 | -- for the same type-family F
|
| 1952 | - -- Precondition: um_foralls is empty
|
|
| 1953 | 1975 | go_fam_fam substs tc tys1 tys2 kco
|
| 1954 | 1976 | -- Decompose (F tys1 ~ F tys2): (ATF9)
|
| 1955 | 1977 | -- Use injectivity information of F: (ATF10)
|
| ... | ... | @@ -1957,7 +1979,7 @@ uVarOrFam env ty1 ty2 kco |
| 1957 | 1979 | = do { bind_fam_if_poss -- (ATF11)
|
| 1958 | 1980 | ; unify_tys env inj_tys1 inj_tys2 -- (ATF10)
|
| 1959 | 1981 | ; unless (um_inj_tf env) $ -- (ATF12)
|
| 1960 | - don'tBeSoSure MARTypeFamily $ -- (ATF9)
|
|
| 1982 | + don'tBeSoSure MARTypeFamily $ -- (ATF9-1)
|
|
| 1961 | 1983 | unify_tys env noninj_tys1 noninj_tys2 }
|
| 1962 | 1984 | where
|
| 1963 | 1985 | inj = case tyConInjectivityInfo tc of
|
| ... | ... | @@ -1970,6 +1992,8 @@ uVarOrFam env ty1 ty2 kco |
| 1970 | 1992 | bind_fam_if_poss
|
| 1971 | 1993 | | not (um_unif env) -- Not when matching (ATF11-1)
|
| 1972 | 1994 | = return ()
|
| 1995 | + | under_forall -- Not under a forall (ATF3)
|
|
| 1996 | + = return ()
|
|
| 1973 | 1997 | | BindMe <- um_bind_fam_fun env tc tys1 rhs1
|
| 1974 | 1998 | = unless (uOccursCheck substs emptyVarSet (TyFamLHS tc tys1) rhs1) $
|
| 1975 | 1999 | extendFamEnv tc tys1 rhs1
|
| ... | ... | @@ -102,7 +102,6 @@ module GHC.Driver.Main |
| 102 | 102 | , dumpIfaceStats
|
| 103 | 103 | , ioMsgMaybe
|
| 104 | 104 | , showModuleIndex
|
| 105 | - , hscAddSptEntries
|
|
| 106 | 105 | , writeInterfaceOnlyMode
|
| 107 | 106 | , loadByteCode
|
| 108 | 107 | , genModDetails
|
| ... | ... | @@ -2515,9 +2514,6 @@ hscParsedDecls hsc_env decls = runInteractiveHsc hsc_env $ do |
| 2515 | 2514 | let src_span = srcLocSpan interactiveSrcLoc
|
| 2516 | 2515 | _ <- liftIO $ loadDecls interp hsc_env src_span linkable
|
| 2517 | 2516 | |
| 2518 | - {- Load static pointer table entries -}
|
|
| 2519 | - liftIO $ hscAddSptEntries hsc_env (cg_spt_entries tidy_cg)
|
|
| 2520 | - |
|
| 2521 | 2517 | let tcs = filterOut isImplicitTyCon (mg_tcs simpl_mg)
|
| 2522 | 2518 | patsyns = mg_patsyns simpl_mg
|
| 2523 | 2519 | |
| ... | ... | @@ -2539,18 +2535,6 @@ hscParsedDecls hsc_env decls = runInteractiveHsc hsc_env $ do |
| 2539 | 2535 | fam_insts defaults fix_env
|
| 2540 | 2536 | return (new_tythings, new_ictxt)
|
| 2541 | 2537 | |
| 2542 | --- | Load the given static-pointer table entries into the interpreter.
|
|
| 2543 | --- See Note [Grand plan for static forms] in "GHC.Iface.Tidy.StaticPtrTable".
|
|
| 2544 | -hscAddSptEntries :: HscEnv -> [SptEntry] -> IO ()
|
|
| 2545 | -hscAddSptEntries hsc_env entries = do
|
|
| 2546 | - let interp = hscInterp hsc_env
|
|
| 2547 | - let add_spt_entry :: SptEntry -> IO ()
|
|
| 2548 | - add_spt_entry (SptEntry n fpr) = do
|
|
| 2549 | - -- These are only names from the current module
|
|
| 2550 | - (val, _, _) <- loadName interp hsc_env n
|
|
| 2551 | - addSptEntry interp fpr val
|
|
| 2552 | - mapM_ add_spt_entry entries
|
|
| 2553 | - |
|
| 2554 | 2538 | {-
|
| 2555 | 2539 | Note [Fixity declarations in GHCi]
|
| 2556 | 2540 | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
| ... | ... | @@ -56,8 +56,6 @@ import GHC.Tc.Utils.Monad ( initIfaceCheck, concatMapM ) |
| 56 | 56 | |
| 57 | 57 | import GHC.Runtime.Interpreter
|
| 58 | 58 | import qualified GHC.Linker.Loader as Linker
|
| 59 | -import GHC.Linker.Types
|
|
| 60 | - |
|
| 61 | 59 | |
| 62 | 60 | import GHC.Driver.Config.Diagnostic
|
| 63 | 61 | import GHC.Driver.Pipeline
|
| ... | ... | @@ -72,8 +70,6 @@ import GHC.Driver.MakeSem |
| 72 | 70 | import GHC.Driver.Downsweep
|
| 73 | 71 | import GHC.Driver.MakeAction
|
| 74 | 72 | |
| 75 | -import GHC.ByteCode.Types
|
|
| 76 | - |
|
| 77 | 73 | import GHC.Iface.Load ( cannotFindModule, readIface )
|
| 78 | 74 | import GHC.IfaceToCore ( typecheckIface )
|
| 79 | 75 | import GHC.Iface.Recomp ( RecompileRequired(..), CompileReason(..) )
|
| ... | ... | @@ -1232,31 +1228,9 @@ upsweep_mod :: HscEnv |
| 1232 | 1228 | upsweep_mod hsc_env mHscMessage old_hmi summary mod_index nmods = do
|
| 1233 | 1229 | hmi <- compileOne' mHscMessage hsc_env summary
|
| 1234 | 1230 | mod_index nmods (hm_iface <$> old_hmi) (maybe emptyHomeModInfoLinkable hm_linkable old_hmi)
|
| 1235 | - |
|
| 1236 | - -- MP: This is a bit janky, because before you add the entries you have to extend the HPT with the module
|
|
| 1237 | - -- you just compiled. Another option, would be delay adding anything until after upsweep has finished, but I
|
|
| 1238 | - -- am unsure if this is sound (wrt running TH splices for example).
|
|
| 1239 | - -- This function only does anything if the linkable produced is a BCO, which
|
|
| 1240 | - -- used to only happen with the bytecode backend, but with
|
|
| 1241 | - -- @-fprefer-byte-code@, @HomeModInfo@ has bytecode even when generating
|
|
| 1242 | - -- object code, see #25230.
|
|
| 1243 | 1231 | hscInsertHPT hmi hsc_env
|
| 1244 | - addSptEntries (hsc_env)
|
|
| 1245 | - (homeModInfoByteCode hmi)
|
|
| 1246 | - |
|
| 1247 | 1232 | return hmi
|
| 1248 | 1233 | |
| 1249 | --- | Add the entries from a BCO linkable to the SPT table, see
|
|
| 1250 | --- See Note [Grand plan for static forms] in GHC.Iface.Tidy.StaticPtrTable.
|
|
| 1251 | -addSptEntries :: HscEnv -> Maybe Linkable -> IO ()
|
|
| 1252 | -addSptEntries hsc_env mlinkable =
|
|
| 1253 | - hscAddSptEntries hsc_env
|
|
| 1254 | - [ spt
|
|
| 1255 | - | linkable <- maybeToList mlinkable
|
|
| 1256 | - , bco <- linkableBCOs linkable
|
|
| 1257 | - , spt <- bc_spt_entries bco
|
|
| 1258 | - ]
|
|
| 1259 | - |
|
| 1260 | 1234 | |
| 1261 | 1235 | -- Note [When source is considered modified]
|
| 1262 | 1236 | -- ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
| ... | ... | @@ -3763,12 +3763,17 @@ makeDynFlagsConsistent dflags |
| 3763 | 3763 | -- only supports dynamic code
|
| 3764 | 3764 | | LinkInMemory <- ghcLink dflags
|
| 3765 | 3765 | , sTargetRTSLinkerOnlySupportsSharedLibs $ settings dflags
|
| 3766 | +#if defined(HAVE_INTERNAL_INTERPRETER)
|
|
| 3767 | + , not (ways dflags `hasWay` WayDyn)
|
|
| 3768 | +#else
|
|
| 3766 | 3769 | , not (ways dflags `hasWay` WayDyn && gopt Opt_ExternalInterpreter dflags)
|
| 3770 | +#endif
|
|
| 3767 | 3771 | = flip loopNoWarn "Forcing dynamic way because target RTS linker only supports dynamic code" $
|
| 3768 | - -- See checkOptions, -fexternal-interpreter is
|
|
| 3769 | - -- required when using --interactive with a non-standard
|
|
| 3770 | - -- way (-prof, -static, or -dynamic).
|
|
| 3772 | +#if !defined(HAVE_INTERNAL_INTERPRETER)
|
|
| 3773 | + -- Force -fexternal-interpreter if internal-interpreter is not
|
|
| 3774 | + -- available at this stage
|
|
| 3771 | 3775 | setGeneralFlag' Opt_ExternalInterpreter $
|
| 3776 | +#endif
|
|
| 3772 | 3777 | addWay' WayDyn dflags
|
| 3773 | 3778 | |
| 3774 | 3779 | | LinkInMemory <- ghcLink dflags
|
| ... | ... | @@ -124,7 +124,7 @@ Here is a running example: |
| 124 | 124 | * If we are compiling for the byte-code interpreter, we instead explicitly add
|
| 125 | 125 | the SPT entries (recorded in CgGuts' cg_spt_entries field) to the interpreter
|
| 126 | 126 | process' SPT table using the addSptEntry interpreter message. This happens
|
| 127 | - in upsweep after we have compiled the module (see GHC.Driver.Make.upsweep').
|
|
| 127 | + when the bytecode object is linked in `dynLinkBCOs`.
|
|
| 128 | 128 | -}
|
| 129 | 129 | |
| 130 | 130 | import GHC.Prelude
|
| ... | ... | @@ -718,6 +718,7 @@ loadDecls interp hsc_env span linkable = do |
| 718 | 718 | let ce2 = extendClosureEnv (closure_env le2) nms_fhvs
|
| 719 | 719 | !pls2 = pls { linker_env = le2 { closure_env = ce2 }
|
| 720 | 720 | , linked_breaks = lb2 }
|
| 721 | + mapM_ (linkSptEntry interp ce2) (concatMap bc_spt_entries cbcs)
|
|
| 721 | 722 | return (pls2, (nms_fhvs, links_needed, units_needed))
|
| 722 | 723 | where
|
| 723 | 724 | cbcs = linkableBCOs linkable
|
| ... | ... | @@ -951,10 +952,28 @@ dynLinkBCOs interp pls bcos = do |
| 951 | 952 | -- Wrap finalizers on the ones we want to keep
|
| 952 | 953 | new_binds <- makeForeignNamedHValueRefs interp to_add
|
| 953 | 954 | |
| 955 | + |
|
| 954 | 956 | let ce2 = extendClosureEnv (closure_env le2) new_binds
|
| 957 | + |
|
| 958 | + -- Add SPT entries
|
|
| 959 | + mapM_ (linkSptEntry interp ce2) (concatMap bc_spt_entries cbcs)
|
|
| 960 | + |
|
| 955 | 961 | return $! pls1 { linker_env = le2 { closure_env = ce2 }
|
| 956 | 962 | , linked_breaks = lb2 }
|
| 957 | 963 | |
| 964 | +-- | Register SPT entries for this module in the interpreter
|
|
| 965 | +-- Assumes that the name from the SPT has already been loaded into the interpreter.
|
|
| 966 | +linkSptEntry :: Interp -> ClosureEnv -> SptEntry -> IO ()
|
|
| 967 | +linkSptEntry interp ce (SptEntry name fpr) = do
|
|
| 968 | + case lookupNameEnv ce name of
|
|
| 969 | + -- The SPT entries only point to locally defined names, which should have already been
|
|
| 970 | + -- loaded into the interpreter before this function is called.
|
|
| 971 | + Nothing -> pprPanic "linkSptEntry" (ppr name)
|
|
| 972 | + Just (_, hval) -> addSptEntry interp fpr hval
|
|
| 973 | + |
|
| 974 | + |
|
| 975 | + |
|
| 976 | + |
|
| 958 | 977 | -- Link a bunch of BCOs and return references to their values
|
| 959 | 978 | linkSomeBCOs :: Interp
|
| 960 | 979 | -> PkgsLoaded
|
| ... | ... | @@ -1614,6 +1633,9 @@ gccSearchDirCache = unsafePerformIO $ newIORef [] |
| 1614 | 1633 | -- which dominate a large percentage of startup time on Windows.
|
| 1615 | 1634 | getGccSearchDirectory :: Logger -> DynFlags -> String -> IO [FilePath]
|
| 1616 | 1635 | getGccSearchDirectory logger dflags key = do
|
| 1636 | +#if defined(wasm32_HOST_ARCH)
|
|
| 1637 | + pure []
|
|
| 1638 | +#else
|
|
| 1617 | 1639 | cache <- readIORef gccSearchDirCache
|
| 1618 | 1640 | case lookup key cache of
|
| 1619 | 1641 | Just x -> return x
|
| ... | ... | @@ -1640,6 +1662,7 @@ getGccSearchDirectory logger dflags key = do |
| 1640 | 1662 | x:_ -> case break (=='=') x of
|
| 1641 | 1663 | (_ , []) -> []
|
| 1642 | 1664 | (_, (_:xs)) -> xs
|
| 1665 | +#endif
|
|
| 1643 | 1666 | |
| 1644 | 1667 | -- | Get a list of system search directories, this to alleviate pressure on
|
| 1645 | 1668 | -- the findSysDll function.
|
| ... | ... | @@ -214,7 +214,7 @@ data JSInterpConfig = JSInterpConfig |
| 214 | 214 | |
| 215 | 215 | data WasmInterpConfig = WasmInterpConfig
|
| 216 | 216 | { wasmInterpDyLD :: !FilePath -- ^ Location of dyld.mjs script
|
| 217 | - , wasmInterpLibDir :: FilePath -- ^ wasi-sdk sysroot libdir containing libc.so, etc
|
|
| 217 | + , wasmInterpLibDir :: !FilePath -- ^ wasi-sdk sysroot libdir containing libc.so, etc
|
|
| 218 | 218 | , wasmInterpOpts :: ![String] -- ^ Additional command line arguments for iserv
|
| 219 | 219 | |
| 220 | 220 | -- wasm ghci browser mode
|
| ... | ... | @@ -1120,8 +1120,6 @@ or contexts in two parts: |
| 1120 | 1120 | -- | The arguments in a Haskell98-style data constructor.
|
| 1121 | 1121 | type HsConDeclH98Details pass
|
| 1122 | 1122 | = HsConDetails (HsConDeclField pass) (XRec pass [LHsConDeclRecField pass])
|
| 1123 | --- The Void argument to HsConDetails here is a reflection of the fact that
|
|
| 1124 | --- type applications are not allowed in data constructor declarations.
|
|
| 1125 | 1123 | |
| 1126 | 1124 | -- | The arguments in a GADT constructor. Unlike Haskell98-style constructors,
|
| 1127 | 1125 | -- GADT constructors cannot be declared with infix syntax. As a result, we do
|
| ... | ... | @@ -448,11 +448,6 @@ AC_SUBST([CmmCPPCmd]) |
| 448 | 448 | AC_SUBST([CmmCPPArgs])
|
| 449 | 449 | AC_SUBST([CmmCPPSupportsG0])
|
| 450 | 450 | |
| 451 | -FP_SET_CFLAGS_C99([CC],[CFLAGS],[CPPFLAGS])
|
|
| 452 | -FP_SET_CFLAGS_C99([CC_STAGE0],[CONF_CC_OPTS_STAGE0],[CONF_CPP_OPTS_STAGE0])
|
|
| 453 | -FP_SET_CFLAGS_C99([CC],[CONF_CC_OPTS_STAGE1],[CONF_CPP_OPTS_STAGE1])
|
|
| 454 | -FP_SET_CFLAGS_C99([CC],[CONF_CC_OPTS_STAGE2],[CONF_CPP_OPTS_STAGE2])
|
|
| 455 | - |
|
| 456 | 451 | dnl ** Do we have a compatible emsdk version?
|
| 457 | 452 | dnl --------------------------------------------------------------
|
| 458 | 453 | EMSDK_VERSION("3.1.20", "", "")
|
| ... | ... | @@ -163,11 +163,6 @@ AC_SUBST([CmmCPPCmd]) |
| 163 | 163 | AC_SUBST([CmmCPPArgs])
|
| 164 | 164 | AC_SUBST([CmmCPPSupportsG0])
|
| 165 | 165 | |
| 166 | -FP_SET_CFLAGS_C99([CC],[CFLAGS],[CPPFLAGS])
|
|
| 167 | -dnl FP_SET_CFLAGS_C99([CC_STAGE0],[CONF_CC_OPTS_STAGE0],[CONF_CPP_OPTS_STAGE0])
|
|
| 168 | -FP_SET_CFLAGS_C99([CC],[CONF_CC_OPTS_STAGE1],[CONF_CPP_OPTS_STAGE1])
|
|
| 169 | -FP_SET_CFLAGS_C99([CC],[CONF_CC_OPTS_STAGE2],[CONF_CPP_OPTS_STAGE2])
|
|
| 170 | - |
|
| 171 | 166 | dnl ** Which ld to use?
|
| 172 | 167 | dnl --------------------------------------------------------------
|
| 173 | 168 | FIND_LD([$target],[GccUseLdOpt])
|
| ... | ... | @@ -82,15 +82,18 @@ packageArgs = do |
| 82 | 82 | ]
|
| 83 | 83 | |
| 84 | 84 | , builder (Cabal Flags) ? mconcat
|
| 85 | - -- For the ghc library, internal-interpreter only makes
|
|
| 86 | - -- sense when we're not cross compiling. For cross GHC,
|
|
| 87 | - -- external interpreter is used for loading target code
|
|
| 88 | - -- and internal interpreter is supposed to load native
|
|
| 89 | - -- code for plugins (!7377), however it's unfinished work
|
|
| 90 | - -- (#14335) and completely untested in CI for cross
|
|
| 91 | - -- backends at the moment, so we might as well disable it
|
|
| 92 | - -- for cross GHC.
|
|
| 93 | - [ andM [expr (ghcWithInterpreter stage), notCross] `cabalFlag` "internal-interpreter"
|
|
| 85 | + -- In order to enable internal-interpreter for the ghc
|
|
| 86 | + -- library:
|
|
| 87 | + --
|
|
| 88 | + -- 1. ghcWithInterpreter must be True ("Use interpreter" =
|
|
| 89 | + -- "YES")
|
|
| 90 | + -- 2. For non-cross case it can be enabled
|
|
| 91 | + -- 3. For cross case, disable for stage0 since that runs
|
|
| 92 | + -- on the host and must rely on external interpreter to
|
|
| 93 | + -- load target code, otherwise enable for stage1 since
|
|
| 94 | + -- that runs on the target and can use target's own
|
|
| 95 | + -- ghci object linker
|
|
| 96 | + [ andM [expr (ghcWithInterpreter stage), orM [notCross, stage1]] `cabalFlag` "internal-interpreter"
|
|
| 94 | 97 | , orM [ notM cross, haveCurses ] `cabalFlag` "terminfo"
|
| 95 | 98 | , arg "-build-tool-depends"
|
| 96 | 99 | , flag UseLibzstd `cabalFlag` "with-libzstd"
|
| ... | ... | @@ -113,8 +113,7 @@ foreign import javascript unsafe "__ghc_wasm_jsffi_dyld.lookupSymbol($1)" |
| 113 | 113 | js_lookupSymbol :: JSString -> IO (Ptr a)
|
| 114 | 114 | |
| 115 | 115 | lookupSymbolInDLL :: Ptr LoadedDLL -> String -> IO (Maybe (Ptr a))
|
| 116 | -lookupSymbolInDLL _ sym =
|
|
| 117 | - throwIO $ ErrorCall $ "lookupSymbolInDLL: unsupported on wasm for " <> sym
|
|
| 116 | +lookupSymbolInDLL _ _ = pure Nothing
|
|
| 118 | 117 | |
| 119 | 118 | resolveObjs :: IO Bool
|
| 120 | 119 | resolveObjs = pure True
|
| ... | ... | @@ -56,27 +56,6 @@ else |
| 56 | 56 | AC_MSG_RESULT([no])
|
| 57 | 57 | fi
|
| 58 | 58 | |
| 59 | -AC_MSG_CHECKING([the C-- preprocessor for C99 support])
|
|
| 60 | -cat > conftest.c <<EOF
|
|
| 61 | -#include <stdio.h>
|
|
| 62 | -#if !defined __STDC_VERSION__ || __STDC_VERSION__ < 199901L
|
|
| 63 | -# error "Compiler does not advertise C99 conformance"
|
|
| 64 | -#endif
|
|
| 65 | -EOF
|
|
| 66 | -if "$CMM_CPP_CMD" $CMM_CPP_ARGS conftest.c -o conftest -g0 >/dev/null 2>&1; then
|
|
| 67 | - AC_MSG_RESULT([yes])
|
|
| 68 | -else
|
|
| 69 | - # Try -std=gnu99
|
|
| 70 | - if "$CMM_CPP_CMD" -std=gnu99 $CMM_CPP_ARGS conftest.c -o conftest -g0 >/dev/null 2>&1; then
|
|
| 71 | - $3="-std=gnu99 $$3"
|
|
| 72 | - AC_MSG_RESULT([needs -std=gnu99])
|
|
| 73 | - else
|
|
| 74 | - AC_MSG_ERROR([C99-compatible compiler needed])
|
|
| 75 | - fi
|
|
| 76 | -fi
|
|
| 77 | -rm -f conftest.c conftest.o conftest
|
|
| 78 | - |
|
| 79 | - |
|
| 80 | 59 | $2="$CMM_CPP_CMD"
|
| 81 | 60 | $3="$$3 $CMM_CPP_ARGS"
|
| 82 | 61 | |
| ... | ... | @@ -85,4 +64,3 @@ unset CMM_CPP_CMD |
| 85 | 64 | unset CMM_CPP_ARGS
|
| 86 | 65 | |
| 87 | 66 | ]) |
| 88 | - |
| 1 | -# FP_SET_CFLAGS_C99
|
|
| 2 | -# ----------------------------------
|
|
| 3 | -# figure out which CFLAGS are needed to place the compiler into C99 mode
|
|
| 4 | -# $1 is name of CC variable (unmodified)
|
|
| 5 | -# $2 is name of CC flags variable (augmented if needed)
|
|
| 6 | -# $3 is name of CPP flags variable (augmented if needed)
|
|
| 7 | -AC_DEFUN([FP_SET_CFLAGS_C99],
|
|
| 8 | -[
|
|
| 9 | - dnl save current state of AC_PROG_CC_C99
|
|
| 10 | - FP_COPY_SHELLVAR([CC],[fp_save_CC])
|
|
| 11 | - FP_COPY_SHELLVAR([CFLAGS],[fp_save_CFLAGS])
|
|
| 12 | - FP_COPY_SHELLVAR([CPPFLAGS],[fp_save_CPPFLAGS])
|
|
| 13 | - FP_COPY_SHELLVAR([ac_cv_prog_cc_c99],[fp_save_cc_c99])
|
|
| 14 | - dnl set local state
|
|
| 15 | - CC="$$1"
|
|
| 16 | - CFLAGS="$$2"
|
|
| 17 | - CPPFLAGS="$$3"
|
|
| 18 | - unset ac_cv_prog_cc_c99
|
|
| 19 | - dnl perform detection
|
|
| 20 | - AC_PROG_CC_C99
|
|
| 21 | - fp_cc_c99="$ac_cv_prog_cc_c99"
|
|
| 22 | - case "x$ac_cv_prog_cc_c99" in
|
|
| 23 | - x) ;; # noop
|
|
| 24 | - xno) AC_MSG_ERROR([C99-compatible compiler needed]) ;;
|
|
| 25 | - *) $2="$$2 $ac_cv_prog_cc_c99"
|
|
| 26 | - $3="$$3 $ac_cv_prog_cc_c99"
|
|
| 27 | - ;;
|
|
| 28 | - esac
|
|
| 29 | - dnl restore saved state
|
|
| 30 | - FP_COPY_SHELLVAR([fp_save_CC],[CC])
|
|
| 31 | - FP_COPY_SHELLVAR([fp_save_CFLAGS],[CFLAGS])
|
|
| 32 | - FP_COPY_SHELLVAR([fp_save_CPPFLAGS],[CPPFLAGS])
|
|
| 33 | - FP_COPY_SHELLVAR([fp_save_cc_c99],[ac_cv_prog_cc_c99])
|
|
| 34 | - dnl cleanup
|
|
| 35 | - unset fp_save_CC
|
|
| 36 | - unset fp_save_CFLAGS
|
|
| 37 | - unset fp_save_cc_c99
|
|
| 38 | -]) |
| ... | ... | @@ -699,7 +699,7 @@ INFO_TABLE(stg_AP_STACK,/*special layout*/0,0,AP_STACK,"AP_STACK","AP_STACK") |
| 699 | 699 | |
| 700 | 700 | /* ensure there is at least AP_STACK_SPLIM words of headroom available
|
| 701 | 701 | * after unpacking the AP_STACK. See bug #1466 */
|
| 702 | - PUSH_UPD_FRAME(Sp - SIZEOF_StgUpdateFrame, R1);
|
|
| 702 | + PUSH_BH_UPD_FRAME(Sp - SIZEOF_StgUpdateFrame, R1);
|
|
| 703 | 703 | Sp = Sp - SIZEOF_StgUpdateFrame - WDS(Words);
|
| 704 | 704 | |
| 705 | 705 | TICK_ENT_AP();
|
| ... | ... | @@ -15,6 +15,7 @@ |
| 15 | 15 | #include "RaiseAsync.h"
|
| 16 | 16 | #include "Trace.h"
|
| 17 | 17 | #include "Threads.h"
|
| 18 | +#include "Messages.h"
|
|
| 18 | 19 | #include "sm/NonMovingMark.h"
|
| 19 | 20 | |
| 20 | 21 | #include <string.h> // for memmove()
|
| ... | ... | @@ -314,52 +315,66 @@ threadPaused(Capability *cap, StgTSO *tso) |
| 314 | 315 | continue;
|
| 315 | 316 | }
|
| 316 | 317 | |
| 317 | - // an EAGER_BLACKHOLE or CAF_BLACKHOLE gets turned into a
|
|
| 318 | - // BLACKHOLE here.
|
|
| 318 | + // If we have a frame that is already eagerly blackholed, we
|
|
| 319 | + // shouldn't overwrite its payload: There may already be a blocking
|
|
| 320 | + // queue (see #26324).
|
|
| 321 | + if(frame_info == &stg_bh_upd_frame_info) {
|
|
| 322 | + // eager black hole: we do nothing
|
|
| 323 | + |
|
| 324 | + // it should be a black hole that we own
|
|
| 325 | + ASSERT(bh_info == &stg_BLACKHOLE_info ||
|
|
| 326 | + bh_info == &__stg_EAGER_BLACKHOLE_info ||
|
|
| 327 | + bh_info == &stg_CAF_BLACKHOLE_info);
|
|
| 328 | + ASSERT(blackHoleOwner(bh) == tso || blackHoleOwner(bh) == NULL);
|
|
| 329 | + } else {
|
|
| 330 | + // lazy black hole
|
|
| 331 | + |
|
| 319 | 332 | #if defined(THREADED_RTS)
|
| 320 | - // first we turn it into a WHITEHOLE to claim it, and if
|
|
| 321 | - // successful we write our TSO and then the BLACKHOLE info pointer.
|
|
| 322 | - cur_bh_info = (const StgInfoTable *)
|
|
| 323 | - cas((StgVolatilePtr)&bh->header.info,
|
|
| 324 | - (StgWord)bh_info,
|
|
| 325 | - (StgWord)&stg_WHITEHOLE_info);
|
|
| 326 | - |
|
| 327 | - if (cur_bh_info != bh_info) {
|
|
| 328 | - bh_info = cur_bh_info;
|
|
| 333 | + // first we turn it into a WHITEHOLE to claim it, and if
|
|
| 334 | + // successful we write our TSO and then the BLACKHOLE info pointer.
|
|
| 335 | + cur_bh_info = (const StgInfoTable *)
|
|
| 336 | + cas((StgVolatilePtr)&bh->header.info,
|
|
| 337 | + (StgWord)bh_info,
|
|
| 338 | + (StgWord)&stg_WHITEHOLE_info);
|
|
| 339 | + |
|
| 340 | + if (cur_bh_info != bh_info) {
|
|
| 341 | + bh_info = cur_bh_info;
|
|
| 329 | 342 | #if defined(PROF_SPIN)
|
| 330 | - NONATOMIC_ADD(&whitehole_threadPaused_spin, 1);
|
|
| 343 | + NONATOMIC_ADD(&whitehole_threadPaused_spin, 1);
|
|
| 331 | 344 | #endif
|
| 332 | - busy_wait_nop();
|
|
| 333 | - goto retry;
|
|
| 334 | - }
|
|
| 345 | + busy_wait_nop();
|
|
| 346 | + goto retry;
|
|
| 347 | + }
|
|
| 335 | 348 | #endif
|
| 336 | - |
|
| 337 | - IF_NONMOVING_WRITE_BARRIER_ENABLED {
|
|
| 338 | - if (ip_THUNK(INFO_PTR_TO_STRUCT(bh_info))) {
|
|
| 339 | - // We are about to replace a thunk with a blackhole.
|
|
| 340 | - // Add the free variables of the closure we are about to
|
|
| 341 | - // overwrite to the update remembered set.
|
|
| 342 | - // N.B. We caught the WHITEHOLE case above.
|
|
| 343 | - updateRemembSetPushThunkEager(cap,
|
|
| 344 | - THUNK_INFO_PTR_TO_STRUCT(bh_info),
|
|
| 345 | - (StgThunk *) bh);
|
|
| 349 | + ASSERT(bh_info != &stg_WHITEHOLE_info);
|
|
| 350 | + |
|
| 351 | + IF_NONMOVING_WRITE_BARRIER_ENABLED {
|
|
| 352 | + if (ip_THUNK(INFO_PTR_TO_STRUCT(bh_info))) {
|
|
| 353 | + // We are about to replace a thunk with a blackhole.
|
|
| 354 | + // Add the free variables of the closure we are about to
|
|
| 355 | + // overwrite to the update remembered set.
|
|
| 356 | + // N.B. We caught the WHITEHOLE case above.
|
|
| 357 | + updateRemembSetPushThunkEager(cap,
|
|
| 358 | + THUNK_INFO_PTR_TO_STRUCT(bh_info),
|
|
| 359 | + (StgThunk *) bh);
|
|
| 360 | + }
|
|
| 346 | 361 | }
|
| 347 | - }
|
|
| 348 | 362 | |
| 349 | - // zero out the slop so that the sanity checker can tell
|
|
| 350 | - // where the next closure is. N.B. We mustn't do this until we have
|
|
| 351 | - // pushed the free variables to the update remembered set above.
|
|
| 352 | - OVERWRITING_CLOSURE_SIZE(bh, closure_sizeW_(bh, INFO_PTR_TO_STRUCT(bh_info)));
|
|
| 363 | + // zero out the slop so that the sanity checker can tell
|
|
| 364 | + // where the next closure is. N.B. We mustn't do this until we have
|
|
| 365 | + // pushed the free variables to the update remembered set above.
|
|
| 366 | + OVERWRITING_CLOSURE_SIZE(bh, closure_sizeW_(bh, INFO_PTR_TO_STRUCT(bh_info)));
|
|
| 353 | 367 | |
| 354 | - // The payload of the BLACKHOLE points to the TSO
|
|
| 355 | - RELEASE_STORE(&((StgInd *)bh)->indirectee, (StgClosure *)tso);
|
|
| 356 | - SET_INFO_RELEASE(bh,&stg_BLACKHOLE_info);
|
|
| 368 | + // The payload of the BLACKHOLE points to the TSO
|
|
| 369 | + RELEASE_STORE(&((StgInd *)bh)->indirectee, (StgClosure *)tso);
|
|
| 370 | + SET_INFO_RELEASE(bh,&stg_BLACKHOLE_info);
|
|
| 357 | 371 | |
| 358 | - // .. and we need a write barrier, since we just mutated the closure:
|
|
| 359 | - recordClosureMutated(cap,bh);
|
|
| 372 | + // .. and we need a write barrier, since we just mutated the closure:
|
|
| 373 | + recordClosureMutated(cap,bh);
|
|
| 360 | 374 | |
| 361 | - // We pretend that bh has just been created.
|
|
| 362 | - LDV_RECORD_CREATE(bh);
|
|
| 375 | + // We pretend that bh has just been created.
|
|
| 376 | + LDV_RECORD_CREATE(bh);
|
|
| 377 | + }
|
|
| 363 | 378 | |
| 364 | 379 | frame = (StgClosure *) ((StgUpdateFrame *)frame + 1);
|
| 365 | 380 | if (prev_was_update_frame) {
|
| 1 | +import Control.Exception
|
|
| 2 | +import Control.Monad.IO.Class
|
|
| 3 | +import Data.Maybe
|
|
| 4 | +import GHC
|
|
| 5 | +import GHC.Plugins
|
|
| 6 | +import GHC.Runtime.Interpreter
|
|
| 7 | +import System.Environment.Blank
|
|
| 8 | + |
|
| 9 | +main :: IO ()
|
|
| 10 | +main = do
|
|
| 11 | + [libdir] <- getArgs
|
|
| 12 | + defaultErrorHandler defaultFatalMessager defaultFlushOut $
|
|
| 13 | + runGhc (Just libdir) $
|
|
| 14 | + do
|
|
| 15 | + dflags0 <- getSessionDynFlags
|
|
| 16 | + let dflags1 =
|
|
| 17 | + dflags0
|
|
| 18 | + { ghcMode = CompManager,
|
|
| 19 | + backend = interpreterBackend,
|
|
| 20 | + ghcLink = LinkInMemory
|
|
| 21 | + }
|
|
| 22 | + logger <- getLogger
|
|
| 23 | + (dflags2, _, _) <-
|
|
| 24 | + parseDynamicFlags logger dflags1 $
|
|
| 25 | + map noLoc ["-package", "ghc"]
|
|
| 26 | + _ <- setSessionDynFlags dflags2
|
|
| 27 | + addTarget =<< guessTarget "hello.hs" Nothing Nothing
|
|
| 28 | + _ <- load LoadAllTargets
|
|
| 29 | + setContext
|
|
| 30 | + [ IIDecl $ simpleImportDecl $ mkModuleName "Prelude",
|
|
| 31 | + IIDecl $ simpleImportDecl $ mkModuleName "Main"
|
|
| 32 | + ]
|
|
| 33 | + hsc_env <- getSession
|
|
| 34 | + fhv <- compileExprRemote "main"
|
|
| 35 | + liftIO $ evalIO (fromJust $ hsc_interp hsc_env) fhv |
| 1 | +main = putStrLn "hello world" |
| ... | ... | @@ -10,3 +10,11 @@ test('T26430', [ |
| 10 | 10 | extra_hc_opts('-L. -lT26430B')]
|
| 11 | 11 | , compile_and_run, ['']
|
| 12 | 12 | )
|
| 13 | + |
|
| 14 | +test('T26431', [
|
|
| 15 | + extra_files(['../../../.gitlab/hello.hs']),
|
|
| 16 | + extra_hc_opts('-package ghc'),
|
|
| 17 | + extra_run_opts(f'"{config.libdir}"'),
|
|
| 18 | + ignore_stderr]
|
|
| 19 | +, compile_and_run, ['']
|
|
| 20 | +) |
| 1 | +{-# LANGUAGE Haskell2010 #-}
|
|
| 2 | +{-# LANGUAGE RankNTypes #-}
|
|
| 3 | +{-# LANGUAGE ScopedTypeVariables #-}
|
|
| 4 | +{-# LANGUAGE DefaultSignatures #-}
|
|
| 5 | +{-# LANGUAGE MultiParamTypeClasses #-}
|
|
| 6 | +{-# LANGUAGE TypeFamilies #-}
|
|
| 7 | + |
|
| 8 | +module T26457 where
|
|
| 9 | + |
|
| 10 | +import Data.Kind
|
|
| 11 | +import Data.Proxy
|
|
| 12 | + |
|
| 13 | +type family FC (be :: Type) (entity :: Type) :: Constraint
|
|
| 14 | + |
|
| 15 | +class Database be where
|
|
| 16 | + fun :: Proxy be -> (forall tbl. FC be tbl => Proxy tbl -> ()) -> ()
|
|
| 17 | + default fun :: Proxy be -> (forall tbl. FC be tbl => Proxy tbl -> ()) -> ()
|
|
| 18 | + fun _ _ = undefined |
| ... | ... | @@ -952,4 +952,4 @@ test('T26346', normal, compile, ['']) |
| 952 | 952 | test('T26358', expect_broken(26358), compile, [''])
|
| 953 | 953 | test('T26345', normal, compile, [''])
|
| 954 | 954 | test('T26376', normal, compile, [''])
|
| 955 | - |
|
| 955 | +test('T26457', normal, compile, ['']) |
| ... | ... | @@ -11,7 +11,6 @@ module GHC.Toolchain.Tools.Cc |
| 11 | 11 | , compileC
|
| 12 | 12 | , compileAsm
|
| 13 | 13 | , addPlatformDepCcFlags
|
| 14 | - , checkC99Support
|
|
| 15 | 14 | ) where
|
| 16 | 15 | |
| 17 | 16 | import Control.Monad
|
| ... | ... | @@ -51,12 +50,8 @@ findCc archOs llvmTarget progOpt = do |
| 51 | 50 | cc1 <- ignoreUnusedArgs cc0
|
| 52 | 51 | cc2 <- ccSupportsTarget archOs llvmTarget cc1
|
| 53 | 52 | checking "whether Cc works" $ checkCcWorks cc2
|
| 54 | - cc3 <- oneOf "cc doesn't support C99" $ map checkC99Support
|
|
| 55 | - [ cc2
|
|
| 56 | - , cc2 & _ccFlags %++ "-std=gnu99"
|
|
| 57 | - ]
|
|
| 58 | - checkCcSupportsExtraViaCFlags cc3
|
|
| 59 | - return cc3
|
|
| 53 | + checkCcSupportsExtraViaCFlags cc2
|
|
| 54 | + return cc2
|
|
| 60 | 55 | |
| 61 | 56 | checkCcWorks :: Cc -> M ()
|
| 62 | 57 | checkCcWorks cc = withTempDir $ \dir -> do
|
| ... | ... | @@ -88,17 +83,6 @@ ccSupportsTarget archOs target cc = |
| 88 | 83 | checking "whether Cc supports --target" $
|
| 89 | 84 | supportsTarget archOs _ccProgram checkCcWorks target cc
|
| 90 | 85 | |
| 91 | -checkC99Support :: Cc -> M Cc
|
|
| 92 | -checkC99Support cc = checking "for C99 support" $ withTempDir $ \dir -> do
|
|
| 93 | - let test_o = dir </> "test.o"
|
|
| 94 | - compileC cc test_o $ unlines
|
|
| 95 | - [ "#include <stdio.h>"
|
|
| 96 | - , "#if !defined __STDC_VERSION__ || __STDC_VERSION__ < 199901L"
|
|
| 97 | - , "# error \"Compiler does not advertise C99 conformance\""
|
|
| 98 | - , "#endif"
|
|
| 99 | - ]
|
|
| 100 | - return cc
|
|
| 101 | - |
|
| 102 | 86 | checkCcSupportsExtraViaCFlags :: Cc -> M ()
|
| 103 | 87 | checkCcSupportsExtraViaCFlags cc = checking "whether cc supports extra via-c flags" $ withTempDir $ \dir -> do
|
| 104 | 88 | let test_o = dir </> "test.o"
|
| ... | ... | @@ -19,7 +19,7 @@ import GHC.Toolchain.Prelude |
| 19 | 19 | import GHC.Toolchain.Program
|
| 20 | 20 | |
| 21 | 21 | import GHC.Toolchain.Tools.Cc
|
| 22 | -import GHC.Toolchain.Utils (withTempDir, oneOf, expectFileExists)
|
|
| 22 | +import GHC.Toolchain.Utils (withTempDir, expectFileExists)
|
|
| 23 | 23 | |
| 24 | 24 | newtype Cpp = Cpp { cppProgram :: Program
|
| 25 | 25 | }
|
| ... | ... | @@ -160,13 +160,7 @@ findJsCpp progOpt cc = checking "for JavaScript C preprocessor" $ do |
| 160 | 160 | findCmmCpp :: ProgOpt -> Cc -> M CmmCpp
|
| 161 | 161 | findCmmCpp progOpt cc = checking "for a Cmm preprocessor" $ do
|
| 162 | 162 | -- Use the specified CPP or try to use the c compiler
|
| 163 | - foundCppProg <- findProgram "Cmm preprocessor" progOpt [] <|> pure (programFromOpt progOpt (prgPath $ ccProgram cc) [])
|
|
| 164 | - -- Check whether the C preprocessor needs -std=gnu99 (only very old toolchains need this)
|
|
| 165 | - Cc cpp <- oneOf "cc doesn't support C99" $ map checkC99Support
|
|
| 166 | - [ Cc foundCppProg
|
|
| 167 | - , Cc (foundCppProg & _prgFlags %++ "-std=gnu99")
|
|
| 168 | - ]
|
|
| 169 | - |
|
| 163 | + cpp <- findProgram "Cmm preprocessor" progOpt [] <|> pure (programFromOpt progOpt (prgPath $ ccProgram cc) [])
|
|
| 170 | 164 | cmmCppSupportsG0 <- withTempDir $ \dir -> do
|
| 171 | 165 | let conftest = dir </> "conftest.c"
|
| 172 | 166 | writeFile conftest "int main(void) {}"
|
| ... | ... | @@ -181,14 +175,9 @@ findCmmCpp progOpt cc = checking "for a Cmm preprocessor" $ do |
| 181 | 175 | findCpp :: ProgOpt -> Cc -> M Cpp
|
| 182 | 176 | findCpp progOpt cc = checking "for C preprocessor" $ do
|
| 183 | 177 | -- Use the specified CPP or try to use the c compiler
|
| 184 | - foundCppProg <- findProgram "C preprocessor" progOpt [] <|> pure (programFromOpt progOpt (prgPath $ ccProgram cc) [])
|
|
| 185 | - -- Check whether the C preprocessor needs -std=gnu99 (only very old toolchains need this)
|
|
| 186 | - Cc cpp2 <- oneOf "cc doesn't support C99" $ map checkC99Support
|
|
| 187 | - [ Cc foundCppProg
|
|
| 188 | - , Cc (foundCppProg & _prgFlags %++ "-std=gnu99")
|
|
| 189 | - ]
|
|
| 178 | + cpp <- findProgram "C preprocessor" progOpt [] <|> pure (programFromOpt progOpt (prgPath $ ccProgram cc) [])
|
|
| 190 | 179 | -- Always add the -E flag to the CPP, regardless of the user options
|
| 191 | - let cppProgram = addFlagIfNew "-E" cpp2
|
|
| 180 | + let cppProgram = addFlagIfNew "-E" cpp
|
|
| 192 | 181 | return Cpp{cppProgram}
|
| 193 | 182 | |
| 194 | 183 | --------------------------------------------------------------------------------
|