切腹のイラスト

compiler-rtをglibcとstaticにlinkする

{
  date: "",
}

問題

% 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
...

ふえぇ

解決

% clang -rtlib=compiler-rt -static hoge.c -Wl,-unresolved-symbols=ignore-in-object-files
% file a.out
a.out: ELF 64-bit LSB executable, x86-64, version 1 (SYSV), statically linked, for GNU/Linux 3.2.0, not stripped

ヨシ!(えっ)

原因

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/ にある)。

蛇足

他には

  • muslを使う
  • glibcにパッチを当てる
  • そもそも,gccもしくはlibgccを使う

という選択肢もある。

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