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
  1. /* Find the proper template for this insn.  */  
  2. template = get_insn_template (insn_code_number, insn);  

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

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

この template は、insn_data[] というテーブルを引いてるだけ。
  1. const char *  
  2. get_insn_template (int code, rtx insn)  
  3. {  
  4.   switch (insn_data[code].output_format)  
  5.     {  
  6.     case INSN_OUTPUT_FORMAT_SINGLE:  
  7.       return insn_data[code].output.single;  
  8.     case INSN_OUTPUT_FORMAT_MULTI:  
  9.       return insn_data[code].output.multi[which_alternative];  
  10.     case INSN_OUTPUT_FORMAT_FUNCTION:  
  11.       gcc_assert (insn);  
  12.       return (*insn_data[code].output.function) (recog_data.operand, insn);  
  13.   
  14.     default:  
  15.       gcc_unreachable ();  
  16.     }  
  17. }  

insn_data[] は、insn-output.c の中で定数として持たれている。
  1. const struct insn_data insn_data[] =   
  2. {  
  3.   /* ../../gcc-4.3.2/gcc/config/i386/i386.md:694 */  
  4.   {  
  5.     "*cmpsi_ccno_1",  
  6. #if HAVE_DESIGNATED_INITIALIZERS  
  7.     { .multi = output_0 },  
  8. #else  
  9.     { 0, output_0, 0 },  
  10. #endif  
  11.     0,  
  12.     &operand_data[1],  
  13.     2,  
  14.     0,  
  15.     2,  
  16.     2  
  17.   },  
  18.   /* ../../gcc-4.3.2/gcc/config/i386/i386.md:706 */  
  19.   {  
  20.     "*cmpsi_minus_1",  
  21. #if HAVE_DESIGNATED_INITIALIZERS  
  22.     { .single =  
  23. #else  
  24.     {  
  25. #endif  
  26.     "cmp{l}\t{%1, %0|%0, %1}",  
  27. #if HAVE_DESIGNATED_INITIALIZERS  
  28.     },  
  29. #else  
  30.     0, 0 },  
  31. #endif  
  32.     0,  
  33.     &operand_data[3],  
  34.     2,  
  35.     0,  
  36.     2,  
  37.     1  
  38.   },  
  39. ...  

さっきデバッガで見てたテンプレート "lea{l}\t{%a1, %0|%0, %a1}" はここか。
  1. /* ../../gcc-4.3.2/gcc/config/i386/i386.md:5571 */  
  2. {  
  3.   "*lea_1",  
  4. f HAVE_DESIGNATED_INITIALIZERS  
  5.   { .single =  
  6. lse  
  7.   {  
  8. ndif  
  9.   "lea{l}\t{%a1, %0|%0, %a1}",  
  10. f HAVE_DESIGNATED_INITIALIZERS  
  11.   },  
  12. lse  
  13.   0, 0 },  
  14. ndif  
  15.   0,  
  16.   &operand_data[359],  
  17.   2,  
  18.   0,  
  19.   1,  
  20.   1  
  21. },  

そしてこの 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 件のコメント: