目次: GCC
実はGCC 9.1ではcarg, atan2を並べてもエラーが発生しませんので、バグがどこかで直っています。GCC 9.1と8.3の動作の違いを調べることで、原因と直し方がわかるはずです。
GIMPLEを出力しながらコードを追っていくと、下記の関数でcargがatan2に変換され、その後internal compile errorになるようです。
// gcc/gcc/builtins.c
/* Fold a call to builtin carg(a+bi) -> atan2(b,a). */
static tree
fold_builtin_carg (location_t loc, tree arg, tree type)
{
if (validate_arg (arg, COMPLEX_TYPE)
&& TREE_CODE (TREE_TYPE (TREE_TYPE (arg))) == REAL_TYPE)
{
tree atan2_fn = mathfn_built_in (type, BUILT_IN_ATAN2); //★★この関数がNULL以外を返す条件がある
if (atan2_fn)
{
tree new_arg = builtin_save_expr (arg); //★★ここにくるとcarg → atan2に変換される
tree r_arg = fold_build1_loc (loc, REALPART_EXPR, type, new_arg);
tree i_arg = fold_build1_loc (loc, IMAGPART_EXPR, type, new_arg);
return build_call_expr_loc (loc, atan2_fn, 2, i_arg, r_arg);
}
}
return NULL_TREE;
}
関数mathfn_built_in() はbuiltin_info[uns_fncode].implicit_pがセットされていないとNULLを返す仕組みになっています。
// gcc/gcc/builtins.c
/* Like mathfn_built_in_1, but always use the implicit array. */
tree
mathfn_built_in (tree type, combined_fn fn)
{
return mathfn_built_in_1 (type, fn, /*implicit=*/ 1); //★★
}
/* Return mathematic function equivalent to FN but operating directly on TYPE,
if available. If IMPLICIT_P is true use the implicit builtin declaration,
otherwise use the explicit declaration. If we can't do the conversion,
return null. */
static tree
mathfn_built_in_1 (tree type, combined_fn fn, bool implicit_p)
{
built_in_function fcode2 = mathfn_built_in_2 (type, fn);
if (fcode2 == END_BUILTINS)
return NULL_TREE;
if (implicit_p && !builtin_decl_implicit_p (fcode2)) //★★implicit_pフラグがセットされないと変換されない
return NULL_TREE;
return builtin_decl_explicit (fcode2); //★★指定された数学関数のtreeを返す(今回はatan2f)
}
// gcc/gcc/tree.h
/* Return whether the standard builtin function can be used implicitly. */
static inline bool
builtin_decl_implicit_p (enum built_in_function fncode)
{
size_t uns_fncode = (size_t)fncode;
gcc_checking_assert (BUILTIN_VALID_P (fncode));
return (builtin_info[uns_fncode].decl != NULL_TREE
&& builtin_info[uns_fncode].implicit_p); //★★implicit_pフラグがセットされないと変換されない
}
// gcc/gcc/builtins.c
#define CASE_MATHFN(MATHFN) \
CASE_CFN_##MATHFN: \
fcode = BUILT_IN_##MATHFN; fcodef = BUILT_IN_##MATHFN##F ; \
fcodel = BUILT_IN_##MATHFN##L ; break;
/* Return a function equivalent to FN but operating on floating-point
values of type TYPE, or END_BUILTINS if no such function exists.
This is purely an operation on function codes; it does not guarantee
that the target actually has an implementation of the function. */
static built_in_function
mathfn_built_in_2 (tree type, combined_fn fn)
{
tree mtype;
...
switch (fn)
{
...
CASE_MATHFN (ATAN)
CASE_MATHFN (ATAN2) //★★ここにヒットしてbreak
CASE_MATHFN (ATANH)
CASE_MATHFN (CBRT)
...
default:
return END_BUILTINS;
}
mtype = TYPE_MAIN_VARIANT (type);
if (mtype == double_type_node)
return fcode;
else if (mtype == float_type_node)
return fcodef; //★★ここにくる、返り値はBUILTIN_ATAN2F
else if (mtype == long_double_type_node)
return fcodel;
...
else if (mtype == float128x_type_node)
return fcodef128x;
else
return END_BUILTINS;
}
しかし、cargf → atan2f変換自体はおかしいことではないはずです。
GCC 9.1と動作を比較してみます。
| GCC 9.1 (OK) | GCC 8.3 (NG) |
|---|---|
| analyze_functions(true) でimplicit_p: false → true | analyze_functions(true) でimplicit_p: false → true |
| pass_lower_cfでcargf → atan2fに置き換え | pass_forwpropでcargf → atan2fに置き換え |
| pass_lower_cfでimplicit_p: true → true | pass_forwpropでimplicit_p: true → true |
| pass_build_ssaでvuseがSSA_NAMEに置き換わる | (VAR_DECLのまま) |
| pass_forwpropでsimplify_builtin_call() | pass_forwpropでsimplify_builtin_call() → エラー!! |
パスの実行順序は早い順にpass_lower_cf (008t.lower), pass_build_ssa (019t.ssa), pass_forwprop (029t.forwprop1) になります。カッコ内はGCC 9.1でdump-tree-allを指定したときのダンプファイルとの対応です。8.3の場合はpass_forwprop (033t.forwprop) になります。
動作の違いはcargf() → atan2f() の変換が行われるパスです。GCC 9.1はpass_lower_cfですが、GCC 8.3はpass_forwpropです。GCC 9.1は序盤のパスでcargf() → atan2f() の変換が行われるため、pass_build_ssaでvuseが適切に書き換えられて救われるようです。
光明が見えてきました。
この記事にコメントする
目次: GCC
最初に書いておくと、vuseから追う解析は正解には至りませんでしたが、試行錯誤のあとも一応残しておきます。再現環境とデバッグの準備ができました。エラーが発生する箇所を調べます。
// gcc/gcc/tree-ssa-forwprop.c
static bool
simplify_builtin_call (gimple_stmt_iterator *gsi_p, tree callee2)
{
gimple *stmt1, *stmt2 = gsi_stmt (*gsi_p);
tree vuse = gimple_vuse (stmt2);
if (vuse == NULL)
return false;
stmt1 = SSA_NAME_DEF_STMT (vuse); //★★ここでエラー
// gcc/gcc/tree.h
/* Returns the statement which defines this SSA name. */
#define SSA_NAME_DEF_STMT(NODE) SSA_NAME_CHECK (NODE)->ssa_name.def_stmt
// gcc/gcc/tree-check.h
#define SSA_NAME_CHECK(t) TREE_CHECK (t, SSA_NAME)
// gcc/gcc/tree.h
/* When checking is enabled, errors will be generated if a tree node
is accessed incorrectly. The macros die with a fatal error. */
#if defined ENABLE_TREE_CHECKING && (GCC_VERSION >= 2007)
//★★enable-checking=yesだとこちらが有効になるので、エラーが発生する
#define TREE_CHECK(T, CODE) \
(tree_check ((T), __FILE__, __LINE__, __FUNCTION__, (CODE)))
...
#else /* not ENABLE_TREE_CHECKING, or not gcc */
...
//★★enable-checking=releaseだとこちらが有効になるので、エラーが発生しない
#define TREE_CHECK(T, CODE) (T)
// gcc/gcc/tree.h
//★★
// SSA_NAME_DEF_STMT (vuse)
// TREE_CHECK (vuse, SSA_NAME)
// tree_check (vuse, __FILE__, __LINE__, __FUNCTION__, SSA_NAME)
//
// vuseのTREE_CODEはVAR_DECL
inline tree
tree_check (tree __t, const char *__f, int __l, const char *__g, tree_code __c)
{
if (TREE_CODE (__t) != __c) //★★TREE_CODEがSSA_NAMEではないので、このチェックに引っかかる
tree_check_failed (__t, __f, __l, __g, __c, 0);
return __t;
}
正直、これを見ても「だから何??」ですよね。
GCC Internalsを見てもいまいち要領を得ませんが、変数への参照を表しているようです。エラーの原因となっているので、調べるしかありません。どこから来るのでしょうか?
// gcc/gcc/tree-ssa-forwprop.c
static bool
simplify_builtin_call (gimple_stmt_iterator *gsi_p, tree callee2)
{
//★★stmt2はイテレータgsi_pが指している先頭の要素
gimple *stmt1, *stmt2 = gsi_stmt (*gsi_p);
//★★vuseはgimple stmt2をgimple_statement_with_memory_opsにキャストしたときのvuseメンバ
tree vuse = gimple_vuse (stmt2);
if (vuse == NULL)
return false;
stmt1 = SSA_NAME_DEF_STMT (vuse); //★★ここでエラー
// gcc/gcc/gimple.h
/* Return the single VUSE operand of the statement G. */
static inline tree
gimple_vuse (const gimple *g)
{
const gimple_statement_with_memory_ops *mem_ops_stmt =
dyn_cast <const gimple_statement_with_memory_ops *> (g);
if (!mem_ops_stmt)
return NULL_TREE;
return mem_ops_stmt->vuse;
}
// gcc/gcc/gimple-iterator.h
/* Return the current stmt. */
static inline gimple *
gsi_stmt (gimple_stmt_iterator i)
{
return i.ptr;
}
このvuseメンバを設定するのはどこでしょうか?ソースコードから探すのは困難そうなので、watchpointで探しましょう。
$ gdb /path/to/build/_install/libexec/gcc/x86_64-unknown-elf/8.3.0/cc1
(gdb) r -quiet a.c -mtune=generic -march=x86-64 -g -O2 -Wall -std=c99 -o zzzzzzzz.s
...エラーが出ることを確認する...
(gdb) b tree-ssa-forwprop.c:1246
Breakpoint 1 at 0x11360b5: file ../../gcc/tree-ssa-forwprop.c, line 1246.
(gdb) r
Breakpoint 1, simplify_builtin_call (gsi_p=0x7fffffffd680,
callee2=0x7ffff74af300) at ../../gcc/tree-ssa-forwprop.c:1246
1246 stmt1 = SSA_NAME_DEF_STMT (vuse);
(gdb) p *stmt2
$2 = {code = GIMPLE_CALL, no_warning = 0, visited = 0, nontemporal_move = 0,
...
★★code = GIMPLE_CALLなのでgcallにキャストしてもう一回ダンプ
(gdb) p *(gcall *)stmt2
$3 = {<gimple_statement_with_memory_ops_base> = {<gimple_statement_with_ops_base> = {<gimple> = {code = GIMPLE_CALL, no_warning = 0, visited = 0,
nontemporal_move = 0, plf = 0, modified = 0, has_volatile_ops = 0,
pad = 0, subcode = 0, uid = 0, location = 2147483655, num_ops = 5,
bb = 0x7ffff7475410, next = 0x7ffff7476118, prev = 0x7ffff7599b90},
use_ops = 0x7ffff75b14f8}, vdef = 0x7ffff7ffbf30,
vuse = 0x7ffff7ffbf30}, ★★これ★★
call_used = {anything = 1, nonlocal = 0,
...
★★stmt2->vuseのアドレスを調べる
(gdb) p &((gcall *)stmt2)->vuse
$4 = (tree *) 0x7ffff75b30c8
エラーが発生するときのvuseは0x7ffff7ffbf30で、vuseを持っている変数 ((gcall *)stmt2)->vuseのアドレスは0x7ffff75b30c8です。デバッグ時、アドレスは毎回同じになることを利用して、先程調べたアドレスにwatchpointを設定し、何か値が書き込まれたら止めます。
★★stmt2->vuseを書き換える箇所を特定するためwatchpointを設定する
(gdb) watch *(int *)0x7ffff75b30c8
(gdb) r
...memset系で止まるところは無視...
Old value = 0
New value = -134234320
gimple_set_vuse (g=0x7ffff75b3090, vuse=0x7ffff7ffbf30)
at ../../gcc/gimple.h:2084
2084 }
それらしき関数gimple_set_vuse() が見つかりました。vuseの値も0x7ffff7ffbf30で関数simplify_builtin_call() で観測した値と一致しており、別の用事で書き換えられたわけではなさそうです。
さらに追っていくと、vuseはcfun->gimple_df->vopが元になっていることがわかり、cfun->gimple_df->vopはcreate_vop_var() によって生成されていることがわかるのですが、そこで行き詰まってしまいます。GCCはエラーメッセージからエラーが発生した箇所はすぐにわかります。しかしエラーの原因はわからないことがほとんどです。GCCのデバッグの辛いところですね。
別のアプローチが必要そうです。
この記事にコメントする
目次: 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のコードを追う準備ができました。
この記事にコメントする
目次: GCC
前回(2021年3月29日の日記参照)はconfigureオプションに --disable-bootstrapを指定してブートストラップモードを無効にしてビルドしました。ブートストラップモードが有効なときについても、メモしておこうと思います。
ブートストラップモードはホストのコンパイラでSTAGE1コンパイラをビルドし、STAGE1コンパイラを使ってSTAGE2とSTAGE3コンパイラをビルドして、ビルド結果に食い違いがないことを比較するモードです。ライブラリのビルドなどに使われる(最終的にインストールされる)のはSTAGE3のコンパイラのようです。3回GCCをビルドするので、ビルド時間は非ブートストラップモードの3倍近い時間がかかります。
ブートストラップモードのときはconfigureにCFLAGS, CXXFLAGSを指定する方法は使えません。代わりに GCCのマニュアルに記載がある通りmake BOOT_CFLAGS="-O0 -g -fno-inline" bootstrapとすれば良いです。
こちらがおそらく正規の手順で、configureにCFLAGS, CXXFLAGSを指定する方法は邪道なんでしょうけど、ブートストラップモードはビルドが遅くて辛いんだよなー……。
$ mkdir build $ cd build $ ../configure \ --prefix=`pwd`/_install \ --enable-languages=c,c++ $ make -j8 BOOT_CFLAGS="-O0 -g -fno-inline" bootstrap $ make install
ただしBOOT_CFLAGSの指定はSTAGE1には効きません。STAGE1だけは常に手堅い安定したオプションでビルドされます。
# gcc/Makefile.in
...
# Flags to pass to stage2 and later makes. They are defined
# here so that they can be overridden by Makefile fragments.
BOOT_CFLAGS= -g -O2
BOOT_LDFLAGS=
BOOT_ADAFLAGS= -gnatpg
...
# Defaults for all stages; some are overridden below.
STAGE_CFLAGS = $(BOOT_CFLAGS) ★★STAGE_CFLAGS = BOOT_CFLAGS★★
STAGE_TFLAGS = $(TFLAGS)
STAGE_CONFIGURE_FLAGS=@stage2_werror_flag@
# Defaults for stage 1; some are overridden below.
STAGE1_CFLAGS = $(STAGE_CFLAGS) ★★STAGE1_CFLAGS = STAGE_CFLAGS★★
STAGE1_CXXFLAGS = $(CXXFLAGS)
@if target-libstdc++-v3-bootstrap
# Override the above if we're bootstrapping C++.
STAGE1_CXXFLAGS = $(STAGE1_CFLAGS)
@endif target-libstdc++-v3-bootstrap
...
# By default, C and C++ are the only stage1 languages, because they are the
# only ones we require to build with the bootstrap compiler, and also the
# only ones useful for building stage2.
STAGE1_CFLAGS = @stage1_cflags@ ★★STAGE1_CFLAGSだけ無理やり上書きされる★★
STAGE1_CHECKING = @stage1_checking@
STAGE1_LANGUAGES = @stage1_languages@
当然ですがSTAGE2とSTAGE3には設定が反映されます。STAGE1コンパイラを手動で使って何かビルドする人はほぼいないと思うので、特に問題ないでしょう。
この記事にコメントする
目次: GCC
去年あたりにGCCのデバッグ環境について書きました(2019年5月17日の日記参照)。GDBでGCCの動作を調べる際に、最適化が効いていると色々デバッグ時に不都合が生じます。例えば、
通常のアプリケーションだと気になりませんが、相手は魔界GCCです。勝手にブレークポイントがずれてもらってはたまったものではないです。こういうときはGCCのビルドオプションを変えて、最適化を全てOFFにしてしまうと見やすいです。
環境はDebian Testingです。GCCは8.3を使っています。
$ mkdir build $ cd build $ ../configure \ --prefix=`pwd`/_install \ --enable-languages=c,c++ \ --disable-libsanitizer \ --disable-bootstrap \ CFLAGS="-O0 -g -fno-inline" \ CXXFLAGS="-O0 -g -fno-inline" $ make -j8 $ make install
私はCとC++ だけ使えれば良いので、--enable-languages=c,c++ を指定して、ついでにビルド時間短縮しています。C以外の言語(Fortranなど)に用事がある場合は、適宜足してください。Debian TestingでGCC 8.3をビルドするとなんでかlibsanitizerがビルドエラーになった(深追いしてません)ので、--disable-libsanitizerを付けて回避しました。環境によっては要らないかも?
また、ブートストラップモードだと、ビルドに時間がかかりすぎるので --disable-bootstrapで無効にしています。ビルドオプションは "-O0 -g -fno-inline" 最適化なし、デバッグ情報あり、インライン展開なし、です。
インストール先はどこでも良いですが、インストールするディレクトリは、build下の _installディレクトリにしています。buildディレクトリと一緒に消せて、間違って古いバイナリを使う心配がほぼないため、最近お気に入りのインストール先です。
オプション -O2 -gでビルドしたバイナリを使って、GDBでインライン関数にブレークポイントを設定すると、こんなふうになります。
/* Set the implicit flag for a builtin function. */
static inline void
set_builtin_decl_implicit_p (enum built_in_function fncode, bool implicit_p)
{
size_t uns_fncode = (size_t)fncode;
gcc_checking_assert (BUILTIN_VALID_P (fncode)
&& builtin_info[uns_fncode].decl != NULL_TREE);
builtin_info[uns_fncode].implicit_p = implicit_p; //★ここにブレークポイントを設定★
}
$ gdb /path/to/gcc/build/_install/libexec/gcc/x86_64-pc-linux-gnu/8.3.0/cc1
(gdb) b tree.h:5245
Breakpoint 1 at 0x7cc7c3: tree.h:5245. (2 locations)
(gdb) r -quiet -imultiarch x86_64-linux-gnu a.c -dumpbase a.c -mtune=generic \
-march=x86-64 -auxbase a -g -O2 -Wall -std=c99 -o zzzzzzzz.s
Breakpoint 1, set_builtin_decl_implicit_p (implicit_p=true, fncode=12304)
at ../../gcc/tree.h:5245
5245 builtin_info[uns_fncode].implicit_p = implicit_p;
(gdb) p uns_fncode
$1 = <optimized out>
一応ブレークはしますが、表示がおかしいです。引数の順序が逆ですし、fncodeの値もおかしい(16のはず)です。ローカル変数は最適化によって消されてprint不可能です。
#0 set_builtin_decl_implicit_p (implicit_p=true, fncode=12304)
at ../../gcc/tree.h:5245
#1 gimplify_addr_expr (expr_p=expr_p@entry=0x7ffff76682e0, pre_p=pre_p@entry=0x7fffffffd600, post_p=post_p@entry=0x7fffffffd190)
at ../../gcc/gimplify.c:6051
#2 0x000000000084301d in gimplify_expr (expr_p=0x7ffff76682e0, pre_p=<optimized out>, post_p=<optimized out>, gimple_test_f=<optimized out>, fallback=<optimized out>)
at ../../gcc/gimplify.c:11581
#3 0x0000000000846a55 in gimplify_call_expr (expr_p=0x7ffff77eaee0, pre_p=0x7fffffffd600, want_value=<optimized out>)
at ../../gcc/gimplify.c:3308
#4 0x00000000008436d6 in gimplify_expr (expr_p=0x7ffff77eaee0, pre_p=<optimized out>, post_p=<optimized out>, gimple_test_f=<optimized out>, fallback=<optimized out>)
at ../../gcc/gimplify.c:11506
#5 0x0000000000843c0e in gimplify_stmt (seq_p=<optimized out>, stmt_p=<optimized out>)
at ../../gcc/gimplify.c:6690
#6 gimplify_statement_list (pre_p=<optimized out>, expr_p=0x7ffff743ddd0)
at ../../gcc/gimplify.c:1764
#7 gimplify_expr (expr_p=0x7ffff743ddd0, pre_p=<optimized out>, post_p=<optimized out>, gimple_test_f=<optimized out>, fallback=<optimized out>)
at ../../gcc/gimplify.c:11963
#8 0x0000000000848f42 in gimplify_stmt (seq_p=0x7fffffffd600, stmt_p=0x7ffff743ddd0)
at ../../gcc/gimplify.c:6690
#9 gimplify_bind_expr (expr_p=expr_p@entry=0x7ffff744b1c0, pre_p=pre_p@entry=0x7fffffffd7e8)
at ../../gcc/gimplify.c:1331
#10 0x000000000084344b in gimplify_expr (expr_p=0x7ffff744b1c0, pre_p=<optimized out>, post_p=<optimized out>, gimple_test_f=<optimized out>, fallback=<optimized out>)
at ../../gcc/gimplify.c:11735
#11 0x0000000000847508 in gimplify_stmt (seq_p=0x7fffffffd7e8, stmt_p=0x7ffff744b1c0)
at ../../gcc/gimplify.c:6690
#12 gimplify_body (fndecl=0x7ffff744b100, do_parms=<optimized out>)
at ../../gcc/gimplify.c:12735
#13 0x00000000008478e6 in gimplify_function_tree (fndecl=fndecl@entry=0x7ffff744b100)
at ../../gcc/gimplify.c:12900
#14 0x00000000006f6ab0 in cgraph_node::analyze (this=0x7ffff74472e0)
at ../../gcc/cgraphunit.c:670
#15 0x00000000006f8e68 in analyze_functions (first_time=<optimized out>)
at ../../gcc/cgraphunit.c:1131
#16 0x00000000006f99c3 in symbol_table::finalize_compilation_unit (this=0x7ffff7658100)
at ../../gcc/cgraphunit.c:2691
#17 0x0000000000a689fb in compile_file ()
at ../../gcc/toplev.c:480
#18 0x00000000005bbe3d in do_compile ()
at ../../gcc/toplev.c:2132
#19 toplev::main (this=this@entry=0x7fffffffda9e, argc=<optimized out>, argc@entry=17, argv=<optimized out>, argv@entry=0x7fffffffdba8)
at ../../gcc/toplev.c:2267
#20 0x00000000005be0cf in main (argc=17, argv=0x7fffffffdba8)
at ../../gcc/main.c:39
このケースだとバックトレースに抜けはなさそうですが、表示される引数にoptimized outが多く、何が渡されたのかわかりません。
ビルドオプション -O0 -g -fno-inlineでビルドして、GDBでインライン関数にブレークを設定します。
$ gdb /path/to/gcc/build/_install/libexec/gcc/x86_64-pc-linux-gnu/8.3.0/cc1
(gdb) b tree.h:5245
Breakpoint 1 at 0x7cc7c3: tree.h:5245. (2 locations)
(gdb) r -quiet -imultiarch x86_64-linux-gnu a.c -dumpbase a.c -mtune=generic \
-march=x86-64 -auxbase a -g -O2 -Wall -std=c99 -o zzzzzzzz.s
Breakpoint 1, set_builtin_decl_implicit_p (fncode=BUILT_IN_ATAN2F,
implicit_p=true) at ../../gcc/tree.h:5245
5245 builtin_info[uns_fncode].implicit_p = implicit_p;
(gdb) p uns_fncode
$1 = 16
引数のenumも名前で出ていますし、ローカル変数も表示できます。
#0 set_builtin_decl_implicit_p (fncode=BUILT_IN_ATAN2F, implicit_p=true)
at ../../gcc/tree.h:5245
#1 0x0000000000b55843 in gimplify_addr_expr (expr_p=0x7ffff76682e0, pre_p=0x7fffffffd3f0, post_p=0x7fffffffcc08)
at ../../gcc/gimplify.c:6051
#2 0x0000000000b636a5 in gimplify_expr (expr_p=0x7ffff76682e0, pre_p=0x7fffffffd3f0, post_p=0x7fffffffcc08, gimple_test_f=0xb16def <is_gimple_call_addr(tree_node*)>, fallback=1)
at ../../gcc/gimplify.c:11581
#3 0x0000000000b4f52c in gimplify_call_expr (expr_p=0x7ffff77eaee0, pre_p=0x7fffffffd3f0, want_value=false)
at ../../gcc/gimplify.c:3308
#4 0x0000000000b6336e in gimplify_expr (expr_p=0x7ffff77eaee0, pre_p=0x7fffffffd3f0, post_p=0x7fffffffcf58, gimple_test_f=0xb5411f <is_gimple_stmt(tree)>, fallback=0)
at ../../gcc/gimplify.c:11506
#5 0x0000000000b571dd in gimplify_stmt (stmt_p=0x7ffff77eaee0, seq_p=0x7fffffffd3f0)
at ../../gcc/gimplify.c:6690
#6 0x0000000000b4bcb9 in gimplify_statement_list (expr_p=0x7ffff743ddd0, pre_p=0x7fffffffd3f0)
at ../../gcc/gimplify.c:1764
#7 0x0000000000b647a5 in gimplify_expr (expr_p=0x7ffff743ddd0, pre_p=0x7fffffffd3f0, post_p=0x7fffffffd208, gimple_test_f=0xb5411f <is_gimple_stmt(tree)>, fallback=0)
at ../../gcc/gimplify.c:11963
#8 0x0000000000b571dd in gimplify_stmt (stmt_p=0x7ffff743ddd0, seq_p=0x7fffffffd3f0)
at ../../gcc/gimplify.c:6690
#9 0x0000000000b4ad3a in gimplify_bind_expr (expr_p=0x7ffff744b1c0, pre_p=0x7fffffffd708)
at ../../gcc/gimplify.c:1331
#10 0x0000000000b63d56 in gimplify_expr (expr_p=0x7ffff744b1c0, pre_p=0x7fffffffd708, post_p=0x7fffffffd558, gimple_test_f=0xb5411f <is_gimple_stmt(tree)>, fallback=0)
at ../../gcc/gimplify.c:11735
#11 0x0000000000b571dd in gimplify_stmt (stmt_p=0x7ffff744b1c0, seq_p=0x7fffffffd708)
at ../../gcc/gimplify.c:6690
#12 0x0000000000b6610a in gimplify_body (fndecl=0x7ffff744b100, do_parms=true)
at ../../gcc/gimplify.c:12735
#13 0x0000000000b66740 in gimplify_function_tree (fndecl=0x7ffff744b100)
at ../../gcc/gimplify.c:12900
#14 0x00000000009798ad in cgraph_node::analyze (this=0x7ffff74472e0)
at ../../gcc/cgraphunit.c:670
#15 0x000000000097aa60 in analyze_functions (first_time=true)
at ../../gcc/cgraphunit.c:1131
#16 0x000000000097e71a in symbol_table::finalize_compilation_unit (this=0x7ffff7658100)
at ../../gcc/cgraphunit.c:2691
#17 0x0000000000e79db0 in compile_file ()
at ../../gcc/toplev.c:480
#18 0x0000000000e7c68a in do_compile ()
at ../../gcc/toplev.c:2132
#19 0x0000000000e7c966 in toplev::main (this=0x7fffffffda7e, argc=18, argv=0x7fffffffdb88)
at ../../gcc/toplev.c:2267
#20 0x00000000019e07e6 in main (argc=18, argv=0x7fffffffdb88)
at ../../gcc/main.c:39
バックトレースの引数表示もうまくいっているようです。
この記事にコメントする
3階で思い出したんですが、私は高所恐怖症らしく、背丈の2〜3倍くらいの高さから下を見ると、動悸がして手から変な汗が出ます。
崖、高い吊り橋など、誰でも怖いところは当然怖いんですけど、他の人が怖くないのに、私だけ怖がっている(=理解してもらえない)恐怖スポットとして、
(※)自分の背の半分以下の柵、高さがあっても頭が通るくらいの隙間が空いてる柵は怖いです。

私が怖いと感じるタイプの階段(パナソニックのサイトから引用)
何が怖いの?と聞かれますが、説明が難しいです。強いて言えば「一歩踏み出したら隙間に吸い込まれそうな恐怖感」でしょうか。隙間から落ちることはないと理解していても、それでも怖いから不思議です。
観光地の「景観スポット」はたいてい恐怖スポットです。さらに良くないことに、周りの人は私が冗談を言ってるように聞こえるようで、ふざけて段差側に押されたりします。本当に恐怖です。勘弁して……。
Facebookではいくつかコメントいただいて、興味深かったです。高いところが怖いというのは割と普遍的ですが、怖さの感じるポイントや、感じ方は人それぞれです。
閉所恐怖症なんてのも教えてもらいました。そういうのもあるのか。この年になるとどこかに閉じ込められるという経験をすることはほぼないので、自分が閉所恐怖症なのかどうかすらわからないですね。
メモ: 技術系の話はFacebookから転記しておくことにした。階段の板の名前の図を追加。
この記事にコメントする
実家を出て20年が経ちました。振り返ると、9割「3階に住んで」います。自分の意志で借りた部屋に限れば、全て3階です。住所の遍歴はこんな感じ。
こう書くと、3階に恨みでもあるか、憑りついている地縛霊みたいですが、私は人間です。さておき真面目な話、1階の部屋と3階の部屋(2〜5階もほぼ同条件)を比べ下記の点が気に入っています。
こちらから不動産屋に「3階がいい」と1度も言ったことはないので、1度くらい4階や5階と巡り合っても不思議はなかったはずですが、結局ずっと3階でした。謎の縁ですね。
メモ: 技術系の話はFacebookから転記しておくことにした。
この記事にコメントする
目次: OpenCL
一部OpenVXの話も含まれています。
目次: 一覧の一覧
この記事にコメントする
| < | 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 | - |
wiki
Linux JM
Java API
2002年
2003年
2004年
2005年
2006年
2007年
2008年
2009年
2010年
2011年
2012年
2013年
2014年
2015年
2016年
2017年
2018年
2019年
2020年
2021年
2022年
2023年
2024年
2025年
過去日記について
アクセス統計
サーバ一覧
サイトの情報合計:
本日: