Recursive Types using the llvm support library

As far as I can tell, when you construct a type using the support
library StructType::get, you have to pass in a list of types. How can
you make a Recursive type by passing in a pointer to the type you are
constucting.

An example where something really simple like the line below was output
would be perfect.

%struct.linked_list = type { %struct.linked_list*, %sbyte* }

Thanks for any help,
       John

Use something like this:

   PATypeHolder StructTy = OpaqueType::get();
   std::vector<const Type*> Elts;
   Elts.push_back(PointerType::get(StructTy));
   Elts.push_back(PointerType::get(Type::SByteTy));
   StructType *NewSTy = StructType::get(Elts);

   // At this point, NewSTy = "{ opaque*, sbyte* }", tell VMCore that
   // the struct and the opaque type are actually the same.
   cast<OpaqueType>(StructTy.get())->refineAbstractTypeTo(NewSTy);

   // NewSTy is potentially invalidated, but StructTy (a PATypeHolder) is
   // kept up-to-date.
   NewSTy = StructTy.get();

-Chris

Thanks much, Chris.

An example where something really simple like the line below was output
would be perfect.

%struct.linked_list = type { %struct.linked_list*, %sbyte* }

Use something like this:

  PATypeHolder StructTy = OpaqueType::get();
  std::vector<const Type*> Elts;
  Elts.push_back(PointerType::get(StructTy));
  Elts.push_back(PointerType::get(Type::SByteTy));
  StructType *NewSTy = StructType::get(Elts);

  // At this point, NewSTy = "{ opaque*, sbyte* }", tell VMCore that
  // the struct and the opaque type are actually the same.
  cast<OpaqueType>(StructTy.get())->refineAbstractTypeTo(NewSTy);

  // NewSTy is potentially invalidated, but StructTy (a PATypeHolder) is
  // kept up-to-date.
  NewSTy = StructTy.get();

Is assert(!NewSTy->isAbstract()) must pass after this line?

Vladimir

In this case, yup.

-Chris

I create test program and assert failed in it:

{ \2 *, sbyte * }
Assertion failed: (!NewSTy->isAbstract()), function main, file /usr/home/wanderer/work/LLVMTest/obj/../src/tools/tool/Test.cc, line 28.

Testcase source attached.

Vladimir

Test.cc (796 Bytes)

Thanks, that definitely is a bug. Patch here:
http://mail.cs.uiuc.edu/pipermail/llvm-commits/Week-of-Mon-20050307/024522.html

BTW, what are you using the isAbstract bit for?

-Chris

In some asserts in my YAFL frontend (may be i will have free time to finish it).

Vladimir

How do I decode the \2 in this? I am creating types through this
interface and I get quite a mess seen below. And this is relatively
simple. Any ideas?

-John

  alloca { { int, uint, sbyte*, \4* (), \4* (\4*), { { int, uint, sbyte*, \4* (), { { int, uint, sbyte*, \4 (), \4 (\4), \8* (\4), \4 (\4) } }* (\4*), \4* (\4*), \4* (\4*), { { int, uint, sbyte*, \4 (), \4 (\4), \8* (\4), \4 (\4) } }* (\4*), \4* (\4*, \4*), \4* (\4*, { { int, uint, sbyte*, \4 (), \4 (\4), \8* (\4), \4 (\4) } }*, { { int, uint, sbyte*, \4 (), \4 (\4), \8* (\4), \4 (\4) } }*) } }* (\4*), \4* (\4*) } } ; <{ { int, uint, sbyte*, \4* (), \4* (\4*), { { int, uint, sbyte*, \4* (), { { int, uint, sbyte*, \4 (), \4 (\4), \8* (\4), \4 (\4) } }* (\4*), \4* (\4*), \4* (\4*), { { int, uint, sbyte*, \4 (), \4 (\4), \8* (\4), \4 (\4) } }* (\4*), \4* (\4*, \4*), \4* (\4*, { { int, uint, sbyte*, \4 (), \4 (\4), \8* (\4), \4 (\4) } }*, { { int, uint, sbyte*, \4 (), \4 (\4), \8* (\4), \4 (\4) } }*) } }* (\4*), \4* (\4*) } }*>:2 [#uses=0]

Is assert(!NewSTy->isAbstract()) must pass after this line?

In this case, yup.

I create test program and assert failed in it:

{ \2 *, sbyte * }

How do I decode the \2 in this? I am creating types through this
interface and I get quite a mess seen below. And this is relatively
simple. Any ideas?

"\2" is an upreference, which refers to a containing type. For example, this type:

  \1*

Is a pointer to pointer to pointer to pointer.... In "{\2*}", the upreference refers to the structure type, not the pointer, with \4, it means go 4 types up etc.

In practice, this is leads to a horrible mess, as you've noticed. As such, I'd suggest using Module::addTypeName to give these things names so that you have a hope to understand them and so they are more compact :slight_smile:

-Chris

  alloca { { int, uint, sbyte*, \4* (), \4* (\4*), { { int, uint, sbyte*, \4* (), { { int, uint, sbyte*, \4 (), \4 (\4), \8* (\4), \4 (\4) } }* (\4*), \4* (\4*), \4* (\4*), { { int, uint, sbyte*, \4 (), \4 (\4), \8* (\4), \4 (\4) } }* (\4*), \4* (\4*, \4*), \4* (\4*, { { int, uint, sbyte*, \4 (), \4 (\4), \8* (\4), \4 (\4) } }*, { { int, uint, sbyte*, \4 (), \4 (\4), \8* (\4), \4 (\4) } }*) } }* (\4*), \4* (\4*) } } ; <{ { int, uint, sbyte*, \4* (), \4* (\4*), { { int, uint, sbyte*, \4* (), { { int, uint, sbyte*, \4 (), \4 (\4), \8* (\4), \4 (\4) } }* (\4*), \4* (\4*), \4* (\4*), { { int, uint, sbyte*, \4 (), \4 (\4), \8* (\4), \4 (\4) } }* (\4*), \4* (\4*, \4*), \4* (\4*, { { int, uint, sbyte*, \4 (), \4 (\4), \8* (\4), \4 (\4) } }*, { { int, uint, sbyte*, \4 (), \4 (\4), \8* (\4), \4 (\4) } }*) } }* (\4*), \4* (\4*) } }*>:2 [#uses=0]

_______________________________________________
LLVM Developers mailing list
LLVMdev@cs.uiuc.edu http://llvm.cs.uiuc.edu
http://mail.cs.uiuc.edu/mailman/listinfo/llvmdev

-Chris

I took your advide and used Module::addTypeName which is a great idea
that I didn't know about.

Now I am getting a seg fault, here

SymbolTable.cpp:251
  if (T->isAbstract()) {
    cast<DerivedType>(T)->addAbstractTypeUser(this);

I am assuming the patch mentioned earlier on the thread will fix this.
I just wanted to ask to make sure before i went ahead and recompiled.

-John

You would have to give me more context to say for sure, but updating to current CVS can't hurt.

-Chris

The patch worked great. I appreciate all your help.

-John