Studying note of GCC-3.4.6 source (42)

4.2.1.2.    Initialize hash tables

Simliar with the front-end, the back-end also uses hashtable to cache commonly used and shared objects. In later sections, with the compilation, we see the meaning of the elements in these hashtable.

Then in init_emit_once, between line 5474 ~ 5494, finds the mode fits byte type, word type and double type, while ptr_mode is determined by mode_for_size at line 5494.

4.2.1.3.    Create rtl objects

4.2.1.3.1.            Rtl language

Now, init_emit_once begins to create unique rtx objects. Unlike the tree used by the front-end, the back-end uses the tree constructed by rtx objects. The node in the tree of the front-end is close to source language. But RTL is much simpler than source language, so we can translate RTL to assemble language for the target machine much easier and can be in a uniform way. In RTL language, code is used to describe the aspects of action to take. rtx_code is defined in rtl.h as below.

 

41    #define RTX_CODE     enum rtx_code                                                                      in rtl.h

42    enum rtx_code  {

43   

44    #define DEF_RTL_EXPR(ENUM, NAME, FORMAT, CLASS)   ENUM ,

45    #include "rtl.def"          /* rtl expressions are documented here */

46    #undef DEF_RTL_EXPR

47   

48      LAST_AND_UNUSED_RTX_CODE};   /* A convenient way to get a value for

49                            NUM_RTX_CODE.

50                            Assumes default enum value assignment.  */

 

Rtl.def contains expression definitions and descriptions for all targets. In the file, all rtx objects are given in form of DEF_RTL_EXPR(ENUM, NAME, FORMAT, CLASS). By defining DEF_RTL_EXPR accordingly like here, we can get corresponding data for the rtx objects (i.e, rtx_class, rtx_format).

RTL uses five kinds of objects: expressions, integers, wide integers, strings and vectors.  Expressions are the most important ones. An RTL expression ("RTX", for short) is a C structure, but it is usually referred to with a pointer; a type that is given the typedef name rtx.

An integer is simply an int; their written form uses decimal digits. A wide integer is an integral object whose type is HOST_WIDE_INT; their written form uses decimal digits.

A string is a sequence of characters. In core it is represented as a char * in usual C fashion, and it is written in C syntax as well. However, strings in RTL may never be null. If you write an empty string in a machine description, it is represented in core as a null pointer rather than as a pointer to a null character. In certain contexts, these null pointers instead of strings are valid. Within RTL code, strings are most commonly found inside symbol_ref expressions, but they appear in other contexts in the RTL expressions that make up machine descriptions.

In a machine description, strings are normally written with double quotes, as you would in C.  However, strings in machine descriptions may extend over many lines, which is invalid C, and adjacent string constants are not concatenated as they are in C. Any string constant may be surrounded with a single set of parentheses. Sometimes this makes the machine description easier to read.

There is also a special syntax for strings, which can be useful when C code is embedded in a machine description. Wherever a string can appear, it is also valid to write a C-style brace block.  The entire brace block, including the outermost pair of braces, is considered to be the string constant. Double quote characters inside the braces are not special. Therefore, if you write string constants in the C code, you need not escape each quote character with a backslash.

A vector contains an arbitrary number of pointers to expressions. The number of elements in the vector is explicitly present in the vector. The written form of a vector consists of square brackets (`[...]') surrounding the elements, in sequence and with whitespace separating them. Vectors of length zero are not created; null pointers are used instead.

Expressions are classified by "expression codes" (also called RTX codes). The expression code is a name defined in rtl.def, which is also (in uppercase) a C enumeration constant. The possible expression codes and their meanings are machine-independent. The code of an RTX can be extracted with the macro GET_CODE (X) and altered with PUT_CODE (X, NEWCODE).

The expression code determines how many operands the expression contains, and what kinds of objects they are. In RTL, unlike Lisp, you cannot tell by looking at an operand what kind of object it is. Instead, you must know from its context--from the expression code of the containing expression. For example, in an expression of code subreg, the first operand is to be regarded as an expression and the second operand as an integer. In an expression of code plus, there are two operands, both of which are to be regarded as expressions. In a symbol_ref expression, there is one operand, which is to be regarded as a string.

Expressions are written as parentheses containing the name of the expression type, its flags and machine mode if any, and then the operands of the expression (separated by spaces).

Expression code names in the md file are written in lowercase, but when they appear in C code they are written in uppercase. In this manual, they are shown as follows: const_int.

In a few contexts a null pointer is valid where an expression is normally wanted. The written form of this is (nil).

The various expression codes are divided into several "classes", which are represented by single characters. You can determine the class of an RTX code with the macro GET_RTX_CLASS (CODE). Currently, rtx.def defines these classes:

Ÿ        The internal name of the rtx used in the C source. It is a tag in the enumeration "enum rtx_code" defined in "rtl.h". By convention these are in UPPER_CASE.

Ÿ        The name of the rtx in the external ASCII format read by read_rtx(), and printed by print_rtx(). These names are stored in rtx_name[]. By convention these are the internal (field 1) names in lower_case.

Ÿ        The print format, and type of each rtx->u.fld[] (field) in this rtx. These formats are stored in rtx_format[]. The meaning of the formats is documented in front of this array in rtl.c

Ÿ        The class of the rtx. These are stored in rtx_class and are accessed via the GET_RTX_CLASS macro. They are defined as follows:

w          "o" an rtx code that can be used to represent an object (e.g, REG, MEM)

w          "<" an rtx code for a comparison (e.g, EQ, NE, LT)

w          "1" an rtx code for a unary arithmetic expression (e.g, NEG, NOT)

w          "c" an rtx code for a commutative binary operation (e.g, PLUS, MULT)

w          "3" an rtx code for a non-bitfield three input operation (IF_THEN_ELSE)

w          "2" an rtx code for a non-commutative binary operation (e.g., MINUS, DIV)

w          "b" an rtx code for a bit-field operation (ZERO_EXTRACT, SIGN_EXTRACT)

w          "i" an rtx code for a machine insn (INSN, JUMP_INSN, CALL_INSN)

w          "m" an rtx code for something that matches in insns (e.g, MATCH_DUP)

w          "g" an rtx code for grouping insns together (e.g, GROUP_PARALLEL)

w          "a" an rtx code for autoincrement addressing modes (e.g. POST_DEC)

w          "x" everything else

4.2.1.3.2.            Object Generation
4.2.1.3.2.1.      Objects for Registers and Related

Following is the meaning of some variables created below:

virtual_incoming_args_rtx: This points to the first word of the incoming arguments passed on the stack, either by the caller or by the callee when pretending it was passed by the caller.

virtual_stack_vars_rtx: If FRAME_GROWS_DOWNWARD, this points to immediately above the first variable on the stack. Otherwise, it points to the first variable on the stack.

virtual_stack_dynamic_rtx: This points to the location of dynamically-allocated memory on the stack immediately after the stack pointer has been adjusted by the amount desired.

virtual_cfa_rtx: This points to the Canonical Frame Address of the function. This should correspond to the CFA produced by INCOMING_FRAME_SP_OFFSET, but is calculated relative to the arg pointer for simplicity; the frame pointer nor stack pointer are necessarily fixed relative to the CFA until after reload.

virtual_outgoing_args_rtx: This points to the location in the stack at which outgoing arguments should be written when the stack is pre-pushed (arguments pushed using push insns always use sp).

static_regno_reg_rtx: Commonly used RTL for hard registers. These objects are not necessarily unique, so we allocate them separately from global_rtl. They are initialized once per compilation unit, then copied into regno_reg_rtx at the beginning of each function.

 

init_emit_once (continue)

 

5496   /* Assign register numbers to the globally defined register rtx.

5497     This must be done at runtime because the register number field

5498     is in a union and some compilers can't initialize unions.  */

5499

5500   pc_rtx = gen_rtx (PC, VOIDmode);

5501   cc0_rtx = gen_rtx (CC0, VOIDmode);

5502   stack_pointer_rtx = gen_raw_REG (Pmode, STACK_POINTER_REGNUM);

5503   frame_pointer_rtx = gen_raw_REG (Pmode, FRAME_POINTER_REGNUM);

5504   if (hard_frame_pointer_rtx == 0)

5505     hard_frame_pointer_rtx = gen_raw_REG (Pmode,

5506                       HARD_FRAME_POINTER_REGNUM);

5507   if (arg_pointer_rtx == 0)

5508     arg_pointer_rtx = gen_raw_REG (Pmode, ARG_POINTER_REGNUM);

5509   virtual_incoming_args_rtx =

5510     gen_raw_REG (Pmode, VIRTUAL_INCOMING_ARGS_REGNUM);

5511   virtual_stack_vars_rtx =

5512     gen_raw_REG (Pmode, VIRTUAL_STACK_VARS_REGNUM);

5513   virtual_stack_dynamic_rtx =

5514     gen_raw_REG (Pmode, VIRTUAL_STACK_DYNAMIC_REGNUM);

5515   virtual_outgoing_args_rtx =

5516     gen_raw_REG (Pmode, VIRTUAL_OUTGOING_ARGS_REGNUM);

5517   virtual_cfa_rtx = gen_raw_REG (Pmode, VIRTUAL_CFA_REGNUM);

5518

5519   /* Initialize RTL for commonly used hard registers. These are

5520     copied into regno_reg_rtx as we begin to compile each function.  */

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

5522     static_regno_reg_rtx[i] = gen_raw_REG (reg_raw_mode[i], i);

5523

5524 #ifdef INIT_EXPANDERS

5525   /* This is to initialize {init|mark|free}_machine_status before the first

5526     call to push_function_context_to. This is needed by the Chill front

5527     end which calls push_function_context_to before the first call to

5528     init_function_start.  */

5529   INIT_EXPANDERS;

5530 #endif

 

At line 5500 and 5501 above, pc_rtx (program counter) and cc0_rtx (conditional code) are both elements of a global rtx array global_rtl. From the index we can see what reigsters are referred. Most of them don’t correspond to hard register, they created just for the convient handling of the rtl language.

 

1807 enum global_rtl_index                                                                                      in rtl.h

1808 {

1809   GR_PC,

1810   GR_CC0,

1811   GR_STACK_POINTER,

1812   GR_FRAME_POINTER,

1813   /* For register elimination to work properly these hard_frame_pointer_rtx,

1814     frame_pointer_rtx, and arg_pointer_rtx must be the same if they refer to

1815     the same register.  */

1816 #if FRAME_POINTER_REGNUM == ARG_POINTER_REGNUM

1817   GR_ARG_POINTER = GR_FRAME_POINTER,

1818 #endif

1819 #if HARD_FRAME_POINTER_REGNUM == FRAME_POINTER_REGNUM

1820   GR_HARD_FRAME_POINTER = GR_FRAME_POINTER,

1821 #else

1822   GR_HARD_FRAME_POINTER,

1823 #endif

1824 #if FRAME_POINTER_REGNUM != ARG_POINTER_REGNUM

1825 #if HARD_FRAME_POINTER_REGNUM == ARG_POINTER_REGNUM

1826   GR_ARG_POINTER = GR_HARD_FRAME_POINTER,

1827 #else

1828   GR_ARG_POINTER,

1829 #endif

1830 #endif

1831   GR_VIRTUAL_INCOMING_ARGS,

1832   GR_VIRTUAL_STACK_ARGS,

1833   GR_VIRTUAL_STACK_DYNAMIC,

1834   GR_VIRTUAL_OUTGOING_ARGS,

1835   GR_VIRTUAL_CFA,

1836

1837   GR_MAX

1838 };

 

gen_rtx is used to create common rtx object except register assigned with register number. In creating pc_rtx and cc0_rtx, below code is run.

 

673  rtx

674  gen_rtx (enum rtx_code code, enum machine_mode mode, ...)                             in emit-rtl.c

675  {

676    int i;          /* Array indices...   */

677    const char *fmt; /* Current rtx's format...       */

678    rtx rt_val;          /* RTX to return to caller...   */

679    va_list p;

680 

681    va_start (p, mode);

682 

683    switch (code)

684    {

   

706      default:

707        rt_val = rtx_alloc (code);        /* Allocate the storage space.  */

708        rt_val->mode = mode;             /* Store the machine mode...  */

709 

710        fmt = GET_RTX_FORMAT (code);  /* Find the right format...  */

711         for (i = 0; i < GET_RTX_LENGTH (code); i++)

712         {

       

750        }

751      }

752      break;

753   }

754 

755    va_end (p);

756    return rt_val;

757  }

 

Above at line 707, rtx object is created and managed by GCC garbage collector. Every rtx object is allocated according to its size. This size is recorded in rtx_size which is also global array with definition as below.

 

101    const unsigned char rtx_size[NUM_RTX_CODE] = {                                         in rtl.c

102    #define DEF_RTL_EXPR(ENUM, NAME, FORMAT, CLASS)                           /

103      ((ENUM) == CONST_INT || (ENUM) == CONST_DOUBLE                  /

104       ? RTX_HDR_SIZE + (sizeof FORMAT - 1) * sizeof (HOST_WIDE_INT)       /

105       : RTX_HDR_SIZE + (sizeof FORMAT - 1) * sizeof (rtunion)),

106   

107    #include "rtl.def"

108    #undef DEF_RTL_EXPR

109    };

 

The content of the rtl.def are rtl expressions like: rtx code, string of the name, format defining in string, class defining in string. So PC and CC0 are defined in rtx form as following. Note that the format of both objects are null strings, the rtx_length of both objects are 0.

 

803  /* program counter. Ordinary jumps are represented                                             in rtl.def

804    by a SET whose first operand is (PC).  */

805    DEF_RTL_EXPR(PC, "pc", "", 'o')

 

873    /* The condition code register is represented, in our imagination,

874      as a register holding a value that can be compared to zero.

875      In fact, the machine has already compared them and recorded the

876      results; but instructions that look at the condition code

877      pretend to be looking at the entire value and comparing it.  */

878    DEF_RTL_EXPR(CC0, "cc0", "", 'o')

 

In the definition of rtx_size at line 104 and 105, RTX_HDR_SIZE is defined as the offset from the beginning of rtx_def to the u field of it.

 

225    #define RTX_HDR_SIZE offsetof (struct rtx_def, u)                                         in rtl.h

 

For PC and CC0 objects, they only has size of RTX_HDR_SIZE, as (sizeof FORMAT – 1) is 0. At line 710 and 711 in gen_rtx, the macros GET_RTX_... are used to retrieve corresponding fields of the rtl definition.

 

56    #define GET_RTX_LENGTH(CODE)         (rtx_length[(int) (CODE)])                 in rtl.h

62    #define GET_RTX_FORMAT(CODE)         (rtx_format[(int) (CODE)])

 

rtx_format and rtx_length both are global arrays. They are defined by the content of rtl.def .

 

57    const char * const rtx_format[NUM_RTX_CODE] = {                                         in rtl.c

58      /* "*" undefined.

59             can cause a warning message

60        "0" field is unused (or used in a phase-dependent manner)

61             prints nothing

62        "i" an integer

63             prints the integer

64        "n" like "i", but prints entries from `note_insn_name'

65        "w" an integer of width HOST_BITS_PER_WIDE_INT

66             prints the integer

67        "s" a pointer to a string

68             prints the string

69        "S" like "s", but optional:

70             the containing rtx may end before this operand

71        "T" like "s", but treated specially by the RTL reader;

72             only found in machine description patterns.

73        "e" a pointer to an rtl expression

74             prints the expression

75        "E" a pointer to a vector that points to a number of rtl expressions

76             prints a list of the rtl expressions

77        "V" like "E", but optional:

78             the containing rtx may end before this operand

79        "u" a pointer to another insn

80             prints the uid of the insn.

81        "b" is a pointer to a bitmap header.

82        "B" is a basic block pointer.

83        "t" is a tree pointer.  */

84   

85    #define DEF_RTL_EXPR(ENUM, NAME, FORMAT, CLASS)   FORMAT ,

86    #include "rtl.def"          /* rtl expressions are defined here */

87    #undef DEF_RTL_EXPR

88    };

 

35    #define DEF_RTL_EXPR(ENUM, NAME, FORMAT, CLASS) sizeof FORMAT - 1 ,

 

37    const unsigned char rtx_length[NUM_RTX_CODE] = {

38    #include "rtl.def"

39    };

 

While in the source code of the gcc, the rtx object is represented by struct rtx_def as below.

 

139  struct rtx_def GTY((chain_next ("RTX_NEXT (&%h)"),                                      in rtl.h

140             chain_prev ("RTX_PREV (&%h)")))

141  {

142    /* The kind of expression this is.  */

143    ENUM_BITFIELD(rtx_code) code: 16;

144 

145    /* The kind of value the expression has.  */

146    ENUM_BITFIELD(machine_mode) mode : 8;

147 

148    /* 1 in a MEM if we should keep the alias set for this mem unchanged

149      when we access a component.

150      1 in a CALL_INSN if it is a sibling call.

151      1 in a SET that is for a return.

152      In a CODE_LABEL, part of the two-bit alternate entry field.  */

153    unsigned int jump : 1;

154   /* In a CODE_LABEL, part of the two-bit alternate entry field.

155      1 in a MEM if it cannot trap.  */

156    unsigned int call : 1;

157   /* 1 in a REG, MEM, or CONCAT if the value is set at most once, anywhere.

158      1 in a SUBREG if it references an unsigned object whose mode has been

159      from a promoted to a wider mode.

160      1 in a SYMBOL_REF if it addresses something in the per-function

161      constants pool.

162      1 in a CALL_INSN, NOTE, or EXPR_LIST for a const or pure call.

163      1 in a JUMP_INSN, CALL_INSN, or INSN of an annulling branch.  */

164    unsigned int unchanging : 1;

165    /* 1 in a MEM or ASM_OPERANDS expression if the memory reference is volatile.

166      1 in an INSN, CALL_INSN, JUMP_INSN, CODE_LABEL, BARRIER, or NOTE

167      if it has been deleted.

168      1 in a REG expression if corresponds to a variable declared by the user,

169      0 for an internally generated temporary.

170      1 in a SUBREG with a negative value.

171      1 in a LABEL_REF or in a REG_LABEL note for a non-local label.

172      In a SYMBOL_REF, this flag is used for machine-specific purposes.  */

173    unsigned int volatil : 1;

174    /* 1 in a MEM referring to a field of an aggregate.

175      0 if the MEM was a variable or the result of a * operator in C;

176      1 if it was the result of a . or -> operator (on a struct) in C.

177      1 in a REG if the register is used only in exit code a loop.

178      1 in a SUBREG expression if was generated from a variable with a

179      promoted mode.

180      1 in a CODE_LABEL if the label is used for nonlocal gotos

181      and must not be deleted even if its count is zero.

182      1 in a LABEL_REF if this is a reference to a label outside the

183      current loop.

184      1 in an INSN, JUMP_INSN or CALL_INSN if this insn must be scheduled

185      together with the preceding insn. Valid only within sched.

186      1 in an INSN, JUMP_INSN, or CALL_INSN if insn is in a delay slot and

187      from the target of a branch. Valid from reorg until end of compilation;

188      cleared before used.

189      1 in an INSN, JUMP_INSN or CALL_INSN or related rtx if this insn is

190      dead code. Valid only during dead-code elimination phase; cleared

191      before use.  */

192    unsigned int in_struct : 1;

193    /* At the end of RTL generation, 1 if this rtx is used. This is used for

194      copying shared structure. See `unshare_all_rtl'.

195      In a REG, this is not needed for that purpose, and used instead

196      in `leaf_renumber_regs_insn'.

197      1 in a SYMBOL_REF, means that emit_library_call

198      has used it as the function.  */

199    unsigned int used : 1;

200   /* Nonzero if this rtx came from procedure integration.

201      1 in a REG or PARALLEL means this rtx refers to the return value

202     of the current function.

203      1 in a SYMBOL_REF if the symbol is weak.  */

204    unsigned integrated : 1;

205   /* 1 in an INSN or a SET if this rtx is related to the call frame,

206      either changing how we compute the frame address or saving and

207      restoring registers in the prologue and epilogue.

208      1 in a MEM if the MEM refers to a scalar, rather than a member of

209      an aggregate.

210      1 in a REG if the register is a pointer.

211       1 in a SYMBOL_REF if it addresses something in the per-function

212      constant string pool.  */

213    unsigned frame_related : 1;

214 

215    /* The first element of the operands of this rtx.

216      The number of operands and their types are controlled

217      by the `code' field, according to rtl.def.  */

218    union u {

219      rtunion fld[1];

220      HOST_WIDE_INT hwint[1];

221    } GTY ((special ("rtx_def"), desc ("GET_CODE (&%0)"))) u;

222  };

 

In above definition, ENUM_BITFIELD in this version is defined as enum. Field union u holds the elements of the rtl expression. This field is an array for real rtx expression. Every element of the array holds every subpart of the expression.

For example, with expression 2+3+5, when transformed into rtx language, it takes infix notation form as: + (2) + (3) (5). For the rtx expression created, it will be:

Studying note of GCC-3.4.6 source (42)_第1张图片

figure 18: example of rtx expression

 

Of course, rtunion must be another union type. It needs to keep all informations for generating code for the target.

 

119   union rtunion_def                                                                                             in rtl.h

120  {

121    int rtint;

122    unsigned int rtuint;

123    const char *rtstr;

124    rtx rtx;

125    rtvec rtvec;

126    enum machine_mode rttype;

127    addr_diff_vec_flags rt_addr_diff_vec_flags;

128    struct cselib_val_struct *rt_cselib;

129    struct bitmap_head_def *rtbit;

130    tree rttree;

131    struct basic_block_def *bb;

132    mem_attrs *rtmem;

133    reg_attrs *rtreg;

134  };

135  typedef union rtunion_def rtunion;

 

In it, rtinit used for RTX expression for integer, rtuint for unsigned integer, rtstr is for string object, rtx used for expression (for above figure, rtx_expression, cont_int_RTX are both kept in rtx field of rtunion), rtvec for array objects, rttype for mode of data type, addr_diff_vec_flags saves information used for optimizing branch block, bb saves information for basic block (one entry point, one exit point), rtmem and rtreg saves attributes of memory and register respectively, rttree points to the correpsonding subtree of the front-end.

In init_emit_once following, from line 5502 to 5517, other objects in global_rtl are created by gen_raw_REG , which includes register objects specified with register number.

 

377  rtx

378  gen_raw_REG (enum machine_mode mode, int regno)                                  in emit-rtl.c

379  {

380    rtx x = gen_rtx_raw_REG (mode, regno);

381    ORIGINAL_REGNO (x) = regno;

382    return x;

383  }

 

gen_rtx_raw_REG is generated by tool gengenrtl from rtl.def. By this way, we can easily expand RTL language without takes the trouble to rewrite some files, but just the rtl.def. And even when a large revision for the language is expected, all we need to do is to rewrite gengenrtl.c and rtl.def. It’s a clever design for a developing software. gen_rtx_raw_REG is the alias of gen_rtx_fmt_i00.

 

245  #define gen_rtx_raw_REG(MODE, ARG0) /                                                in genrtl.h

246     gen_rtx_fmt_i00 (REG, (MODE), (ARG0))

 

The name of gen_rtx_fmt_i00 reveals following information: the ‘i’ means the type of the first element of rtx->u.fld is int, ‘0’ following means the type of following element of rtx->u.fld are not used. The meaning of the characters are the same as rtx_format. The total size of rtx->u.fld is 3.

 

630  rtx

631  gen_rtx_fmt_i00 (RTX_CODE code, enum machine_mode mode,                  in genrtl.c

632                int arg0)

633  {

634    rtx rt;

635    rt = ggc_alloc_rtx (code);

636 

637    memset (rt, 0, RTX_HDR_SIZE);

638 

639    PUT_CODE (rt, code);

640    PUT_MODE (rt, mode);

641    XINT (rt, 0) = arg0;

642    X0EXP (rt, 1) = NULL_RTX;

643    X0EXP (rt, 2) = NULL_RTX;

644 

645    return rt;

646  }

 

GCC defines a serire of macros to check the validation of the RTX object first then fetch specified field of it. From the call site, we see that the arg0 is the register number. XINT is one of these macros.

 

506  #define XINT(RTX, N) (RTL_CHECK2 (RTX, N, 'i', 'n').rtint)                                    in rtl.h

 

RTL_CHECK2 is similar with RTL_CHECK1, except need validate two formats provided.

For X0EXP, the 0 in its name stands for the rtx_format ‘0’ applied, the meaning of ‘0’ is unused (or used in a phase-dependent manner), EXP indicates the contain of the rtx is the rtx expression.

 

525  #define X0EXP(RTX, N)         (RTL_CHECK1 (RTX, N, '0').rtx)                       in rtl.h

 

If defines ENABLE_RTL_CHECKING, RTL_CHECK1 will do the validation checking. It is useful during GCC development. While at pulishment, undefines ENABLE_RTL_CHECKING to set RTL_CHECK1 as “RTX->u.fld[N]” which runs much faster.

 

302  #if defined ENABLE_RTL_CHECKING && (GCC_VERSION >= 2007)             in rtl.h

303  /* The bit with a star outside the statement expr and an & inside is

304    so that N can be evaluated only once.  */

305  #define RTL_CHECK1(RTX, N, C1) __extension__                        /

306  (*({ rtx const _rtx = (RTX); const int _n = (N);                     /

307       const enum rtx_code _code = GET_CODE (_rtx);                  /

308       if (_n < 0 || _n >= GET_RTX_LENGTH (_code))                   /

309         rtl_check_failed_bounds (_rtx, _n, __FILE__, __LINE__,          /

310                               __FUNCTION__);                      /

311        if (GET_RTX_FORMAT(_code)[_n] != C1)                           /

312         rtl_check_failed_type1 (_rtx, _n, C1, __FILE__, __LINE__,      /

313                              __FUNCTION__);                       /

314     &_rtx->u.fld[_n]; }))

 

However, when gen_rtx_raw_REG return, in gen_raw_REG rewrites the 2 second element of the rtunion with the register number, which should hold the number the register originally had. For a pseudo register turned into a hard register this will hold the old pseudo register number.

 

1019 #define ORIGINAL_REGNO(RTX) X0UINT (RTX, 1)                                        in rtl.h

1020 #define X0UINT(RTX, N)       (RTL_CHECK1 (RTX, N, '0').rtuint)

 

Then in init_emit_once, at line 5522, it begins to create rtx object for general purpose registers. reg_raw_mode records the largest mode certain register can hold, which is initialized in init_reg_modes_once.

At line 5529, for x86 machine except ia64, INIT_EXPANDERS is not defined.

 

init_emit_once (continue)

 

5532   /* Create the unique rtx's for certain rtx codes and operand values.  */

5533

5534   /* Don't use gen_rtx here since gen_rtx in this case

5535     tries to use these variables.  */

5536   for (i = - MAX_SAVED_CONST_INT; i <= MAX_SAVED_CONST_INT; i++)

5537     const_int_rtx[i + MAX_SAVED_CONST_INT] =

5538       gen_rtx_raw_CONST_INT (VOIDmode, (HOST_WIDE_INT) i);

5539

5540   if (STORE_FLAG_VALUE >= - MAX_SAVED_CONST_INT

5541       && STORE_FLAG_VALUE <= MAX_SAVED_CONST_INT)

5542     const_true_rtx = const_int_rtx[STORE_FLAG_VALUE + MAX_SAVED_CONST_INT];

5543   else

5544     const_true_rtx = gen_rtx_CONST_INT (VOIDmode, STORE_FLAG_VALUE);

 

Line 5537, const_int_rtx keeps one copy of (const_int C) where C is in [-64, 64] to save space during the compilation and simplify comparisons of integers. MAX_SAVED_CONST_INT is defined as 64. The rtx object of these constants is created by gen_rtx_raw_CONST_INT.

 

233  #define gen_rtx_raw_CONST_INT(MODE, ARG0) /                                           in genrtl.h

234    gen_rtx_fmt_w (CONST_INT, (MODE), (ARG0))

 

Fucntion gen_rtx_fmt_w is generated by gengenrtl tool from rtl.def too. Again, its name reveals its content. The ‘w’ means the content of the rtx expression is wide int, so rtx->u.wint is used this time. And rtx->u.wint also is an array.

 

599  rtx

600  gen_rtx_fmt_w (RTX_CODE code, enum machine_mode mode,                     in genrtl.c

601          HOST_WIDE_INT arg0)

602  {

603   rtx rt;

604    rt = ggc_alloc_rtx (code);

605 

606    memset (rt, 0, RTX_HDR_SIZE);

607 

608    PUT_CODE (rt, code);

609    PUT_MODE (rt, mode);

610    XWINT (rt, 0) = arg0;

611  

612    return rt;

613  }

 

350  #define XWINT(RTX, N) __extension__                                 /                    in rtl.h

351  (*({ rtx const _rtx = (RTX); const int _n = (N);                     /

352       const enum rtx_code _code = GET_CODE (_rtx);                  /

353       if (_n < 0 || _n >= GET_RTX_LENGTH (_code))                   /

354         rtl_check_failed_bounds (_rtx, _n, __FILE__, __LINE__,          /

355                               __FUNCTION__);                      /

356       if (GET_RTX_FORMAT(_code)[_n] != 'w')                           /

357         rtl_check_failed_type1 (_rtx, _n, 'w', __FILE__, __LINE__,       /

358                                   __FUNCTION__);                        /

359         &_rtx->u.hwint[_n]; }))

 

At line 5540 in init_emit_once above, for x86 system, STORE_FLAG_VALUE is defined as 1. So const_true_rtx is just an alias of const_int_rtx [65].

 

 

你可能感兴趣的:(Studying note of GCC-3.4.6 source (42))