diff options
author | Ian Lynagh <igloo@earth.li> | 2012-03-20 16:11:04 +0000 |
---|---|---|
committer | Ian Lynagh <igloo@earth.li> | 2012-03-20 16:12:06 +0000 |
commit | d0a477123cd6ba5c4d6bb2c650e532d7d972fbf9 (patch) | |
tree | 615fe7b41b8e1a1e8f6718b926b1afc0b5b26a9f /compiler/nativeGen | |
parent | 8986122779d3e96d839aadc7a4094b67c1422205 (diff) | |
download | haskell-d0a477123cd6ba5c4d6bb2c650e532d7d972fbf9.tar.gz |
Fix for Win64 codegen
We need to leave stack space for arguments that we are passing in
registers.
Diffstat (limited to 'compiler/nativeGen')
-rw-r--r-- | compiler/nativeGen/X86/CodeGen.hs | 29 |
1 files changed, 22 insertions, 7 deletions
diff --git a/compiler/nativeGen/X86/CodeGen.hs b/compiler/nativeGen/X86/CodeGen.hs index f134255578..9bcd77bcbd 100644 --- a/compiler/nativeGen/X86/CodeGen.hs +++ b/compiler/nativeGen/X86/CodeGen.hs @@ -1930,7 +1930,10 @@ genCCall64 target dest_regs args = (CmmPrim _ (Just stmts), _) -> stmtsToInstrs stmts - _ -> genCCall64' target dest_regs args + _ -> + do dflags <- getDynFlags + let platform = targetPlatform dflags + genCCall64' platform target dest_regs args where divOp signed width [CmmHinted res_q _, CmmHinted res_r _] [CmmHinted arg_x _, CmmHinted arg_y _] @@ -1952,11 +1955,12 @@ genCCall64 target dest_regs args = divOp _ _ _ _ = panic "genCCall64: Wrong number of arguments/results for divOp" -genCCall64' :: CmmCallTarget -- function to call +genCCall64' :: Platform + -> CmmCallTarget -- function to call -> [HintedCmmFormal] -- where to put the result -> [HintedCmmActual] -- arguments (of mixed type) -> NatM InstrBlock -genCCall64' target dest_regs args = do +genCCall64' platform target dest_regs args = do -- load up the register arguments (stack_args, aregs, fregs, load_args_code) <- load_args args allArgRegs allFPArgRegs nilOL @@ -1967,7 +1971,7 @@ genCCall64' target dest_regs args = do arg_regs = [eax] ++ int_regs_used ++ fp_regs_used -- for annotating the call instruction with sse_regs = length fp_regs_used - tot_arg_size = arg_size * length stack_args + tot_arg_size = arg_size * (length stack_args + length int_regs_used) -- Align stack to 16n for calls, assuming a starting stack @@ -1985,6 +1989,11 @@ genCCall64' target dest_regs args = do -- push the stack args, right to left push_code <- push_args (reverse stack_args) nilOL + -- On Win64, we also have to leave stack space for the arguments + -- that we are passing in registers + lss_code <- if platformOS platform == OSMinGW32 + then leaveStackSpace (length int_regs_used) + else return nilOL delta <- getDeltaNat -- deal with static vs dynamic call targets @@ -2041,6 +2050,7 @@ genCCall64' target dest_regs args = do return (load_args_code `appOL` adjust_rsp `appOL` push_code `appOL` + lss_code `appOL` assign_eax sse_regs `appOL` call `appOL` assign_code dest_regs) @@ -2082,9 +2092,7 @@ genCCall64' target dest_regs args = do (arg_reg, arg_code) <- getSomeReg arg delta <- getDeltaNat setDeltaNat (delta-arg_size) - dflags <- getDynFlags - let platform = targetPlatform dflags - code' = code `appOL` arg_code `appOL` toOL [ + let code' = code `appOL` arg_code `appOL` toOL [ SUB (intSize wordWidth) (OpImm (ImmInt arg_size)) (OpReg rsp) , DELTA (delta-arg_size), MOV (floatSize width) (OpReg arg_reg) (OpAddr (spRel platform 0))] @@ -2106,6 +2114,13 @@ genCCall64' target dest_regs args = do arg_rep = cmmExprType arg width = typeWidth arg_rep + leaveStackSpace n = do + delta <- getDeltaNat + setDeltaNat (delta - n * arg_size) + return $ toOL [ + SUB II64 (OpImm (ImmInt (n * wORD_SIZE))) (OpReg rsp), + DELTA (delta - n * arg_size)] + -- | We're willing to inline and unroll memcpy/memset calls that touch -- at most these many bytes. This threshold is the same as the one -- used by GCC and LLVM. |