Implement s390x LLVM backend.
authorStefan Schulze Frielinghaus <stefansf@linux.ibm.com>
Tue, 8 Oct 2019 10:32:15 +0000 (12:32 +0200)
committerMarge Bot <ben+marge-bot@smart-cactus.org>
Tue, 22 Oct 2019 06:39:03 +0000 (02:39 -0400)
This patch adds support for the s390x architecture for the LLVM code
generator. The patch includes a register mapping of STG registers onto
s390x machine registers which enables a registerised build.

27 files changed:
aclocal.m4
compiler/GHC/Platform/Regs.hs
compiler/GHC/Platform/S390X.hs [new file with mode: 0644]
compiler/ghc.cabal.in
compiler/llvmGen/LlvmCodeGen/Data.hs
compiler/nativeGen/AsmCodeGen.hs
compiler/nativeGen/RegAlloc/Graph/TrivColorable.hs
compiler/nativeGen/RegAlloc/Linear/FreeRegs.hs
compiler/nativeGen/RegAlloc/Linear/Main.hs
compiler/nativeGen/TargetReg.hs
configure.ac
hadrian/src/Oracles/Flag.hs
includes/CodeGen.Platform.hs
includes/stg/MachRegs.h
includes/stg/MachRegsForHost.h
includes/stg/SMP.h
libraries/ghc-boot/GHC/Platform.hs
libraries/ghci/GHCi/InfoTable.hsc
llvm-targets
mk/config.mk.in
rts/Capability.h
rts/Libdw.c
rts/StgCRunAsm.S
rts/ghc.mk
rts/linker/Elf.c
rts/rts.cabal.in
utils/llvm-targets/gen-data-layout.sh

index fd115e4..ab66dfe 100644 (file)
@@ -195,6 +195,9 @@ AC_DEFUN([FPTOOLS_SET_HASKELL_PLATFORM_VARS],
         powerpc64le)
             test -z "[$]2" || eval "[$]2=\"ArchPPC_64 {ppc_64ABI = ELF_V2}\""
             ;;
+        s390x)
+            test -z "[$]2" || eval "[$]2=ArchS390X"
+            ;;
         sparc)
             test -z "[$]2" || eval "[$]2=ArchSPARC"
             ;;
@@ -217,7 +220,7 @@ AC_DEFUN([FPTOOLS_SET_HASKELL_PLATFORM_VARS],
         mipsel)
             test -z "[$]2" || eval "[$]2=ArchMipsel"
             ;;
-        hppa|hppa1_1|ia64|m68k|nios2|riscv32|riscv64|rs6000|s390|s390x|sh4|vax)
+        hppa|hppa1_1|ia64|m68k|nios2|riscv32|riscv64|rs6000|s390|sh4|vax)
             test -z "[$]2" || eval "[$]2=ArchUnknown"
             ;;
         *)
index e7887fb..fe6588d 100644 (file)
@@ -12,6 +12,7 @@ import Reg
 import qualified GHC.Platform.ARM        as ARM
 import qualified GHC.Platform.ARM64      as ARM64
 import qualified GHC.Platform.PPC        as PPC
+import qualified GHC.Platform.S390X      as S390X
 import qualified GHC.Platform.SPARC      as SPARC
 import qualified GHC.Platform.X86        as X86
 import qualified GHC.Platform.X86_64     as X86_64
@@ -27,6 +28,7 @@ callerSaves platform
  = case platformArch platform of
    ArchX86    -> X86.callerSaves
    ArchX86_64 -> X86_64.callerSaves
+   ArchS390X  -> S390X.callerSaves
    ArchSPARC  -> SPARC.callerSaves
    ArchARM {} -> ARM.callerSaves
    ArchARM64  -> ARM64.callerSaves
@@ -48,6 +50,7 @@ activeStgRegs platform
  = case platformArch platform of
    ArchX86    -> X86.activeStgRegs
    ArchX86_64 -> X86_64.activeStgRegs
+   ArchS390X  -> S390X.activeStgRegs
    ArchSPARC  -> SPARC.activeStgRegs
    ArchARM {} -> ARM.activeStgRegs
    ArchARM64  -> ARM64.activeStgRegs
@@ -64,6 +67,7 @@ haveRegBase platform
  = case platformArch platform of
    ArchX86    -> X86.haveRegBase
    ArchX86_64 -> X86_64.haveRegBase
+   ArchS390X  -> S390X.haveRegBase
    ArchSPARC  -> SPARC.haveRegBase
    ArchARM {} -> ARM.haveRegBase
    ArchARM64  -> ARM64.haveRegBase
@@ -80,6 +84,7 @@ globalRegMaybe platform
  = case platformArch platform of
    ArchX86    -> X86.globalRegMaybe
    ArchX86_64 -> X86_64.globalRegMaybe
+   ArchS390X  -> S390X.globalRegMaybe
    ArchSPARC  -> SPARC.globalRegMaybe
    ArchARM {} -> ARM.globalRegMaybe
    ArchARM64  -> ARM64.globalRegMaybe
@@ -96,6 +101,7 @@ freeReg platform
  = case platformArch platform of
    ArchX86    -> X86.freeReg
    ArchX86_64 -> X86_64.freeReg
+   ArchS390X  -> S390X.freeReg
    ArchSPARC  -> SPARC.freeReg
    ArchARM {} -> ARM.freeReg
    ArchARM64  -> ARM64.freeReg
diff --git a/compiler/GHC/Platform/S390X.hs b/compiler/GHC/Platform/S390X.hs
new file mode 100644 (file)
index 0000000..8599bb6
--- /dev/null
@@ -0,0 +1,10 @@
+{-# LANGUAGE CPP #-}
+
+module GHC.Platform.S390X where
+
+import GhcPrelude
+
+#define MACHREGS_NO_REGS 0
+#define MACHREGS_s390x 1
+#include "../../../includes/CodeGen.Platform.hs"
+
index 4737d13..7e9171a 100644 (file)
@@ -285,6 +285,7 @@ Library
         GHC.Platform.ARM64
         GHC.Platform.NoRegs
         GHC.Platform.PPC
+        GHC.Platform.S390X
         GHC.Platform.SPARC
         GHC.Platform.X86
         GHC.Platform.X86_64
index 70a04e6..4c07f8e 100644 (file)
@@ -71,6 +71,7 @@ genLlvmData (sec, Statics lbl xs) = do
     label <- strCLabel_llvm lbl
     static <- mapM genData xs
     lmsec <- llvmSection sec
+    platform <- getLlvmPlatform
     let types   = map getStatType static
 
         strucTy = LMStruct types
@@ -79,7 +80,8 @@ genLlvmData (sec, Statics lbl xs) = do
         struct         = Just $ LMStaticStruc static tyAlias
         link           = linkage lbl
         align          = case sec of
-                            Section CString _ -> Just 1
+                            Section CString _ -> if (platformArch platform == ArchS390X)
+                                                    then Just 2 else Just 1
                             _                 -> Nothing
         const          = if isSecConstant sec then Constant else Global
         varDef         = LMGlobalVar label tyAlias link lmsec align const
index 4c883e7..6b85d38 100644 (file)
@@ -168,6 +168,7 @@ nativeCodeGen dflags this_mod modLoc h us cmms
       ArchX86       -> nCG' (x86NcgImpl    dflags)
       ArchX86_64    -> nCG' (x86_64NcgImpl dflags)
       ArchPPC       -> nCG' (ppcNcgImpl    dflags)
+      ArchS390X     -> panic "nativeCodeGen: No NCG for S390X"
       ArchSPARC     -> nCG' (sparcNcgImpl  dflags)
       ArchSPARC64   -> panic "nativeCodeGen: No NCG for SPARC64"
       ArchARM {}    -> panic "nativeCodeGen: No NCG for ARM"
index 5d4fd41..773db33 100644 (file)
@@ -119,6 +119,7 @@ trivColorable platform virtualRegSqueeze realRegSqueeze RcInteger conflicts excl
                             ArchAlpha     -> panic "trivColorable ArchAlpha"
                             ArchMipseb    -> panic "trivColorable ArchMipseb"
                             ArchMipsel    -> panic "trivColorable ArchMipsel"
+                            ArchS390X     -> panic "trivColorable ArchS390X"
                             ArchJavaScript-> panic "trivColorable ArchJavaScript"
                             ArchUnknown   -> panic "trivColorable ArchUnknown")
         , count2        <- accSqueeze 0 cALLOCATABLE_REGS_INTEGER
@@ -149,6 +150,7 @@ trivColorable platform virtualRegSqueeze realRegSqueeze RcFloat conflicts exclus
                             ArchAlpha     -> panic "trivColorable ArchAlpha"
                             ArchMipseb    -> panic "trivColorable ArchMipseb"
                             ArchMipsel    -> panic "trivColorable ArchMipsel"
+                            ArchS390X     -> panic "trivColorable ArchS390X"
                             ArchJavaScript-> panic "trivColorable ArchJavaScript"
                             ArchUnknown   -> panic "trivColorable ArchUnknown")
         , count2        <- accSqueeze 0 cALLOCATABLE_REGS_FLOAT
@@ -181,6 +183,7 @@ trivColorable platform virtualRegSqueeze realRegSqueeze RcDouble conflicts exclu
                             ArchAlpha     -> panic "trivColorable ArchAlpha"
                             ArchMipseb    -> panic "trivColorable ArchMipseb"
                             ArchMipsel    -> panic "trivColorable ArchMipsel"
+                            ArchS390X     -> panic "trivColorable ArchS390X"
                             ArchJavaScript-> panic "trivColorable ArchJavaScript"
                             ArchUnknown   -> panic "trivColorable ArchUnknown")
         , count2        <- accSqueeze 0 cALLOCATABLE_REGS_DOUBLE
index 5a4f1c6..0feddc6 100644 (file)
@@ -75,6 +75,7 @@ maxSpillSlots dflags
                 ArchX86       -> X86.Instr.maxSpillSlots dflags
                 ArchX86_64    -> X86.Instr.maxSpillSlots dflags
                 ArchPPC       -> PPC.Instr.maxSpillSlots dflags
+                ArchS390X     -> panic "maxSpillSlots ArchS390X"
                 ArchSPARC     -> SPARC.Instr.maxSpillSlots dflags
                 ArchSPARC64   -> panic "maxSpillSlots ArchSPARC64"
                 ArchARM _ _ _ -> panic "maxSpillSlots ArchARM"
index cdaf738..eac9194 100644 (file)
@@ -211,6 +211,7 @@ linearRegAlloc dflags entry_ids block_live sccs
  = case platformArch platform of
       ArchX86        -> go $ (frInitFreeRegs platform :: X86.FreeRegs)
       ArchX86_64     -> go $ (frInitFreeRegs platform :: X86_64.FreeRegs)
+      ArchS390X      -> panic "linearRegAlloc ArchS390X"
       ArchSPARC      -> go $ (frInitFreeRegs platform :: SPARC.FreeRegs)
       ArchSPARC64    -> panic "linearRegAlloc ArchSPARC64"
       ArchPPC        -> go $ (frInitFreeRegs platform :: PPC.FreeRegs)
index da39b63..e0eca92 100644 (file)
@@ -44,6 +44,7 @@ targetVirtualRegSqueeze platform
       ArchX86       -> X86.virtualRegSqueeze
       ArchX86_64    -> X86.virtualRegSqueeze
       ArchPPC       -> PPC.virtualRegSqueeze
+      ArchS390X     -> panic "targetVirtualRegSqueeze ArchS390X"
       ArchSPARC     -> SPARC.virtualRegSqueeze
       ArchSPARC64   -> panic "targetVirtualRegSqueeze ArchSPARC64"
       ArchPPC_64 _  -> PPC.virtualRegSqueeze
@@ -62,6 +63,7 @@ targetRealRegSqueeze platform
       ArchX86       -> X86.realRegSqueeze
       ArchX86_64    -> X86.realRegSqueeze
       ArchPPC       -> PPC.realRegSqueeze
+      ArchS390X     -> panic "targetRealRegSqueeze ArchS390X"
       ArchSPARC     -> SPARC.realRegSqueeze
       ArchSPARC64   -> panic "targetRealRegSqueeze ArchSPARC64"
       ArchPPC_64 _  -> PPC.realRegSqueeze
@@ -79,6 +81,7 @@ targetClassOfRealReg platform
       ArchX86       -> X86.classOfRealReg platform
       ArchX86_64    -> X86.classOfRealReg platform
       ArchPPC       -> PPC.classOfRealReg
+      ArchS390X     -> panic "targetClassOfRealReg ArchS390X"
       ArchSPARC     -> SPARC.classOfRealReg
       ArchSPARC64   -> panic "targetClassOfRealReg ArchSPARC64"
       ArchPPC_64 _  -> PPC.classOfRealReg
@@ -96,6 +99,7 @@ targetMkVirtualReg platform
       ArchX86       -> X86.mkVirtualReg
       ArchX86_64    -> X86.mkVirtualReg
       ArchPPC       -> PPC.mkVirtualReg
+      ArchS390X     -> panic "targetMkVirtualReg ArchS390X"
       ArchSPARC     -> SPARC.mkVirtualReg
       ArchSPARC64   -> panic "targetMkVirtualReg ArchSPARC64"
       ArchPPC_64 _  -> PPC.mkVirtualReg
@@ -113,6 +117,7 @@ targetRegDotColor platform
       ArchX86       -> X86.regDotColor platform
       ArchX86_64    -> X86.regDotColor platform
       ArchPPC       -> PPC.regDotColor
+      ArchS390X     -> panic "targetRegDotColor ArchS390X"
       ArchSPARC     -> SPARC.regDotColor
       ArchSPARC64   -> panic "targetRegDotColor ArchSPARC64"
       ArchPPC_64 _  -> PPC.regDotColor
index f1c9269..46e1fdd 100644 (file)
@@ -244,7 +244,7 @@ dnl --------------------------------------------------------------
 
 AC_MSG_CHECKING(whether target supports a registerised ABI)
 case "$TargetArch" in
-    i386|x86_64|powerpc|powerpc64|powerpc64le|arm|aarch64)
+    i386|x86_64|powerpc|powerpc64|powerpc64le|s390x|arm|aarch64)
         UnregisterisedDefault=NO
         AC_MSG_RESULT([yes])
         ;;
@@ -279,7 +279,7 @@ AC_MSG_CHECKING(whether target supports tables next to code)
 case "$Unregisterised" in
     NO)
         case "$TargetArch" in
-            ia64|powerpc64|powerpc64le)
+            ia64|powerpc64|powerpc64le|s390x)
                 TablesNextToCodeDefault=NO
                 AC_MSG_RESULT([no])
                 ;;
@@ -308,7 +308,7 @@ AC_SUBST(TablesNextToCode)
 dnl ** Does target have runtime linker support?
 dnl --------------------------------------------------------------
 case "$target" in
-    powerpc64-*|powerpc64le-*|powerpc-ibm-aix*)
+    powerpc64-*|powerpc64le-*|powerpc-ibm-aix*|s390x-ibm-linux)
         TargetHasRTSLinker=NO
         ;;
     *)
index 93babda..134edc7 100644 (file)
@@ -59,7 +59,7 @@ platformSupportsSharedLibs = do
 
 ghcWithSMP :: Action Bool
 ghcWithSMP = do
-    goodArch <- anyTargetArch ["i386", "x86_64", "sparc", "powerpc", "arm"]
+    goodArch <- anyTargetArch ["i386", "x86_64", "sparc", "powerpc", "arm", "s390x"]
     ghcUnreg <- flag GhcUnregisterised
     return $ goodArch && not ghcUnreg
 
index 99d774b..b108a61 100644 (file)
@@ -344,6 +344,42 @@ import Reg
 # define f30 62
 # define f31 63
 
+#elif defined(MACHREGS_s390x)
+
+# define r0   0
+# define r1   1
+# define r2   2
+# define r3   3
+# define r4   4
+# define r5   5
+# define r6   6
+# define r7   7
+# define r8   8
+# define r9   9
+# define r10 10
+# define r11 11
+# define r12 12
+# define r13 13
+# define r14 14
+# define r15 15
+
+# define f0  16
+# define f1  17
+# define f2  18
+# define f3  19
+# define f4  20
+# define f5  21
+# define f6  22
+# define f7  23
+# define f8  24
+# define f9  25
+# define f10 26
+# define f11 27
+# define f12 28
+# define f13 29
+# define f14 30
+# define f15 31
+
 #endif
 
 callerSaves :: GlobalReg -> Bool
@@ -630,7 +666,8 @@ haveRegBase = False
 globalRegMaybe :: GlobalReg -> Maybe RealReg
 #if defined(MACHREGS_i386) || defined(MACHREGS_x86_64) \
     || defined(MACHREGS_sparc) || defined(MACHREGS_powerpc) \
-    || defined(MACHREGS_arm) || defined(MACHREGS_aarch64)
+    || defined(MACHREGS_arm) || defined(MACHREGS_aarch64) \
+    || defined(MACHREGS_s390x)
 # if defined(REG_Base)
 globalRegMaybe BaseReg                  = Just (RealRegSingle REG_Base)
 # endif
index 0afc881..ea1125b 100644 (file)
@@ -589,6 +589,78 @@ the stack. See Note [Overlapping global registers] for implications.
 #define REG_D3          d14
 #define REG_D4          d15
 
+/* -----------------------------------------------------------------------------
+   The s390x register mapping
+
+   Register    | Role(s)                                 | Call effect
+   ------------+-------------------------------------+-----------------
+   r0,r1       | -                                       | caller-saved
+   r2          | Argument / return value                 | caller-saved
+   r3,r4,r5    | Arguments                               | caller-saved
+   r6          | Argument                                | callee-saved
+   r7...r11    | -                                       | callee-saved
+   r12         | (Commonly used as GOT pointer)          | callee-saved
+   r13         | (Commonly used as literal pool pointer) | callee-saved
+   r14         | Return address                          | caller-saved
+   r15         | Stack pointer                           | callee-saved
+   f0          | Argument / return value                 | caller-saved
+   f2,f4,f6    | Arguments                               | caller-saved
+   f1,f3,f5,f7 | -                                       | caller-saved
+   f8...f15    | -                                       | callee-saved
+   v0...v31    | -                                       | caller-saved
+
+   Each general purpose register r0 through r15 as well as each floating-point
+   register f0 through f15 is 64 bits wide. Each vector register v0 through v31
+   is 128 bits wide.
+
+   Note, the vector registers v0 through v15 overlap with the floating-point
+   registers f0 through f15.
+
+   -------------------------------------------------------------------------- */
+
+#elif defined(MACHREGS_s390x)
+
+#define REG(x) __asm__("%" #x)
+
+#define REG_Base        r7
+#define REG_Sp          r8
+#define REG_Hp          r10
+#define REG_R1          r11
+#define REG_R2          r12
+#define REG_R3          r13
+#define REG_R4          r6
+#define REG_R5          r2
+#define REG_R6          r3
+#define REG_R7          r4
+#define REG_R8          r5
+#define REG_SpLim       r9
+#define REG_MachSp      r15
+
+#define REG_F1          f8
+#define REG_F2          f9
+#define REG_F3          f10
+#define REG_F4          f11
+#define REG_F5          f0
+#define REG_F6          f1
+
+#define REG_D1          f12
+#define REG_D2          f13
+#define REG_D3          f14
+#define REG_D4          f15
+#define REG_D5          f2
+#define REG_D6          f3
+
+#define CALLER_SAVES_R5
+#define CALLER_SAVES_R6
+#define CALLER_SAVES_R7
+#define CALLER_SAVES_R8
+
+#define CALLER_SAVES_F5
+#define CALLER_SAVES_F6
+
+#define CALLER_SAVES_D5
+#define CALLER_SAVES_D6
+
 #else
 
 #error Cannot find platform to give register info for
index 135c797..3597b2b 100644 (file)
 #define MACHREGS_darwin   1
 #endif
 
+#if defined(s390x_HOST_ARCH)
+#define MACHREGS_s390x    1
+#endif
+
 #endif
 
 #include "MachRegs.h"
index 4be11d1..2d6a220 100644 (file)
@@ -336,6 +336,8 @@ write_barrier(void) {
 #elif defined(powerpc_HOST_ARCH) || defined(powerpc64_HOST_ARCH) \
     || defined(powerpc64le_HOST_ARCH)
     __asm__ __volatile__ ("lwsync" : : : "memory");
+#elif defined(s390x_HOST_ARCH)
+    __asm__ __volatile__ ("" : : : "memory");
 #elif defined(sparc_HOST_ARCH)
     /* Sparc in TSO mode does not require store/store barriers. */
     __asm__ __volatile__ ("" : : : "memory");
@@ -357,6 +359,8 @@ store_load_barrier(void) {
 #elif defined(powerpc_HOST_ARCH) || defined(powerpc64_HOST_ARCH) \
     || defined(powerpc64le_HOST_ARCH)
     __asm__ __volatile__ ("sync" : : : "memory");
+#elif defined(s390x_HOST_ARCH)
+    __asm__ __volatile__ ("bcr 14,0" : : : "memory");
 #elif defined(sparc_HOST_ARCH)
     __asm__ __volatile__ ("membar #StoreLoad" : : : "memory");
 #elif defined(arm_HOST_ARCH)
@@ -379,6 +383,8 @@ load_load_barrier(void) {
 #elif defined(powerpc_HOST_ARCH) || defined(powerpc64_HOST_ARCH) \
     || defined(powerpc64le_HOST_ARCH)
     __asm__ __volatile__ ("lwsync" : : : "memory");
+#elif defined(s390x_HOST_ARCH)
+    __asm__ __volatile__ ("" : : : "memory");
 #elif defined(sparc_HOST_ARCH)
     /* Sparc in TSO mode does not require load/load barriers. */
     __asm__ __volatile__ ("" : : : "memory");
index 8e4ae5f..341b551 100644 (file)
@@ -106,6 +106,7 @@ data Arch
         | ArchPPC_64
           { ppc_64ABI :: PPC_64ABI
           }
+        | ArchS390X
         | ArchSPARC
         | ArchSPARC64
         | ArchARM
@@ -145,6 +146,7 @@ stringEncodeArch = \case
   ArchPPC_64 { ppc_64ABI = abi } -> case abi of
     ELF_V1 -> "powerpc64"
     ELF_V2 -> "powerpc64le"
+  ArchS390X -> "s390x"
   ArchSPARC -> "sparc"
   ArchSPARC64 -> "sparc64"
   ArchARM { armISA = isa, armISAExt = _, armABI = _ } -> "arm" ++ vsuf
index ab13485..587e39b 100644 (file)
@@ -76,6 +76,7 @@ data Arch = ArchSPARC
           | ArchARM64
           | ArchPPC64
           | ArchPPC64LE
+          | ArchS390X
           | ArchUnknown
  deriving Show
 
@@ -99,6 +100,8 @@ platform =
        ArchPPC64
 #elif defined(powerpc64le_HOST_ARCH)
        ArchPPC64LE
+#elif defined(s390x_HOST_ARCH)
+       ArchS390X
 #else
 #    if defined(TABLES_NEXT_TO_CODE)
 #        error Unimplemented architecture
@@ -268,6 +271,20 @@ mkJumpToAddr a = case platform of
                    0x618C0000 .|. lo16 w32,
                    0x7D8903A6, 0x4E800420 ]
 
+    ArchS390X ->
+        -- Let 0xAABBCCDDEEFFGGHH be the address to jump to.
+        -- The following code loads the address into scratch
+        -- register r1 and jumps to it.
+        --
+        --    0:   C0 1E AA BB CC DD       llihf   %r1,0xAABBCCDD
+        --    6:   C0 19 EE FF GG HH       iilf    %r1,0xEEFFGGHH
+        --   12:   07 F1                   br      %r1
+
+        let w64 = fromIntegral (funPtrToInt a) :: Word64
+        in Left [ 0xC0, 0x1E, byte7 w64, byte6 w64, byte5 w64, byte4 w64,
+                  0xC0, 0x19, byte3 w64, byte2 w64, byte1 w64, byte0 w64,
+                  0x07, 0xF1 ]
+
     -- This code must not be called. You either need to
     -- add your architecture as a distinct case or
     -- use non-TABLES_NEXT_TO_CODE mode
index 8f5717d..9cf9698 100644 (file)
@@ -33,6 +33,7 @@
 ,("powerpc64le-unknown-linux-gnu", ("e-m:e-i64:64-n32:64", "ppc64le", ""))
 ,("powerpc64le-unknown-linux-musl", ("e-m:e-i64:64-n32:64", "ppc64le", ""))
 ,("powerpc64le-unknown-linux", ("e-m:e-i64:64-n32:64", "ppc64le", ""))
+,("s390x-ibm-linux", ("E-m:e-i1:8:16-i8:8:16-i64:64-f128:64-a:8:16-n32:64", "z10", ""))
 ,("i386-apple-darwin", ("e-m:o-p:32:32-f64:32:64-f80:128-n8:16:32-S128", "yonah", ""))
 ,("x86_64-apple-darwin", ("e-m:o-i64:64-f80:128-n8:16:32:64-S128", "core2", ""))
 ,("armv7-apple-ios", ("e-m:o-p:32:32-f64:32:64-v64:32:64-v128:32:128-a:0:32-n32-S32", "generic", ""))
index 8bbfde2..05ad6ad 100644 (file)
@@ -192,7 +192,7 @@ ifeq "$(TargetArch_CPP)" "arm"
 # We don't support load/store barriers pre-ARMv7. See #10433.
 ArchSupportsSMP=$(if $(filter $(ARM_ISA),ARMv5 ARMv6),NO,YES)
 else
-ArchSupportsSMP=$(strip $(patsubst $(TargetArch_CPP), YES, $(findstring $(TargetArch_CPP), i386 x86_64 sparc powerpc powerpc64 powerpc64le aarch64)))
+ArchSupportsSMP=$(strip $(patsubst $(TargetArch_CPP), YES, $(findstring $(TargetArch_CPP), i386 x86_64 sparc powerpc powerpc64 powerpc64le s390x aarch64)))
 endif
 
 # The THREADED_RTS requires `BaseReg` to be in a register and the
@@ -365,7 +365,7 @@ FFIIncludeDir=@FFIIncludeDir@
 
 # GHC needs arch-specific tweak at least in
 #     rts/Libdw.c:set_initial_registers()
-GhcRtsWithLibdw=$(strip $(if $(filter $(TargetArch_CPP),i386 x86_64),@UseLibdw@,NO))
+GhcRtsWithLibdw=$(strip $(if $(filter $(TargetArch_CPP),i386 x86_64 s390x),@UseLibdw@,NO))
 
 ################################################################################
 #
index 2a5f127..0833006 100644 (file)
@@ -160,7 +160,9 @@ struct Capability_ {
 } // typedef Capability is defined in RtsAPI.h
   // We never want a Capability to overlap a cache line with anything
   // else, so round it up to a cache line size:
-#if !defined(mingw32_HOST_OS)
+#if defined(s390x_HOST_ARCH)
+  ATTRIBUTE_ALIGNED(256)
+#elif !defined(mingw32_HOST_OS)
   ATTRIBUTE_ALIGNED(64)
 #endif
   ;
index 33a40a1..d45d9d0 100644 (file)
@@ -330,6 +330,35 @@ static bool set_initial_registers(Dwfl_Thread *thread,
         );
     return dwfl_thread_state_registers(thread, 0, 9, regs);
 }
+#elif defined(s390x_HOST_ARCH)
+static bool set_initial_registers(Dwfl_Thread *thread,
+                                  void *arg STG_UNUSED) {
+    Dwarf_Word regs[32];
+    __asm__ ("stmg %%r0,%%r15,0(%0)\n\t"
+             "std  %%f0,  128(0,%0)\n\t"
+             "std  %%f2,  136(0,%0)\n\t"
+             "std  %%f4,  144(0,%0)\n\t"
+             "std  %%f6,  152(0,%0)\n\t"
+             "std  %%f1,  160(0,%0)\n\t"
+             "std  %%f3,  168(0,%0)\n\t"
+             "std  %%f5,  176(0,%0)\n\t"
+             "std  %%f7,  184(0,%0)\n\t"
+             "std  %%f8,  192(0,%0)\n\t"
+             "std  %%f10, 200(0,%0)\n\t"
+             "std  %%f12, 208(0,%0)\n\t"
+             "std  %%f14, 216(0,%0)\n\t"
+             "std  %%f9,  224(0,%0)\n\t"
+             "std  %%f11, 232(0,%0)\n\t"
+             "std  %%f13, 240(0,%0)\n\t"
+             "std  %%f15, 248(0,%0)\n\t"
+             "larl %%r0,0\n\t"
+             "stg  %%r0,  112(0,%0)\n\t"
+             :                            /* no output */
+             :"r" (&regs[0])              /* input */
+             :"%r0"                       /* clobbered */
+        );
+    return dwfl_thread_state_registers(thread, 0, 32, regs);
+}
 #else
 #    error "Please implement set_initial_registers() for your arch"
 #endif
index 1dd74d3..946f577 100644 (file)
@@ -180,4 +180,96 @@ StgReturn:
        blr
 
 # endif // aix_HOST_OS
+
+#elif defined(s390x_HOST_ARCH)
+# define STACK_FRAME_SIZE (RESERVED_C_STACK_BYTES+160)
+       .text
+       .align 8
+       .globl StgRun
+       .type StgRun, @function
+StgRun:
+       .cfi_startproc
+       /* save callee-saved registers */
+       stmg %r6,%r14,16(%r15)
+       std  %f8,     88(%r15)
+       std  %f9,     96(%r15)
+       std  %f10,   104(%r15)
+       std  %f11,   112(%r15)
+       std  %f12,   120(%r15)
+       std  %f13,   128(%r15)
+       std  %f14,   136(%r15)
+       std  %f15,   144(%r15)
+       .cfi_offset  6, -144
+       .cfi_offset  7, -136
+       .cfi_offset  8, -128
+       .cfi_offset  9, -120
+       .cfi_offset 10, -112
+       .cfi_offset 11, -104
+       .cfi_offset 12,  -96
+       .cfi_offset 13,  -88
+       .cfi_offset 14,  -80
+       .cfi_offset 15,  -72
+       .cfi_offset 24,  -64
+       .cfi_offset 28,  -56
+       .cfi_offset 25,  -48
+       .cfi_offset 29,  -40
+       .cfi_offset 26,  -32
+       .cfi_offset 30,  -24
+       .cfi_offset 27,  -16
+       .cfi_offset 31,   -8
+       /* allocate stack frame */
+       aghi %r15,-STACK_FRAME_SIZE
+       .cfi_def_cfa_offset -(STACK_FRAME_SIZE+160)
+       /* set STGs BaseReg from S390Xs r3 */
+       lgr  %r7,%r3
+       /* jump to STG function */
+       br   %r2
+       .cfi_endproc
+       .size StgRun, .-StgRun
+
+       .text
+       .align 8
+       .globl StgReturn
+       .type StgReturn, @function
+StgReturn:
+       .cfi_startproc
+       /* set return value from STGs R1 (S390Xs r11) */
+       lgr  %r2,%r11
+       /* deallocate stack frame */
+       aghi %r15,STACK_FRAME_SIZE
+       .cfi_def_cfa_offset (STACK_FRAME_SIZE+160)
+       /* restore callee-saved registers */
+       lmg  %r6,%r14, 16(%r15)
+       ld   %f8,      88(%r15)
+       ld   %f9,      96(%r15)
+       ld   %f10,    104(%r15)
+       ld   %f11,    112(%r15)
+       ld   %f12,    120(%r15)
+       ld   %f13,    128(%r15)
+       ld   %f14,    136(%r15)
+       ld   %f15,    144(%r15)
+       .cfi_restore  6
+       .cfi_restore  7
+       .cfi_restore  8
+       .cfi_restore  9
+       .cfi_restore 10
+       .cfi_restore 11
+       .cfi_restore 12
+       .cfi_restore 13
+       .cfi_restore 14
+       .cfi_restore 24
+       .cfi_restore 28
+       .cfi_restore 25
+       .cfi_restore 29
+       .cfi_restore 26
+       .cfi_restore 30
+       .cfi_restore 27
+       .cfi_restore 31
+       .cfi_def_cfa 15, 160
+       /* jump back to caller of StgRun() */
+       br   %r14
+       .cfi_endproc
+       .size StgReturn, .-StgReturn
+
+       .section        .note.GNU-stack,"",@progbits
 #endif
index c07cfae..dca22fb 100644 (file)
@@ -55,7 +55,7 @@ ifneq "$(findstring $(TargetArch_CPP), i386 powerpc powerpc64)" ""
 rts_S_SRCS += rts/AdjustorAsm.S
 endif
 # this matches substrings of powerpc64le, including "powerpc" and "powerpc64"
-ifneq "$(findstring $(TargetArch_CPP), powerpc64le)" ""
+ifneq "$(findstring $(TargetArch_CPP), powerpc64le s390x)" ""
 # unregisterised builds use the mini interpreter
 ifneq "$(GhcUnregisterised)" "YES"
 rts_S_SRCS += rts/StgCRunAsm.S
index 0882f8d..79786cc 100644 (file)
@@ -391,6 +391,12 @@ ocVerifyImage_ELF ( ObjectCode* oc )
                      oc->fileName);
           return 0;
 #endif
+#if defined(EM_S390)
+      case EM_S390:  IF_DEBUG(linker,debugBelch( "s390" ));
+          errorBelch("%s: RTS linker not implemented on s390",
+                     oc->fileName);
+          return 0;
+#endif
 #if defined(EM_X86_64)
       case EM_X86_64: IF_DEBUG(linker,debugBelch( "x86_64" )); break;
 #elif defined(EM_AMD64)
index 99f1e72..30c829a 100644 (file)
@@ -370,7 +370,7 @@ library
 
     if arch(i386) || arch(powerpc) || arch(powerpc64)
        asm-sources: AdjustorAsm.S
-    if arch(powerpc) || arch(powerpc64) || arch(powerpc64le)
+    if arch(powerpc) || arch(powerpc64) || arch(powerpc64le) || arch(s390x)
        asm-sources: StgCRunAsm.S
 
     c-sources: Adjustor.c
index a73da49..4f4a1ef 100755 (executable)
@@ -70,6 +70,8 @@ TARGETS=(
     "powerpc64le-unknown-linux-gnu"
     "powerpc64le-unknown-linux-musl"
     "powerpc64le-unknown-linux"
+    # Linux s390x
+    "s390x-ibm-linux"
 
     #########################
     # Darwin