More kinds of recursive types in llvm

The language I am working on connecting to an llvm back-end (Modula-3)
allows a fairly extensive set of recursive declarations. It looks
like I can translate all its high-level types using four llvm types that
refer to another type: function, struct, pointer, and array.

It looks like I can alter an llvm struct type in place after it has
been created, using StructType::setBody. I don't see a way to do this
for the other three.

I have to handle cases such as an array type of pointers to itself
(OK, not very useful, but legal, and I should handle it) and, quite
realistically, a function with a parameter or result that is a pointer
to itself. In general, I can get type recursions involving any subset
of the four.

So what would be the best way to build llvm IR for these cases? If I
add my own mutator functions to the llvm type classes, and carefully
only use them during initial IR building, before any transformations,
will it break anything? It looks like things are too private to do
this with added outside code, and I am trying very hard to avoid
touching llvm in-tree code. (We've been down that path with the
current gcc-derived back-end.) Also, could the assembly language
handle these new kinds of cycles in type definitions?

Alternatively, is it possible to construct a system whereby the llvm
operators are sometimes given a slightly artificial type, perhaps
whose component(s) have the same size, alignment, etc. as the real
one(s)? This would presumably entail some educated guesses as to how
much of the type would actually matter to a given operator, but that
might usually be intuitively obvious. Would this also require
bitcasts between uses of the same value with the different types?

(Note: I am building IR with core.h, etc., not generating .ll
assembly.)

The current idea it to go the other way actually: have a single
pointer type and remove cycles. See
http://lists.cs.uiuc.edu/pipermail/llvm-commits/Week-of-Mon-20141201/247285.html
for some of the discussion.

You can just cast one pointer type to another for now.

Cheers,
Rafael

The language I am working on connecting to an llvm back-end (Modula-3)
allows a fairly extensive set of recursive declarations. It looks
like I can translate all its high-level types using four llvm types that
refer to another type: function, struct, pointer, and array.

It looks like I can alter an llvm struct type in place after it has
been created, using StructType::setBody. I don't see a way to do this
for the other three.

The current idea it to go the other way actually: have a single
pointer type and remove cycles. See
http://lists.cs.uiuc.edu/pipermail/llvm-commits/Week-of-Mon-20141201/247285.html
for some of the discussion.

You can just cast one pointer type to another for now.

Hmm, I have been working on a different scheme, to selectively
wrap a pointer in a one-member struct, as needed to break cycles.
I'm not sure what the pros/cons of this are, relative to a single
pointer type, say i8*. For uses, it would be a GEP vs. a cast.
I presume the wrapping would be optimized away. It does leave
more type information in the IR, but as an llvm newcomer, I have
very little idea what parts of the type info matter.