Primitive types

Hello,
I'm getting this in debugger, where 't' is 'Type*':

   (gdb) p t->isPrimitiveType()
   $15 = false
   (gdb) p t->getPrimitiveID()
   $16 = PointerTyID
   (gdb) p t->getPrimitiveSize()
   $17 = 0

There are a couple of things that I'd like to ask. First, if isPrimitiveType()
returns false, that the fact that getPrimitiveID returns reasonable value is
quite strange. Maybe, the method is better called just getID, since it can
get id for both primitive and derived types.

Second, why getPrimitiveSize() returns 0? In seems that LLVM knows the size a
pointer occupies (at least it puts in in LLVM assembly), so why not return
it? For me, that would be quite convenient -- I would only check that type
passed to a function has size of either 4 or 8 bytes and that would catch
both primitives and pointers.

- Volodya

I'm getting this in debugger, where 't' is 'Type*':

   (gdb) p t->isPrimitiveType()
   $15 = false
   (gdb) p t->getPrimitiveID()
   $16 = PointerTyID
   (gdb) p t->getPrimitiveSize()
   $17 = 0

There are a couple of things that I'd like to ask. First, if
isPrimitiveType() returns false, that the fact that getPrimitiveID
returns reasonable value is quite strange. Maybe, the method is better
called just getID, since it can get id for both primitive and derived
types.

You're right, getPrimitiveID seems misnamed. It should be named
getTypeID() or something.

Second, why getPrimitiveSize() returns 0? In seems that LLVM knows the size a
pointer occupies (at least it puts in in LLVM assembly), so why not return
it? For me, that would be quite convenient -- I would only check that type
passed to a function has size of either 4 or 8 bytes and that would catch
both primitives and pointers.

It returns zero because it's not a primitive type :), and because it
doesn't know the size at that point. All primitive types have fixed sizes
independent of the target machine (a 32-bit int is always 4 bytes), so
this method makes sense for primitives. For derived types, a variety of
target-specific properties can effect the size of objects (field
alignment, structure layout rules, etc).

Because of this, all of this information is encapsulated in the TargetData
structure. It can tell you the size of an arbitrary type, field offsets,
etc. If you're working in the context of an LLVM pass, you just
addRequired<TargetData> and getAnalysis<TargetData> when needed (there are
lots of examples in the source base).

It would be somewhat convenient to put these into the type objects
themselves, but type objects are shared between LLVM modules, and it's
possible to have multiple LLVM modules loaded for multiple different
targets at the same time. They would all refer to the same types, but
they could have different sizes in the context of the different targets
they are being compiled for.

-Chris

BTW, I just fixed this. You will probably have to make minor changes to
your source, but just s/PrimitiveID/TypeID/ should work.

http://mail.cs.uiuc.edu/pipermail/llvm-commits/Week-of-Mon-20040614/015245.html

The getPrimitiveSize() method retains its name, as it still only works on
primitive types.

-Chris

Chris Lattner wrote:

> There are a couple of things that I'd like to ask. First, if
> isPrimitiveType() returns false, that the fact that getPrimitiveID
> returns reasonable value is quite strange. Maybe, the method is better
> called just getID, since it can get id for both primitive and derived
> types.

You're right, getPrimitiveID seems misnamed. It should be named
getTypeID() or something.

Ok, thanks for changing that in code.

> Second, why getPrimitiveSize() returns 0? In seems that LLVM knows the
> size a pointer occupies (at least it puts in in LLVM assembly), so why
> not return it? For me, that would be quite convenient -- I would only
> check that type passed to a function has size of either 4 or 8 bytes and
> that would catch both primitives and pointers.

It returns zero because it's not a primitive type :), and because it
doesn't know the size at that point. All primitive types have fixed sizes
independent of the target machine (a 32-bit int is always 4 bytes), so
this method makes sense for primitives. For derived types, a variety of
target-specific properties can effect the size of objects (field
alignment, structure layout rules, etc).

Because of this, all of this information is encapsulated in the TargetData
structure. It can tell you the size of an arbitrary type, field offsets,
etc. If you're working in the context of an LLVM pass, you just
addRequired<TargetData> and getAnalysis<TargetData> when needed (there are
lots of examples in the source base).

Thanks, I'll use this.

- Volodya