From 8a356fafb7da6cafd6c4f31b99a9f9554e150676 Mon Sep 17 00:00:00 2001 From: LemonBoy Date: Thu, 18 Oct 2018 14:30:31 +0200 Subject: [PATCH] Make the swap procs safe for unaligned input ptrs (#9210) * Make the swap procs safe for unaligned input ptrs The copy to a temporary local variable is often elided by a sufficiently smart compiler when it can prove the input pointer is aligned. Refs #9206 * Explain why copyMem is used (cherry picked from commit 1fe949b9d5f3b5128fe44fd566c434648e880eb1) --- lib/pure/endians.nim | 21 ++++++++++++--------- 1 file changed, 12 insertions(+), 9 deletions(-) diff --git a/lib/pure/endians.nim b/lib/pure/endians.nim index 6f80d56ef4..771ecaacaa 100644 --- a/lib/pure/endians.nim +++ b/lib/pure/endians.nim @@ -44,20 +44,23 @@ else: const useBuiltinSwap = false when useBuiltinSwap: + template swapOpImpl(T: typedesc, op: untyped) = + ## We have to use `copyMem` here instead of a simple deference because they + ## may point to a unaligned address. A sufficiently smart compiler _should_ + ## be able to elide them when they're not necessary. + var tmp: T + copyMem(addr tmp, inp, sizeOf(T)) + tmp = op(tmp) + copyMem(outp, addr tmp, sizeOf(T)) + proc swapEndian64*(outp, inp: pointer) {.inline, nosideeffect.}= - var i = cast[ptr uint64](inp) - var o = cast[ptr uint64](outp) - o[] = builtin_bswap64(i[]) + swapOpImpl(uint64, builtin_bswap64) proc swapEndian32*(outp, inp: pointer) {.inline, nosideeffect.}= - var i = cast[ptr uint32](inp) - var o = cast[ptr uint32](outp) - o[] = builtin_bswap32(i[]) + swapOpImpl(uint32, builtin_bswap32) proc swapEndian16*(outp, inp: pointer) {.inline, nosideeffect.}= - var i = cast[ptr uint16](inp) - var o = cast[ptr uint16](outp) - o[] = builtin_bswap16(i[]) + swapOpImpl(uint16, builtin_bswap16) else: proc swapEndian64*(outp, inp: pointer) =