Studying note of GCC-3.4.6 source (41)

来源:互联网 发布:php 遍历对象 编辑:程序博客网 时间:2024/06/06 10:04

4.2. Initialize the back-end

After handling command options, do_compile will do initialization for back-end.

 

do_compile (continue)

 

4638   /* Don't do any more if an error has already occurred.  */

4639   if (!errorcount)

4640   {

4641     /* This must be run always, because it is needed to compute the FP

4642         predefined macros, such as __LDBL_MAX__, for targets using non

4643         default FP formats.  */

4644     init_adjust_machine_modes ();

4645

4646     /* Set up the back-end if requested.  */

4647     if (!no_backend)

4648          backend_init ();

 

At line 4644, init_adjust_machine_modes is target dependent and generated by back-end tools genmodes. It determines the attributions of machine mode of extended floating which is used for IEEE extended floating point - a twelve byte floating point number.

 

516  void

517  init_adjust_machine_modes (void)                                                               in insn-modes.c

518  {

519    size_t s ATTRIBUTE_UNUSED;

520 

521    /* config/i386/i386-modes.def:35 */

522    s = TARGET_128BIT_LONG_DOUBLE ? 16 : 12;

523    mode_size[XFmode] = s;

524    mode_base_align[XFmode] = s & (~s + 1);

525    mode_size[XCmode] = 2*s;

526    mode_base_align[XCmode] = s & (~s + 1);

527 

528    /* config/i386/i386-modes.def:36 */

529    s = TARGET_128BIT_LONG_DOUBLE ? 16 : 4;

530    mode_base_align[XFmode] = s;

531    mode_base_align[XCmode] = s;

532 

533    /* config/i386/i386-modes.def:34 */

534    REAL_MODE_FORMAT (XFmode) = (TARGET_128BIT_LONG_DOUBLE? &ieee_extended_intel_128_format: TARGET_96_ROUND_53_LONG_DOUBLE? &ieee_extended_intel_96_round_53_format : &ieee_extended_intel_96_format);

535  }

 

Next, at line 4648, if we don’t require only preprocessing, backend_init will be called.

 

4495 static void

4496 backend_init (void)                                                                                   in toplev.c

4497 {

4498   init_emit_once (debug_info_level == DINFO_LEVEL_NORMAL

4499                || debug_info_level == DINFO_LEVEL_VERBOSE

4500 #ifdef VMS_DEBUGGING_INFO

4501                  /* Enable line number info for traceback.  */

4502                  || debug_info_level > DINFO_LEVEL_NONE

4503 #endif

4504                  || flag_test_coverage

4505                  || warn_notreached);

4506

4507   init_regs ();

4508   init_fake_stack_mems ();

4.2.1. Create unique shared objects of back-end

Like the front-end, the compiler also uses delicate data structures for the back-end. Below, function init_emit_once creates some permanent unique rtl objects shared between all functions in the back-end (the back-end uses rtl tree instead of the intermediate tree used by the front-end).

 

5443 void

5444 init_emit_once (int line_numbers)                                                                      in emit-rtl.c

5445 {

5446   int i;

5447   enum machine_mode mode;

5448   enum machine_mode double_mode;

5449

5450   /* We need reg_raw_mode, so initialize the modes now.  */

5451   init_reg_modes_once ();

5452

5453   /* Initialize the CONST_INT, CONST_DOUBLE, and memory attribute hash

5454     tables.  */

5455   const_int_htab = htab_create_ggc (37, const_int_htab_hash,

5456                                const_int_htab_eq, NULL);

5457

5458   const_double_htab = htab_create_ggc (37, const_double_htab_hash,

5459                                   const_double_htab_eq, NULL);

5460

5461   mem_attrs_htab = htab_create_ggc (37, mem_attrs_htab_hash,

5462                                mem_attrs_htab_eq, NULL);

5463   reg_attrs_htab = htab_create_ggc (37, reg_attrs_htab_hash,

5464                                reg_attrs_htab_eq, NULL);

5465

5466   no_line_numbers = ! line_numbers;

5467

5468   /* Compute the word and byte modes.  */

5469

5470   byte_mode = VOIDmode;

5471   word_mode = VOIDmode;

5472   double_mode = VOIDmode;

5473

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

5475        mode = GET_MODE_WIDER_MODE (mode))

5476   {

5477     if (GET_MODE_BITSIZE (mode) == BITS_PER_UNIT

5478            && byte_mode == VOIDmode)

5479          byte_mode = mode;

5480

5481     if (GET_MODE_BITSIZE (mode) == BITS_PER_WORD

5482            && word_mode == VOIDmode)

5483          word_mode = mode;

5484   }

5485

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

5487        mode = GET_MODE_WIDER_MODE (mode))

5488   {

5489     if (GET_MODE_BITSIZE (mode) == DOUBLE_TYPE_SIZE

5490           && double_mode == VOIDmode)

5491          double_mode = mode;

5492  }

5493

5494   ptr_mode = mode_for_size (POINTER_SIZE, GET_MODE_CLASS (Pmode), 0);

4.2.1.1.    Set registers’ mode

In init_emit_once, at line 5451, init_reg_modes_once initializes reg_raw_modes for all hard registers available for the specified system. reg_raw_modes, corresponding to every hard register, records the widest mode object that it can contain. This will be a MODE_INT mode if the register can hold integers. Otherwise it will be a MODE_FLOAT or a MODE_CC mode, whichever is valid for the register. This mode is determined by choose_hard_reg_mode.

 

539  void

540  init_reg_modes_once (void)                                                                        in regclass.c

541  {

542    int i;

543 

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

545    {

546      reg_raw_mode[i] = choose_hard_reg_mode (i, 1, false);

547 

548      /* If we couldn't find a valid mode, just use the previous mode.

549        ??? One situation in which we need to do this is on the mips where

550             HARD_REGNO_NREGS (fpreg, [SD]Fmode) returns 2. Ideally we'd like

551            to use DF mode for the even registers and VOIDmode for the odd

552            (for the cpu models where the odd ones are inaccessible).  */

553      if (reg_raw_mode[i] == VOIDmode)

554            reg_raw_mode[i] = i == 0 ? word_mode : reg_raw_mode[i-1];

555    }

556  }

 

choose_hard_reg_mode is machine dependence. For x86 machine, it is defined as below:

 

647  enum machine_mode

648  choose_hard_reg_mode (unsigned int regno ATTRIBUTE_UNUSED,              in regclass.c

649                      unsigned int nregs, bool call_saved)

650  {

651    unsigned int /* enum machine_mode */ m;

652    enum machine_mode found_mode = VOIDmode, mode;

653 

654    /* We first look for the largest integer mode that can be validly

655      held in REGNO. If none, we look for the largest floating-point mode.

656      If we still didn't find a valid mode, try CCmode.  */

657 

658    for (mode = GET_CLASS_NARROWEST_MODE (MODE_INT);

659         mode != VOIDmode;

660         mode = GET_MODE_WIDER_MODE (mode))

661      if ((unsigned) HARD_REGNO_NREGS (regno, mode) == nregs

662            && HARD_REGNO_MODE_OK (regno, mode)

663            && (! call_saved || ! HARD_REGNO_CALL_PART_CLOBBERED (regno, mode)))

664        found_mode = mode;

665 

666    if (found_mode != VOIDmode)

667      return found_mode;

668 

669    for (mode = GET_CLASS_NARROWEST_MODE (MODE_FLOAT);

670         mode != VOIDmode;

671         mode = GET_MODE_WIDER_MODE (mode))

672      if ((unsigned) HARD_REGNO_NREGS (regno, mode) == nregs

673            && HARD_REGNO_MODE_OK (regno, mode)

674            && (! call_saved || ! HARD_REGNO_CALL_PART_CLOBBERED (regno, mode)))

675        found_mode = mode;

676 

677    if (found_mode != VOIDmode)

678      return found_mode;

679 

680    for (mode = GET_CLASS_NARROWEST_MODE (MODE_VECTOR_FLOAT);

681         mode != VOIDmode;

682         mode = GET_MODE_WIDER_MODE (mode))

683      if ((unsigned) HARD_REGNO_NREGS (regno, mode) == nregs

684            && HARD_REGNO_MODE_OK (regno, mode)

685            && (! call_saved || ! HARD_REGNO_CALL_PART_CLOBBERED (regno, mode)))

686        found_mode = mode;

687 

688    if (found_mode != VOIDmode)

689      return found_mode;

690 

691    for (mode = GET_CLASS_NARROWEST_MODE (MODE_VECTOR_INT);

692         mode != VOIDmode;

693         mode = GET_MODE_WIDER_MODE (mode))

694      if ((unsigned) HARD_REGNO_NREGS (regno, mode) == nregs

695            && HARD_REGNO_MODE_OK (regno, mode)

696            && (! call_saved || ! HARD_REGNO_CALL_PART_CLOBBERED (regno, mode)))

697        found_mode = mode;

698 

699    if (found_mode != VOIDmode)

700      return found_mode;

701 

702   /* Iterate over all of the CCmodes.  */

703    for (m = (unsigned int) CCmode; m < (unsigned int) NUM_MACHINE_MODES; ++m)

704    {

705      mode = (enum machine_mode) m;

706      if ((unsigned) HARD_REGNO_NREGS (regno, mode) == nregs

707            && HARD_REGNO_MODE_OK (regno, mode)

708             && (! call_saved || ! HARD_REGNO_CALL_PART_CLOBBERED (regno, mode)))

709            return mode;

710    }

711 

712    /* We can't find a mode valid for this register.  */

713    return VOIDmode;

714  }

 

choose_hard_reg_mode finds out the largest mode specified register can hold, the basic information about registers has already ready this moment and we will come to this topic soon, here we just keep in mind that every register is known belong to certain mode. In x86 machine, macro at line 663, 674, 696, 708, HARD_REGNO_CALL_PART_CLOBBERED is defined as 0.

mode_precision, mode_wider, class_narrowest_mode are all global arrays, their content are dependent on the target machine, which are generated from machmode.def and ‘target’-mode.def (i386-mode.def here) by genmodes tool. They are contained in the generated file insn-modes.h. By carefully checking the file, no Pmode (mode of pointer) related information is generated, as Pmode is architecture dependent, and it is the alias of certain mode, for example, SImode or DImode.

mode_precision records the effective bits of the mode, mode_wider records the next wider mode for the specified mode, for the widest mode of every class, the next wider mode is VIODmode. While class_narrowest_mode records the narrowest mode for specified class.

As we have seen in section Initialize registers sets, the registers available on x86 machine, their number, the class they belong to are given by Table 6: register classes for x86 machine, macros like *_REGNO_P ensure specified register is the expected type, for example, FP_REGNO_P check whether register specified by REGNO is a register for float.

 

1055 #define HARD_REGNO_NREGS(REGNO, MODE)   /                                     in i386.h

1056   (FP_REGNO_P (REGNO) || SSE_REGNO_P (REGNO)||MMX_REGNO_P (REGNO)/

1057    ? (COMPLEX_MODE_P (MODE) ? 2 : 1)                              /

1058    : ((MODE) == XFmode                                           /

1059     ? (TARGET_64BIT ? 2 : 3)                                    /

1060     : (MODE) == XCmode                                          /

1061     ? (TARGET_64BIT ? 4 : 6)                                    /

1062     : ((GET_MODE_SIZE (MODE) + UNITS_PER_WORD - 1) / UNITS_PER_WORD)))

 

From HARD_REGNO_NREGS, we can see that register for FP, SSE, and MMX is so big, it just assumes that one such register can hold all kinds of mode except complex ones. For other registers, in 32bits machine of x86, they will be of size 4 bytes (size of WORD here), and XFmode and XCmode are fixed.

Though HARD_REGNO_NREGS does the rough selection by size, it needs ensure that the specified register is suitable for the mode. ix86_hard_regno_mode_ok takes the work.

 

1109 #define HARD_REGNO_MODE_OK(REGNO, MODE)   /                                  in i386.h

1110    ix86_hard_regno_mode_ok ((REGNO), (MODE))

 

14926 int

14927 ix86_hard_regno_mode_ok (int regno, enum machine_mode mode)                     in i386.c

14928 {

14929   /* Flags and only flags can only hold CCmode values.  */

14930   if (CC_REGNO_P (regno))

14931     return GET_MODE_CLASS (mode) == MODE_CC;

14932   if (GET_MODE_CLASS (mode) == MODE_CC

14933       || GET_MODE_CLASS (mode) == MODE_RANDOM

14934       || GET_MODE_CLASS (mode) == MODE_PARTIAL_INT)

14935     return 0;

14936   if (FP_REGNO_P (regno))

14937     return VALID_FP_MODE_P (mode);

14938   if (SSE_REGNO_P (regno))

14939   {

14940     /* HACK! We didn't change all of the constraints for SSE1 for the

14941     scalar modes on the branch. Fortunately, they're not required

14942     for ABI compatibility.  */

14943     if (!TARGET_SSE2 && !VECTOR_MODE_P (mode))

14944       return VALID_SSE_REG_MODE (mode);

14945

14946     /* We implement the move patterns for all vector modes into and

14947       out of SSE registers, even when no operation instructions

14948       are available.  */

14949     return (VALID_SSE_REG_MODE (mode)

14950           || VALID_SSE2_REG_MODE (mode)

14951           || VALID_MMX_REG_MODE (mode)

14952           || VALID_MMX_REG_MODE_3DNOW (mode));

14953   }

14954   if (MMX_REGNO_P (regno))

14955   {

14956     /* We implement the move patterns for 3DNOW modes even in MMX mode,

14957       so if the register is available at all, then we can move data of

14958       the given mode into or out of it.  */

14959     return (VALID_MMX_REG_MODE (mode)

14960           || VALID_MMX_REG_MODE_3DNOW (mode));

14961   }

14962   /* We handle both integer and floats in the general purpose registers.

14963     In future we should be able to handle vector modes as well.  */

14964   if (!VALID_INT_MODE_P (mode) && !VALID_FP_MODE_P (mode))

14965     return 0;

14966   /* Take care for QImode values - they can be in non-QI regs, but then

14967     they do cause partial register stalls.  */

14968   if (regno < 4 || mode != QImode || TARGET_64BIT)

14969     return 1;

14970   return reload_in_progress || reload_completed || !TARGET_PARTIAL_REG_STALL;

14971 }

 

Above, at line 14930, CC_REGNO_P checks if specified register belongs to CC class, for x86 machine, registers (note not hard register) flags (register number 17), fpsr (register number 18) are the only registers for this purpose. Other *_REGNO_P acts in similar way. And from above VALID_* macros, we can see which types of data the registers can hold. Remember that for 32 bits ABI of x86 machine, Pmode is alias of SImode. Only registers of MMX and INT can hold address in the machine (supports SImode).

 

1064 #define VALID_SSE2_REG_MODE(MODE) /                                            in i386.h

1065     ((MODE) == V16QImode || (MODE) == V8HImode || (MODE) == V2DFmode    /

1066      || (MODE) == V2DImode || (MODE) == DFmode)

1067

1068 #define VALID_SSE_REG_MODE(MODE)                                  /

1069     ((MODE) == TImode || (MODE) == V4SFmode || (MODE) == V4SImode    /

1070      || (MODE) == SFmode || (MODE) == TFmode)

1071

1072 #define VALID_MMX_REG_MODE_3DNOW(MODE) /

1073     ((MODE) == V2SFmode || (MODE) == SFmode)

1074

1075 #define VALID_MMX_REG_MODE(MODE)                                /

1076     ((MODE) == DImode || (MODE) == V8QImode || (MODE) == V4HImode   /

1077      || (MODE) == V2SImode || (MODE) == SImode)

 

1084 #define VALID_FP_MODE_P(MODE)                                         /

1085     ((MODE) == SFmode || (MODE) == DFmode || (MODE) == XFmode          /

1086      || (MODE) == SCmode || (MODE) == DCmode || (MODE) == XCmode)     /

1087

1088 #define VALID_INT_MODE_P(MODE)                                       /

1089     ((MODE) == QImode || (MODE) == HImode || (MODE) == SImode            /

1090      || (MODE) == DImode                                         /

1091      || (MODE) == CQImode || (MODE) == CHImode || (MODE) == CSImode  /

1092      || (MODE) == CDImode                                       /

1093      || (TARGET_64BIT && ((MODE) == TImode || (MODE) == CTImode              /

1094          || (MODE) == TFmode || (MODE) == TCmode)))

 

原创粉丝点击