compiler-rtをglibcとstaticにlinkする(予定)

後で確認する為にメモを残しておく。

問題

% clang -rtlib=compiler-rt -static hoge.c
ld.lld: error: undefined symbol: __unordtf2
>>> referenced by printf_fphex.o:(__printf_fphex) in archive /usr/lib/gcc/x86_64-pc-linux-gnu/12.2.0/../../../../lib64/libc.a
>>> referenced by printf_fphex.o:(__printf_fphex) in archive /usr/lib/gcc/x86_64-pc-linux-gnu/12.2.0/../../../../lib64/libc.a
>>> referenced by printf_fp.o:(__printf_fp_l) in archive /usr/lib/gcc/x86_64-pc-linux-gnu/12.2.0/../../../../lib64/libc.a
>>> referenced 1 more times

ld.lld: error: undefined symbol: __letf2
>>> referenced by printf_fphex.o:(__printf_fphex) in archive /usr/lib/gcc/x86_64-pc-linux-gnu/12.2.0/../../../../lib64/libc.a
>>> referenced by printf_fp.o:(__printf_fp_l) in archive /usr/lib/gcc/x86_64-pc-linux-gnu/12.2.0/../../../../lib64/libc.a
...

ふえぇ

原因

4倍精度浮動小数点関連のシンボルがcompiler-rtに含まれていないのが原因。

compiler-rtにも一応実装はある( lib/builtins/comparetf2.c )が,中身はただのプリミティブ型の演算のようだ。 ターゲットが対応している以上のサイズを扱うことはできない。

CRT_HAS_128BITCRT_LDBL_128BITがそれぞれ lib/builtins/int_types.hlib/builtins/fp_lib.h に定義されていて,今回の環境では__LDBL_MANT_DIG__64(ネイティブに対応しているのが倍精度まで)だった為,4倍精度の関数はコンパイルされていない。
※clangが定義するマクロについては以下で確認できる。

% clang -dM -E -xc /dev/null

libgccではネイティブで対応している以上のサイズのものをソフトウェアで実装している(実装は libgcc/soft-fp/ にある)。

結論

glibcを使い続けるならcompiler-rtの実装を待つ(あるいはパッチを書く)しかなさげ。

そもそも

  • muslを使う
  • libgccの関数をリンクする
  • glibcにパッチを当てる

という選択肢もある。

ちなみに,天下のGoogle様は(今のところ)glibcの4倍精度浮動小数点を無効化して対応しているようだ(参考: glibc向けのパッチ )。