您的位置:首页 > 编程语言

Gcc源代码分析,insn和rtx的关系

2014-01-13 11:06 525 查看
insn --> mov ax,8

rtx    ax

rtx    8

rtx    mov ax,8

上图可以很清楚的表示出insn和rtx的关系

    可以看出rtl就是一种抽象的汇编语言,汇编一般都是直接操作寄存器,内存地址,当然也有call

ret和jump指令。

而instruction既是insn的意思就是指令,既然是指令就应该有操作数,可以是0个,可以是1个,可以是2个。

rtl.def被包含进rtl.h文件中和rtl.c文件中。这3个文件是理解rtx的insn的最好的资料。

里面有rtx的定义,insn的定义,以及怎样打印出hello.c.rtl的代码!

DEF_RTL_EXPR(CALL_INSN, "call_insn", "iuueiee")

(call_insn 7 6 9 (set (reg:SI 0)

       (call (mem:QI (symbol_ref/v:SI ("printf")))

           (const_int 4))) -1 (nil)

   (nil))

第一部分7,第二部分6,第三部分9,第四部分(set (reg:SI 0)       (call (mem:QI (symbol_ref/v:SI ("printf")))     
(const_int 4)))
第五部分-1,第六部分(nil)第七部分(nil)

当然打印任何的rtx都要先打印左括号(和rtx的名字 然后打印格式字符串对应的内容,然后是),既是右括号。

(const_int 4) 也是一个rtx,它的格式字符串为"i",长度为1,当然意义是常数的值。对应insn来说是insn的编号。

DEF_RTL_EXPR(CONST_INT, "const_int", "i")

可以下一个定义:rtx的fmt既格式化字符串前3个字符依次为"iuu"的rtx就是insn。

下面是hello.c.rtl里面一部分的内容:

(call_insn 7 6 9 (set (reg:SI 0)

       (call (mem:QI (symbol_ref/v:SI ("printf")))

           (const_int 4))) -1 (nil)

   (nil))

(insn 9 7 10 (set (reg/i:SI 0)

       (const_int 0)) -1 (nil)

   (nil))

(insn 10 9 11 (use (reg/i:SI 0)) -1 (nil)

   (nil))

(jump_insn 11 10 12 (set (pc)

       (label_ref 15)) -1 (nil)

   (nil))

(barrier 12 11 13)

(note 13 12 15 "" NOTE_INSN_FUNCTION_END)

(code_label 15 13 0 1)

下面是rtl.def的一部分内容:

DEF_RTL_EXPR(INSN, "insn", "iuueiee")

DEF_RTL_EXPR(JUMP_INSN, "jump_insn", "iuueiee0")

DEF_RTL_EXPR(CALL_INSN, "call_insn", "iuueiee")

DEF_RTL_EXPR(BARRIER, "barrier", "iuu")

DEF_RTL_EXPR(CODE_LABEL, "code_label", "iuui0")

insn是rtx的一个子集,也就是insn一定是rtx,但是rtx不一定是insn。

下面的代码能解释出为什么insn输出的顺序是,自己的编号,上一个insn的标号,下一个insn的编号。请注意下面的case:"i"和case"u"的部分!

还有上面的定义中的3个insn都是"iuu"开始的


/* Printing rtl for debugging dumps.  */

static FILE *outfile;

char spaces[] = "                                                                                                                                                                ";

static int sawclose = 0;

/* Print IN_RTX onto OUTFILE.  This is the recursive part of printing.  */

static void

print_rtx (in_rtx,file)

     register rtx in_rtx;

{

  static int indent;

  register int i, j;

  register char *format_ptr;

  if (sawclose)

    {

      fprintf (outfile, "\n%s",

           (spaces + (sizeof spaces - indent * 2)));

      sawclose = 0;

    }

  if (in_rtx == 0)

    {

      fprintf (outfile, "(nil)");

      sawclose = 1;

      return;

    }

  /* print name of expression code */

  fprintf (outfile, "(%s", GET_RTX_NAME (GET_CODE (in_rtx)));

  if (in_rtx->in_struct)

    fprintf (outfile, "/s");

  if (in_rtx->volatil)

    fprintf (outfile, "/v");

  if (in_rtx->unchanging)

    fprintf (outfile, "/u");

  if (in_rtx->integrated)

    fprintf (outfile, "/i");

  if (GET_MODE (in_rtx) != VOIDmode)

    {

      /* Print REG_NOTE names for EXPR_LIST and INSN_LIST.  */

      if (GET_CODE (in_rtx) == EXPR_LIST || GET_CODE (in_rtx) == INSN_LIST)

    fprintf (outfile, ":%s", GET_REG_NOTE_NAME (GET_MODE (in_rtx)));

      else

    fprintf (outfile, ":%s", GET_MODE_NAME (GET_MODE (in_rtx)));

    }

  format_ptr = GET_RTX_FORMAT (GET_CODE (in_rtx));

  for (i = 0; i < GET_RTX_LENGTH (GET_CODE (in_rtx)); i++)

    switch (*format_ptr++)

      {

      case 'S':

      case 's':

    if (XSTR (in_rtx, i) == 0)

      fprintf (outfile, " \"\"");

    else

      fprintf (outfile, " (\"%s\")", XSTR (in_rtx, i));

    sawclose = 1;

    break;

    /* 0 indicates a field for internal use that should not be printed.  */

      case '0':

    break;

      case 'e':

    indent += 2;

    if (!sawclose)

      fprintf (outfile, " ");

    print_rtx (XEXP (in_rtx, i));

    indent -= 2;

    break;

      case 'E':

    indent += 2;

    if (sawclose)

      {

        fprintf (outfile, "\n%s",

             (spaces + (sizeof spaces - indent * 2)));

        sawclose = 0;

      }

    fprintf (outfile, "[ ");

    if (NULL != XVEC (in_rtx, i))

      {

        indent += 2;

        if (XVECLEN (in_rtx, i))

          sawclose = 1;

        for (j = 0; j < XVECLEN (in_rtx, i); j++)

          print_rtx (XVECEXP (in_rtx, i, j));

        indent -= 2;

      }

    if (sawclose)

      fprintf (outfile, "\n%s",

           (spaces + (sizeof spaces - indent * 2)));

    fprintf (outfile, "] ");

    sawclose = 1;

    indent -= 2;

    break;

      case 'i':

    fprintf (outfile, " %d", XINT (in_rtx, i));

    sawclose = 0;


    break;

      /* Print NOTE_INSN names rather than integer codes.  */

      case 'n':

    if (XINT (in_rtx, i) <= 0)

      fprintf (outfile, " %s", GET_NOTE_INSN_NAME (XINT (in_rtx, i)));

    else

      fprintf (outfile, " %d", XINT (in_rtx, i));

    sawclose = 0;

    break;

      case 'u':

    if (XEXP (in_rtx, i) != NULL)

      fprintf(outfile, " %d", INSN_UID (XEXP (in_rtx, i)));

    else

      fprintf(outfile, " 0");


    sawclose = 0;

    break;

      default:

    fprintf (stderr,

         "switch format wrong in rtl.print_rtx(). format was: %c.\n",

         format_ptr[-1]);

    abort ();

      }

  fprintf (outfile, ")");

  sawclose = 1;

}

关于GET_RTX_LENGTH,在rtl.h里面定义

#define GET_RTX_LENGTH(CODE)        (rtx_length[(int)(CODE)])

而在init_rtl函数运行的时候就已经初始化了,比如,我们研究的call_insn的长度是strlen("iuueiee")=7。

/* This is called once per compilation, before any rtx's are constructed.

   It initializes the vector `rtx_length'.  */

void

init_rtl ()

{

  int i;

  for (i = 0; i < NUM_RTX_CODE; i++)

    rtx_length[i] = strlen (rtx_format[i]);
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  gcc 分析 源代码