summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorBen Gamari <ben@well-typed.com>2022-06-23 12:41:12 -0400
committerZubin Duggal <zubin.duggal@gmail.com>2022-07-14 14:39:37 +0530
commit85aa822901b0d1b50c95fd25261da2e4aa0e8e41 (patch)
tree47f7e7f56664eb54dc71c605af0d5dbe6a468fac
parentae114f51337c734444ddf1295f26442d9d7fcb43 (diff)
downloadhaskell-85aa822901b0d1b50c95fd25261da2e4aa0e8e41.tar.gz
CmmToAsm/AArch64: Sign-extend narrow C arguments
The AArch64/Darwin ABI requires that function arguments narrower than 32-bits must be sign-extended by the caller. We neglected to do this, resulting in #20735. Fixes #20735. (cherry picked from commit 696d64c347364ce75e23d37884ec0bd2543b0a6a)
-rw-r--r--compiler/GHC/CmmToAsm/AArch64/CodeGen.hs16
1 files changed, 14 insertions, 2 deletions
diff --git a/compiler/GHC/CmmToAsm/AArch64/CodeGen.hs b/compiler/GHC/CmmToAsm/AArch64/CodeGen.hs
index 01881d9e8b..4f72d26959 100644
--- a/compiler/GHC/CmmToAsm/AArch64/CodeGen.hs
+++ b/compiler/GHC/CmmToAsm/AArch64/CodeGen.hs
@@ -1619,9 +1619,21 @@ genCCall target dest_regs arg_regs bid = do
-- size we want to pack. Failure to get this right can result in pretty
-- subtle bugs, e.g. #20137.
- passArguments pack (gpReg:gpRegs) fpRegs ((r, format, _hint, code_r):args) stackSpace accumRegs accumCode | isIntFormat format = do
+ passArguments pack (gpReg:gpRegs) fpRegs ((r, format, hint, code_r):args) stackSpace accumRegs accumCode | isIntFormat format = do
+ platform <- getPlatform
let w = formatToWidth format
- mov = MOV (OpReg w gpReg) (OpReg w r)
+ mov
+ -- Specifically, Darwin/AArch64's ABI requires that the caller
+ -- sign-extend arguments which are smaller than 32-bits.
+ | w < W32
+ , platformCConvNeedsExtension platform
+ , SignedHint <- hint
+ = case w of
+ W8 -> SXTB (OpReg W64 gpReg) (OpReg w r)
+ W16 -> SXTH (OpReg W64 gpReg) (OpReg w r)
+ _ -> panic "impossible"
+ | otherwise
+ = MOV (OpReg w gpReg) (OpReg w r)
accumCode' = accumCode `appOL`
code_r `snocOL`
ann (text "Pass gp argument: " <> ppr r) mov