[RTL, ColdFire 15/63] Avoid out-of-segment constants on uClinux.

Jeffrey Law law@redhat.com
Thu Jan 11 17:15:00 GMT 2007


On Wed, 2007-01-10 at 11:05 +0000, Richard Sandiford wrote:
> One of the big problems with the uClinux flat format is that it cannot
> cope with relocations that point outside the symbol's containing segment.
> E.g. things like:
> 
>     extern unsigned char a[];
>     ... &a[12345 - x] ...
> 
> cannot be implemented as "&a[12345] - x" because "a" might be less than
> 12345 bytes from the end of the segment.  This problem applies to both
> text and data relocations: we should never emit a symbolic constant
> if we are unsure whether it is contained within the symbol's segment.
> 
> MIPS has a similar problem for other reasons, so this patch moves two
> helper routines, mips_offset_within_block_p and mips_split_const,
> from mips.c to rtlanal.c (removing the mips_ prefixes, of course).
> 
> The patch also removes the unused predicates from the movsi expander.
> It seems odd to handle non-legitimate operands in something that appears
> to be (but really isn't) guarded by *_operand predicates.
> 
> One problem with this patch is that we sometimes need to access
> individual bytes or words of wider MEMs.  This will ICE if the
> wider MEM has a legitimate constant address but the narrower
> one doesn't.  This is a generic problem that applies to all
> addresses with limited ranges, and a later patch will fix it.
> 
> FWIW, bfin_legitimate_constant_p does something similar, but it
> doesn't cope with constant pool entries or object blocks, neither
> of which the Blackfin port uses.
> 
> The split_const function is similar to get_related_value and
> get_integer_term, but has the advantage of (a) only walking the
> rtl once and (b) returning an rtx offset, so that if the caller
> needs an rtx, it doesn't need to regenerate one from the HOST_WIDE_INT.
> (get_related_value and get_integer_term also cope with MINUS of a
> CONST_INT, but that isn't canonical rtl.)
> 
> Boostrapped & regression-tested on x86_64-linux-gnu.  I also compared
> the assembly output of mipsisa64-elf and mips64-linux-gnu for the
> C and C++ testsuites, using the options:
> 
>   -O0
>   -O2
>   -mabi=n32
>   -mabi=64
>   -mabi=eabi -mno-abicalls
>   -mabi=32
>   -mabi=o64
> 
> There were no differences.  I'll sign off on the MIPS bits if
> everything else is OK.
> 
> Richard
> 
> 
> gcc/
> 	* Makefile.in (rtlanal.o): Depend on tree.h.
> 	* rtl.h (offset_within_section_p, split_const): Declare.
> 	* rtlanal.c: Include tree.h.
> 	(offset_within_block_p): New function, taken from
> 	mips_offset_within_object_p.
> 	(split_const): New function, taken from mips_split_const.
> 	* config/m68k/m68k-protos.h (m68k_illegitimate_symbolic_constant_p):
> 	Declare.
> 	* config/m68k/m68k.h (M68K_OFFSETS_MUST_BE_WITHIN_SECTIONS_P): Define.
> 	(CONSTANT_ADDRESS_P): Only accept legitimate constants.
> 	(LEGITIMATE_CONSTANT_P): Check m68k_illegitimate_symbolic_constant_p.
> 	* config/m68k/m68k.c (TARGET_CANNOT_FORCE_CONST_MEM): Define.
> 	(m68k_illegitimate_symbolic_constant_p): New function.
> 	* config/m68k/m68k.md (movsi): Remove misleading predicates.
> 	If M68K_OFFSETS_MUST_BE_WITHIN_SECTIONS_P and the source is a
> 	symbolic constant that might be outside the symbol's section,
> 	move the symbol first and then add the offset.
> 	* config/m68k/uclinux.h (M68K_OFFSETS_MUST_BE_WITHIN_SECTIONS_P):
> 	Override.
> 	* config/mips/mips.c (mips_split_const): Delete.
> 	(mips_offset_within_object_p): Delete.
> 	(mips_symbolic_constant_p): Use offset_within_section_p and
> 	split_const instead of mips_offset_within_object_p and
> 	mips_split_const.
> 	(mips_cannot_force_const_mem, mips_const_insns, mips_unspec_address)
> 	(mips_legitimize_const_move, print_operand_reloc)
> 	(mips_dangerous_for_la25_p): Use split_const instead of
> 	mips_split_const.
OK.  THanks.

Jeff




More information about the Gcc-patches mailing list