?? emit-rtl.c
字號:
insn = make_insn_raw (pattern, NULL); add_insn (insn); } return insn;}/* Emit the insns in a chain starting with INSN. */rtxemit_insns (insn) rtx insn;{ while (insn) { rtx next = NEXT_INSN (insn); add_insn (insn); insn = next; }}/* Make an insn of code JUMP_INSN with pattern PATTERN and add it to the end of the doubly-linked list. */rtxemit_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; }}/* Make an insn of code CALL_INSN with pattern PATTERN and add it to the end of the doubly-linked list. */rtxemit_call_insn (pattern) rtx pattern;{ if (GET_CODE (pattern) == SEQUENCE) return emit_insn (pattern); else { register rtx insn = make_insn_raw (pattern, NULL); add_insn (insn); PUT_CODE (insn, CALL_INSN); return insn; }}/* Add the label LABEL to the end of the doubly-linked list. */rtxemit_label (label) rtx label;{ /* This can be called twice for the same label as a result of the confusion that follows a syntax error! So make it harmless. */ if (INSN_UID (label) == 0) { INSN_UID (label) = cur_insn_uid++; add_insn (label); } return label;}/* Make an insn of code BARRIER and add it to the end of the doubly-linked list. */rtxemit_barrier (){ register rtx barrier = rtx_alloc (BARRIER); INSN_UID (barrier) = cur_insn_uid++; add_insn (barrier); return barrier;}/* Make an insn of code NOTE with data-fields specified by FILE and LINE and add it to the end of the doubly-linked list, but only if line-numbers are desired for debugging info. */rtxemit_line_note (file, line) char *file; int line;{ emit_filename = file; emit_lineno = line;#if 0 if (no_line_numbers) return 0;#endif return emit_note (file, line);}/* Make an insn of code NOTE with data-fields specified by FILE and LINE and add it to the end of the doubly-linked list. If it is a line-number NOTE, omit it if it matches the previous one. */rtxemit_note (file, line) char *file; int line;{ register rtx note; if (line > 0) { if (file && last_filename && !strcmp (file, last_filename) && line == last_linenum) return 0; last_filename = file; last_linenum = line; } if (no_line_numbers && line > 0) { cur_insn_uid++; return 0; } note = rtx_alloc (NOTE); INSN_UID (note) = cur_insn_uid++; XSTR (note, 3) = file; XINT (note, 4) = line; add_insn (note); return note;}/* Emit a NOTE, and don't omit it even if LINE it the previous note. */rtxemit_line_note_force (file, line) char *file; int line;{ last_linenum = -1; return emit_line_note (file, line);}/* Cause next statement to emit a line note even if the line number has not changed. This is used at the beginning of a function. */voidforce_next_line_note (){ last_linenum = -1;}/* Return an indication of which type of insn should have X as a body. The value is CODE_LABEL, INSN, CALL_INSN or JUMP_INSN. */enum rtx_codeclassify_insn (x) rtx x;{ if (GET_CODE (x) == CODE_LABEL) return CODE_LABEL; if (GET_CODE (x) == CALL) return CALL_INSN; if (GET_CODE (x) == RETURN) return JUMP_INSN; if (GET_CODE (x) == SET) { if (SET_DEST (x) == pc_rtx) return JUMP_INSN; else if (GET_CODE (SET_SRC (x)) == CALL) return CALL_INSN; else return INSN; } if (GET_CODE (x) == PARALLEL) { register int j; for (j = XVECLEN (x, 0) - 1; j >= 0; j--) if (GET_CODE (XVECEXP (x, 0, j)) == CALL) return CALL_INSN; else if (GET_CODE (XVECEXP (x, 0, j)) == SET && SET_DEST (XVECEXP (x, 0, j)) == pc_rtx) return JUMP_INSN; else if (GET_CODE (XVECEXP (x, 0, j)) == SET && GET_CODE (SET_SRC (XVECEXP (x, 0, j))) == CALL) return CALL_INSN; } return INSN;}/* Emit the rtl pattern X as an appropriate kind of insn. If X is a label, it is simply added into the insn chain. */voidemit (x) rtx x;{ enum rtx_code code = classify_insn (x); if (code == CODE_LABEL) emit_label (x); else if (code == INSN) emit_insn (x); else if (code == JUMP_INSN) { register rtx insn = emit_jump_insn (x); if (simplejump_p (insn) || GET_CODE (x) == RETURN) emit_barrier (); } else if (code == CALL_INSN) emit_call_insn (x);}/* Begin emitting insns to a sequence which can be packaged in an RTL_EXPR. Return an rtx containing data on any sequence already in progress. */rtxstart_sequence (){ sequence_stack = gen_rtx (INSN_LIST, VOIDmode, first_insn, gen_rtx (INSN_LIST, VOIDmode, last_insn, sequence_stack)); first_insn = 0; last_insn = 0; return sequence_stack;}/* Set up the insn chain starting with FIRST as the current sequence, saving the previously current one. */voidpush_to_sequence (first) rtx first;{ rtx last; for (last = first; last && NEXT_INSN (last); last = NEXT_INSN (last)); sequence_stack = gen_rtx (INSN_LIST, VOIDmode, first_insn, gen_rtx (INSN_LIST, VOIDmode, last_insn, sequence_stack)); first_insn = first; last_insn = last;}/* After emitting to a sequence, restore previous saved state. The argument SAVED is no longer used. To get the contents of the sequence just made, you must call `gen_sequence' *before* calling here. */voidend_sequence (saved) rtx saved;{ first_insn = XEXP (sequence_stack, 0); last_insn = XEXP (XEXP (sequence_stack, 1), 0); sequence_stack = XEXP (XEXP (sequence_stack, 1), 1);}/* Generate a SEQUENCE rtx containing the insns already emitted to the current sequence. This is how the gen_... function from a DEFINE_EXPAND constructs the SEQUENCE that it returns. */rtxgen_sequence (){ rtx tem; rtvec newvec; int i; int len; /* Count the insns in the chain. */ len = 0; for (tem = first_insn; tem; tem = NEXT_INSN (tem)) len++; /* For an empty sequence... */ if (len == 0) return gen_rtx (SEQUENCE, VOIDmode, NULL); /* If only one insn, return its pattern rather than a SEQUENCE. */ if (len == 1 && (GET_CODE (first_insn) == INSN || GET_CODE (first_insn) == JUMP_INSN || GET_CODE (first_insn) == CALL_INSN)) return PATTERN (first_insn); /* Put them in a vector. */ newvec = rtvec_alloc (len); i = 0; for (tem = first_insn; tem; tem = NEXT_INSN (tem), i++) newvec->elem[i].rtx = tem; /* Make a SEQUENCE from this vector. */ return gen_rtx (SEQUENCE, VOIDmode, newvec);}/* Set up regno_reg_rtx, reg_rtx_no and regno_pointer_flag according to the chain of insns starting with FIRST. Also set cur_insn_uid to exceed the largest uid in that chain. This is used when an inline function's rtl is saved and passed to rest_of_compilation later. */static void restore_reg_data_1 ();voidrestore_reg_data (first) rtx first;{ register rtx insn; int i; register int max_uid = 0; for (insn = first; insn; insn = NEXT_INSN (insn)) { if (INSN_UID (insn) >= max_uid) max_uid = INSN_UID (insn); switch (GET_CODE (insn)) { case NOTE: case CODE_LABEL: case BARRIER: break; case JUMP_INSN: case CALL_INSN: case INSN: restore_reg_data_1 (PATTERN (insn)); break; } } /* Don't duplicate the uids already in use. */ cur_insn_uid = max_uid + 1; /* If any regs are missing, make them up. */ for (i = FIRST_PSEUDO_REGISTER; i < reg_rtx_no; i++) if (regno_reg_rtx[i] == 0) regno_reg_rtx[i] = gen_rtx (REG, SImode, i);}static voidrestore_reg_data_1 (orig) rtx orig;{ register rtx x = orig; register int i; register enum rtx_code code; register char *format_ptr; code = GET_CODE (x); switch (code) { case QUEUED: case CONST_INT: case CONST_DOUBLE: case SYMBOL_REF: case CODE_LABEL: case PC: case CC0: case LABEL_REF: return; case REG: if (REGNO (x) >= FIRST_PSEUDO_REGISTER) { /* Make sure regno_pointer_flag and regno_reg_rtx are large enough to have an element for this pseudo reg number. */ if (REGNO (x) >= reg_rtx_no) { reg_rtx_no = REGNO (x); if (reg_rtx_no >= regno_pointer_flag_length) { int newlen = max (regno_pointer_flag_length * 2, reg_rtx_no + 30); rtx *new1; char *new = (char *) oballoc (newlen); bzero (new, newlen); bcopy (regno_pointer_flag, new, regno_pointer_flag_length); new1 = (rtx *) oballoc (newlen * sizeof (rtx)); bzero (new1, newlen * sizeof (rtx)); bcopy (regno_reg_rtx, new1, regno_pointer_flag_length * sizeof (rtx)); regno_pointer_flag = new; regno_reg_rtx = new1; regno_pointer_flag_length = newlen; } reg_rtx_no ++; } regno_reg_rtx[REGNO (x)] = x; } return; case MEM: if (GET_CODE (XEXP (x, 0)) == REG) mark_reg_pointer (XEXP (x, 0)); restore_reg_data_1 (XEXP (x, 0)); return; } /* Now scan the subexpressions recursively. */ format_ptr = GET_RTX_FORMAT (code); for (i = 0; i < GET_RTX_LENGTH (code); i++) { switch (*format_ptr++) { case 'e': restore_reg_data_1 (XEXP (x, i)); break; case 'E': if (XVEC (x, i) != NULL) { register int j; for (j = 0; j < XVECLEN (x, i); j++) restore_reg_data_1 (XVECEXP (x, i, j)); } break; } }}/* Initialize data structures and variables in this file before generating rtl for each function. WRITE_SYMBOLS is nonzero if any kind of debugging info is to be generated. */voidinit_emit (write_symbols) int write_symbols;{ first_insn = NULL; last_insn = NULL; sequence_stack = NULL; cur_insn_uid = 1; reg_rtx_no = FIRST_PSEUDO_REGISTER; last_linenum = 0; last_filename = 0; first_label_num = label_num; no_line_numbers = ! write_symbols; /* Init the tables that describe all the pseudo regs. */ regno_pointer_flag_length = FIRST_PSEUDO_REGISTER + 100; regno_pointer_flag = (char *) oballoc (regno_pointer_flag_length); bzero (regno_pointer_flag, regno_pointer_flag_length); regno_reg_rtx = (rtx *) oballoc (regno_pointer_flag_length * sizeof (rtx)); bzero (regno_reg_rtx, regno_pointer_flag_length * sizeof (rtx));}/* Create some permanent unique rtl objects shared between all functions. */voidinit_emit_once (){ /* Create the unique rtx's for certain rtx codes and operand values. */ pc_rtx = gen_rtx (PC, VOIDmode); cc0_rtx = gen_rtx (CC0, VOIDmode); /* Don't use gen_rtx here since gen_rtx in this case tries to use these variables. */ const0_rtx = rtx_alloc (CONST_INT); INTVAL (const0_rtx) = 0; const1_rtx = rtx_alloc (CONST_INT); INTVAL (const1_rtx) = 1; fconst0_rtx = rtx_alloc (CONST_DOUBLE); dconst0_rtx = rtx_alloc (CONST_DOUBLE); { union real_extract u;#ifdef REAL_IS_NOT_DOUBLE bzero (&u, sizeof u); u.d = REAL_VALUE_ATOF ("0");#else u.d = 0;#endif bcopy (&u, &CONST_DOUBLE_LOW (fconst0_rtx), sizeof u); CONST_DOUBLE_MEM (fconst0_rtx) = cc0_rtx; PUT_MODE (fconst0_rtx, SFmode); bcopy (&u, &CONST_DOUBLE_LOW (dconst0_rtx), sizeof u); CONST_DOUBLE_MEM (dconst0_rtx) = cc0_rtx; PUT_MODE (dconst0_rtx, DFmode); } stack_pointer_rtx = gen_rtx (REG, Pmode, STACK_POINTER_REGNUM); frame_pointer_rtx = gen_rtx (REG, Pmode, FRAME_POINTER_REGNUM);#ifdef STRUCT_VALUE struct_value_rtx = STRUCT_VALUE;#else struct_value_rtx = gen_rtx (REG, Pmode, STRUCT_VALUE_REGNUM);#endif#ifdef STRUCT_VALUE_INCOMING struct_value_incoming_rtx = STRUCT_VALUE_INCOMING;#else#ifdef STRUCT_VALUE_INCOMING_REGNUM struct_value_incoming_rtx = gen_rtx (REG, Pmode, STRUCT_VALUE_INCOMING_REGNUM);#else struct_value_incoming_rtx = struct_value_rtx;#endif#endif static_chain_rtx = gen_rtx (REG, Pmode, STATIC_CHAIN_REGNUM);#ifdef STATIC_CHAIN_INCOMING_REGNUM if (STATIC_CHAIN_INCOMING_REGNUM != STATIC_CHAIN_REGNUM) static_chain_incoming_rtx = gen_rtx (REG, Pmode, STATIC_CHAIN_INCOMING_REGNUM); else#endif static_chain_incoming_rtx = static_chain_rtx; if (FRAME_POINTER_REGNUM == ARG_POINTER_REGNUM) arg_pointer_rtx = frame_pointer_rtx; else arg_pointer_rtx = gen_rtx (REG, Pmode, ARG_POINTER_REGNUM);}
?? 快捷鍵說明
復(fù)制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -