2008年11月27日木曜日

MD ファイルからアセンブリが作られるまで

最後のアセンブリをファイルに fprintf (のようなこと。実際はフォーマット文字列を自前で解釈して putc(c, asm_out_file) とかしている) するところ。
  1. FINAL.C      :  final_scan_insn()
  2. FINAL.C      :   output_asm_insn()

gcc-4.3.2/gcc/final.c

/* Find the proper template for this insn. */
template = get_insn_template (insn_code_number, insn);


/* Output assembler code from the template. */
output_asm_insn (template, recog_data.operand);

template は const char * で、fprintf の format のような感じの文字列 (例 : "lea{l}\t{%a1, %0|%0, %a1}\0")

この template は、insn_data[] というテーブルを引いてるだけ。

const char *
get_insn_template (int code, rtx insn)
{
switch (insn_data[code].output_format)
{
case INSN_OUTPUT_FORMAT_SINGLE:
return insn_data[code].output.single;
case INSN_OUTPUT_FORMAT_MULTI:
return insn_data[code].output.multi[which_alternative];
case INSN_OUTPUT_FORMAT_FUNCTION:
gcc_assert (insn);
return (*insn_data[code].output.function) (recog_data.operand, insn);

default:
gcc_unreachable ();
}
}

insn_data[] は、insn-output.c の中で定数として持たれている。

const struct insn_data insn_data[] =
{
/* ../../gcc-4.3.2/gcc/config/i386/i386.md:694 */
{
"*cmpsi_ccno_1",
#if HAVE_DESIGNATED_INITIALIZERS
{ .multi = output_0 },
#else
{ 0, output_0, 0 },
#endif
0,
&operand_data[1],
2,
0,
2,
2
},
/* ../../gcc-4.3.2/gcc/config/i386/i386.md:706 */
{
"*cmpsi_minus_1",
#if HAVE_DESIGNATED_INITIALIZERS
{ .single =
#else
{
#endif
"cmp{l}\t{%1, %0|%0, %1}",
#if HAVE_DESIGNATED_INITIALIZERS
},
#else
0, 0 },
#endif
0,
&operand_data[3],
2,
0,
2,
1
},
...

さっきデバッガで見てたテンプレート "lea{l}\t{%a1, %0|%0, %a1}" はここか。

/* ../../gcc-4.3.2/gcc/config/i386/i386.md:5571 */
{
"*lea_1",
#if HAVE_DESIGNATED_INITIALIZERS
{ .single =
#else
{
#endif
"lea{l}\t{%a1, %0|%0, %a1}",
#if HAVE_DESIGNATED_INITIALIZERS
},
#else
0, 0 },
#endif
0,
&operand_data[359],
2,
0,
1,
1
},

そしてこの insn_data[] は、i386.md などの MD ファイルから genoutput で生成されている。

(define_insn "*cmpsi_ccno_1"
[(set (reg FLAGS_REG)
(compare (match_operand:SI 0 "nonimmediate_operand" "r,?mr")
(match_operand:SI 1 "const0_operand" "n,n")))]
"ix86_match_ccmode (insn, CCNOmode)"
"@
test{l}\t%0, %0
cmp{l}\t{%1, %0|%0, %1}"
[(set_attr "type" "test,icmp")
(set_attr "length_immediate" "0,1")
(set_attr "mode" "SI")])

(define_insn "*cmpsi_minus_1"
[(set (reg FLAGS_REG)
(compare (minus:SI (match_operand:SI 0 "nonimmediate_operand" "rm,r")
(match_operand:SI 1 "general_operand" "ri,mr"))
(const_int 0)))]
"ix86_match_ccmode (insn, CCGOCmode)"
"cmp{l}\t{%1, %0|%0, %1}"
[(set_attr "type" "icmp")
(set_attr "mode" "SI")])

...

(define_insn "*lea_1"
[(set (match_operand:SI 0 "register_operand" "=r")
(match_operand:SI 1 "no_seg_address_operand" "p"))]
"!TARGET_64BIT"
"lea{l}\t{%a1, %0|%0, %a1}"
[(set_attr "type" "lea")
(set_attr "mode" "SI")])

0 件のコメント: