Hi,
I'm running into some strange errors with the CBE. I've narrowed the
problem down to a very simple CPP program:
main.cpp:
--------------------------------------------------------------------------------
#include <string>
static std::string hello("Hello world!");
int main() {
return 0;
}
--------------------------------------------------------------------------------
When I generate C code (using LLVM's C backend) with the following
commands, I get a compile error on the resulting C code:
$ llvm-g++ -emit-llvm -O2 -c -o main.bc main.cpp
$ llc -f -march=c main.bc
$ gcc -c main.cbe.c
main.cbe.c:223: warning: conflicting types for built-in function
‘malloc’
main.cbe.c: In function ‘main’:
main.cbe.c:254: warning: return type of ‘main’ is not ‘int’
main.cbe.c: In function ‘__tcf_0’:
main.cbe.c:286: error: ‘_ZL22__gthrw_pthread_cancelm’ undeclared
(first use in this function)
main.cbe.c:286: error: (Each undeclared identifier is reported only once
main.cbe.c:286: error: for each function it appears in.)
Here are the relevant lines from main.cbe.c. Notice that
"pthread_cancel" is declared as a weak external symbol, but
"_ZL22__gthrw_pthread_cancelm" is never declared (even though it is
used).
$ grep -Hn pthread_cancel main.cbe.c
main.cbe.c:213:extern unsigned int pthread_cancel(unsigned long long )
__EXTERNAL_WEAK__;
main.cbe.c:286: if ((((unsigned char )(bool )(((unsigned int )(bool )
(_ZL22__gthrw_pthread_cancelm != ((unsigned int (*) (unsigned long
long ))/*NULL*/0))) != 0u)) != ((unsigned char )0))) {
Here are the relevant lines from the LLVM bitcode. The bitcode
appears correct since "pthread_cancel" is declared as extern_weak and
the alias "_ZL22__gthrw_pthread_cancelm" is declared as a weak alias
of "pthread_cancel". I'm just a bit confused about
"pthread_cancel"
-- shouldn't it be declared as a regular external symbol?
$ llvm-dis main.bc
$ grep -Hn pthread_cancel main.ll
main.ll:24:@_ZL22__gthrw_pthread_cancelm = alias weak i32 (i64)*
@pthread_cancel ; <i32 (i64)*> [#uses=1]
main.ll:57: br i1 icmp ne (i8 zext (i1 icmp ne (i32 zext (i1 icmp ne
(i32 (i64)* @_ZL22__gthrw_pthread_cancelm, i32 (i64)* null) to i32),
i32 0) to i8), i8 0), label %bb69, label %bb76
main.ll:120:declare extern_weak i32 @pthread_cancel(i64)
Finally, looking at the preprocessed main.cpp file (before running it
through LLVM), I can see the appropriate declarations for
"pthread_cancel" and its alias. This (mostly) matches the LLVM
representation above.
$ llvm-g++ -emit-llvm -E -o main.E.cpp main.cpp
$ grep -Hn pthread_cancel main.E.cpp
main.E.cpp:4414:extern int pthread_cancel (pthread_t __th);
main.E.cpp:6058:static __typeof(pthread_cancel) __gthrw_pthread_cancel
__attribute__ ((__weakref__("pthread_cancel")));
main.E.cpp:6075: = __extension__ (void *) &__gthrw_pthread_cancel;
So, it looks like the CBE code generator is not producing correct
output for the alias, since the LLVM bitcode appears correct. Has
anybody seen anything like this before? Or, am I just doing something
wrong? I'm not quite sure why pthreads are involved with just
creating a std::string; but, if I understand it correctly, the alias
is meant to be a "weak" symbol that resolves to NULL if the symbol is
not found during linking. (This makes sense, since the code is
checking to see whether the symbol value is NULL.) The CBE correctly
generates an external weak declaration for pthread_cancel, but it
produces no declaration for the associated alias. This problem only
appears when I turn on optimization (any level above 0) -- the code
compiles fine at "-O0".
I'm using LLVM release 2.3, but I also verified that the problem
occurs with the latest trunk revision from SVN. I'm on x86_64 linux
(Fedora 8).
Any help would be appreciated! (If you want copies of my files, just
let me know and I'll post them somewhere -- however, the problem
should be easy to duplicate with the input file I gave above.)
Thanks!
Jeff Sandoval