gccのアセンブリコード出力部分のソースコードを読んでみたので、分かったことを書いてみました。
まぁ、分かってみると、ただのテンプレートエンジンみたいな文字列処理をしているだけでしたよ。
gccはgithub https://github.com/gcc-mirror/gcc/
にある2018-04-26のソースコードを使いました。
final()
gccの アセンブリコード 出力はfinal.cのfinal()で行います。
final()に、引数としてコード生成済みのrtxと出力先のアセンブラファイルのファイルポインタを私ます。
void
final (rtx_insn *first, FILE *file, int optimize_p)
で実際の アセンブリコード出力部分はここから、もうちょっと奥に進んだ部分です。
final() -> final_1() -> final_scan_insn() -> final_scan_insn_1()
final_scan_insn_1()も長い関数なのですが、重要なのは3つの処理です。
- insnのリストから、insnを一つ取り出し、そのinsnに対応するコード番号を取得する。
- コード番号から、テンプレートを取得する。
- テンプレートにはコード番号に対応したアセンブラコード文字列が格納されています。このテンプレートは各アーキテクチャの*.mdファイルに記載されています。
- テンプレートを使ってアセンブラ出力する。 (recog_data.operandはrecog_memoized()を呼ぶと設定されるグローバル変数で、中身はアセンブラ命令のオペランドです。)
insn_code_number = recog_memoized (insn);
...
/* Find the proper template for this insn. */
templ = get_insn_template (insn_code_number, insn);
...
/* Output assembler code from the template. */
output_asm_insn (templ, recog_data.operand);
#output_asm_insn()
output_asm_insn()内で実際にファイルにアセンブリコードを出力しています。
output_asm_insn()の最低限必要な部分だけ示すと下記になります。
void
output_asm_insn (const char *templ, rtx *operands)
{
const char *p;
int c;
int oporder[MAX_RECOG_OPERANDS];
char opoutput[MAX_RECOG_OPERANDS];
int ops = 0;
...
memset (opoutput, 0, sizeof opoutput);
p = templ;
putc ('\t', asm_out_file);
while ((c = *p++))
switch (c)
{
...
case '%':
if (*p == '%'
)
{
...
}
/* % followed by a digit outputs an operand the default way. */
else if (ISDIGIT (*p))
{
unsigned long opnum;
char *endptr;
opnum = strtoul (p, &endptr, 10);
if (this_is_asm_operands && opnum >= insn_noperands)
output_operand_lossage ("operand number out of range");
else
output_operand (operands[opnum], 0);
if (!opoutput[opnum])
oporder[ops++] = opnum;
opoutput[opnum] = 1;
p = endptr;
c = *p;
}
...
break;
default:
putc (c, asm_out_file);
}
putc ('\n', asm_out_file);
}
ざっくりとした処理の内容
- \tを出力
- テンプレートの文字列を1文字ずつ出力
- テンプレートに含まれる%数字を、数字に対応するoperandに置き換えて出力
- 改行を出力
この処理を例で示すと、templateがmovl %2, %0
で、operandが%ebx
とNULL_RTX
と%ecx
ならば、
movl %ecx, %ebx
がアセンブリコード出力されます。
gccのソースコードを読みを再開してみたのですが、ソースコード全体の理解度が上がってきたので、以前よりは、だいぶ動作が追えるようになってきた気がする。