目次: GCC
以前(2020年5月24日の日記参照)、変数の代入操作をexpandで展開する際、代入を分割するか分割しないか、を決める条件の1つとして、optab_handler() という関数が出てきました。optab_handler() の動作を決めるgenopinitというツールの動作を調べます。
バイナリはbuild_gcc/build/genopinitに生成されます(以降build_gccはGCCのビルドディレクトリを指すものとします)。実行する際の引数は下記の通りです。
# build_gcc/Makefile
s-opinit: $(MD_DEPS) build/genopinit$(build_exeext) insn-conditions.md
$(RUN_GEN) build/genopinit$(build_exeext) $(md_file) \
insn-conditions.md -htmp-opinit.h -ctmp-opinit.c
# ビルドログ
build/genopinit ./gcc/gcc/common.md ./gcc/gcc/config/riscv/riscv.md \
insn-conditions.md -htmp-opinit.h -ctmp-opinit.c
上記のビルドログでは一時ファイルに出力していますが、最終的にはbuild_gcc/insn-opinit.h, build_gcc/insn-opinit.cの2つのファイルを生成します。
前回はoptab_handler() にブレークポイントを設定するため、enum optab_tagの値を使いました。この値はgenopinitが生成しています。
// gcc/optabs-query.h
/* Return the insn used to implement mode MODE of OP, or CODE_FOR_nothing
if the target does not have such an insn. */
inline enum insn_code
optab_handler (optab op, machine_mode mode)
{
unsigned scode = (op << 16) | mode; //★★以前はop = mov_optab, mode = E_V64SImodeでブレークを掛けた
gcc_assert (op > LAST_CONV_OPTAB);
return raw_optab_handler (scode); //★★次回以降、調べます
}
// build_gcc/insn-opinit.h
enum optab_tag {
unknown_optab,
sext_optab,
...
mov_optab, //★★この値のこと
...
};
...
typedef enum optab_tag optab;
これらの値はgensupport.cのoptab_defから生成されています。実際にoptab_defの中身を定義するのはoptabs.defファイルです。この *.defファイルは、C言語で素直に書くと重複、冗長になる情報を簡潔に表すための、いわゆるDSL(Domain Specific Language)だと思われます。
DSLっぽいものを使うとき、下記のような邪悪なincludeの使い方をします。GCC凶悪デザインパターンの1つですね。良い子は真似してはいけません。
// gcc/gensupport.c
#define OPTAB_DC(o, p, c) { #o, p, NS, ZS, NS, o, c, c, 4 },
#define OPTAB_D(o, p) { #o, p, NS, ZS, NS, o, UNKNOWN, UNKNOWN, 4 },
...
/* An array of all optabs. Note that the same optab can appear more
than once, with a different pattern. */
optab_def optabs[] = {
{ "unknown_optab", NULL, NS, ZS, NS, unknown_optab, UNKNOWN, UNKNOWN, 0 },
#include "optabs.def" //★★上記のようにoptabs.def内で使われるマクロを、都合の良い定義に変えてからinclude
};
// gcc/optabs.def
OPTAB_DC(mov_optab, "mov$a", SET) //★★マクロの定義はincludeされる場所によって違うので、展開後の結果は場所による
OPTAB_DC(movstrict_optab, "movstrict$a", STRICT_LOW_PART)
OPTAB_D (movmisalign_optab, "movmisalign$a")
...
// gcc/genopinit.c
int
main (int argc, const char **argv)
{
...
/* Emit the optab enumeration for the header file. */
fprintf (h_file, "enum optab_tag {\n");
for (i = j = 0; i < n; ++i)
{
optabs[i].op = i;
fprintf (h_file, " %s,\n", optabs[i].name); //★★optabsの名前を出力
if (optabs[i].kind != j)
last_kind[j++] = i - 1;
}
fprintf (h_file, " FIRST_CONV_OPTAB = %s,\n", optabs[last_kind[0]+1].name);
...
せっかくDSLっぽいものがあるのに、genopinitのようにコード自動生成ツールも混ぜて使うのはどうしてなんでしょう?GCCは理解不能です。
< | 2020 | > | ||||
<< | < | 06 | > | >> | ||
日 | 月 | 火 | 水 | 木 | 金 | 土 |
- | 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 | - | - | - | - |
合計:
本日:
管理者: Katsuhiro Suzuki(katsuhiro( a t )katsuster.net)
This is Simple Diary 1.0
Copyright(C) Katsuhiro Suzuki 2006-2023.
Powered by PHP 8.2.15.
using GD bundled (2.1.0 compatible)(png support.)