Gcc源代码分析,gcc-1.40
主要目的是找到rtl如何生成的?
rtl如何和i386.md连接起来的?
就把这两个问题解决了,即可。
emit_jump_insn()定义在emit-rtl.c文件中
被Expmed.c Expr.c Insn-emit.c Stmt.c中调用
/* Make an insn of code JUMP_INSN with pattern PATTERN
and add it to the end of the doubly-linked list. */
rtx
emit_jump_insn (pattern)
rtx pattern;
{
if (GET_CODE (pattern) == SEQUENCE)
return emit_insn (pattern);
else
{
register rtx insn = make_jump_insn_raw (pattern, NULL);
add_insn (insn);
return insn;
}
}
#define GET_CODE(RTX) ((enum rtx_code) ((RTX)->code))
在rtl.h中定义
rtx
gen_lowpart (mode, x)
enum machine_mode mode;
register rtx x;
{
/* This case loses if X is a subreg. To catch bugs early,
complain if an invalid MODE is used even in other cases. */
if (GET_MODE_SIZE (mode) > UNITS_PER_WORD
&& GET_MODE_SIZE (mode) != GET_MODE_UNIT_SIZE (GET_MODE (x)))
abort ();
if (GET_MODE (x) == mode)
return x;
if (GET_CODE (x) == CONST_INT)
return gen_rtx (CONST_INT, VOIDmode, INTVAL (x) & GET_MODE_MASK (mode));
if (GET_CODE (x) == CONST_DOUBLE)
enum machine_mode {
#include "machmode.def"
MAX_MACHINE_MODE };
会调用 gen_rtx()函数 定义在emit-rtl.c文件中!!!
/* rtx gen_rtx (code, mode, [element1, ..., elementn])
**
** This routine generates an RTX of the size specified by
** <code>, which is an RTX code. The RTX structure is initialized
** from the arguments <element1> through <elementn>, which are
** interpreted according to the specific RTX type's format. The
** special machine mode associated with the rtx (if any) is specified
** in <mode>.
**
** gen_rtx() can be invoked in a way which resembles the lisp-like
** rtx it will generate. For example, the following rtx structure:
**
** (plus:QI (mem:QI (reg:SI 1))
** (mem:QI (plusw:SI (reg:SI 2) (reg:SI 3))))
**
** ...would be generated by the following C code:
**
** gen_rtx (PLUS, QImode,
** gen_rtx (MEM, QImode,
** gen_rtx (REG, SImode, 1)),
** gen_rtx (MEM, QImode,
** gen_rtx (PLUS, SImode,
** gen_rtx (REG, SImode, 2),
** gen_rtx (REG, SImode, 3)))),
*/
/*VARARGS2*/
rtx
gen_rtx (va_alist)
va_dcl
{
va_list p;
enum rtx_code code;
enum machine_mode mode;
register int i; /* Array indices... */
register char *fmt; /* Current rtx's format... */
register rtx rt_val; /* RTX to return to caller... */
va_start (p);
code = va_arg (p, enum rtx_code);
mode = va_arg (p, enum machine_mode);
if (code == CONST_INT)
{
int arg = va_arg (p, int);
if (arg == 0)
return const0_rtx;
if (arg == 1)
return const1_rtx;
rt_val = rtx_alloc (code);
INTVAL (rt_val) = arg;
}
else
{
rt_val = rtx_alloc (code); /* Allocate the storage space. */
rt_val->mode = mode; /* Store the machine mode... */
fmt = GET_RTX_FORMAT (code); /* Find the right format... */
for (i = 0; i < GET_RTX_LENGTH (code); i++)
{
switch (*fmt++)
{
case '0': /* Unused field. */
break;
case 'i': /* An integer? */
XINT (rt_val, i) = va_arg (p, int); 定义在gvarargs.h
break;
case 's': /* A string? */
XSTR (rt_val, i) = va_arg (p, char *);
break;
case 'e': /* An expression? */
case 'u': /* An insn? Same except when printing. */
XEXP (rt_val, i) = va_arg (p, rtx);
break;
case 'E': /* An RTX vector? */
XVEC (rt_val, i) = va_arg (p, rtvec);
break;
default:
abort();
}
}
}
va_end (p);
return rt_val; /* Return the new RTX... */
}
#define GET_RTX_FORMAT(CODE) (rtx_format[(int)(CODE)]) 在rtl.h中
rtx_format 定义在rtl.c中
/* Indexed by rtx code, gives a sequence of operand-types for
rtx's of that code. The sequence is a C string in which
each charcter describes one operand. */
char *rtx_format[] = {
/* "*" undefined.
can cause a warning message
"0" field is unused (or used in a phase-dependent manner)
prints nothing
"i" an integer
prints the integer
"s" a pointer to a string
prints the string
"S" like "s", but optional:
the containing rtx may end before this operand
"e" a pointer to an rtl expression
prints the expression
"E" a pointer to a vector that points to a number of rtl expressions
prints a list of the rtl expressions
"u" a pointer to another insn
prints the uid of the insn. */
#define DEF_RTL_EXPR(ENUM, NAME, FORMAT) FORMAT ,
#include "rtl.def" /* rtl expressions are defined here */
#undef DEF_RTL_EXPR
};
#define XINT(RTX, N) ((RTX)->fld[N].rtint) 定义在rtl.h中
;; Call subroutine returning no value.
(define_insn "call"
[(call (match_operand:QI 0 "indirect_operand" "m")
(match_operand:SI 1 "general_operand" "g"))]
;; Operand 1 not really used on the m68000.
""
"*
{
if (GET_CODE (operands[0]) == MEM
&& ! CONSTANT_ADDRESS_P (XEXP (operands[0], 0)))
{
operands[0] = XEXP (operands[0], 0);
return \"call %*%0\";
}
else
return \"call %0\";
}")
;; Function main
(note 2 0 3 "" NOTE_INSN_DELETED)
(note 3 2 4 "" NOTE_INSN_FUNCTION_BEG)
(note 4 3 6 "" NOTE_INSN_DELETED)
(insn 6 4 7 (set (mem:SI (pre_dec:SI (reg:SI 7)))
(symbol_ref:SI ("*LC0"))) -1 (nil)
(nil))
(call_insn 7 6 9 (set (reg:SI 0)
(call (mem:QI (symbol_ref/v:SI ("printf")))
(const_int 4))) -1 (nil)
(nil))
(insn 9 7 10 (set (reg/i:SI 0)
(const_int 0)) -1 (nil)
(nil))
(insn 10 9 11 (use (reg/i:SI 0)) -1 (nil)
(nil))
(jump_insn 11 10 12 (set (pc)
(label_ref 15)) -1 (nil)
(nil))
(barrier 12 11 13)
(note 13 12 15 "" NOTE_INSN_FUNCTION_END)
(code_label 15 13 0 1)
.file "hello.c"
gcc_compiled.:
.text
LC0:
.ascii "Hello, world!\12\0"
.align 2
.globl _main
_main:
pushl %ebp
movl %esp,%ebp
pushl $LC0
call _printf
xorl %eax,%eax
jmp L1
.align 2
L1:
leave
ret