目次: GCC
GCC 8.3のバグを追った記録です。来月になったら絶対に忘れて、説明できなくなるので、できる限り詳細にメモしておきたいと思います。
再現は簡単で、下記のコードをコンパイルするとinternal compile errorになります。
float cargf(float _Complex z);
float atan2f(float y, float x);
void func(float _Complex cval, float val)
{
__builtin_cargf(cval);
__builtin_atan2f(val, 1.0f);
}
$ x86_64-unknown-elf-gcc -Wall -O2 -g a.c a.c: In function 'func': a.c:7:2: warning: statement with no effect [-Wunused-value] __builtin_cargf(cval); ^~~~~~~~~~~~~~~~~~~~~ during GIMPLE pass: forwprop a.c:9:1: internal compiler error: tree check: expected ssa_name, have var_decl in simplify_builtin_call, at tree-ssa-forwprop.c:1246 } ^ 0x1331604 tree_check_failed(tree_node const*, char const*, int, char const*, ...) ../../gcc/tree.c:9338 0x7ca7f2 tree_check(tree_node*, char const*, int, char const*, tree_code) ../../gcc/tree.h:3142 0x1135fb9 simplify_builtin_call ../../gcc/tree-ssa-forwprop.c:1246 0x113b55f execute ../../gcc/tree-ssa-forwprop.c:2527 Please submit a full bug report, with preprocessed source if appropriate. Please include the complete backtrace with any bug report. See <https://gcc.gnu.org/bugs/> for instructions.
再現にあたり重要なポイントは2点です。
なぜこの2点が重要か?については、追々説明します。この条件だけで原因が「ああ、あれか」と見当がつく人は超凄いです。GCCマスターか天才ですね。この記事は一切読む必要がないです。ちなみに私は解析に1週間近く掛かりました。辛かったです……。
このエラーはディストリビューションが配布するGCC 8.3のバイナリでは発生しません。x86_64向けのGCCでも発生させるには、下記に示すように特殊なビルド条件にする必要があります。
(※)GNUのビルドシステムが使うシステム名の表し方です。machine-vendor-operatingsystemの順で表します。
PC向けでは特殊なビルド条件ですが、ベアメタル向けのクロスコンパイラだと、割とこの条件に当てはまるものは多いです。
$ ../configure \ --target=x86_64-unknown-elf \ --prefix=/path/to/gcc/build/_install \ --disable-bootstrap \ --disable-libsanitizer \ --enable-checking=yes \ --enable-languages="c,c++" \ CFLAGS="-g -O0 -fno-inline" \ CXXFLAGS="-g -O0 -fno-inline" $ make -j8 all-gcc $ make install-gcc
ビルドコンフィグの一例を示しました。disable-bootstrapはデバッグ用ビルドオプション(CFLAGS, CXXFLAGS)を指定するために使っています(詳しくは 2021年3月30日の日記参照)。disable-libsanitizerは私の環境でビルドエラーになったので、仕方なくビルド対象から外しています。enable-languagesはFortranなどの今回使わない言語を削ってビルド時間を短縮するためです。
デバッグする対象はおなじみcc1です。なぜcc1なのかは以前書いた(2019年5月17日の日記参照)とおりです。
#### gdbでデバッグするなら $ gdb /path/to/build/_install/libexec/gcc/x86_64-unknown-elf/8.3.0/cc1 (gdb) run -quiet a.c -mtune=generic -march=x86-64 \ -g -O2 -Wall -std=c99 -o zzzzzzzz.s #### gdbserverを使うなら $ gdbserver --multi localhost:1234 \ -quiet a.c -mtune=generic -march=x86-64 \ -g -O2 -Wall -std=c99 -o zzzzzzzz.s
問題の再現と、GCCのコードを追う準備ができました。
< | 2021 | > | ||||
<< | < | 04 | > | >> | ||
日 | 月 | 火 | 水 | 木 | 金 | 土 |
- | - | - | - | 1 | 2 | 3 |
4 | 5 | 6 | 7 | 8 | 9 | 10 |
11 | 12 | 13 | 14 | 15 | 16 | 17 |
18 | 19 | 20 | 21 | 22 | 23 | 24 |
25 | 26 | 27 | 28 | 29 | 30 | - |
合計:
本日: