GCC-3.4.6源代码学习笔记(43)

4.2.1.3.2.2.      浮点常量对象

接下来,init_emit_once初始化浮点常量。

 

init_emit_once (continue)

 

5546   REAL_VALUE_FROM_INT (dconst0,   0,  0, double_mode);

5547   REAL_VALUE_FROM_INT (dconst1,   1,  0, double_mode);

5548   REAL_VALUE_FROM_INT (dconst2,   2,  0, double_mode);

5549   REAL_VALUE_FROM_INT (dconst3,   3,  0, double_mode);

5550   REAL_VALUE_FROM_INT (dconst10, 10,  0, double_mode);

5551   REAL_VALUE_FROM_INT (dconstm1, -1, -1, double_mode);

5552   REAL_VALUE_FROM_INT (dconstm2, -2, -1, double_mode);

5553

5554   dconsthalf = dconst1;

5555   dconsthalf.exp--;

5556

5557   real_arithmetic (&dconstthird, RDIV_EXPR, &dconst1, &dconst3);

5558

5559   /* Initialize mathematical constants for constant folding builtins.

5560     These constants need to be given to at least 160 bits precision.  */

5561   real_from_string (&dconstpi,

5562     "3.1415926535897932384626433832795028841971693993751058209749445923078");

5563   real_from_string (&dconste,

5564     "2.7182818284590452353602874713526624977572470936999595749669676277241");

 

REAL_VALUE_FROM_INT用于从整数常量创建RTX浮点常量。形如dconst…都是real_value类型的全局变量。

 

279  #define REAL_VALUE_FROM_INT(r, lo, hi, mode) /                                         in real.h

280    real_from_integer (&(r), mode, lo, hi, 0)

 

接着在init_emit_once中的5554行,为浮点数常量1/2创建对象,接着在5557行,为1/3创建对象,在55615563行,则是πe

 

init_emit_once (continue)

 

5566   for (i = 0; i < (int) ARRAY_SIZE (const_tiny_rtx); i++)

5567   {

5568     REAL_VALUE_TYPE *r =

5569            (i == 0 ? &dconst0 : i == 1 ? &dconst1 : &dconst2);

5570

5571     for (mode = GET_CLASS_NARROWEST_MODE (MODE_FLOAT); mode != VOIDmode;

5572          mode = GET_MODE_WIDER_MODE (mode))

5573        const_tiny_rtx[i][(int) mode] =

5574             CONST_DOUBLE_FROM_REAL_VALUE (*r, mode);

5575

5576     const_tiny_rtx[i][(int) VOIDmode] = GEN_INT (i);

5577

5578     for (mode = GET_CLASS_NARROWEST_MODE (MODE_INT); mode != VOIDmode;

5579          mode = GET_MODE_WIDER_MODE (mode))

5580        const_tiny_rtx[i][(int) mode] = GEN_INT (i);

5581

5582      for (mode = GET_CLASS_NARROWEST_MODE (MODE_PARTIAL_INT);

5583         mode != VOIDmode;

5584           mode = GET_MODE_WIDER_MODE (mode))

5585        const_tiny_rtx[i][(int) mode] = GEN_INT (i);

5586    }

5587

5588   for (mode = GET_CLASS_NARROWEST_MODE (MODE_VECTOR_INT);

5589        mode != VOIDmode;

5590        mode = GET_MODE_WIDER_MODE (mode))

5591     const_tiny_rtx[0][(int) mode] = gen_const_vector_0 (mode);

5592

5593   for (mode = GET_CLASS_NARROWEST_MODE (MODE_VECTOR_FLOAT);

5594        mode != VOIDmode;

5595        mode = GET_MODE_WIDER_MODE (mode))

5596     const_tiny_rtx[0][(int) mode] = gen_const_vector_0 (mode);

5597

5598   for (i = (int) CCmode; i < (int) MAX_MACHINE_MODE; ++i)

5599     if (GET_MODE_CLASS ((enum machine_mode) i) == MODE_CC)

5600       const_tiny_rtx[0][i] = const0_rtx;

5601

5602   const_tiny_rtx[0][(int) BImode] = const0_rtx;

5603   if (STORE_FLAG_VALUE == 1)

5604     const_tiny_rtx[1][(int) BImode] = const1_rtx;

5605

5606 #ifdef RETURN_ADDRESS_POINTER_REGNUM

5607   return_address_pointer_rtx

5608     = gen_raw_REG (Pmode, RETURN_ADDRESS_POINTER_REGNUM);

5609 #endif

5610

5611 #ifdef STATIC_CHAIN_REGNUM

5612   static_chain_rtx = gen_rtx_REG (Pmode, STATIC_CHAIN_REGNUM);

5613

5614 #ifdef STATIC_CHAIN_INCOMING_REGNUM

5615   if (STATIC_CHAIN_INCOMING_REGNUM != STATIC_CHAIN_REGNUM)

5616     static_chain_incoming_rtx

5617       = gen_rtx_REG (Pmode, STATIC_CHAIN_INCOMING_REGNUM);

5618   else

5619 #endif

5620     static_chain_incoming_rtx = static_chain_rtx;

5621 #endif

5622

5623 #ifdef STATIC_CHAIN

5624   static_chain_rtx = STATIC_CHAIN;

5625

5626 #ifdef STATIC_CHAIN_INCOMING

5627   static_chain_incoming_rtx = STATIC_CHAIN_INCOMING;

5628 #else

5629   static_chain_incoming_rtx = static_chain_rtx;

5630 #endif

5631 #endif

5632

5633   if ((unsigned) PIC_OFFSET_TABLE_REGNUM != INVALID_REGNUM)

5634     pic_offset_table_rtx = gen_raw_REG (Pmode, PIC_OFFSET_TABLE_REGNUM);

5635 }

 

同样在上面,const_tiny_rtx是一个全局数组,它的定义为:rtx const_tiny_rtx[3][(int) MAX_MACHINE_MODE]。它记录了可能的具有各种可用模式的浮点或整型常量012。确保了这些对象的唯一性及全局性。

5574行,CONST_DOUBLE_FROM_REAL_VALUE用于从值0.01.02.0来创建浮点常量的rtx对象。

 

350    #define CONST_DOUBLE_FROM_REAL_VALUE(r, m) /                                 in real.h

351      const_double_from_real_value (r, m)

 

436    rtx

437    const_double_from_real_value (REAL_VALUE_TYPE value, enum machine_mode mode)

438    {

439      rtx real = rtx_alloc (CONST_DOUBLE);

440      PUT_MODE (real, mode);

441   

442      memcpy (&CONST_DOUBLE_LOW (real), &value, sizeof (REAL_VALUE_TYPE));

443   

444      return lookup_const_double (real);

445    }

 

下面的宏用于处理rtx对象中的浮点值。其中的XCWINT访问rtx对象的rtunion部分的hwint域。

 

1050 #define CONST_DOUBLE_LOW(r) XCWINT (r, 0, CONST_DOUBLE)                     in rtl.h

1051 #define CONST_DOUBLE_HIGH(r) XCWINT (r, 1, CONST_DOUBLE)

1052 #define CONST_DOUBLE_REAL_VALUE(r) ((struct real_value *)&CONST_DOUBLE_LOW(r))

 

在上面444行,lookup_const_double在哈希表const_double_htab中查找指定对象是否已经创建。如果找到,就直接返回这个对象,否则由该函数创建新对象并插入哈希表中。

GEN_INT是创建整数常量rtx对象的函数。

 

1882 #define GEN_INT(N)  gen_rtx_CONST_INT (VOIDmode, (HOST_WIDE_INT) (N)) in rtl.h

 

389    rtx

390    gen_rtx_CONST_INT (enum machine_mode mode ATTRIBUTE_UNUSED, HOST_WIDE_INT arg)

391    {

392      void **slot;

393   

394      if (arg >= - MAX_SAVED_CONST_INT && arg <= MAX_SAVED_CONST_INT)

395        return const_int_rtx[arg + MAX_SAVED_CONST_INT];

396   

397    #if STORE_FLAG_VALUE != 1 && STORE_FLAG_VALUE != -1

398      if (const_true_rtx && arg == STORE_FLAG_VALUE)

399        return const_true_rtx;

400    #endif

401   

402     /* Look up the CONST_INT in the hash table.  */

403      slot = htab_find_slot_with_hash (const_int_htab, &arg,

404                                 (hashval_t) arg, INSERT);

405      if (*slot == 0)

406        *slot = gen_rtx_raw_CONST_INT (VOIDmode, arg);

407   

408      return (rtx) *slot;

409    }

 

init_emit_once55915596行,gen_const_vector_0用于为向量模式创建0常量。结果亦存于const_tiny_rtx中。

 

5402 static rtx

5403 gen_const_vector_0 (enum machine_mode mode)                                         in emit-rtl.c

5404 {

5405   rtx tem;

5406   rtvec v;

5407   int units, i;

5408   enum machine_mode inner;

5409

5410   units = GET_MODE_NUNITS (mode);

5411   inner = GET_MODE_INNER (mode);

5412

5413   v = rtvec_alloc (units);

5414

5415   /* We need to call this function after we to set CONST0_RTX first.  */

5416   if (!CONST0_RTX (inner))

5417     abort ();

5418

5419   for (i = 0; i < units; ++i)

5420     RTVEC_ELT (v, i) = CONST0_RTX (inner);

5421

5422   tem = gen_rtx_raw_CONST_VECTOR (mode, v);

5423   return tem;

5424 }

 

54105411GET_MODE_NUNITSGET_MODE_INNERmode_nunits mode_inner中提取指定的元素。它们亦是由工具genmodes产生,输入至insn-modes.c文件中。mode_nunits定义了向量的大小。mode_inner定义了向量中元素的机器模式。

5406行,类型rtvec被定义为指向rtvec_def结构的指针。Rtvec_defrtunion中的一个域。

 

261    struct rtvec_def GTY(()) {                                                                               in rtl.h

262      int num_elem;         /* number of elements */

263      rtx GTY ((length ("%h.num_elem"))) elem[1];

264    };

 

5420行的RTVEC_ELT用于访问rtvec中指定的元素。

 

343    #define RTVEC_ELT(RTVEC, I) __extension__                           /                    in rtl.h

344    (*({ rtvec const _rtvec = (RTVEC); const int _i = (I);                  /

345         if (_i < 0 || _i >= GET_NUM_ELEM (_rtvec))                           /

346           rtvec_check_failed_bounds (_rtvec, _i, __FILE__, __LINE__,  /

347                                __FUNCTION__);                   /

348         &_rtvec->elem[_i]; }))

 

在上面的5416行,宏CONST0_RTXconst_tiny_rtx中选择具有指定模式的对象。

 

1789 #define CONST0_RTX(MODE) (const_tiny_rtx[0][(int) (MODE)])                       in rtl.h

 

5422gen_rtx_raw_CONST_VECTOR的定义如下

 

235  #define gen_rtx_raw_CONST_VECTOR(MODE, ARG0) /                             in genrtl.h

236      gen_rtx_fmt_E (CONST_VECTOR, (MODE), (ARG0))

 

gen_rtx_fmt_E亦是由工具gengenrtl产生并输出至genrtl.c文件。从其名字,可以知道它所创建的rtx对象仅具有一个类型为rtvec的子对象。

init_emit_once的余下部分,在5603行,STORE_FLAG_VALUE对于x86系统为1,在5606行,RETURN_ADDRESS_POINTER_REGNUM没有被定义,在561456235626STATIC_CHAIN_INCOMING_REGNUMSTATIC_CHAIN_INCOMINGSTATIC_CHAINx86系统中均没有定义。

5611行,宏STATIC_CHAIN_REGNUM指明了用于传递给函数的静态链(static chain)的寄存器的编号。对于32位的ABI(例如pentium)使用的是ecx。而对于64ABI(例如IA64ecx是一个参数寄存器,因而使用r10

在允许嵌套词法作用域的语言中,指向包含域(the enclosing scope)的活动记录(一个包含,特定函数或其他类似函数的语言构造的调用实例的,重要状态信息的数据结构)的指针——这个指针被称为静态链。在大多数这样的语言中,通常要求在调用链的某个位置,包含函数(the enclosing function)已被调用(在并发语言里,函数可能在不同的线程中被调用)。而在C/C++这样的语言里,嵌套词法作用域是不允许或受限(标准C/C++不允许函数嵌套函数),静态链不是必须的。但GNU C++提供了一个扩展,支持函数嵌套函数。

最后,init_emit_once创建保存用于访问位置无关代码中数据项基址的寄存器的rtx对象。对于64位的x86系统,PIC_OFFSET_TABLE_REGNUM被定义为INVALID_REGNUM——不创建pic_offset_table_rtx。为了避免不必要地破坏调用保存的寄存器,gcc尽可能对pic寄存器重编号。此处,起先,ebx被设为这个PIC寄存器。

4.2.2. 初始化寄存器集

回到backend_init,对于机器来说,寄存器是很宝贵的资源。在运行程序时,很多次的,需要把寄存器的内容放到内存中,使它可以被用于下一条指令,然后在需要时再把这个内容从内存中恢复回来。然而寄存器和内存间过多的交换将产生瓶颈。因此寄存器的分配必须小心仔细。为了便利寄存器的分配,寄存器,根据其用处及特定环境下其可用性,进行分组,随后组间的关系被尽可能地收集。所有这一切由函数init_regs完成。

 

561  void

562  init_regs (void)                                                                                         in regclass.c

563  {

564    /* This finishes what was started by init_reg_sets, but couldn't be done

565      until after register usage was specified.  */

566    init_reg_sets_1 ();

567 

568    init_reg_autoinc ();

569  }

 

296  static void

297  init_reg_sets_1 (void)                                                                                in regclass.c

298  {

299    unsigned int i, j;

300    unsigned int /* enum machine_mode */ m;

301    char allocatable_regs_of_mode [MAX_MACHINE_MODE];

302 

303    /* This macro allows the fixed or call-used registers

304      and the register classes to depend on target flags.  */

305 

306  #ifdef CONDITIONAL_REGISTER_USAGE

307    CONDITIONAL_REGISTER_USAGE;

308  #endif

4.2.3. 确定寄存器集

回忆在init_reg_sets中,已经收集了与目标机器相关的寄存器信息,并保存至fixed_regscall_used_regsreg_class_content。这些信息描述了,对于机器的各种变种,可用的寄存器及其能力,因此现在需要根据作为目标机器使用的变种,来细化信息。这个更新由CONDITIONAL_REGISTER_USAGE来完成。

 

1005 /* Macro to conditionally modify fixed_regs/call_used_regs.  */                   in i386.h

1006 #define CONDITIONAL_REGISTER_USAGE                              /

1007 do {                                                               /

1008     int i;                                                       /

1009     for (i = 0; i < FIRST_PSEUDO_REGISTER; i++)                        /

1010     {                                                            /

1011       fixed_regs[i] = (fixed_regs[i] & (TARGET_64BIT ? 2 : 1)) != 0;  /

1012       call_used_regs[i] = (call_used_regs[i]                          /

1013                   & (TARGET_64BIT ? 2 : 1)) != 0;            /

1014     }                                                            /

1015     if (PIC_OFFSET_TABLE_REGNUM != INVALID_REGNUM)                   /

1016     {                                                            /

1017       fixed_regs[PIC_OFFSET_TABLE_REGNUM] = 1;                    /

1018       call_used_regs[PIC_OFFSET_TABLE_REGNUM] = 1;                     /

1019     }                                                            /

1020     if (! TARGET_MMX)                                            /

1021     {                                                            /

1022       int i;                                                   /

1023       for (i = 0; i < FIRST_PSEUDO_REGISTER; i++)                     /

1024         if (TEST_HARD_REG_BIT (reg_class_contents[(int)MMX_REGS], i)) /

1025           fixed_regs[i] = call_used_regs[i] = 1;                  /

1026     }                                                            /

1027     if (! TARGET_SSE)                                              /

1028     {                                                            /

1029       int i;                                                   /

1030       for (i = 0; i < FIRST_PSEUDO_REGISTER; i++)                     /

1031         if (TEST_HARD_REG_BIT (reg_class_contents[(int)SSE_REGS], i))    /

1032           fixed_regs[i] = call_used_regs[i] = 1;                  /

1033     }                                                            /

1034     if (! TARGET_80387 && ! TARGET_FLOAT_RETURNS_IN_80387)          /

1035     {                                                            /

1036       int i;                                                   /

1037       HARD_REG_SET x;                                                 /

1038       COPY_HARD_REG_SET (x, reg_class_contents[(int)FLOAT_REGS]);     /

1039       for (i = 0; i < FIRST_PSEUDO_REGISTER; i++)                     /

1040         if (TEST_HARD_REG_BIT (x, i))                         /

1041           fixed_regs[i] = call_used_regs[i] = 1;                    /

1042     }                                                            /

1043   } while (0)

 

上面,记住对于fixed_regscall_used_regs中的每个字节,非0值表示,对于特定的机器变种,该寄存器不可用。第一个比特用于32位系统,第二个比特用于64位系统(参见6x86机器的寄存器分组)。

4.2.3.1.    确定子集及超集关系

因为寄存器集间有重合部分,某些集合是其他集合的子集。接下来就是要找出这些关系。

 

init_reg_sets_1 (continue)

 

310    /* Compute number of hard regs in each class.  */

311  

312    memset (reg_class_size, 0, sizeof reg_class_size);

313    for (i = 0; i < N_REG_CLASSES; i++)

314      for (j = 0; j < FIRST_PSEUDO_REGISTER; j++)

315        if (TEST_HARD_REG_BIT (reg_class_contents[i], j))

316          reg_class_size[i]++;

317 

318   /* Initialize the table of subunions.

319      reg_class_subunion[I][J] gets the largest-numbered reg-class

320      that is contained in the union of classes I and J.  */

321 

322    for (i = 0; i < N_REG_CLASSES; i++)

323    {

324      for (j = 0; j < N_REG_CLASSES; j++)

325      {

326        HARD_REG_SET c;

327        int k;

328 

329        COPY_HARD_REG_SET (c, reg_class_contents[i]);

330        IOR_HARD_REG_SET (c, reg_class_contents[j]);

331        for (k = 0; k < N_REG_CLASSES; k++)

332        {

333          GO_IF_HARD_REG_SUBSET (reg_class_contents[k], c,

334                            subclass1);

335          continue;

336 

337        subclass1:

338          /* Keep the largest subclass.  */           /* SPEE 900308 */

339          GO_IF_HARD_REG_SUBSET (reg_class_contents[k],

340                            reg_class_contents[(int) reg_class_subunion[i][j]],

341                            subclass2);

342          reg_class_subunion[i][j] = (enum reg_class) k;

343        subclass2:

344          ;

345        }

346      }

347    }

348 

349   /* Initialize the table of superunions.

350      reg_class_superunion[I][J] gets the smallest-numbered reg-class

351      containing the union of classes I and J.  */

352 

353    for (i = 0; i < N_REG_CLASSES; i++)

354    {

355      for (j = 0; j < N_REG_CLASSES; j++)

356      {

357        HARD_REG_SET c;

358        int k;

359 

360        COPY_HARD_REG_SET (c, reg_class_contents[i]);

361        IOR_HARD_REG_SET (c, reg_class_contents[j]);

362        for (k = 0; k < N_REG_CLASSES; k++)

363          GO_IF_HARD_REG_SUBSET (c, reg_class_contents[k], superclass);

364 

365    superclass:

366        reg_class_superunion[i][j] = (enum reg_class) k;

367      }

368    }

369 

370    /* Initialize the tables of subclasses and superclasses of each reg class.

371      First clear the whole table, then add the elements as they are found.  */

372 

373    for (i = 0; i < N_REG_CLASSES; i++)

374    {

375      for (j = 0; j < N_REG_CLASSES; j++)

376      {

377        reg_class_superclasses[i][j] = LIM_REG_CLASSES;

378        reg_class_subclasses[i][j] = LIM_REG_CLASSES;

379      }

380    }

381 

382    for (i = 0; i < N_REG_CLASSES; i++)

383    {

384      if (i == (int) NO_REGS)

385        continue;

386 

387      for (j = i + 1; j < N_REG_CLASSES; j++)

388      {

389        enum reg_class *p;

390 

391        GO_IF_HARD_REG_SUBSET (reg_class_contents[i], reg_class_contents[j],

392                       subclass);

393        continue;

394    subclass:

395        /* Reg class I is a subclass of J.

396         Add J to the table of superclasses of I.  */

397        p = &reg_class_superclasses[i][0];

398        while (*p != LIM_REG_CLASSES) p++;

399          *p = (enum reg_class) j;

400        /* Add I to the table of superclasses of J.  */

401        p = &reg_class_subclasses[j][0];

402        while (*p != LIM_REG_CLASSES) p++;

403          *p = (enum reg_class) i;

404      }

405    }

 

上面,312~316行计算每类寄存器的数目并把该值存入reg_class_size。然后322~347行找出任意2类寄存器合集的最大子集并把结果存入reg_class_subunion,而353~368行找出任意2类寄存器合集的最小超集并把结果存入reg_class_superunion。注意到在reg_class_contents中由寄存器编号索引的比特位,为1表示存在对应的寄存器。

GO_IF_HARD_REG_SUBSET (X, Y, TO)的行为是:如果XY所包含则跳到TO。然后373~405行找出被指定寄存器类别所包含的寄存器类别,反之亦然(即,如果XY所包含,YX的超类,而XY的子类)。

 

init_reg_sets_1 (continue)

 

407    /* Initialize "constant" tables.  */

408 

409    CLEAR_HARD_REG_SET (fixed_reg_set);

410    CLEAR_HARD_REG_SET (call_used_reg_set);

411     CLEAR_HARD_REG_SET (call_fixed_reg_set);

412    CLEAR_HARD_REG_SET (regs_invalidated_by_call);

413 

414    memcpy (call_fixed_regs, fixed_regs, sizeof call_fixed_regs);

415 

416    n_non_fixed_regs = 0;

417 

418    for (i = 0; i < FIRST_PSEUDO_REGISTER; i++)

419    {

420      if (fixed_regs[i])

421        SET_HARD_REG_BIT (fixed_reg_set, i);

422      else

423        n_non_fixed_regs++;

424 

425      if (call_used_regs[i])

426        SET_HARD_REG_BIT (call_used_reg_set, i);

427      if (call_fixed_regs[i])

428        SET_HARD_REG_BIT (call_fixed_reg_set, i);

429      if (CLASS_LIKELY_SPILLED_P (REGNO_REG_CLASS (i)))

430        SET_HARD_REG_BIT (losing_caller_save_reg_set, i);

431 

432      /* There are a couple of fixed registers that we know are safe to

433        exclude from being clobbered by calls:

434 

435        The frame pointer is always preserved across calls. The arg pointer

436        is if it is fixed. The stack pointer usually is, unless

437        RETURN_POPS_ARGS, in which case an explicit CLOBBER will be present.

438        If we are generating PIC code, the PIC offset table register is

439        preserved across calls, though the target can override that.  */

440 

441      if (i == STACK_POINTER_REGNUM)

442        ;

443      else if (global_regs[i])

444        SET_HARD_REG_BIT (regs_invalidated_by_call, i);

445      else if (i == FRAME_POINTER_REGNUM)

446        ;

447  #if HARD_FRAME_POINTER_REGNUM != FRAME_POINTER_REGNUM

448      else if (i == HARD_FRAME_POINTER_REGNUM)

449        ;

450  #endif

451  #if ARG_POINTER_REGNUM != FRAME_POINTER_REGNUM

452      else if (i == ARG_POINTER_REGNUM && fixed_regs[i])

453        ;

454  #endif

455  #ifndef PIC_OFFSET_TABLE_REG_CALL_CLOBBERED

456      else if (i == (unsigned) PIC_OFFSET_TABLE_REGNUM && fixed_regs[i])

457        ;

458  #endif

459      else if (CALL_REALLY_USED_REGNO_P (i))

460        SET_HARD_REG_BIT (regs_invalidated_by_call, i);

461    }

462 

463    memset (contains_reg_of_mode, 0, sizeof (contains_reg_of_mode));

464    memset (allocatable_regs_of_mode, 0, sizeof (allocatable_regs_of_mode));

465    for (m = 0; m < (unsigned int) MAX_MACHINE_MODE; m++)

466      for (i = 0; i < N_REG_CLASSES; i++)

467        if ((unsigned) CLASS_MAX_NREGS (i, m) <= reg_class_size[i])

468         for (j = 0; j < FIRST_PSEUDO_REGISTER; j++)

469           if (!fixed_regs [j] && TEST_HARD_REG_BIT (reg_class_contents[i], j)

470              && HARD_REGNO_MODE_OK (j, m))

471          {

472           contains_reg_of_mode [i][m] = 1;

473            allocatable_regs_of_mode [m] = 1;

474            break;

475          }

 

另外,对应于数组fixed_regscall_used_regscall_fixed_regs,有比特版的对象——fixed_reg_setcall_used_reg_setcall_fixed_reg_set。它们更紧凑,是编译器从现在开始使用的数据。 同时,每个寄存器类别所能使用的机器模式的信息也是非常有用的。在464行,数组allocatable_regs_of_mode表示指定的寄存器是否能用于指定的模式,而不考虑其类别。

 

你可能感兴趣的:(GCC-3.4.6源代码学习笔记(43))