summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorStefan Schulze Frielinghaus <stefansf@linux.ibm.com>2019-10-08 12:32:15 +0200
committerMarge Bot <ben+marge-bot@smart-cactus.org>2019-10-22 02:39:03 -0400
commitfd8b666acfee5524a2d7c8b845a3782f6a89bec7 (patch)
tree4ce0d732ef341bcffa721f6d25f2cf4dcd476fd8
parentaa31ceaf7568802590f73a740ffbc8b800096342 (diff)
downloadhaskell-fd8b666acfee5524a2d7c8b845a3782f6a89bec7.tar.gz
Implement s390x LLVM backend.
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.
-rw-r--r--aclocal.m45
-rw-r--r--compiler/GHC/Platform/Regs.hs6
-rw-r--r--compiler/GHC/Platform/S390X.hs10
-rw-r--r--compiler/ghc.cabal.in1
-rw-r--r--compiler/llvmGen/LlvmCodeGen/Data.hs4
-rw-r--r--compiler/nativeGen/AsmCodeGen.hs1
-rw-r--r--compiler/nativeGen/RegAlloc/Graph/TrivColorable.hs3
-rw-r--r--compiler/nativeGen/RegAlloc/Linear/FreeRegs.hs1
-rw-r--r--compiler/nativeGen/RegAlloc/Linear/Main.hs1
-rw-r--r--compiler/nativeGen/TargetReg.hs5
-rw-r--r--configure.ac6
-rw-r--r--hadrian/src/Oracles/Flag.hs2
-rw-r--r--includes/CodeGen.Platform.hs39
-rw-r--r--includes/stg/MachRegs.h72
-rw-r--r--includes/stg/MachRegsForHost.h4
-rw-r--r--includes/stg/SMP.h6
-rw-r--r--libraries/ghc-boot/GHC/Platform.hs2
-rw-r--r--libraries/ghci/GHCi/InfoTable.hsc17
-rw-r--r--llvm-targets1
-rw-r--r--mk/config.mk.in4
-rw-r--r--rts/Capability.h4
-rw-r--r--rts/Libdw.c29
-rw-r--r--rts/StgCRunAsm.S92
-rw-r--r--rts/ghc.mk2
-rw-r--r--rts/linker/Elf.c6
-rw-r--r--rts/rts.cabal.in2
-rwxr-xr-xutils/llvm-targets/gen-data-layout.sh2
27 files changed, 315 insertions, 12 deletions
diff --git a/aclocal.m4 b/aclocal.m4
index fd115e46f8..ab66dfe35d 100644
--- a/aclocal.m4
+++ b/aclocal.m4
@@ -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"
;;
*)
diff --git a/compiler/GHC/Platform/Regs.hs b/compiler/GHC/Platform/Regs.hs
index e7887fbe72..fe6588d067 100644
--- a/compiler/GHC/Platform/Regs.hs
+++ b/compiler/GHC/Platform/Regs.hs
@@ -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
index 0000000000..8599bb67c0
--- /dev/null
+++ b/compiler/GHC/Platform/S390X.hs
@@ -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"
+
diff --git a/compiler/ghc.cabal.in b/compiler/ghc.cabal.in
index 4737d13c0b..7e9171adc9 100644
--- a/compiler/ghc.cabal.in
+++ b/compiler/ghc.cabal.in
@@ -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
diff --git a/compiler/llvmGen/LlvmCodeGen/Data.hs b/compiler/llvmGen/LlvmCodeGen/Data.hs
index 70a04e6bc9..4c07f8ee8f 100644
--- a/compiler/llvmGen/LlvmCodeGen/Data.hs
+++ b/compiler/llvmGen/LlvmCodeGen/Data.hs
@@ -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
diff --git a/compiler/nativeGen/AsmCodeGen.hs b/compiler/nativeGen/AsmCodeGen.hs
index 4c883e7185..6b85d388bb 100644
--- a/compiler/nativeGen/AsmCodeGen.hs
+++ b/compiler/nativeGen/AsmCodeGen.hs
@@ -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"
diff --git a/compiler/nativeGen/RegAlloc/Graph/TrivColorable.hs b/compiler/nativeGen/RegAlloc/Graph/TrivColorable.hs
index 5d4fd418c3..773db33293 100644
--- a/compiler/nativeGen/RegAlloc/Graph/TrivColorable.hs
+++ b/compiler/nativeGen/RegAlloc/Graph/TrivColorable.hs
@@ -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
diff --git a/compiler/nativeGen/RegAlloc/Linear/FreeRegs.hs b/compiler/nativeGen/RegAlloc/Linear/FreeRegs.hs
index 5a4f1c65a8..0feddc67d8 100644
--- a/compiler/nativeGen/RegAlloc/Linear/FreeRegs.hs
+++ b/compiler/nativeGen/RegAlloc/Linear/FreeRegs.hs
@@ -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"
diff --git a/compiler/nativeGen/RegAlloc/Linear/Main.hs b/compiler/nativeGen/RegAlloc/Linear/Main.hs
index cdaf738d68..eac9194c6a 100644
--- a/compiler/nativeGen/RegAlloc/Linear/Main.hs
+++ b/compiler/nativeGen/RegAlloc/Linear/Main.hs
@@ -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)
diff --git a/compiler/nativeGen/TargetReg.hs b/compiler/nativeGen/TargetReg.hs
index da39b635b2..e0eca9235d 100644
--- a/compiler/nativeGen/TargetReg.hs
+++ b/compiler/nativeGen/TargetReg.hs
@@ -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
diff --git a/configure.ac b/configure.ac
index f1c926903c..46e1fdd0f7 100644
--- a/configure.ac
+++ b/configure.ac
@@ -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
;;
*)
diff --git a/hadrian/src/Oracles/Flag.hs b/hadrian/src/Oracles/Flag.hs
index 93babda794..134edc706e 100644
--- a/hadrian/src/Oracles/Flag.hs
+++ b/hadrian/src/Oracles/Flag.hs
@@ -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
diff --git a/includes/CodeGen.Platform.hs b/includes/CodeGen.Platform.hs
index 99d774b02c..b108a61c0a 100644
--- a/includes/CodeGen.Platform.hs
+++ b/includes/CodeGen.Platform.hs
@@ -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
diff --git a/includes/stg/MachRegs.h b/includes/stg/MachRegs.h
index 0afc88152e..ea1125bbf8 100644
--- a/includes/stg/MachRegs.h
+++ b/includes/stg/MachRegs.h
@@ -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
diff --git a/includes/stg/MachRegsForHost.h b/includes/stg/MachRegsForHost.h
index 135c7974bd..3597b2be90 100644
--- a/includes/stg/MachRegsForHost.h
+++ b/includes/stg/MachRegsForHost.h
@@ -67,6 +67,10 @@
#define MACHREGS_darwin 1
#endif
+#if defined(s390x_HOST_ARCH)
+#define MACHREGS_s390x 1
+#endif
+
#endif
#include "MachRegs.h"
diff --git a/includes/stg/SMP.h b/includes/stg/SMP.h
index 4be11d1f64..2d6a220a9e 100644
--- a/includes/stg/SMP.h
+++ b/includes/stg/SMP.h
@@ -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");
diff --git a/libraries/ghc-boot/GHC/Platform.hs b/libraries/ghc-boot/GHC/Platform.hs
index 8e4ae5f4b9..341b551fc5 100644
--- a/libraries/ghc-boot/GHC/Platform.hs
+++ b/libraries/ghc-boot/GHC/Platform.hs
@@ -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
diff --git a/libraries/ghci/GHCi/InfoTable.hsc b/libraries/ghci/GHCi/InfoTable.hsc
index ab13485e28..587e39bbed 100644
--- a/libraries/ghci/GHCi/InfoTable.hsc
+++ b/libraries/ghci/GHCi/InfoTable.hsc
@@ -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
diff --git a/llvm-targets b/llvm-targets
index 8f5717d98b..9cf969822c 100644
--- a/llvm-targets
+++ b/llvm-targets
@@ -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", ""))
diff --git a/mk/config.mk.in b/mk/config.mk.in
index 8bbfde2e26..05ad6ad199 100644
--- a/mk/config.mk.in
+++ b/mk/config.mk.in
@@ -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))
################################################################################
#
diff --git a/rts/Capability.h b/rts/Capability.h
index 2a5f127793..0833006b0c 100644
--- a/rts/Capability.h
+++ b/rts/Capability.h
@@ -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
;
diff --git a/rts/Libdw.c b/rts/Libdw.c
index 33a40a1f37..d45d9d0e5d 100644
--- a/rts/Libdw.c
+++ b/rts/Libdw.c
@@ -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
diff --git a/rts/StgCRunAsm.S b/rts/StgCRunAsm.S
index 1dd74d3652..946f5775ea 100644
--- a/rts/StgCRunAsm.S
+++ b/rts/StgCRunAsm.S
@@ -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
diff --git a/rts/ghc.mk b/rts/ghc.mk
index c07cfaec86..dca22fb733 100644
--- a/rts/ghc.mk
+++ b/rts/ghc.mk
@@ -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
diff --git a/rts/linker/Elf.c b/rts/linker/Elf.c
index 0882f8d349..79786ccd3d 100644
--- a/rts/linker/Elf.c
+++ b/rts/linker/Elf.c
@@ -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)
diff --git a/rts/rts.cabal.in b/rts/rts.cabal.in
index 99f1e7296d..30c829ad42 100644
--- a/rts/rts.cabal.in
+++ b/rts/rts.cabal.in
@@ -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
diff --git a/utils/llvm-targets/gen-data-layout.sh b/utils/llvm-targets/gen-data-layout.sh
index a73da499f3..4f4a1ef079 100755
--- a/utils/llvm-targets/gen-data-layout.sh
+++ b/utils/llvm-targets/gen-data-layout.sh
@@ -70,6 +70,8 @@ TARGETS=(
"powerpc64le-unknown-linux-gnu"
"powerpc64le-unknown-linux-musl"
"powerpc64le-unknown-linux"
+ # Linux s390x
+ "s390x-ibm-linux"
#########################
# Darwin