Skip to content

Commit

Permalink
Don't perform unaligned writes when forbidden
Browse files Browse the repository at this point in the history
Some architectures, such as SPARC, trap on unaligned memory accesses,
and poke makes no guarantees about its behaviour if the address is not
sufficiently aligned. Therefore we should use a temporary buffer if
asked to write to an unaligned address, unless we know for sure the
architecture supports it without trapping.
  • Loading branch information
jrtc27 committed Aug 1, 2017
1 parent d232262 commit 3eaaf8a
Show file tree
Hide file tree
Showing 2 changed files with 10 additions and 3 deletions.
3 changes: 0 additions & 3 deletions Data/ByteString/Builder/Prim/Binary.hs
Original file line number Diff line number Diff line change
Expand Up @@ -272,9 +272,6 @@ int64LE :: FixedPrim Int64
int64LE = fromIntegral >$< word64LE


-- TODO: Ensure that they are safe on architectures where an unaligned write is
-- an error.

-- | Encode a single native machine 'Int'. The 'Int's is encoded in host order,
-- host endian form, for the machine you are on. On a 64 bit machine the 'Int'
-- is an 8 byte value, on a 32 bit machine, 4 bytes. Values encoded this way
Expand Down
10 changes: 10 additions & 0 deletions Data/ByteString/Builder/Prim/Internal.hs
Original file line number Diff line number Diff line change
Expand Up @@ -198,7 +198,17 @@ liftFixedToBounded = toB

{-# INLINE CONLIKE storableToF #-}
storableToF :: forall a. Storable a => FixedPrim a
-- Not all architectures are forgiving of unaligned accesses; whitelist ones
-- which are known not to trap (either to the kernel for emulation, or crash).
#if defined(i386_HOST_ARCH) || defined(x86_64_HOST_ARCH) || \
defined(powerpc_HOST_ARCH) || defined(powerpc64_HOST_ARCH) || \
defined(powerpc64le_HOST_ARCH)
storableToF = FP (sizeOf (undefined :: a)) (\x op -> poke (castPtr op) x)
#else
storableToF = FP (sizeOf (undefined :: a)) $ \x op ->
if (ptrToWordPtr op) `mod` (fromIntegral (alignment (undefined :: a))) == 0 then poke (castPtr op) x
else with x $ \tp -> copyBytes op (castPtr tp) (sizeOf (undefined :: a))
#endif

{-
{-# INLINE CONLIKE liftIOF #-}
Expand Down

0 comments on commit 3eaaf8a

Please sign in to comment.