-
Notifications
You must be signed in to change notification settings - Fork 86
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Fix 32 bit compilation #322
base: master
Are you sure you want to change the base?
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,41 @@ | ||
name: Other CI | ||
on: | ||
- push | ||
- pull_request | ||
jobs: | ||
i386: | ||
name: i386 - ${{ matrix.ghc }} | ||
runs-on: ubuntu-latest | ||
container: | ||
image: i386/debian:bookworm | ||
strategy: | ||
fail-fast: false | ||
matrix: | ||
ghc: | ||
- 9.8.1 | ||
- 9.6.3 | ||
- 9.4.8 | ||
- 9.2.8 | ||
- 9.0.2 | ||
- 8.10.7 | ||
- 8.8.4 | ||
- 8.6.5 | ||
- 8.4.4 | ||
steps: | ||
- name: Install system dependencies | ||
run: | | ||
apt-get update -y | ||
apt-get install -y build-essential curl libffi-dev libffi8 libgmp-dev libgmp10 libncurses-dev libncurses5 libtinfo5 zlib1g-dev | ||
curl --proto '=https' --tlsv1.2 -sSf https://get-ghcup.haskell.org | sh | ||
env: | ||
BOOTSTRAP_HASKELL_NONINTERACTIVE: 1 | ||
BOOTSTRAP_HASKELL_INSTALL_NO_STACK: 1 | ||
BOOTSTRAP_HASKELL_GHC_VERSION: ${{ matrix.ghc }} | ||
- uses: actions/checkout@v1 | ||
|
||
- name: Build and test | ||
run: | | ||
. ~/.ghcup/env | ||
cabal configure --enable-tests --enable-benchmarks | ||
cabal build all | ||
cabal test all --test-show-details=direct |
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -63,7 +63,7 @@ import qualified Data.Text as T | |
import qualified Data.Text.Encoding as T | ||
import Data.Word | ||
import GHC.Word | ||
#if defined(ARCH_32bit) | ||
#if defined(ARCH_32bit) && !MIN_VERSION_ghc_prim(0,8,0) | ||
import GHC.IntWord64 | ||
#endif | ||
import GHC.Exts | ||
|
@@ -510,8 +510,8 @@ go_fast !bs da@(ConsumeNegWord64Canonical k) = | |
go_fast !bs da@(ConsumeInt64Canonical k) = | ||
case tryConsumeInt64 (BS.unsafeHead bs) bs of | ||
DecodeFailure -> go_fast_end bs da | ||
DecodedToken sz i@(I64# i#) | ||
| isInt64Canonical sz i -> k i# >>= go_fast (BS.unsafeDrop sz bs) | ||
DecodedToken sz (I64# i#) | ||
| isInt64Canonical sz i# -> k i# >>= go_fast (BS.unsafeDrop sz bs) | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I'm confused by this. Did this simply never work? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I would have to do some |
||
| otherwise -> go_fast_end bs da | ||
|
||
go_fast !bs da@(ConsumeListLen64Canonical k) = | ||
|
@@ -994,8 +994,8 @@ go_fast_end !bs (ConsumeNegWord64Canonical k) = | |
go_fast_end !bs (ConsumeInt64Canonical k) = | ||
case tryConsumeInt64 (BS.unsafeHead bs) bs of | ||
DecodeFailure -> return $! SlowFail bs "expected int64" | ||
DecodedToken sz i@(I64# i#) | ||
| isInt64Canonical sz i -> k i# >>= go_fast_end (BS.unsafeDrop sz bs) | ||
DecodedToken sz (I64# i#) | ||
| isInt64Canonical sz i# -> k i# >>= go_fast_end (BS.unsafeDrop sz bs) | ||
| otherwise -> return $! SlowFail bs "non-canonical int64" | ||
|
||
go_fast_end !bs (ConsumeListLen64Canonical k) = | ||
|
@@ -1271,7 +1271,7 @@ go_slow da bs !offset = do | |
|
||
SlowPeekByteOffset bs' k -> | ||
lift | ||
#if MIN_VERSION_base(4,17,0) | ||
#if MIN_VERSION_base(4,17,0) && !defined(ARCH_32bit) | ||
(k (int64ToInt# off#)) | ||
#else | ||
(k off#) | ||
|
@@ -1381,7 +1381,7 @@ go_slow_overlapped da sz bs_cur bs_next !offset = | |
SlowPeekByteOffset bs_empty k -> | ||
assert (BS.null bs_empty) $ do | ||
lift | ||
#if MIN_VERSION_base(4,17,0) | ||
#if MIN_VERSION_base(4,17,0) && !defined(ARCH_32bit) | ||
(k (int64ToInt# off#)) | ||
#else | ||
(k off#) | ||
|
@@ -1565,17 +1565,17 @@ isIntCanonical sz i | |
{-# INLINE isWord64Canonical #-} | ||
isWord64Canonical :: Int -> Word64 -> Bool | ||
isWord64Canonical sz w | ||
| sz == 2 = w > 0x17) | ||
| sz == 3 = w > 0xff) | ||
| sz == 5 = w > 0xffff) | ||
| sz == 9 = w > 0xffffffff) | ||
| sz == 2 = w > 0x17 | ||
| sz == 3 = w > 0xff | ||
| sz == 5 = w > 0xffff | ||
| sz == 9 = w > 0xffffffff | ||
| otherwise = True | ||
|
||
{-# INLINE isInt64Canonical #-} | ||
isInt64Canonical :: Int -> Int64# -> Bool | ||
isInt64Canonical sz i# | ||
| isTrue# (i# `ltInt64#` intToInt64# 0#) = isWord64Canonical sz (not64# w#) | ||
| otherwise = isWord64Canonical sz w# | ||
| isTrue# (i# `ltInt64#` intToInt64# 0#) = isWord64Canonical sz (W64# (not64# w#)) | ||
| otherwise = isWord64Canonical sz (W64# w#) | ||
where | ||
w# = int64ToWord64# i# | ||
#endif | ||
|
@@ -1796,7 +1796,7 @@ tryConsumeInteger hdr !bs = case word8ToWord hdr of | |
0x1b -> let !w = eatTailWord64 bs | ||
sz = 9 | ||
#if defined(ARCH_32bit) | ||
in DecodedToken sz (BigIntToken (isWord64Canonical sz (word64ToWord w)) $! toInteger w) | ||
in DecodedToken sz (BigIntToken (isWord64Canonical sz w) $! toInteger w) | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Also looks like this couldn't ever have been type correct. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. see #322 (comment) |
||
#else | ||
in DecodedToken sz (BigIntToken (isWordCanonical sz (word64ToWord w)) $! toInteger w) | ||
#endif | ||
|
@@ -1838,7 +1838,7 @@ tryConsumeInteger hdr !bs = case word8ToWord hdr of | |
0x3b -> let !w = eatTailWord64 bs | ||
sz = 9 | ||
#if defined(ARCH_32bit) | ||
in DecodedToken sz (BigIntToken (isWord64Canonical sz (word64ToWord w)) $! (-1 - toInteger w)) | ||
in DecodedToken sz (BigIntToken (isWord64Canonical sz w) $! (-1 - toInteger w)) | ||
#else | ||
in DecodedToken sz (BigIntToken (isWordCanonical sz (word64ToWord w)) $! (-1 - toInteger w)) | ||
#endif | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Surely this can't be quite the right logic, because 32bit arches prior to some ghc version did need
intToInt64#
didn't they?There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
PeekByteOffset
always provides anInt64#
on 32bit:cborg/cborg/src/Codec/CBOR/Decoding.hs
Lines 191 to 195 in c8013b3
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
which would mean this logic here is wrong. The logic currently says "use intToInt64 if base >= 4.17 and only on 64bit arches".
But what you're saying above is that it should be "always use intToInt64 on 32bit arches", so the combo would be
so that we use intToInt64 on 32bit arches (for all base versions), and we also use it on all arches from base 4.17 onwards.
Did we check this patch actually compiles on 32bit arches prior to ghc 9.2?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think the existing logic is exactly right (it also compiles on all GHC versions >=8.4), as seen eg by a case distinction.
The purpose of this code is to fill the hole
_f
inPeekByteOffset $ \off# -> k (I64# (_f off#))
(wherek
has input typeByteOffset ~ Int64
).We have
off# :: Int64#
andI64# :: Int64# -> Int64
on all GHCs. Hence, we can fill_f = id
.We have
off# :: Int#
.I64# :: Int# -> Int64
.Hence, we can fill
_f = id
.I64# :: Int64# -> Int64
(FTR: corresponding section in the migration guide for 9.4).Hence, we can fill
_f = intToInt64# :: Int# -> Int64#
Note that we can fill
_f = id
except when we are on GHC >=9.4 and on 64bit, which is exactly the existing condition.Would be neat if there were some more principled/locally understandable alternative to the current CPP maze 😅
Yes, to double check once again, I pushed to a branch in my fork with the second commit (Support GHC >=9.2 on 32bit) removed: https://github.com/amesgen/cborg/actions/runs/6183531233
One can see that i686 compilation with all GHCs from 8.4 to 9.0 succeeds (as expected, compilation on >=9.2 fails as the respective commit was removed).
Also, here is the CI run that everything works on all GHCs with all three commits: https://github.com/amesgen/cborg/actions/runs/6138762687