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.
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
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:
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].