CodeReading: GCC "$cputype.cと$cputype.md"
Kazuki Ohta, 2006/02/10
コンパイラについての本を見ていた所、唐突にgccの中身を見たくなった。手元に有ったコード(version 4.0.1)を眺めていると、gcc/config以下に有るアーキテクチャ依存部分が目に止まった。ので、ここを読んでみる事にする。このディレクトリには様々なアーキテクチャに依存する部分が記述して有り、特定のCPUアーキテクチャについての知識に加えてgccの内部表現(RTL)にも精通している必要が有る。中々美味しそうな部分だ。
GCCの内部についてはGNU Compiler Collection (GCC) Internalsが参考になる。gcc/config以下を見てみると、.cや.hの他に.mdというファイルが見付かる。これはMachine Descriptionファイルと呼ばれるようだ。その辺りを考慮に入れつつ、重要そうな3つの章にざっと目を通した。
さて、とりあえず気になるのはgcc本体とアーキテクチャ依存部分(以下バックエンド)の橋渡しがどのようになっているかという点だ。それを理解していないと何も始まらない気がする。
まずは.mdファイルがどのように利用されるかを調べてみる。コンパイルされる事は無いだろうし、スクリプトみたいに処理されるのだろうと思いビルドシステム(gcc/config.gcc, gcc/configure.ac, gcc/Makefile.in)を覗いてみる。gcc/configure.acを覗いていると、こんなブロックが見付かった。
# --------------------------------------------------------
# Build, host, and target specific configuration fragments
# --------------------------------------------------------
# Collect build-machine-specific information.
. ${srcdir}/config.build
# Collect host-machine-specific information.
. ${srcdir}/config.host
target_gtfiles=
# Collect target-machine-specific information.
. ${srcdir}/config.gcc
extra_objs="${host_extra_objs} ${extra_objs}"
extra_gcc_objs="${host_extra_gcc_objs} ${extra_gcc_objs}"
# Default the target-machine variables that were not explicitly set.
if test x"$tm_file" = x
then tm_file=$cpu_type/$cpu_type.h; fi
if test x"$extra_headers" = x
then extra_headers=; fi
if test x$md_file = x
then md_file=$cpu_type/$cpu_type.md; fi
if test x$out_file = x
then out_file=$cpu_type/$cpu_type.c; fi
if test x"$tmake_file" = x
then tmake_file=$cpu_type/t-$cpu_type
fi
if test x"$dwarf2" = xyes
then tm_file="$tm_file tm-dwarf2.h"
fi
# Say what files are being used for the output code and MD file.
echo "Using \`$srcdir/config/$out_file' for machine-specific logic."
echo "Using \`$srcdir/config/$md_file' as machine description file."
# The following pair of rules has this effect: # genconfig is run only if the md has changed since genconfig was last run; # but the file insn-config.h is touched only when its contents actually change. # Each of the other insn-* files is handled by a similar pair of rules. # This causes an anomaly in the results of make -n # because insn-* is older than s-* # and thus make -n thinks that insn-* will be updated # and force recompilation of things that depend on it. # We use move-if-change precisely to avoid such recompilation. # But there is no way to teach make -n that it will be avoided. # Each of the insn-*.[ch] rules has a semicolon at the end, # for otherwise the system Make on SunOS 4.1 never tries # to recompile insn-*.o. To avoid problems and extra noise from # versions of make which don't like empty commands (nothing after the # trailing `;'), we call true for each. insn-config.h: s-config ; @true s-config : $(MD_DEPS) build/genconfig$(build_exeext) $(RUN_GEN) build/genconfig$(build_exeext) $(md_file) > tmp-config.h $(SHELL) $(srcdir)/../move-if-change tmp-config.h insn-config.h $(STAMP) s-config insn-conditions.c: s-conditions ; @true s-conditions : $(MD_DEPS) build/genconditions$(build_exeext) $(RUN_GEN) build/genconditions$(build_exeext) $(md_file) > tmp-conditions.c $(SHELL) $(srcdir)/../move-if-change tmp-conditions.c insn-conditions.c $(STAMP) s-conditions build/insn-conditions.o : insn-conditions.c $(CONFIG_H) $(SYSTEM_H) \ $(GTM_H) $(RTL_H) $(TM_P_H) $(REGS_H) function.h $(RECOG_H) real.h output.h \ $(FLAGS_H) hard-reg-set.h $(RESOURCE_H) toplev.h reload.h gensupport.h \ insn-constants.h coretypes.h ...以下も同じような感じの記述が続く
int
main (int argc, char **argv)
{
rtx desc;
...
if (init_md_reader_args (argc, argv) != SUCCESS_EXIT_CODE)
return (FATAL_EXIT_CODE);
...
/* Read the machine description. */
while (1)
{
desc = read_md_rtx (&pattern_lineno, &code);
if (desc == NULL)
break;
...
}
...
}
ちょっと歴史を調べてみる。gcc/read-rtl.cの冒頭には1987年のCCが。この頃にはPerlとか無かったんかな?ちょっと調べてみる。Perl Timelineによると1987年にPerl 1.000がリリースされたらしいので、read-rtl.cは丁度Perlの誕生年に書かれたソースか。スクリプト言語が生まれて来るか来ないかの時代みたいだから、まぁ使わんわな。
さて、とりあえずこれで.mdファイルの使われ方が分かった。内容はまだ全然分からんが、それは追い追い。さて、次は$cputype.cとgcc内部とのインターフェースを調べてみる。$cputype.cの方には"Target Description Macros and Functions"を記述するようだ。ドキュメントの該当部分を眺めていると14.1 The Global targetm Variableが参考になりそうだ。どうもstruct gcc_target targetmいうグローバル変数に加え、予め定められたマクロ群(ドキュメントの後半はこのマクロ群のリファレンスになっている)でマシン依存部分を抽象化しているようだ。struct gcc_targetはgcc/target.hで宣言されている。なるほどねーこいつがマシン依存を抽象化している立役者か。次はそれを初期化するTARGET_INITIALIZERマクロを見てみる。これはgcc/target-def.hで宣言されている。
/* The whole shebang. */
#define TARGET_INITIALIZER \
{ \
TARGET_ASM_OUT, \
TARGET_SCHED, \
TARGET_VECTORIZE, \
TARGET_EH_RETURN_FILTER_MODE, \
TARGET_MERGE_DECL_ATTRIBUTES, \
TARGET_MERGE_TYPE_ATTRIBUTES, \
TARGET_ATTRIBUTE_TABLE, \
TARGET_COMP_TYPE_ATTRIBUTES, \
TARGET_SET_DEFAULT_TYPE_ATTRIBUTES, \
TARGET_INSERT_ATTRIBUTES, \
TARGET_FUNCTION_ATTRIBUTE_INLINABLE_P, \
TARGET_MS_BITFIELD_LAYOUT_P, \
TARGET_ALIGN_ANON_BITFIELD, \
TARGET_INIT_BUILTINS, \
TARGET_EXPAND_BUILTIN, \
TARGET_FOLD_BUILTIN, \
TARGET_MANGLE_FUNDAMENTAL_TYPE, \
TARGET_INIT_LIBFUNCS, \
TARGET_SECTION_TYPE_FLAGS, \
TARGET_CANNOT_MODIFY_JUMPS_P, \
TARGET_BRANCH_TARGET_REGISTER_CLASS, \
TARGET_BRANCH_TARGET_REGISTER_CALLEE_SAVED, \
TARGET_CANNOT_FORCE_CONST_MEM, \
TARGET_CANNOT_COPY_INSN_P, \
TARGET_DELEGITIMIZE_ADDRESS, \
TARGET_FUNCTION_OK_FOR_SIBCALL, \
TARGET_IN_SMALL_DATA_P, \
TARGET_BINDS_LOCAL_P, \
TARGET_ENCODE_SECTION_INFO, \
TARGET_STRIP_NAME_ENCODING, \
TARGET_SHIFT_TRUNCATION_MASK, \
TARGET_VALID_POINTER_MODE, \
TARGET_SCALAR_MODE_SUPPORTED_P, \
TARGET_VECTOR_MODE_SUPPORTED_P, \
TARGET_VECTOR_OPAQUE_P, \
TARGET_RTX_COSTS, \
TARGET_ADDRESS_COST, \
TARGET_DWARF_REGISTER_SPAN, \
TARGET_FIXED_CONDITION_CODE_REGS, \
TARGET_CC_MODES_COMPATIBLE, \
TARGET_MACHINE_DEPENDENT_REORG, \
TARGET_BUILD_BUILTIN_VA_LIST, \
TARGET_GIMPLIFY_VA_ARG_EXPR, \
TARGET_GET_PCH_VALIDITY, \
TARGET_PCH_VALID_P, \
TARGET_DEFAULT_SHORT_ENUMS, \
TARGET_BUILTIN_SETJMP_FRAME_VALUE, \
TARGET_MD_ASM_CLOBBERS, \
TARGET_DWARF_CALLING_CONVENTION, \
TARGET_DWARF_HANDLE_FRAME_UNSPEC, \
TARGET_CALLS, \
TARGET_CXX, \
TARGET_HAVE_NAMED_SECTIONS, \
TARGET_HAVE_CTORS_DTORS, \
TARGET_HAVE_TLS, \
TARGET_HAVE_SRODATA_SECTION, \
TARGET_TERMINATE_DW2_EH_FRAME_INFO, \
TARGET_ASM_FILE_START_APP_OFF, \
TARGET_ASM_FILE_START_FILE_DIRECTIVE, \
TARGET_HANDLE_PRAGMA_REDEFINE_EXTNAME, \
TARGET_HANDLE_PRAGMA_EXTERN_PREFIX, \
TARGET_RELAXED_ORDERING, \
}
さて、これで$cputype.cと$cputype.mdとgcc本体との結合部分が有る程度理解出来た。次からは実際に何か1つのアーキテクチャ依存部分を読んでみる事にする。
(続く)
[ return ]