type-system-rewrite branch landing tomorrow

FYI, the type-system-rewrite branch is landing tomorrow morning, in mainline llvm, llvm-gcc and clang. I don't have updates, so dragonegg will have to remain broken until someone can fix it (the changes aren't too terrible, llvm-gcc is a good template).

If you're interested in an early preview, the type-system-rewrite branch contains the code for llvm and clang. I sent the llvm-gcc patch out earlier today. The test passes all the llvm and clang regression tests, as well as llvm-test with both the new clang and an old clang (stress testing the bc autoupgrade logic).

-Chris

... and it's in. Please let me know if you see any problems. Many thanks to Jay for doing the Clang port.

-Chris

... and it's in. Please let me know if you see any problems.

My clang self-hosted build (Release+Asserts on Release+Asserts, Linux
x86_64) fails with:

make[2]: Entering directory `/home/jay/llvm/objdir-self/tools/opt'
llvm[2]: Compiling GraphPrinters.cpp for Debug+Asserts build
clang: /home/jay/svn/llvm-project/llvm/trunk/include/llvm/Support/Casting.h:194:
typename llvm::cast_retty<To, From>::ret_type llvm::cast(const Y&)
[with X = llvm::FunctionType, Y = llvm::Type*, typename
llvm::cast_retty<To, From>::ret_type = llvm::FunctionType*]: Assertion
`isa<X>(Val) && "cast<Ty>() argument of incompatible type!"' failed.

This is one of the cases that was giving me grief when I was working
on the Clang bits! Here's a small C testcase:

$ cat foo.c
struct S;
extern struct T {
  struct S (*p)(void);
} t;
struct S { int i; };
void g(void) {
  t.p();
}
$ clang -cc1 -emit-llvm foo.c
clang: /home/jay/svn/llvm-project/llvm/trunk/include/llvm/Support/Casting.h:194:
typename llvm::cast_retty<To, From>::ret_type llvm::cast(const Y&)
[with X = llvm::FunctionType, Y = llvm::Type*, typename
llvm::cast_retty<To, From>::ret_type = llvm::FunctionType*]: Assertion
`isa<X>(Val) && "cast<Ty>() argument of incompatible type!"' failed.

Jay.

Jay Foad wrote:

... and it's in. Please let me know if you see any problems.

My clang self-hosted build (Release+Asserts on Release+Asserts, Linux
x86_64) fails with:

make[2]: Entering directory `/home/jay/llvm/objdir-self/tools/opt'
llvm[2]: Compiling GraphPrinters.cpp for Debug+Asserts build
clang: /home/jay/svn/llvm-project/llvm/trunk/include/llvm/Support/Casting.h:194:
typename llvm::cast_retty<To, From>::ret_type llvm::cast(const Y&)
[with X = llvm::FunctionType, Y = llvm::Type*, typename
llvm::cast_retty<To, From>::ret_type = llvm::FunctionType*]: Assertion
`isa<X>(Val)&& "cast<Ty>() argument of incompatible type!"' failed.

This is one of the cases that was giving me grief when I was working
on the Clang bits! Here's a small C testcase:

$ cat foo.c
struct S;
extern struct T {
   struct S (*p)(void);
} t;
struct S { int i; };
void g(void) {
   t.p();
}

Here's a subset of that problem. This C program:

   struct S;
   struct T {
     struct S *s;
   } t;
   struct S { int i; };

produces IR with the definition of both %struct.S and %struct.T. This program however:

   struct S;
   struct T {
     struct S (*p)(void);
   } t;
   struct S { int i; };

outputs a "%struct.T = type { {}* }" with no mention of struct S (or for that matter, the fact it's a function!)

Nick

Nick Lewycky wrote:

Jay Foad wrote:

... and it's in. Please let me know if you see any problems.

My clang self-hosted build (Release+Asserts on Release+Asserts, Linux
x86_64) fails with:

make[2]: Entering directory `/home/jay/llvm/objdir-self/tools/opt'
llvm[2]: Compiling GraphPrinters.cpp for Debug+Asserts build
clang: /home/jay/svn/llvm-project/llvm/trunk/include/llvm/Support/Casting.h:194:
typename llvm::cast_retty<To, From>::ret_type llvm::cast(const Y&)
[with X = llvm::FunctionType, Y = llvm::Type*, typename
llvm::cast_retty<To, From>::ret_type = llvm::FunctionType*]: Assertion
`isa<X>(Val)&& "cast<Ty>() argument of incompatible type!"' failed.

This is one of the cases that was giving me grief when I was working
on the Clang bits! Here's a small C testcase:

$ cat foo.c
struct S;
extern struct T {
    struct S (*p)(void);
} t;
struct S { int i; };
void g(void) {
    t.p();
}

Here's a subset of that problem. This C program:

    struct S;
    struct T {
      struct S *s;
    } t;
    struct S { int i; };

produces IR with the definition of both %struct.S and %struct.T. This
program however:

    struct S;
    struct T {
      struct S (*p)(void);
    } t;
    struct S { int i; };

outputs a "%struct.T = type { {}* }" with no mention of struct S (or for
that matter, the fact it's a function!)

I was thinking we should fix this by emitting a function with a reference to abstract %struct.S. Turns out we can't quite do that because the definition of the struct changes whether the function returns the struct or returns void and takes a struct pointer as an sret value, etc. Looks like we just got nailed by the ABI problem.

It looks like we need to have opaque function types? Or we need to defer emission of some types until we've finished the translation unit.

Nick

PS. On a related note, in another thread last week I proposed that we stop changing the function type for the ABI, and instead add ABI-specific notes to the Function. http://lists.cs.uiuc.edu/pipermail/llvmdev/2011-June/040643.html

It looks like we need to have opaque function types? Or we need to defer
emission of some types until we've finished the translation unit.

We were deferring this before, no? We could not produce a function type taking an opaque type. Once it go resolved we would need to revisit the function type.

Maybe it is just the logic for delaying it that got broken in the transition?

Nick

Cheers,
Rafael

What we were doing before is that if a function type depended on an
incomplete type, the function type itself was made opaque, and
subsequently resolved when the type(s) it depended on were completed.
I haven't looked at the committed version closely, but the draft
patches basically ripped out that code because the approach was
unworkable.

-Eli

I'm sorry, I've been away from the computer. I'll investigate this in the next half hour. Thanks for the test cases!

-Chris

One more testcase, which might be of interest; crashes clang on x86-64:

struct T {
  struct T (*p)(void);
} t;

-Eli

This is by-design. Also, the LLVM asmprinter only ever prints out types that are referenced by the module (just like we do for metadata) so if you remove the last use of a type, the type won't be printed.

This is why the DeadTypeElimination pass is obsolete and gone.

-Chris

This testcase is fixed in r134853, Jay's isn't fixed yet though. Thanks for the great testcase!

-Chris

This should be fixed now.

-Chris

struct T {
struct T (*p)(void);
} t;

This testcase also generates infinite recursion when we use llvm-gcc for arm-target.

Because return type of function pointer p's is struct type T which has one element,
llvm-gcc for arm target calls a function which tries to chang aggregate return type
to inner element.
(For example, C.HandleAggregateResultAsScalar(Ty);
--> DefaultABI::HandleReturnType() function gcc/llvm-abi-default.cpp)

In this case, infinite recursion is generated.

So I made a patch.
when function's return type is struct type and this struct type includes only
function's pointer type as element, funtion's return type is not struct type's element
and is struct type in this patch.
and this patch inserts redundant GetLLVMType() function to remove duplicate
StructsDeferred.push_back().

What do you think about this patch?

Please review this patch.

Thanks,
Jin-Gu Kang

llvm-gcc-4.2-for-arm.patch (2.76 KB)

Are the get type methods for IRBuilder, such as const IntegerType *getInt32Ty(), going to have
their return type const qualifiers removed? Doing so would match the semi equivalent static
methods of Type, such as static IntegerType *getInt32Ty(LLVMContext &C).

Thanks in advance

Garrison

Sorry, these IRBuilder methods are really in IRBuilderBase.

Garrison

Attached is a patch for the non ExceptionDemo demos which gets rid of the old
const qualifier usage for Type. Although I recently commited the ExceptionDemo
changes, I did not want to touch code that I did not "own" without other's approval.
Even though trivial, I did not test this patch.

Garrison

Some_examples_const_Type.patch (4.13 KB)

Attached is a patch for the non ExceptionDemo demos which gets rid of the old
const qualifier usage for Type. Although I recently commited the ExceptionDemo
changes, I did not want to touch code that I did not "own" without other's approval.
Even though trivial, I did not test this patch.

Assuming that this fixes the build and haven't been applied already, please commit! I'll fix IRBuilder.

-Chris

struct T {
struct T (*p)(void);
} t;

This testcase also generates infinite recursion when we use llvm-gcc for arm-target.

Because return type of function pointer p's is struct type T which has one element,
llvm-gcc for arm target calls a function which tries to chang aggregate return type
to inner element.
(For example, C.HandleAggregateResultAsScalar(Ty);
--> DefaultABI::HandleReturnType() function gcc/llvm-abi-default.cpp)

In this case, infinite recursion is generated.

So I made a patch.
when function's return type is struct type and this struct type includes only
function's pointer type as element, funtion's return type is not struct type's element
and is struct type in this patch.
and this patch inserts redundant GetLLVMType() function to remove duplicate
StructsDeferred.push_back().

What do you think about this patch?

Please review this patch.

Thanks,
Jin-Gu Kang

I think this error have to be fixed.
This error can be generated on some of architectures.

Thanks,
Jin-Gu Kang