c/8357: Wrong RTL code for attribute(packed) field access on Sparc

Laurent Voisin Laurent.Voisin@ClearSy.com
Fri Oct 25 10:57:00 GMT 2002


>Number:         8357
>Category:       c
>Synopsis:       Wrong RTL code for attribute(packed) field access on Sparc
>Confidential:   no
>Severity:       critical
>Priority:       medium
>Responsible:    unassigned
>State:          open
>Class:          wrong-code
>Submitter-Id:   net
>Arrival-Date:   Fri Oct 25 10:56:01 PDT 2002
>Closed-Date:
>Last-Modified:
>Originator:     Laurent Voisin
>Release:        3.2
>Organization:
ClearSy System Engineering
>Environment:
System: SunOS prvb 5.6 Generic_105181-19 sun4u sparc SUNW,Ultra-5_10
Architecture: sun4

host: sparc-sun-solaris2.6
build: sparc-sun-solaris2.6
target: sparc-sun-solaris2.6
configured with: ../configure --with-as=/usr/ccs/bin/as --with-ld=/usr/ccs/bin/ld --disable-nls
>Description:

	When emitting the RTL code for the assignment of the example,
	GCC considers that the field is aligned on a 32 bit boundary.
	However, depending on the value of the index, the field can be
	aligned only on a 16 bit boundary.  This will then produce a
	SIGBUS at run-time.

	The wrong RTL instruction is near the end of the "yy.c.00.rtl"
	file and looks like:

	  (insn 22 20 23 (set (mem/s/j:SI (plus:SI (reg/f:SI 111)
                (const_int -16 [0xfffffff0])) [0 <variable>.taille+0 S4 A32])
		        (const_int 0 [0x0])) -1 (nil)
			    (nil))

	I would expect two instructions working on half-words and an
	alignment of A16 instead of A32.

	A workaround would be to make the variable global (so that its
	alignment is 16 bits), but that doesn't work for a recursive
	function.

	The call to `highest_pow2_factor_for_type()' has been introduced
	when correcting PR c++/6212.

	This bug might be the same as in PR c/7847.

>How-To-Repeat:
	Run "gcc -dr -S yy.c" on the attached file.

>Fix:
	I had a look to the GCC code.  I expect this bug to be due to the
	call to `highest_pow2_factor_for_type()' in expand_assignment(),
	file "expr.c", line 3711.
	
	Actually, the alignment permitted by the offset is correctly
	computed as 16 bit.  But the alignment of `TREE_TYPE (to)' is
	32 bits.  Then, the `highest_pow2_factor_for_type()' function
	returns 4 bytes.
	
	So there are two possibility : either the call to
	`highest_pow2_factor_for_type()' is wrong, or its first
	parameter is wrong, that is `TREE_TYPE (to)'.

	Also, it seems odd that `to', which is a COMPONENT_REF, has a
	32 bit alignment in its type, although its first operand has a
	16 bit alignment.  The tree for `to' looks like:

	   <component_ref 548bd0
	      type <integer_type 54c380 int SI
	          size <integer_cst 548270 constant 32>
	          unit size <integer_cst 548318 constant 4>
	          align 32 symtab 0 alias set -1 precision 32 min <...> max <...>
	          pointer_to_this <pointer_type 556540>>
   
	      arg 0 <array_ref 548ba0
	          type <record_type 575f80 type_0 BLK
	              size <integer_cst 549818 constant 48>
	              unit size <integer_cst 55a768 constant 6>
	              user align 16 symtab 0 alias set -1 fields <field_decl 575ea0 taille>

	So, maybe the bug lies in the computation of the type of the
	COMPONENT_REF (that type actually is the plain "int" type).
	That, would explain the bug somehow.  I had a look to
	the `build_component_ref' function and it just makes the
	COMPONENT_REF type the same as the FIELD_DECL type (same
	tree node pointer).

	I'm willing to contribute a patch.  However, I'm missing some
	essential information concerning the way alignments are
	coded inside GCC.  I would be glad if I could have a discussion
	with a GCC guru on this point or have a pointer to some
	documentation, besides the code.
>Release-Note:
>Audit-Trail:
>Unformatted:



More information about the Gcc-bugs mailing list