Subject: Re: accessing Lisp values from C
From: Erik Naggum <erik@naggum.no>
Date: 1997/04/29
Newsgroups: comp.lang.lisp
Message-ID: <3071291051192250@naggum.no>


* Heiko Kirschke
| What you get from lisp_value is the direct LISP object in its internal
| Allegro representation.  lisp.h tells you how to decode the arg on the C
| side.  The lower 3 (?) or 2 (?) bits of the value are used as tag bits.
| When these bits are 0, the value must be interpreted as a pointer to a
| memory-allocated area containing the (non-immediate) LISP object.  Very
| roughly, these are all objects requiring allocated memory, like symbols,
| vectors, ...
| 
| When the tag bits are != 0, the value is an `immediate value', i.e. a
| fixnum or a character, without any associated allocated memory.

wrong!  please be careful with the details when you give such advice.  all
of this is easy to understand from actually inspecting lisp.h.

Allegr CL (the real thing, for Unix) uses three tag bits on most
architectures.  0 is even integer and 4 is odd integer (effectively giving
29-bit signed fixnums).  all other tags effectively cause the object to be
offset somewhat from the pointer.  e.g., a cons may have tag 1 and thus you
find the CAR on the address having a numeric value one less than the
pointer. and the CDR on the address three bytes up.  if you can align all
objects on word boundaries, and all allocation on 8-byte boundaries, and
you have a CPU that can do indexing on registers before access, you lose
exactly nothing in performance, and win the ability to use hardware traps
for unaligned memory access in the process.

| > My problem is that lisp_value returns a different number than
| > the registered value in lisp (I noted that it is always multiplied
| > by four, but I am not sure). 
| 
| So your assumption that the value you receive from lisp_value on the C
| side is the value put into the LISP side multiplied by 4 is correct; to
| be exact, it is someting like <C value> := <LISP value> * 4 + <fixnum tag
| bits value>.

yet, to be _exact_, it is multiplied by four (left-shifted two bits), and
that's all there is to it.  one some architectures, having the lower two
bits zero in integers also makes a number of interesting instructions
available.

note that this is the usual way to deal with tags on byte-adressable CPU's
with alignment constraints.

#\Erik
-- 
if we work harder, will obsolescence be farther ahead or closer?