diff options
author | Marc Espie <espie@cvs.openbsd.org> | 2000-09-25 00:33:17 +0000 |
---|---|---|
committer | Marc Espie <espie@cvs.openbsd.org> | 2000-09-25 00:33:17 +0000 |
commit | ca0303bd93ded42cd3c56ff95dd955ade41e415f (patch) | |
tree | 53555906d21e7433708b18165e2c0029a0751e03 | |
parent | 8a7531e06b2c9ad239d5417d7937618823789374 (diff) |
Patch from Alexander N. Kabaev <ak03@gte.com>
Fixes GCC GNATS PR 258 and 413.
-rw-r--r-- | gnu/egcs/gcc/emit-rtl.c | 73 | ||||
-rw-r--r-- | gnu/egcs/gcc/integrate.c | 27 | ||||
-rw-r--r-- | gnu/egcs/gcc/rtl.def | 2 | ||||
-rw-r--r-- | gnu/egcs/gcc/rtl.h | 5 |
4 files changed, 96 insertions, 11 deletions
diff --git a/gnu/egcs/gcc/emit-rtl.c b/gnu/egcs/gcc/emit-rtl.c index 2aa51aca4da..ddbf026e2c2 100644 --- a/gnu/egcs/gcc/emit-rtl.c +++ b/gnu/egcs/gcc/emit-rtl.c @@ -630,9 +630,15 @@ mark_reg_pointer (reg, align) rtx reg; int align; { - REGNO_POINTER_FLAG (REGNO (reg)) = 1; + if (! REGNO_POINTER_FLAG (REGNO (reg))) + { + REGNO_POINTER_FLAG (REGNO (reg)) = 1; - if (align) + if (align) + REGNO_POINTER_ALIGN (REGNO (reg)) = align; + } + else if (align && align < REGNO_POINTER_ALIGN (REGNO (reg))) + /* We can no-longer be sure just how aligned this pointer is */ REGNO_POINTER_ALIGN (REGNO (reg)) = align; } @@ -896,6 +902,22 @@ gen_lowpart_common (mode, x) r = REAL_VALUE_FROM_TARGET_SINGLE (i); return CONST_DOUBLE_FROM_REAL_VALUE (r, mode); } + else if (((HOST_FLOAT_FORMAT == TARGET_FLOAT_FORMAT + && HOST_BITS_PER_WIDE_INT == BITS_PER_WORD) + || flag_pretend_float) + && GET_MODE_CLASS (mode) == MODE_FLOAT + && GET_MODE_SIZE (mode) == UNITS_PER_WORD + && GET_CODE (x) == CONST_INT + && (sizeof (double) * HOST_BITS_PER_CHAR + == HOST_BITS_PER_WIDE_INT)) + { + REAL_VALUE_TYPE r; + HOST_WIDE_INT i; + + i = INTVAL (x); + r = REAL_VALUE_FROM_TARGET_DOUBLE (&i); + return CONST_DOUBLE_FROM_REAL_VALUE (r, mode); + } #endif /* Similarly, if this is converting a floating-point value into a @@ -950,6 +972,11 @@ gen_realpart (mode, x) { if (GET_CODE (x) == CONCAT && GET_MODE (XEXP (x, 0)) == mode) return XEXP (x, 0); + else if (WORDS_BIG_ENDIAN + && GET_MODE_BITSIZE (mode) < BITS_PER_WORD + && REG_P (x) + && REGNO (x) < FIRST_PSEUDO_REGISTER) + fatal ("Unable to access real part of complex value in a hard register on this target"); else if (WORDS_BIG_ENDIAN) return gen_highpart (mode, x); else @@ -968,6 +995,11 @@ gen_imagpart (mode, x) return XEXP (x, 1); else if (WORDS_BIG_ENDIAN) return gen_lowpart (mode, x); + else if (!WORDS_BIG_ENDIAN + && GET_MODE_BITSIZE (mode) < BITS_PER_WORD + && REG_P (x) + && REGNO (x) < FIRST_PSEUDO_REGISTER) + fatal ("Unable to access imaginary part of complex value in a hard register on this target"); else return gen_highpart (mode, x); } @@ -1196,10 +1228,33 @@ operand_subword (op, i, validate_address, mode) /* If OP is a REG or SUBREG, we can handle it very simply. */ if (GET_CODE (op) == REG) { - /* If the register is not valid for MODE, return 0. If we don't - do this, there is no way to fix up the resulting REG later. */ + /* ??? There is a potential problem with this code. It does not + properly handle extractions of a subword from a hard register + that is larger than word_mode. Presumably the check for + HARD_REGNO_MODE_OK catches these most of these cases. */ + + /* If OP is a hard register, but OP + I is not a hard register, + then extracting a subword is impossible. + + For example, consider if OP is the last hard register and it is + larger than word_mode. If we wanted word N (for N > 0) because a + part of that hard register was known to contain a useful value, + then OP + I would refer to a pseudo, not the hard register we + actually wanted. */ + if (REGNO (op) < FIRST_PSEUDO_REGISTER + && REGNO (op) + i >= FIRST_PSEUDO_REGISTER) + return 0; + + /* If the register is not valid for MODE, return 0. Note we + have to check both OP and OP + I since they may refer to + different parts of the register file. + + Consider if OP refers to the last 96bit FP register and we want + subword 3 because that subword is known to contain a value we + needed. */ if (REGNO (op) < FIRST_PSEUDO_REGISTER - && ! HARD_REGNO_MODE_OK (REGNO (op) + i, word_mode)) + && (! HARD_REGNO_MODE_OK (REGNO (op), word_mode) + || ! HARD_REGNO_MODE_OK (REGNO (op) + i, word_mode))) return 0; else if (REGNO (op) >= FIRST_PSEUDO_REGISTER || (REG_FUNCTION_VALUE_P (op) @@ -1596,7 +1651,8 @@ gen_inline_header_rtx (first_insn, first_parm_insn, first_labelno, pops_args, stack_slots, forced_labels, function_flags, outgoing_args_size, original_arg_vector, original_decl_initial, regno_rtx, regno_flag, - regno_align, parm_reg_stack_loc) + regno_align, parm_reg_stack_loc, + nonlocal_goto_handler_labels) rtx first_insn, first_parm_insn; int first_labelno, last_labelno, max_parm_regnum, max_regnum, args_size; int pops_args; @@ -1610,6 +1666,7 @@ gen_inline_header_rtx (first_insn, first_parm_insn, first_labelno, char *regno_flag; char *regno_align; rtvec parm_reg_stack_loc; + rtx nonlocal_goto_handler_labels; { rtx header = gen_rtx_INLINE_HEADER (VOIDmode, cur_insn_uid++, NULL_RTX, @@ -1621,7 +1678,9 @@ gen_inline_header_rtx (first_insn, first_parm_insn, first_labelno, original_arg_vector, original_decl_initial, regno_rtx, regno_flag, regno_align, - parm_reg_stack_loc); + parm_reg_stack_loc, + nonlocal_goto_handler_labels, + nonlocal_goto_handler_labels); return header; } diff --git a/gnu/egcs/gcc/integrate.c b/gnu/egcs/gcc/integrate.c index 33a96c40f91..4165611e480 100644 --- a/gnu/egcs/gcc/integrate.c +++ b/gnu/egcs/gcc/integrate.c @@ -151,6 +151,10 @@ function_cannot_inline_p (fndecl) if (current_function_contains_functions) return N_("function with nested functions cannot be inline"); + if (forced_labels) + return + N_("function with label addresses used in initializers cannot inline"); + if (current_function_cannot_inline) return current_function_cannot_inline; @@ -425,7 +429,8 @@ initialize_for_inline (fndecl, min_labelno, max_labelno, max_reg, copy) arg_vector, (rtx) DECL_INITIAL (fndecl), (rtvec) regno_reg_rtx, regno_pointer_flag, regno_pointer_align, - (rtvec) parm_reg_stack_loc); + (rtvec) parm_reg_stack_loc, + nonlocal_goto_handler_labels); } /* Subroutine for `save_for_inline{copying,nocopy}'. Finishes up the @@ -746,6 +751,15 @@ save_for_inline_copying (fndecl) REG_NOTES (insn_map[INSN_UID (insn)]) = copy_for_inline (REG_NOTES (insn)); + /* Now adjust nonlocal_goto_handler_labels list */ + copy = NULL_RTX; + for (insn = nonlocal_goto_handler_labels; insn ; insn = XEXP (insn, 1)) + if (label_map[CODE_LABEL_NUMBER (XEXP (insn,0))] != NULL_RTX) + copy = gen_rtx_EXPR_LIST (VOIDmode, + label_map[CODE_LABEL_NUMBER (XEXP (insn,0))], + copy); + NONLOCAL_GOTO_LABELS_TRAN(head) = copy; + NEXT_INSN (last_insn) = NULL; finish_inline (fndecl, head); @@ -2130,6 +2144,14 @@ expand_inline_function (fndecl, parms, target, ignore, type, REG_NOTES (map->insn_map[INSN_UID (insn)]) = tem; } + /* Now copy nonlocal_goto_handler_list from the function being + inlined into the current list. */ + for (insn = NONLOCAL_GOTO_LABELS_TRAN(header); insn ; insn = XEXP (insn, 1)) + if ( map->label_map[CODE_LABEL_NUMBER (XEXP (insn,0))] != NULL_RTX) + nonlocal_goto_handler_labels = gen_rtx_EXPR_LIST (VOIDmode, + map->label_map[CODE_LABEL_NUMBER (XEXP (insn,0))], + nonlocal_goto_handler_labels); + if (local_return_label) emit_label (local_return_label); @@ -3402,9 +3424,10 @@ output_inline_function (fndecl) regno_pointer_align = INLINE_REGNO_POINTER_ALIGN (head); max_parm_reg = MAX_PARMREG (head); parm_reg_stack_loc = (rtx *) PARMREG_STACK_LOC (head); - + stack_slot_list = STACK_SLOT_LIST (head); forced_labels = FORCED_LABELS (head); + nonlocal_goto_handler_labels = NONLOCAL_GOTO_LABELS (head); if (FUNCTION_FLAGS (head) & FUNCTION_FLAGS_HAS_COMPUTED_JUMP) current_function_has_computed_jump = 1; diff --git a/gnu/egcs/gcc/rtl.def b/gnu/egcs/gcc/rtl.def index 7b8c84571f0..0d9e08abd8e 100644 --- a/gnu/egcs/gcc/rtl.def +++ b/gnu/egcs/gcc/rtl.def @@ -396,7 +396,7 @@ DEF_RTL_EXPR(NOTE, "note", "iuusn", 'x') it contains helps to build the mapping function between the rtx's of the function to be inlined and the current function being expanded. */ -DEF_RTL_EXPR(INLINE_HEADER, "inline_header", "iuuuiiiiiieeiiEeEssE", 'x') +DEF_RTL_EXPR(INLINE_HEADER, "inline_header", "iuuuiiiiiieeiiEeEssEee", 'x') /* ---------------------------------------------------------------------- Top level constituents of INSN, JUMP_INSN and CALL_INSN. diff --git a/gnu/egcs/gcc/rtl.h b/gnu/egcs/gcc/rtl.h index 8eba5eab5d9..c18ba1dc523 100644 --- a/gnu/egcs/gcc/rtl.h +++ b/gnu/egcs/gcc/rtl.h @@ -704,6 +704,8 @@ extern char *note_insn_name[]; #define INLINE_REGNO_POINTER_FLAG(RTX) ((RTX)->fld[17].rtstr) #define INLINE_REGNO_POINTER_ALIGN(RTX) ((RTX)->fld[18].rtstr) #define PARMREG_STACK_LOC(RTX) ((RTX)->fld[19].rtvec) +#define NONLOCAL_GOTO_LABELS(RTX) ((RTX)->fld[20].rtx) +#define NONLOCAL_GOTO_LABELS_TRAN(RTX) ((RTX)->fld[21].rtx) /* In FUNCTION_FLAGS we save some variables computed when emitting the code for the function and which must be `or'ed into the current flag values when @@ -936,7 +938,8 @@ extern rtx gen_label_rtx PROTO((void)); extern rtx gen_inline_header_rtx PROTO((rtx, rtx, int, int, int, int, int, int, rtx, rtx, int, int, rtvec, rtx, - rtvec, char *, char *, rtvec)); + rtvec, char *, char *, rtvec, + rtx)); extern rtx gen_lowpart_common PROTO((enum machine_mode, rtx)); extern rtx gen_lowpart PROTO((enum machine_mode, rtx)); extern rtx gen_lowpart_if_possible PROTO((enum machine_mode, rtx)); |