diff options
author | Peter Trommler <ptrommler@acm.org> | 2016-06-18 12:28:41 +0200 |
---|---|---|
committer | Ben Gamari <ben@smart-cactus.org> | 2016-06-19 00:27:06 +0200 |
commit | 2897be77123bf31cad1c60dd5560eba7f2f021ce (patch) | |
tree | 9c7e023e6f1995bd0bc1662b896ccb66384b2d23 /compiler/nativeGen | |
parent | f12fb8ab5d5ad7a26c84f98e446bc70064dcdcec (diff) | |
download | haskell-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.hs | 24 | ||||
-rw-r--r-- | compiler/nativeGen/PPC/Regs.hs | 5 |
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 |