From d2872dbe8f4f855bfeef1f7de57454c3713bdfef Mon Sep 17 00:00:00 2001
From: Cheng Shao <terrorjack@type.dance>
Date: Fri, 4 Oct 2024 20:23:08 +0000
Subject: [PATCH] compiler: fix checkNonStdWay for targets that require dynamic
 libraries

This commit fixes checkNonStdWay to ensure that for targets whose RTS
linker can only load dynamic code, the dynamic way of object is
selected.

(cherry picked from commit 94ef949ef8b52cebaf8d4a81d7a169e100da2a73)
---
 compiler/GHC/Linker/Deps.hs   | 11 +++++++++++
 compiler/GHC/Linker/Loader.hs |  1 +
 2 files changed, 12 insertions(+)

diff --git a/compiler/GHC/Linker/Deps.hs b/compiler/GHC/Linker/Deps.hs
index e23b68d7c7a..a6736c8bc16 100644
--- a/compiler/GHC/Linker/Deps.hs
+++ b/compiler/GHC/Linker/Deps.hs
@@ -60,6 +60,7 @@ import System.Directory
 
 data LinkDepsOpts = LinkDepsOpts
   { ldObjSuffix   :: !String                        -- ^ Suffix of .o files
+  , ldForceDyn    :: !Bool                          -- ^ Always use .dyn_o?
   , ldOneShotMode :: !Bool                          -- ^ Is the driver in one-shot mode?
   , ldModuleGraph :: !ModuleGraph                   -- ^ Module graph
   , ldUnitEnv     :: !UnitEnv                       -- ^ Unit environment
@@ -349,6 +350,16 @@ throwProgramError opts doc = throwGhcExceptionIO (ProgramError (renderWithContex
 
 checkNonStdWay :: LinkDepsOpts -> Interp -> SrcSpan -> IO (Maybe FilePath)
 checkNonStdWay _opts interp _srcspan
+  -- On some targets (e.g. wasm) the RTS linker only supports loading
+  -- dynamic code, in which case we need to ensure the .dyn_o object
+  -- is picked (instead of .o which is also present because of
+  -- -dynamic-too)
+  | ldForceDyn _opts = do
+      let target_ways = fullWays $ ldWays _opts
+      pure $ if target_ways `hasWay` WayDyn
+        then Nothing
+        else Just $ waysTag (WayDyn `addWay` target_ways) ++ "_o"
+
   | ExternalInterp {} <- interpInstance interp = return Nothing
     -- with -fexternal-interpreter we load the .o files, whatever way
     -- they were built.  If they were built for a non-std way, then
diff --git a/compiler/GHC/Linker/Loader.hs b/compiler/GHC/Linker/Loader.hs
index bcf4ba9cc59..adc729f31ed 100644
--- a/compiler/GHC/Linker/Loader.hs
+++ b/compiler/GHC/Linker/Loader.hs
@@ -637,6 +637,7 @@ initLinkDepsOpts hsc_env = opts
   where
     opts = LinkDepsOpts
             { ldObjSuffix   = objectSuf dflags
+            , ldForceDyn    = sTargetRTSLinkerOnlySupportsSharedLibs $ settings dflags
             , ldOneShotMode = isOneShot (ghcMode dflags)
             , ldModuleGraph = hsc_mod_graph hsc_env
             , ldUnitEnv     = hsc_unit_env hsc_env
-- 
GitLab