GCC's bacl-end & assemble emission (2)

2.1.2. Overview of DEFINE_INSN pattern

[ A define_insn as an RTL expression containing four or five operands:

1. An optional name. The presence of a name indicates that this instruction pattern can perform a certain standard job for the RTL-generation pass of the compiler. This pass knows certain names and will use the instruction patterns with those names, if the names are defined in the machine description.

The absence of a name is indicated by writing an empty string where the name should go. Nameless instruction patterns are never used for generating RTL code, but they may permit several simpler insns to be combined later on.

Names that are not thus known and used in RTL-generation have no effect; they are equivalent to no name at all.

A name beginning with the ‘*’ character is used only for identifying the instruction in RTL dump; it’s entirely equivalent to having a nameless pattern for all other purposes.

2. The RTL template is a vector of imcomplete RTL expressions which show what the instruction should look like. It is incomplete because it may contain match_operand, match_operator, and match_dup expressions that stand for operands of the instruction.

3. A condition – a string which contains a C expression that is the final test to decide whether an insn body matches this pattern.

4. The output template: a string that says how to output matching insn as assembler code. ‘%’ in this string specifies where to substitute the value of an operand. When simple substitution isn’t general enough, a piece of C code to compute the output.

5. Optionally, a vector containing the values of attributes for insns matching this pattern. ]

 

Now define_insn is recognized, and infile currently stays at the first character of string “cmpdi_ccno_1_rex64”. Following read_rtx handles the content according to the format “sEsTV” which corresponding to the five parts of define_insn.

 

read_rtx (continued)

 

578    /* If what follows is `: mode ', read it and

579      store the mode in the rtx.  */

580 

581    i = read_skip_spaces (infile);

582    if (i == ':')

583    {

584      read_name (tmp_char, infile);

585      for (j = 0; j < NUM_MACHINE_MODES; j++)

586        if (! strcmp (GET_MODE_NAME (j), tmp_char))

587           break ;

588 

589      if (j == MAX_MACHINE_MODE)

590        fatal_with_file_and_line (infile, "unknown mode `%s'", tmp_char);

591 

592      PUT_MODE (return_rtx, (enum machine_mode) j);

593    }

594    else

595      ungetc (i, infile);

596 

597    for (i = 0; i < GET_RTX_LENGTH (GET_CODE (return_rtx)); i++)

598      switch (*format_ptr++)

599      {

600         /* 0 means a field for internal use only.

601           Don't expect it to be present in the input.  */

602        case '0':

603          break ;

604 

605        case 'e':

606        case 'u':

607          XEXP (return_rtx, i) = read_rtx (infile);

608          break ;

609 

610        case 'V':

611          /* 'V' is an optional vector: if a closeparen follows,

612             just store NULL for this element.  */

613          c = read_skip_spaces (infile);

614          ungetc (c, infile);

615          if (c == ')')

616           {

617             XVEC (return_rtx, i) = 0;

618             break ;

619           }

620          /* Now process the vector.  */

621 

622        case 'E':

623        {

624           /* Obstack to store scratch vector in.  */

625          struct obstack vector_stack;

626          int list_counter = 0;

627          rtvec return_vec = NULL_RTVEC;

628 

629          c = read_skip_spaces (infile);

630          if (c != '[')

631              fatal_expected_char (infile, '[', c);

632 

633           /* add expressions to a list, while keeping a count */

634          obstack_init (&vector_stack);

635          while ((c = read_skip_spaces (infile)) && c != ']')

636          {

637            ungetc (c, infile);

638            list_counter++;

639            obstack_ptr_grow (&vector_stack, read_rtx (infile));

640          }

641          if (list_counter > 0)

642          {

643            return_vec = rtvec_alloc (list_counter);

644            memcpy (&return_vec->elem[0], obstack_finish (&vector_stack),

645              list_counter * sizeof (rtx));

646          }

647          XVEC (return_rtx, i) = return_vec;

648          obstack_free (&vector_stack, NULL);

649           /* close bracket gotten */

650      }

651      break ;

652 

653       case 'S':

654        /* 'S' is an optional string: if a closeparen follows,

655           just store NULL for this element.  */

656        c = read_skip_spaces (infile);

657        ungetc (c, infile);

658        if (c == ')')

659        {

660           XSTR (return_rtx, i) = 0;

661           break ;

662        }

663 

664       case 'T':

665       case 's':

666      {

667          char *stringbuf;

668 

669          /* The output template slot of a DEFINE_INSN,

670             DEFINE_INSN_AND_SPLIT, or DEFINE_PEEPHOLE automatically

671             gets a star inserted as its first character, if it is

672             written with a brace block instead of a string constant.  */

673          int star_if_braced = (format_ptr[-1] == 'T');

674 

675          stringbuf = read_string (&rtl_obstack, infile, star_if_braced);

676 

677          /* For insn patterns, we want to provide a default name

678             based on the file and line, like "*foo.md:12", if the

679             given name is blank. These are only for define_insn and

680             define_insn_and_split, to aid debugging.  */

681           if (*stringbuf == '/0'

682              && i == 0

683              && (GET_CODE (return_rtx) == DEFINE_INSN

684               || GET_CODE (return_rtx) == DEFINE_INSN_AND_SPLIT))

685          {

686             char line_name[20];

687             const char *fn = (read_rtx_filename ? read_rtx_filename : "rtx");

688             const char *slash;

689            for (slash = fn; *slash; slash ++)

690            if (*slash == '/' || *slash == '//' || *slash == ':')

691               fn = slash + 1;

692             obstack_1grow (&rtl_obstack, '*');

693            obstack_grow (&rtl_obstack, fn, strlen (fn));

694            sprintf (line_name, ":%d", read_rtx_lineno );

695            obstack_grow (&rtl_obstack, line_name, strlen (line_name)+1);

696            stringbuf = (char *) obstack_finish (&rtl_obstack);

697          }

698 

699             if (star_if_braced)

700            XTMPL (return_rtx, i) = stringbuf;

701             else

702              XSTR (return_rtx, i) = stringbuf;

703      }

704      break ;

705 

706       case 'w':

707        read_name (tmp_char, infile);

708        validate_const_int (infile, tmp_char);

709  #if HOST_BITS_PER_WIDE_INT == HOST_BITS_PER_INT

710        tmp_wide = atoi (tmp_char);

711  #else

712  #if HOST_BITS_PER_WIDE_INT == HOST_BITS_PER_LONG

713        tmp_wide = atol (tmp_char);

714  #else

715        /* Prefer atoll over atoq, since the former is in the ISO C99 standard.

716            But prefer not to use our hand-rolled function above either.  */

717  #if defined (HAVE_ATOLL) || !defined (HAVE_ATOQ)

718        tmp_wide = atoll (tmp_char);

719  #else

720        tmp_wide = atoq (tmp_char);

721  #endif

722  #endif

723  #endif

724        XWINT (return_rtx, i) = tmp_wide;

725        break ;

726 

727        case 'i':

728        case 'n':

729        read_name (tmp_char, infile);

730        validate_const_int (infile, tmp_char);

731        tmp_int = atoi (tmp_char);

732        XINT (return_rtx, i) = tmp_int;

733        break ;

734 

735       default :

736        fprintf (stderr ,

737           "switch format wrong in rtl.read_rtx(). format was: %c./n",

738           format_ptr[-1]);

739        fprintf (stderr , "/tfile position: %ld/n", ftell (infile));

740        abort ();

741    }

742 

743    c = read_skip_spaces (infile);

744    if (c != ')')

745      fatal_expected_char (infile, ')', c);

746 

747    return return_rtx;

748  }

 

‘S’, ‘T’, ‘s’ are almost same, except that ‘S’ is optonal, and ‘T’ is dependent on RTL reader. And more concretely, if string begins with ‘*’ or ‘@’, ‘T’ requires different explaination. Function read_string retrieves the content.

 

325  static char *

326  read_string (struct obstack *ob, FILE *infile, int star_if_braced)                    in read-rtl.c

327  {

328    char *stringbuf;

329    int saw_paren = 0;

330    int c;

331 

332    c = read_skip_spaces (infile);

333    if (c == '(')

334    {

335      saw_paren = 1;

336      c = read_skip_spaces (infile);

337    }

338 

339    if (c == '"')

340      stringbuf = read_quoted_string (ob, infile);

341    else if (c == '{')

342    {

343      if (star_if_braced)

344        obstack_1grow (ob, '*');

345      stringbuf = read_braced_string (ob, infile);

346    }

347    else

348      fatal_with_file_and_line (infile, "expected `/"' or `{', found `%c'", c);

349 

350    if (saw_paren)

351    {

352      c = read_skip_spaces (infile);

353      if (c != ')')

354        fatal_expected_char (infile, ')', c);

355    }

356 

357    return stringbuf;

358  }

 

In md file, the output template in define_insn patterns may be a string enclosed in ‘”’, which commonly tells how to output matching insn as assembler code. But if it begins with ‘*’, following string is assumed be a piece of C program. Other exception includes ‘@’, which indicates a series of templates, each on a separate line. And if the output template is written as a brace block, it is assumed to be C code. However, when creating RTL object, only one style stays – the string form. Above, from line 341 to 345, brace block is replaced by string with star head. Line 681 to 696 create the internal name in case the pattern name begins with ‘*’. At line 700 and 702 in read_rtx , XTMPL and XSTR both access the string in the rtstr field of rtunion but with different validating condition.

Then comes the ‘E’ which corresponds to

[(set (reg 17)

       (compare (match_operand:DI 0 "nonimmediate_operand" "r,?mr")

               (match_operand:DI 1 "const0_operand" "n,n")))]

This part must be enclosed with “[]”. Above at line 630 in read_rtx does the test, and as the content itself is an expression, so read_rtx is recursed at line 639 to handle the expression further. Here it is the set expression, and we can find following defintion in rtl.def.

 

746  DEF_RTL_EXPR(SET, "set", "ee", 'x')

 

The expression has two children. So at line 605, read_rtx is recursed again, once for reg expression, and once for compare expression. No doubtly, compare expression in rtl.def also has two children of expression (‘e’), which are both match_operand expression.

 

129  DEF_RTL_EXPR(MATCH_OPERAND, "match_operand", "iss", 'm')

130  DEF_RTL_EXPR(REG, "reg", "i00", 'o')

 

Guided by format string, it is easy to travel round by read_rtx , and in the end we can get an rtx object of above pattern as following:

http://hi.csdn.net/attachment/201104/16/4457637_130291210053ob.jpgt1

 

figure 1  : genconditions - example of define_insn pattern

In the same way, all patterns except define_constants in the machine description file are treated and allocated with an rtx object like that above. Next this rtx object needs to be recorded by some way.

 

264  static void

265  process_rtx (rtx desc, int lineno)                                                           in gensupport.c

266  {

267    switch (GET_CODE (desc))

268    {

269      case DEFINE_INSN:

270        queue_pattern (desc, &define_insn_tail , read_rtx_filename , lineno);

271        break ;

272 

273      case DEFINE_COND_EXEC:

274        queue_pattern (desc, &define_cond_exec_tail , read_rtx_filename , lineno);

275         break ;

276 

277      case DEFINE_ATTR:

278        queue_pattern (desc, &define_attr_tail , read_rtx_filename , lineno);

279        break ;

280 

281      case INCLUDE:

282        process_include (desc, lineno);

283        break ;

284 

285      case DEFINE_INSN_AND_SPLIT:

286      {

287        const char *split_cond;

288        rtx split;

289        rtvec attr;

290        int i;

291 

292        /* Create a split with values from the insn_and_split.  */

293        split = rtx_alloc (DEFINE_SPLIT);

294 

295        i = XVECLEN (desc, 1);

296        XVEC (split, 0) = rtvec_alloc (i);

297        while (--i >= 0)

298        {

299          XVECEXP (split, 0, i) = copy_rtx (XVECEXP (desc, 1, i));

300          remove_constraints (XVECEXP (split, 0, i));

301        }

302 

303        /* If the split condition starts with "&&", append it to the

304          insn condition to create the new split condition.  */

305        split_cond = XSTR (desc, 4);

306        if (split_cond[0] == '&' && split_cond[1] == '&')

307           split_cond = concat (XSTR (desc, 2), split_cond, NULL);

308        XSTR (split, 1) = split_cond;

309        XVEC (split, 2) = XVEC (desc, 5);

310        XSTR (split, 3) = XSTR (desc, 6);

311 

312        /* Fix up the DEFINE_INSN.  */

313        attr = XVEC (desc, 7);

314        PUT_CODE (desc, DEFINE_INSN);

315        XVEC (desc, 4) = attr;

316 

317        /* Queue them.  */

318        queue_pattern (desc, &define_insn_tail , read_rtx_filename , lineno);

319        queue_pattern (split, &other_tail , read_rtx_filename , lineno);

320        break ;

321      }

322 

323      default :

324        queue_pattern (desc, &other_tail , read_rtx_filename , lineno);

325        break ;

326    }

327  }

 

Instructions and attributes are close related, but till now we still need to save them separatly, function queue_pattern just puts the specified rtx object into the corresponding list.

 

139  static void

140  queue_pattern (rtx pattern, struct queue_elem ***list_tail,                             in gensupport.c

141                 const char *filename, int lineno)

142  {

143    struct queue_elem *e = xmalloc (sizeof (*e));

144    e->data = pattern;

145    e->filename = filename;

146    e->lineno = lineno;

147    e->next = NULL;

148    **list_tail = e;

149    *list_tail = &e->next;

150  }

 

Above, at line 281 in process_rtx , in machine description file, we can include other machine description files by using include statement. Here in process_include , these included machine description files will be read in and treated in the same way. Other special pattern is define_insn_and_split. It is combined pattern; here it is separated into define_insn and define_split. We see the treatment by an exmaple in following:

 

4225 (define_insn_and_split "*fix_truncsi_1"                                                       in i386.md

4226   [(set (match_operand:SI 0 "nonimmediate_operand" "=m,?r")

4227        (fix:SI (match_operand 1 "register_operand" "f,f")))]

4228   "TARGET_80387 && FLOAT_MODE_P (GET_MODE (operands[1]))

4229    && !reload_completed && !reload_in_progress

4230    && !SSE_FLOAT_MODE_P (GET_MODE (operands[1]))"

4231   "#"

4232   "&& 1"

4233   [(const_int 0)]

4234 {

4235   ix86_optimize_mode_switching = 1;

4236   operands[2] = assign_386_stack_local (HImode, 1);

4237   operands[3] = assign_386_stack_local (HImode, 2);

4238   if (memory_operand (operands[0], VOIDmode))

4239     emit_insn (gen_fix_truncsi_memory (operands[0], operands[1],

4240                                     operands[2], operands[3]));

4241   else

4242   {

4243     operands[4] = assign_386_stack_local (SImode, 0);

4244     emit_insn (gen_fix_truncsi_nomemory (operands[0], operands[1],

4245                                      operands[2], operands[3],

4246                                      operands[4]));

4247   }

4248   DONE;

4249 }

4250   [(set_attr "type" "fistp")

4251    (set_attr "mode" "SI")])

 

This pattern after treated in read_rtx , we can get following rtx object.

t2

figure 2  : genconditions - example of define_insn_and_split pattern, figure 1

After processed by case block at line 285, we can get two rtx objects as following:

t3

figure 3  : genconditons - example of define_insn_and_split pattern, figure 2

t4

figure 4  : gencodntion - example of define_insn_and_split pattern, figure 3

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值