夜行録 - 酔歩.net

日暮れて道遠し さらに夜道を行く もって夜行録と名付く

LLVM + gcc frontend を x86_64 で野良 build する手順

拾いもののバイナリじゃ、なんでか他所で compile/link した LLVM バイナリが実行時にエラーとなったので、諦めて野良 build。
てゆーか、 OS 古いぞ。 gcc なんて 3.4.6 だし…。ということで、まずは GCC-4.2 の野良 build からorz

GCC-4.2 を $HOME/GCC 以下にインストールする。 enable-languages は c,c++,fortran (gfortran を使うこともいつかあるだろ)。以降、 $PATH と $LD_LIBRARY_PATH に $HOME/GCC/bin と $HOME/GCC/lib64 を追加。とくに後者は、 libstdc++ をリンクしようとして /lib/ を見に行ってコケるケースが頻出する。

LLVM の gcc frontend の build には LLVM の object ファイルが必要になるので、連続して作業する。
~/tmp/ あたりで作業するとして、 llvm-2.2, llvm-gcc4.2-2.2.source を展開する。 LLVM の流儀で(?)コンパイルはソースツリーとは別の場所で行うので、 llvmobj と llvmgccobj を作成。

cd llvmobj
env  LDFLAGS="-Wl,--rpath -Wl,$HOME/GCC/lib64" F77=gfortran ../llvm-2.2/configure --prefix=$HOME/LLVM --enable-optimized |& tee LOG1 
make -j 3
make install

cd ../llvmgccobj
../llvm-gcc4.2-2.2.source/configure --prefix=$HOME/LLVM/gcc --enable-llvm=`pwd`/../llvmobj --program-prefix=llvm- --disable-shared --disable-multilib --enable-languages=c,c++,fortran 
make -j 3
make install

make の並列度はプロセッサ数に合わせててきとーに指定。 LLVM の configure で F77 が指定されているのはシステムの古い g77 の方を見つけるから。キモは、 LDFLAGS を上のようにして有無を言わさず $HOME/GCC/lib64 の libstdc++ をリンクさせること。
gcc frontend の方では、 LLVM のオブジェクトコードの探索のために --enable-llvm が指定されているが、これが絶対パス指定という制約がある。 README にあるように、 --disable-shared --disable-multilib している。

--disable-multilib がない場合は

/home/yagi/tmp/llvmgccobj/./gcc/xgcc -B/home/yagi/tmp/llvmgccobj/./gcc/ -B/home/yagi/LLVM/gcc/x86_64-unknown-linux-gnu/bin/ -B/home/yagi/LLVM/gcc/x86_64-unknown-linux-gnu/lib/ -isystem /home/yagi/LLVM/gcc/x86_64-unknown-linux-gnu/include -isystem /home/yagi/LLVM/gcc/x86_64-unknown-linux-gnu/sys-include -O2 -O2 -g -O2  -DIN_GCC    -W -Wall -Wwrite-strings -Wstrict-prototypes -Wmissing-prototypes -Wold-style-definition  -isystem ./include  -I. -I32 -I../../llvm-gcc4.2-2.2.source/gcc -I../../llvm-gcc4.2-2.2.source/gcc/32 -I../../llvm-gcc4.2-2.2.source/gcc/../include -I../../llvm-gcc4.2-2.2.source/gcc/../libcpp/include  -I../../llvm-gcc4.2-2.2.source/gcc/../libdecnumber -I../libdecnumber -I/home/yagi/tmp/llvm-2.2/include -I/home/yagi/tmp/llvmgccobj/../llvmobj/include -m32 -g0 -finhibit-size-directive -fno-inline-functions -fno-exceptions -fno-zero-initialized-in-bss -fno-toplevel-reorder  -fno-omit-frame-pointer -fno-asynchronous-unwind-tables \
  -c ../../llvm-gcc4.2-2.2.source/gcc/crtstuff.c -DCRT_BEGIN \
  -o 32/crtbegin.o
Warning: Generation of 64-bit code for a 32-bit processor requested.
Warning: 64-bit processors all have at least SSE2.
cc1: ../../llvm-gcc4.2-2.2.source/gcc/llvm-types.cpp:82: const llvm::Type* llvm_set_type(tree_node*, const llvm::Type*): Assertion `(!(__extension__ ({ const tree __t = (Tr); if (tree_code_type[(int) (((enum tree_code) (__t)->common.code))] != (tcc_type)) tree_class_check_failed (__t, (tcc_type), "../../llvm-gcc4.2-2.2.source/gcc/llvm-types.cpp", 82, __FUNCTION__); __t; })->type.size) || !Ty->isSized() || !isInt64((__extension__ ({ const tree __t = (Tr); if (tree_code_type[(int) (((enum tree_code) (__t)->common.code))] != (tcc_type)) tree_class_check_failed (__t, (tcc_type), "../../llvm-gcc4.2-2.2.source/gcc/llvm-types.cpp", 82, __FUNCTION__); __t; })->type.size), true) || getInt64((__extension__ ({ const tree __t = (Tr); if (tree_code_type[(int) (((enum tree_code) (__t)->common.code))] != (tcc_type)) tree_class_check_failed (__t, (tcc_type), "../../llvm-gcc4.2-2.2.source/gcc/llvm-types.cpp", 82, __FUNCTION__); __t; })->type.size), true) == getTargetData().getABITypeSizeInBits(Ty)) && "LLVM type size doesn't match GCC type size!"' failed.
../../llvm-gcc4.2-2.2.source/gcc/crtstuff.c:267: internal compiler error: Aborted
Please submit a full bug report,
with preprocessed source if appropriate.
See  for instructions.
make[5]: *** [32/crtbegin.o] Error 1

と、よく判らないエラーになった。

--enable-bootstrap もやりたかったが、こちらも

/home/yagi/tmp/llvmgccobj/./prev-gcc/xgcc -B/home/yagi/tmp/llvmgccobj/./prev-gcc/ -B/home/yagi/LLVM/gcc/x86_64-unknown-linux-gnu/bin/ -g -O2  -o makedepend \
  makedepend.o libcpp.a ../libiberty/libiberty.a \
     
libcpp.a(charset.o)(.text+0xf07): In function `init_iconv_desc':
: undefined reference to `alloca'
libcpp.a(charset.o)(.text+0x16fc): In function `_cpp_interpret_identifier':
: undefined reference to `alloca'
libcpp.a(directives.o)(.text+0x1158): In function `parse_assertion':
: undefined reference to `alloca'
libcpp.a(directives.o)(.text+0x271f): In function `destringize_and_run':
: undefined reference to `alloca'
libcpp.a(directives.o)(.text+0x2aca): In function `handle_assertion':
: undefined reference to `alloca'
libcpp.a(directives.o)(.text+0x2b81): more undefined references to `alloca' follow
collect2: ld returned 1 exit status
make[3]: *** [makedepend] Error 1

と、 libcpp の make で微妙なエラーで終了。 Getting Started with LLVM にも、 native コードの生成はできないとあったのであっさり諦めておく。

これでできた llvm-g++ で compile/link したバイナリは正常に動作した。
他所の LLVM で compile/link したバイトコードや、配布されているバイナリ版 gcc frontend だと、こんなエラーで止っていた……。

ERROR: Program used external function '__error' which could not be resolved!
lli[0x8cbe7c]
/lib64/tls/libc.so.6[0x31d662e2b0]
/lib64/tls/libc.so.6(gsignal+0x3d)[0x31d662e21d]
/lib64/tls/libc.so.6(abort+0xfe)[0x31d662fa1e]
lli(llvm::JIT::getPointerToNamedFunction(std::basic_string<char, std::char_trait
s<char>, std::allocator<char> > const&)+0xf1)[0x5dad21]
lli(llvm::JIT::getPointerToFunction(llvm::Function*)+0xe1)[0x5dc021]
lli[0x5dd540]
lli[0x5dd7dc]
lli[0x5de553]
lli[0x4a6fe5]
lli(llvm::MachineFunctionPass::runOnFunction(llvm::Function&)+0x2c)[0x5b2c4c]
lli(llvm::FPPassManager::runOnFunction(llvm::Function&)+0x231)[0x879de1]
lli(llvm::FunctionPassManagerImpl::run(llvm::Function&)+0xdc)[0x87a2dc]
lli(llvm::FunctionPassManager::run(llvm::Function&)+0x30)[0x87a430]
lli(llvm::JIT::runJITOnFunction(llvm::Function*)+0x38)[0x5dadd8]
lli(llvm::JIT::getPointerToFunction(llvm::Function*)+0x12d)[0x5dc06d]
lli(llvm::JIT::runFunction(llvm::Function*, std::vector<llvm::GenericValue, std:
:allocator<llvm::GenericValue> > const&)+0x4c)[0x5db0bc]
lli(llvm::ExecutionEngine::runFunctionAsMain(llvm::Function*, std::vector<std::b
asic_string<char, std::char_traits<char>, std::allocator<char> >, std::allocator
<std::basic_string<char, std::char_traits<char>, std::allocator<char> > > > cons
t&, char const* const*)+0x382)[0x5d41b2]
lli(main+0x233)[0x49c763]
/lib64/tls/libc.so.6(__libc_start_main+0xdb)[0x31d661c3fb]
lli(fmod+0x82)[0x49bc3a]

なんぞね? Program used external function '__error' which could not be resolved! とは?!

追加:
compile したノード上にだけ libltdl.so があって、実行ノードにはなくって実行時エラーになる罠。…うんこ管理人メ、何か頼むと屁理屈こねて「動かなくなる可能性が0ではないのですよ」とかって意地でもなにもしないくせに、何もしてない状況で既に動かないじゃねーか…。
$HOME/NODE01LIB/とか怪しいディレクトリ作って .so をコピっとく。ジョブのスクリプトで、ここを LD_LIBRARY_PATH に追加すればよかべぇ。 $HOME は全ノードで共有されてるので…。

2008年05月05日 (Mon) - 13:53:05 - その他雑記 - 13605x - permalink
Karma points: 5. Do you like this article? [yes/no]