+
+-- | Mac OS X requires that the stack be 16 byte aligned when making a function
+-- call (only really required though when making a call that will pass through
+-- the dynamic linker). During code generation we marked any points where we
+-- make a call that requires this alignment. The alignment isn't correctly
+-- generated by LLVM as LLVM rightly assumes that the stack wil be aligned to
+-- 16n + 12 on entry (since the function call was 16 byte aligned and the return
+-- address should have been pushed, so sub 4). GHC though since it always uses
+-- jumps keeps the stack 16 byte aligned on both function calls and function
+-- entry. We correct LLVM's alignment then by putting inline assembly in that
+-- subtracts and adds 4 to the sp as required.
+fixupStack :: ByteString -> ByteString -> ByteString
+fixupStack fun nfun | BS.null nfun =
+ let -- fixup sub op
+ (a, b) = BS.breakSubstring (BS.pack ", %esp\n") fun
+ (a', num) = BS.breakEnd dollarPred a
+ num' = BS.pack $ show (read (BS.unpack num) + 4)
+ fix = a' `BS.append` num'
+ in if BS.null b
+ then nfun `BS.append` a
+ else fixupStack b (nfun `BS.append` fix)
+
+fixupStack fun nfun =
+ let -- fixup add ops
+ (a, b) = BS.breakSubstring (BS.pack "jmp") fun
+ -- We need to avoid processing jumps to labels, they are of the form:
+ -- jmp\tL..., jmp\t_f..., jmpl\t_f..., jmpl\t*%eax...
+ labelJump = BS.index b 4 == 'L'
+ (jmp, b') = BS.break eolPred b
+ (a', numx) = BS.breakEnd dollarPred a
+ (num, x) = BS.break commaPred numx
+ num' = BS.pack $ show (read (BS.unpack num) + 4)
+ fix = a' `BS.append` num' `BS.append` x `BS.append` jmp
+ in if BS.null b
+ then nfun `BS.append` a
+ else if labelJump
+ then fixupStack b' (nfun `BS.append` a `BS.append` jmp)
+ else fixupStack b' (nfun `BS.append` fix)
+