[LLVMdev] dragonegg svn still broken

Duncan Sands
2011-07-25T15:25:10Z

Hi Chris,

>> Chris made major changes to the LLVM type system, which requires major
changes
>> to dragonegg (c.f. the patch Chris applied to llvm-gcc).  I'm on
holiday which
>> is why I haven't taken care of it yet.
>
> Yeah, sorry about that Duncan.  I can't directly hack on the code, but
I'm happy to answer questions when you get back.

there seems to be a nasty flaw in the scheme you devised for llvm-gcc, involving
arrays.  Consider the following mutually recursive arrays of structs:

   struct S has a field which is a pointer to array type A.
   The element type of array type A is struct T.
   struct T has a field which is a pointer to array type B.
   The element type of array type B is struct S.

When trying to convert one of the structs or arrays, with the current scheme you
inevitably end up forming an array of opaque struct types.  This immediately
blows up dragonegg because it wants to compute the array size to see if it needs
to append padding.  It can blow up llvm-gcc too, because it also wants to get
the size of arrays in more exotic circumstances.

Do you have any suggestions on the best way to handle this?

Here are some cheating approaches:

(1) when converting a pointer, if it is a pointer to an array type with
(recursively) a struct element type, then form a pointer to the struct
rather than a pointer to the array.  This is probably fairly harmless as
far as optimization of code is concerned.

(2) never create array types: instead of [1000 x {i32}] create a struct with
1000 {i32} fields.  Then in the above situation you can start off with an
opaque "array" (in fact struct) type and fill in fields later.  This
would
use up vast amounts of memory for big array types (like Ada's "array
that
spans all of memory" types).

(3) convert all pointers to i8*.  I'm not sure how much this would get in
the way of the optimizers.  Note that dragonegg distinguishes between
register types and in-memory types (I think clang does the same), and pointer
types used for registers would still be sensible (struct S* rather than i8*).

A less cheating approach would be to not actually create LLVM types when
converting things, but instead some kind of front-end fake types for which
you can do type refinement on "pointers"; refine "pointers"
when everything
has been converted; and only then generate LLVM types out of the resulting
front-end types.

Ciao, Duncan.