summaryrefslogtreecommitdiff
path: root/compiler/nativeGen
diff options
context:
space:
mode:
authorPeter Trommler <ptrommler@acm.org>2016-06-18 12:28:41 +0200
committerBen Gamari <ben@smart-cactus.org>2016-06-19 00:27:06 +0200
commit2897be77123bf31cad1c60dd5560eba7f2f021ce (patch)
tree9c7e023e6f1995bd0bc1662b896ccb66384b2d23 /compiler/nativeGen
parentf12fb8ab5d5ad7a26c84f98e446bc70064dcdcec (diff)
downloadhaskell-2897be77123bf31cad1c60dd5560eba7f2f021ce.tar.gz
PPC NCG: Fix float parameter passing on 64-bit.
On Linux 64-bit PowerPC the first 13 floating point parameters are passed in registers. We only passed the first 8 floating point params. The alignment of a floating point single precision value in ELF v1.9 is the second word of a doubleword. For ELF v2 we support only little endian and the least significant word of a doubleword is the first word, so no special handling is required. Add a regression test. Test Plan: validate on powerpc Linux and AIX Reviewers: erikd, hvr, austin, simonmar, bgamari Reviewed By: simonmar Subscribers: thomie Differential Revision: https://phabricator.haskell.org/D2327 GHC Trac Issues: #12134
Diffstat (limited to 'compiler/nativeGen')
-rw-r--r--compiler/nativeGen/PPC/CodeGen.hs24
-rw-r--r--compiler/nativeGen/PPC/Regs.hs5
2 files changed, 22 insertions, 7 deletions
diff --git a/compiler/nativeGen/PPC/CodeGen.hs b/compiler/nativeGen/PPC/CodeGen.hs
index 12d5d88f53..86903e44c7 100644
--- a/compiler/nativeGen/PPC/CodeGen.hs
+++ b/compiler/nativeGen/PPC/CodeGen.hs
@@ -1260,10 +1260,12 @@ genCCall' dflags gcp target dest_regs args
GCPLinux -> roundTo 16 finalStack
GCPLinux64ELF 1 ->
roundTo 16 $ (48 +) $ max 64 $ sum $
- map (widthInBytes . typeWidth) argReps
+ map (roundTo 8 . widthInBytes . typeWidth)
+ argReps
GCPLinux64ELF 2 ->
roundTo 16 $ (32 +) $ max 64 $ sum $
- map (widthInBytes . typeWidth) argReps
+ map (roundTo 8 . widthInBytes . typeWidth)
+ argReps
_ -> panic "genCall': unknown calling conv."
argReps = map (cmmExprType dflags) args
@@ -1414,11 +1416,21 @@ genCCall' dflags gcp target dest_regs args
| otherwise ->
stackOffset
GCPLinux64ELF _ ->
- -- everything on the stack is 8-byte
- -- aligned on a 64 bit system
- -- (except vector status, not used now)
+ -- Everything on the stack is mapped to
+ -- 8-byte aligned doublewords
stackOffset
- stackSlot = AddrRegImm sp (ImmInt stackOffset')
+ stackOffset''
+ | isFloatType rep && typeWidth rep == W32 =
+ case gcp of
+ -- The ELF v1 ABI Section 3.2.3 requires:
+ -- "Single precision floating point values
+ -- are mapped to the second word in a single
+ -- doubleword"
+ GCPLinux64ELF 1 -> stackOffset' + 4
+ _ -> stackOffset'
+ | otherwise = stackOffset'
+
+ stackSlot = AddrRegImm sp (ImmInt stackOffset'')
(nGprs, nFprs, stackBytes, regs)
= case gcp of
GCPAIX ->
diff --git a/compiler/nativeGen/PPC/Regs.hs b/compiler/nativeGen/PPC/Regs.hs
index 780aecc5b1..a1befc7837 100644
--- a/compiler/nativeGen/PPC/Regs.hs
+++ b/compiler/nativeGen/PPC/Regs.hs
@@ -263,7 +263,10 @@ allFPArgRegs platform
= case platformOS platform of
OSAIX -> map (regSingle . fReg) [1..13]
OSDarwin -> map (regSingle . fReg) [1..13]
- OSLinux -> map (regSingle . fReg) [1..8]
+ OSLinux -> case platformArch platform of
+ ArchPPC -> map (regSingle . fReg) [1..8]
+ ArchPPC_64 _ -> map (regSingle . fReg) [1..13]
+ _ -> panic "PPC.Regs.allFPArgRegs: unknown PPC Linux"
_ -> panic "PPC.Regs.allFPArgRegs: not defined for this architecture"
fits16Bits :: Integral a => a -> Bool