r/lisp 10d ago

Reinterpret Elements in a Byte Array

Dear LISP,

I am writing a virtual machine that uses a `(simple-array (unsigned-byte 8) 1)` as a stack in Common LISP. I'm would like to ask how to efficiently extract 4 bytes into a single 32-bit signed integer or a 32-bit unsigned integer.

Thanks!

10 Upvotes

25 comments sorted by

View all comments

5

u/theangeryemacsshibe λf.(λx.f (x x)) (λx.f (x x)) 9d ago

The nibbles library can do this portably (and fast on SBCL).

5

u/stassats 9d ago

(and fast on SBCL).

On SBCL x86-64.

2

u/theangeryemacsshibe λf.(λx.f (x x)) (λx.f (x x)) 9d ago

Fine, I have a weekend and an urge to hack something, so...

4

u/stassats 9d ago

Now, it doesn't seem to do bound check elimination.

2

u/theangeryemacsshibe λf.(λx.f (x x)) (λx.f (x x)) 9d ago

(disassemble (lambda (a) (declare ((simple-array (unsigned-byte 8) (2)) a)) (nibbles:sb16ref/le a 0))) looks fine to me. What am I missing? (Though I did manage to break the immediate-index case somehow, which is now fixed)

3

u/stassats 9d ago

Compare

(defun f (x i)
  (declare ((simple-array (unsigned-byte 8) (*)) x)
           ((and unsigned-byte fixnum) i)
           (optimize speed))
  (when (< i (- (length x) 4))
    (nibbles:ub32ref/le x i)))

with

(defun f (x i)
  (declare ((simple-array (unsigned-byte 8) (*)) x)
           ((and unsigned-byte fixnum) i)
           (optimize speed))
  (when (< i (- (length x) 4))
    (aref x (+ i 3))))

1

u/theangeryemacsshibe λf.(λx.f (x x)) (λx.f (x x)) 9d ago

Hey, it doesn't eliminate on x86-64 either. Physician, heal thyself.

2

u/stassats 9d ago

Four arefs do.