Skip to content

Commit

Permalink
Make the swap procs safe for unaligned input ptrs (nim-lang#9210)
Browse files Browse the repository at this point in the history
* 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 nim-lang#9206

* Explain why copyMem is used
  • Loading branch information
LemonBoy authored and narimiran committed Oct 31, 2018
1 parent bcf5db3 commit 9c092ed
Showing 1 changed file with 12 additions and 9 deletions.
21 changes: 12 additions & 9 deletions lib/pure/endians.nim
Original file line number Diff line number Diff line change
Expand Up @@ -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) =
Expand Down

0 comments on commit 9c092ed

Please sign in to comment.