Wrong short representation using FFI on M1 macbook with GHC 8.10.7 with optimizations
Summary
When calling a c function using the ccall
api on M1 macs and passing it an Int16
, the value is represented as if it is an unsigned short int
instead of a short int
, when compiling with optimizations.
Steps to reproduce
Code
-
code.c
:
#include <stdio.h>
short int func(short int targetType)
{
printf("%d\n", targetType);
return (-1);
}
-
main.hs
:
{-# LANGUAGE ForeignFunctionInterface #-}
module Main where
import Data.Int
foreign import ccall "code.h func" func :: Int16 -> IO Int16
main :: IO ()
main = do
res <- func (-2)
print res
Compiling and running
With optimizations (bug)
$ ghc main.hs code.c -O
$ ./main
65534
-1
Without optimizations (correct)
$ ghc main.hs code.c
$ ./main
-2
-1
Expected behavior
With optimizations should work the same as without optimizations.
Environment
- GHC version used: 8.10.7 arm64
- cabal-install 3.4.0.0
- LLVM 13.0.0
Optional:
- Operating System: MacOS 12.0.1
- System Architecture: M1 chip (a.k.a. arm64, a.k.a. aarch64?)
Original ticket before the minimal reproduction steps. There are more interesting details here!
Summary
I've tried using the fpco/odbc library on M1 and ran into issues when crossing the boundary between Haskell and C. To me this seem like a compiler bug, but let me know if you think differently.
More details, reproduction steps and some debugging thoughts in the fpco/odbc issue #41 thread, including the behavior change when run with traceShowId
and the output of printing targetType in the C layer.
This warning emitted when compiling the project also seems like a relevant suspect:
/var/folders/4p/vsznhmbx6p15bndr9g1fwv3m0000gn/T/ghc3543_0/ghc_1.s:354:2: error:
warning: instruction movi.2d with immediate #0 may not function correctly on this CPU, converting to equivalent movi.16b
movi.2d v0, #0000000000000000
^
|
354 | movi.2d v0, #0000000000000000
| ^
Steps to reproduce
Described in the fpco/odbc issue #41 thread. The gist is:
Compile the odbc project
$ git clone https://github.com/fpco/odbc
$ cabal v2-build odbc
Run MSSQL with docker
$ docker run --name odbc-test-21433 --platform linux/arm64 -e ACCEPT_EULA=1 -e MSSQL_SA_PASSWORD=hUntEr202 -p 127.0.0.1:21433:1433 -d mcr.microsoft.com/azure-sql-edge
Run the odbc exec
$ cabal v2-run odbc -- 'DRIVER={ODBC Driver 17 for SQL Server};SERVER=192.168.0.146,21433;Uid=sa;Pwd=hUntEr202;Encrypt=no'
> CREATE TABLE mytest (a text);
Rows: 0
> insert into mytest values('abc');
Rows: 0
> select * from mytest;
UnsuccessfulReturnCode "getSize" (-1) "[unixODBC][Driver Manager]Program type out of range[unixODBC][Driver Manager]Program type out of range"
> select * from mytest;
[row 0]
a: "abc"
Rows: 1
This can be reproduced after restarting the odbc
executable and running select * from mytest;
again.
Expected behavior
select * from mytest;
should not fail, and return the same output it returned on the second run.