memref

$Revision: 5.0.2.3 $

Function

Package: SYSTEM

Arguments: (object offset pos type &optional coerce)

This function and sys:memref-int provide low-level memory access in Allegro CL. They are tightly integrated for very efficient compilation. Usually, when the type is known at compile-time, the code generated is less than three machine instructions.

Each function calculates an address in memory and performs a read from that address. The width and style of the read depends upon the type.

These functions are setf-able. The setf functions write to the addressed memory instead of reading. WARNING: except when the type is :lisp, these setf-functions do not do any setf-protection. If they are used to store non-lisp values into a memory location that was intended to hold a lisp value, then GC death will occur.

Some checking can be done. When the setf functions for sys:memref and sys:memref-int are given an optional non-nil fifth coerce argument, then runtime checking and coersion is done on the value before it is stored. This is especially useful when the argument is a float value, but of the wrong type, as in

(setf (sys:memref array 0 0 :double-float :coerce) 1.0s0)

Note that when this fifth argument is supplied, then the call is not open-coded when compiled.

object (the first argument of memref) can be any lisp object, whose address (including the tag bits) is used as the base for the memory access. address (the first argument of memref-int) can be any integer that represents a valid address in the lisp. The value of this address (which may be a bignum) is used as the base for the memory access.

offset and pos are equivalent and interchangeable. They are both added as byte-offsets to the base address to determine the final memory address. Usually, the offset is some constant that adjusts for the start of the data in the object being accessed. Some of the offsets for lisp objects are described in <Allegro directory>/misc/lisp.h in the Allegro CL distribution. All offsets are available in the lisp itself using the (undocumented) comp::mdparam function on one of many available offset specifiers (see examples below).

The access-types that are available are as follows:

:unsigned-byte, :signed-byte (1-byte access, 1-byte integer result)
:unsigned-word, :signed-word (2-byte access, 2-byte integer result)
:unsigned-long, :signed-long (4-byte access, 4-byte integer result)
:fixnum (4-byte access, fixnum result [top bits lost on overflow])
:lisp (4-byte access, lisp result [careful, could confuse gc])
:single-float (4-byte access, 4-byte single-float result)
:double-float (8-byte access, 8-byte double-float result)

So, for example, you can access each byte of 1.0 individually:

USER(1): (setq off (comp::mdparam 'comp::md-single-float-data-adj))
-2
USER(2): (sys:memref 1.0 off 0 :unsigned-byte)
63
USER(3): (sys:memref 1.0 off 1 :unsigned-byte)
128
USER(4): (sys:memref 1.0 off 2 :unsigned-byte)
0
USER(5): (sys:memref 1.0 off 3 :unsigned-byte)
0

Or you can look at the whole object:

USER(6): (excl::pointer-to-address 1.0)
8544846
USER(7): (format t "~x" *)
82624e ;; <-- note that the tag is 6, for "other"
NIL
USER(8): (format t "~x" (sys:memref-int #x826248 0 0 :unsigned-long))
40000000 ;; #x40 is the type code for a single-float
NIL
USER(9): (format t "~x" (sys:memref-int #x826248 0 4 :unsigned-long))
3f800000
NIL

You can even set arbitrary locations in lisp objects (user beware):

USER(10): (setq off (comp::mdparam 'comp::md-symbol-plist-adj))
14
USER(11): (symbol-plist 'x)
NIL USER(12): (setf (sys:memref 'x off 0 :lisp) '(foo t))
(FOO T)
USER(13): (symbol-plist 'x)
(FOO T)

The general documentation description is in introduction.htm. The index is in index.htm.

Copyright (C) 1998-1999, Franz Inc., Berkeley, CA. All Rights Reserved.