* [PATCH, PR 57748] Check for out of bounds access @ 2013-09-06 7:03 Bernd Edlinger 2013-09-06 7:31 ` Richard Biener 2013-09-06 9:29 ` [PATCH, PR 57748] Check for out of bounds access Eric Botcazou 0 siblings, 2 replies; 105+ messages in thread From: Bernd Edlinger @ 2013-09-06 7:03 UTC (permalink / raw) To: gcc-patches; +Cc: Richard Biener [-- Attachment #1: Type: text/plain, Size: 361 bytes --] Hi, this patch fixes the ICE and wrong code issues from PR57748. It contains two test cases. One for the ICE and one for the wrong code. Both test cases fail for all gcc versions, and are fixed with this patch. Bootstrapped and tested on x86_64-linux without any problems. OK for trunk and the 4.8 / 4.7 branch? Regards Bernd Edlinger [-- Attachment #2: changelog-pr57748.txt --] [-- Type: text/plain, Size: 252 bytes --] 2013-09-06 Bernd Edlinger <bernd.edlinger@hotmail.de> PR middle-end/57748 * expr.c (expand_assignment): Check for out of bounds access to structures. testsuite: * gcc.dg/torture/pr57748-1.c: New test. * gcc.dg/torture/pr57748-2.c: New test. [-- Attachment #3: patch-pr57748.diff --] [-- Type: application/octet-stream, Size: 2938 bytes --] --- gcc/expr.c 2013-08-06 00:09:45.000000000 +0200 +++ gcc/expr.c 2013-09-03 00:46:28.000000000 +0200 @@ -4707,6 +4707,9 @@ expand_assignment (tree to, tree from, b mode = TYPE_MODE (TREE_TYPE (tem)); if (TREE_CODE (tem) == MEM_REF && mode != BLKmode + && offset == 0 + && bitpos + bitsize <= GET_MODE_BITSIZE (mode) + && !volatilep && ((align = get_object_alignment (tem)) < GET_MODE_ALIGNMENT (mode)) && ((icode = optab_handler (movmisalign_optab, mode)) @@ -4773,6 +4776,8 @@ expand_assignment (tree to, tree from, b if (MEM_P (to_rtx) && GET_MODE (to_rtx) == BLKmode && GET_MODE (XEXP (to_rtx, 0)) != VOIDmode + && bitregion_start == 0 + && bitregion_end == 0 && bitsize > 0 && (bitpos % bitsize) == 0 && (bitsize % GET_MODE_ALIGNMENT (mode1)) == 0 --- gcc/testsuite/gcc.dg/torture/pr57748-1.c 1970-01-01 01:00:00.000000000 +0100 +++ gcc/testsuite/gcc.dg/torture/pr57748-1.c 2013-09-06 08:38:03.718686940 +0200 @@ -0,0 +1,49 @@ +/* PR middle-end/57748 */ +/* { dg-do run } */ +/* ICE in expand_assignment: + misalignp == true, !MEM_P (to_rtx), offset != 0, + => gcc_assert (TREE_CODE (offset) == INTEGER_CST) */ + +#include <stdlib.h> + +extern void abort (void); + +typedef long long V + __attribute__ ((vector_size (2 * sizeof (long long)), may_alias)); + +typedef struct S { V a; V b[0]; } P __attribute__((aligned (1))); + +struct __attribute__((packed)) T { char c; P s; }; + +void __attribute__((noinline, noclone)) +check (struct T *t) +{ + if (t->s.b[0][0] != 3 || t->s.b[0][1] != 4) + abort (); +} + +int __attribute__((noinline, noclone)) +get_i (void) +{ + return 0; +} + +void __attribute__((noinline, noclone)) +foo (P *p) +{ + V a = { 3, 4 }; + int i = get_i (); + p->b[i] = a; +} + +int +main () +{ + struct T *t = (struct T *) calloc (128, 1); + + foo (&t->s); + check (t); + + free (t); + return 0; +} --- gcc/testsuite/gcc.dg/torture/pr57748-2.c 1970-01-01 01:00:00.000000000 +0100 +++ gcc/testsuite/gcc.dg/torture/pr57748-2.c 2013-09-06 08:38:03.718686940 +0200 @@ -0,0 +1,43 @@ +/* PR middle-end/57748 */ +/* { dg-do run } */ +/* wrong code in expand_assignment: + misalignp == true, !MEM_P (to_rtx), + offset == 0, bitpos >= GET_MODE_PRECISION, + => result = NULL */ + +#include <stdlib.h> + +extern void abort (void); + +typedef long long V + __attribute__ ((vector_size (2 * sizeof (long long)), may_alias)); + +typedef struct S { V a; V b[0]; } P __attribute__((aligned (1))); + +struct __attribute__((packed)) T { char c; P s; }; + +void __attribute__((noinline, noclone)) +check (struct T *t) +{ + if (t->s.b[0][0] != 3 || t->s.b[0][1] != 4) + abort (); +} + +void __attribute__((noinline, noclone)) +foo (P *p) +{ + V a = { 3, 4 }; + p->b[0] = a; +} + +int +main () +{ + struct T *t = (struct T *) calloc (128, 1); + + foo (&t->s); + check (t); + + free (t); + return 0; +} ^ permalink raw reply [flat|nested] 105+ messages in thread
* Re: [PATCH, PR 57748] Check for out of bounds access 2013-09-06 7:03 [PATCH, PR 57748] Check for out of bounds access Bernd Edlinger @ 2013-09-06 7:31 ` Richard Biener [not found] ` <DUB122-W323D4AAAEA1AFA890BF243E43C0@phx.gbl> 2013-09-06 9:29 ` [PATCH, PR 57748] Check for out of bounds access Eric Botcazou 1 sibling, 1 reply; 105+ messages in thread From: Richard Biener @ 2013-09-06 7:31 UTC (permalink / raw) To: Bernd Edlinger; +Cc: gcc-patches On Fri, Sep 6, 2013 at 9:03 AM, Bernd Edlinger <bernd.edlinger@hotmail.de> wrote: > Hi, > > this patch fixes the ICE and wrong code issues from PR57748. It contains two test cases. > One for the ICE and one for the wrong code. Both test cases fail for all gcc versions, > and are fixed with this patch. > > Bootstrapped and tested on x86_64-linux without any problems. > > OK for trunk and the 4.8 / 4.7 branch? This doesn't look like the correct test. The movmisalign optab query uses the wrong mode. Richard. > Regards > Bernd Edlinger ^ permalink raw reply [flat|nested] 105+ messages in thread
[parent not found: <DUB122-W323D4AAAEA1AFA890BF243E43C0@phx.gbl>]
[parent not found: <CAFiYyc13wC0jmZ4xELAiL5L5Sbh0yauZWViP2hTdR+H4s0iPSw@mail.gmail.com>]
[parent not found: <DUB122-W4D571A91831593BA22438E43C0@phx.gbl>]
* Re: [PATCH, PR 57748] Check for out of bounds access [not found] ` <DUB122-W4D571A91831593BA22438E43C0@phx.gbl> @ 2013-09-06 9:19 ` Richard Biener 2013-09-06 9:30 ` Bernd Edlinger 2013-09-10 21:33 ` Martin Jambor 0 siblings, 2 replies; 105+ messages in thread From: Richard Biener @ 2013-09-06 9:19 UTC (permalink / raw) To: Bernd Edlinger, Martin Jambor, GCC Patches On Fri, Sep 6, 2013 at 10:35 AM, Bernd Edlinger <bernd.edlinger@hotmail.de> wrote: > Richard, > >> But the movmisalign path skips all this code and with the >> current code thinks the actual access is in the mode of the >> whole structure. (and also misses the address adjustment >> as shown in the other testcase for the bug) >> >> The movmisalign handling in this path is just broken. And >> it's _not_ just for optimization! If you have >> >> struct __attribute__((packed)) { >> double x; >> v2df y; >> } *p; >> >> and do >> >> p = malloc (48); // gets you 8-byte aligned memory >> p->y = (v2df) { 1., 2. }; >> >> then you cannot skip the movmisaling handling because >> we'd generate an aligned move (based on the mode) then. >> > > Ok, test examples are really helpful here. > > This time the structure is BLKmode, unaligned, > movmisalign = false anyway. > > I tried to make a test case out of your example, > and as I expected, the code is also correct: > > foo: > .cfi_startproc > movdqa .LC1(%rip), %xmm0 > movq $-1, (%rdi) > movl $0x4048f5c3, 8(%rdi) > movdqu %xmm0, 12(%rdi) > ret > > movdqu. > > The test executes without trap. > And I did everything to make the object unaligned. Yeah, well - for the expand path with BLKmode it's working fine. We're doing all the dances because of correctness for non-BLKmode expand paths. > I am sure we could completely remove the > movmisalign path, and nothing would happen. > probably. except maybe for a performance regression. In this place probably yes. But we can also fix it to use the proper mode and properly do the offset adjustment. But just adding a bounds check looks broken to me. Note that there may have been a correctness reason for this code in the light of the IPA-SRA code. Maybe Martin remembers. If removing the movmisalign handling inside the handled-component case in expand_assignment works out (make sure to also test a strict-alignment target) then that is probably fine. Richard. > > Bernd. ^ permalink raw reply [flat|nested] 105+ messages in thread
* RE: [PATCH, PR 57748] Check for out of bounds access 2013-09-06 9:19 ` Richard Biener @ 2013-09-06 9:30 ` Bernd Edlinger 2013-09-10 21:33 ` Martin Jambor 1 sibling, 0 replies; 105+ messages in thread From: Bernd Edlinger @ 2013-09-06 9:30 UTC (permalink / raw) To: Richard Biener, Martin Jambor, GCC Patches [-- Attachment #1: Type: text/plain, Size: 2280 bytes --] Just for completeness, these were the test examples on this private communication: On Fri, 6 Sep 2013 11:19:18, Richard Biener wrote: > On Fri, Sep 6, 2013 at 10:35 AM, Bernd Edlinger > <bernd.edlinger@hotmail.de> wrote: >> Richard, >> >>> But the movmisalign path skips all this code and with the >>> current code thinks the actual access is in the mode of the >>> whole structure. (and also misses the address adjustment >>> as shown in the other testcase for the bug) >>> >>> The movmisalign handling in this path is just broken. And >>> it's _not_ just for optimization! If you have >>> >>> struct __attribute__((packed)) { >>> double x; >>> v2df y; >>> } *p; >>> >>> and do >>> >>> p = malloc (48); // gets you 8-byte aligned memory >>> p->y = (v2df) { 1., 2. }; >>> >>> then you cannot skip the movmisaling handling because >>> we'd generate an aligned move (based on the mode) then. >>> >> >> Ok, test examples are really helpful here. >> >> This time the structure is BLKmode, unaligned, >> movmisalign = false anyway. >> >> I tried to make a test case out of your example, >> and as I expected, the code is also correct: >> >> foo: >> .cfi_startproc >> movdqa .LC1(%rip), %xmm0 >> movq $-1, (%rdi) >> movl $0x4048f5c3, 8(%rdi) >> movdqu %xmm0, 12(%rdi) >> ret >> >> movdqu. >> >> The test executes without trap. >> And I did everything to make the object unaligned. > > Yeah, well - for the expand path with BLKmode it's working fine. > We're doing all > the dances because of correctness for non-BLKmode expand paths. > >> I am sure we could completely remove the >> movmisalign path, and nothing would happen. >> probably. except maybe for a performance regression. > > In this place probably yes. But we can also fix it to use the proper mode and > properly do the offset adjustment. But just adding a bounds check looks > broken to me. > > Note that there may have been a correctness reason for this code in the > light of the IPA-SRA code. Maybe Martin remembers. > > If removing the movmisalign handling inside the handled-component > case in expand_assignment works out (make sure to also test a > strict-alignment target) then that is probably fine. > > Richard. > >> >> Bernd. [-- Attachment #2: x.c --] [-- Type: text/plain, Size: 563 bytes --] #include <stdio.h> #include <string.h> typedef long long V __attribute__ ((vector_size (2 * sizeof (long long)), may_alias)); union x { long long a; float b; } __attribute__((aligned(1))) ; struct s { union x xx[0]; V x; } __attribute__((packed)); void __attribute__((noinline, noclone)) foo(struct s * x) { x->xx[0].a = -1; x->xx[0].b = 3.14; x->x[1] = 0x123456789ABCDEF; } int main() { struct s ss; memset(&ss, 0, sizeof(ss)); foo (&ss); printf("%f %llX\n", ss.xx[0].b, ss.xx[0].a); printf("%llX %llX\n", ss.x[0], ss.x[1]); } [-- Attachment #3: y.c --] [-- Type: text/plain, Size: 532 bytes --] #include <stdio.h> #include <string.h> typedef long long V __attribute__ ((vector_size (2 * sizeof (long long)), may_alias)); struct __attribute__((packed)) s { long long a; float b; V x; }; void __attribute__((noinline, noclone)) foo(struct s * x) { V a = { 1, 2 }; x->a = -1; x->b = 3.14; x->x = a; } int main() { long long buf[100]; struct s* ss = (struct s*) ((char*)buf+1); memset(ss, 0, sizeof(*ss)); foo (ss); printf("%f %llX\n", ss->b, ss->a); printf("%llX %llX\n", ss->x[0], ss->x[1]); } ^ permalink raw reply [flat|nested] 105+ messages in thread
* Re: [PATCH, PR 57748] Check for out of bounds access 2013-09-06 9:19 ` Richard Biener 2013-09-06 9:30 ` Bernd Edlinger @ 2013-09-10 21:33 ` Martin Jambor 2013-09-11 14:42 ` Bernd Edlinger 1 sibling, 1 reply; 105+ messages in thread From: Martin Jambor @ 2013-09-10 21:33 UTC (permalink / raw) To: Richard Biener; +Cc: Bernd Edlinger, GCC Patches Hi, On Fri, Sep 06, 2013 at 11:19:18AM +0200, Richard Biener wrote: > On Fri, Sep 6, 2013 at 10:35 AM, Bernd Edlinger > <bernd.edlinger@hotmail.de> wrote: > > Richard, > > > >> But the movmisalign path skips all this code and with the > >> current code thinks the actual access is in the mode of the > >> whole structure. (and also misses the address adjustment > >> as shown in the other testcase for the bug) > >> > >> The movmisalign handling in this path is just broken. And > >> it's _not_ just for optimization! If you have > >> > >> struct __attribute__((packed)) { > >> double x; > >> v2df y; > >> } *p; > >> > >> and do > >> > >> p = malloc (48); // gets you 8-byte aligned memory > >> p->y = (v2df) { 1., 2. }; > >> > >> then you cannot skip the movmisaling handling because > >> we'd generate an aligned move (based on the mode) then. > >> > > > > Ok, test examples are really helpful here. > > > > This time the structure is BLKmode, unaligned, > > movmisalign = false anyway. > > > > I tried to make a test case out of your example, > > and as I expected, the code is also correct: > > > > foo: > > .cfi_startproc > > movdqa .LC1(%rip), %xmm0 > > movq $-1, (%rdi) > > movl $0x4048f5c3, 8(%rdi) > > movdqu %xmm0, 12(%rdi) > > ret > > > > movdqu. > > > > The test executes without trap. > > And I did everything to make the object unaligned. > > Yeah, well - for the expand path with BLKmode it's working fine. > We're doing all > the dances because of correctness for non-BLKmode expand paths. > > > I am sure we could completely remove the > > movmisalign path, and nothing would happen. > > probably. except maybe for a performance regression. > > In this place probably yes. But we can also fix it to use the proper mode and > properly do the offset adjustment. But just adding a bounds check looks > broken to me. > > Note that there may have been a correctness reason for this code in the > light of the IPA-SRA code. Maybe Martin remembers. > The misalignp path was added by you during the 4.7 development to fix PR 50444 which was indeed about expansion of a SRA generated statement MEM[(struct Engine *)e_1(D) + 40B].m = SR.18_17; If I disable this path on the 4.7 branch, the testcase is compiled incorrectly and aborts when run, apparently at least the 4.7's combination of expand_normal and store_field cannot cope with it. The path no longer tests the testcase though, because the component ref is not present in trunk, the LHS is now just MEM[(struct Engine *)e_3(D) + 40B] and so it is now handled just fine by the misaligned mem-ref case at the beginning of expand_assignment. > If removing the movmisalign handling inside the handled-component > case in expand_assignment works out (make sure to also test a > strict-alignment target) then that is probably fine. > I think we'd also better check that we do have a test where we expand a COMPONENT_REF encapsulating a misaligned MEM_REF and a misaligned MEM_REF that is mem_ref_refers_to_non_mem_p. I'm now going through all the new comments in bugzilla and the testcases to see if I can still be of any help. Martin ^ permalink raw reply [flat|nested] 105+ messages in thread
* RE: [PATCH, PR 57748] Check for out of bounds access 2013-09-10 21:33 ` Martin Jambor @ 2013-09-11 14:42 ` Bernd Edlinger 2013-09-11 14:47 ` Richard Biener 0 siblings, 1 reply; 105+ messages in thread From: Bernd Edlinger @ 2013-09-11 14:42 UTC (permalink / raw) To: Martin Jambor, Richard Biener; +Cc: GCC Patches On Tue, 10 Sep 2013 21:32:29, Martin Jambor wrote: > Hi, > > On Fri, Sep 06, 2013 at 11:19:18AM +0200, Richard Biener wrote: >> On Fri, Sep 6, 2013 at 10:35 AM, Bernd Edlinger >> <bernd.edlinger@hotmail.de> wrote: >>> Richard, >>> >>>> But the movmisalign path skips all this code and with the >>>> current code thinks the actual access is in the mode of the >>>> whole structure. (and also misses the address adjustment >>>> as shown in the other testcase for the bug) >>>> >>>> The movmisalign handling in this path is just broken. And >>>> it's _not_ just for optimization! If you have >>>> >>>> struct __attribute__((packed)) { >>>> double x; >>>> v2df y; >>>> } *p; >>>> >>>> and do >>>> >>>> p = malloc (48); // gets you 8-byte aligned memory >>>> p->y = (v2df) { 1., 2. }; >>>> >>>> then you cannot skip the movmisaling handling because >>>> we'd generate an aligned move (based on the mode) then. >>>> >>> >>> Ok, test examples are really helpful here. >>> >>> This time the structure is BLKmode, unaligned, >>> movmisalign = false anyway. >>> >>> I tried to make a test case out of your example, >>> and as I expected, the code is also correct: >>> >>> foo: >>> .cfi_startproc >>> movdqa .LC1(%rip), %xmm0 >>> movq $-1, (%rdi) >>> movl $0x4048f5c3, 8(%rdi) >>> movdqu %xmm0, 12(%rdi) >>> ret >>> >>> movdqu. >>> >>> The test executes without trap. >>> And I did everything to make the object unaligned. >> >> Yeah, well - for the expand path with BLKmode it's working fine. >> We're doing all >> the dances because of correctness for non-BLKmode expand paths. >> >>> I am sure we could completely remove the >>> movmisalign path, and nothing would happen. >>> probably. except maybe for a performance regression. >> >> In this place probably yes. But we can also fix it to use the proper mode and >> properly do the offset adjustment. But just adding a bounds check looks >> broken to me. >> >> Note that there may have been a correctness reason for this code in the >> light of the IPA-SRA code. Maybe Martin remembers. >> > > The misalignp path was added by you during the 4.7 development to fix > PR 50444 which was indeed about expansion of a SRA generated statement > > MEM[(struct Engine *)e_1(D) + 40B].m = SR.18_17; > > If I disable this path on the 4.7 branch, the testcase is compiled > incorrectly and aborts when run, apparently at least the 4.7's > combination of expand_normal and store_field cannot cope with it. > > The path no longer tests the testcase though, because the component > ref is not present in trunk, the LHS is now just > > MEM[(struct Engine *)e_3(D) + 40B] > > and so it is now handled just fine by the misaligned mem-ref case at > the beginning of expand_assignment. I tried to remove the misaligned mem-ref case at the beginning of the expand_assignment, just to see how it fails. I did this on trunk. But still all testcases pass, including pr50444.c... How can this be? >> If removing the movmisalign handling inside the handled-component >> case in expand_assignment works out (make sure to also test a >> strict-alignment target) then that is probably fine. >> > > I think we'd also better check that we do have a test where we expand > a COMPONENT_REF encapsulating a misaligned MEM_REF and a misaligned > MEM_REF that is mem_ref_refers_to_non_mem_p. > > I'm now going through all the new comments in bugzilla and the > testcases to see if I can still be of any help. > > Martin ^ permalink raw reply [flat|nested] 105+ messages in thread
* Re: [PATCH, PR 57748] Check for out of bounds access 2013-09-11 14:42 ` Bernd Edlinger @ 2013-09-11 14:47 ` Richard Biener 2013-09-12 21:07 ` Bernd Edlinger 2013-09-15 19:08 ` Bernd Edlinger 0 siblings, 2 replies; 105+ messages in thread From: Richard Biener @ 2013-09-11 14:47 UTC (permalink / raw) To: Bernd Edlinger; +Cc: Martin Jambor, GCC Patches On Wed, Sep 11, 2013 at 3:41 PM, Bernd Edlinger <bernd.edlinger@hotmail.de> wrote: > On Tue, 10 Sep 2013 21:32:29, Martin Jambor wrote: >> Hi, >> >> On Fri, Sep 06, 2013 at 11:19:18AM +0200, Richard Biener wrote: >>> On Fri, Sep 6, 2013 at 10:35 AM, Bernd Edlinger >>> <bernd.edlinger@hotmail.de> wrote: >>>> Richard, >>>> >>>>> But the movmisalign path skips all this code and with the >>>>> current code thinks the actual access is in the mode of the >>>>> whole structure. (and also misses the address adjustment >>>>> as shown in the other testcase for the bug) >>>>> >>>>> The movmisalign handling in this path is just broken. And >>>>> it's _not_ just for optimization! If you have >>>>> >>>>> struct __attribute__((packed)) { >>>>> double x; >>>>> v2df y; >>>>> } *p; >>>>> >>>>> and do >>>>> >>>>> p = malloc (48); // gets you 8-byte aligned memory >>>>> p->y = (v2df) { 1., 2. }; >>>>> >>>>> then you cannot skip the movmisaling handling because >>>>> we'd generate an aligned move (based on the mode) then. >>>>> >>>> >>>> Ok, test examples are really helpful here. >>>> >>>> This time the structure is BLKmode, unaligned, >>>> movmisalign = false anyway. >>>> >>>> I tried to make a test case out of your example, >>>> and as I expected, the code is also correct: >>>> >>>> foo: >>>> .cfi_startproc >>>> movdqa .LC1(%rip), %xmm0 >>>> movq $-1, (%rdi) >>>> movl $0x4048f5c3, 8(%rdi) >>>> movdqu %xmm0, 12(%rdi) >>>> ret >>>> >>>> movdqu. >>>> >>>> The test executes without trap. >>>> And I did everything to make the object unaligned. >>> >>> Yeah, well - for the expand path with BLKmode it's working fine. >>> We're doing all >>> the dances because of correctness for non-BLKmode expand paths. >>> >>>> I am sure we could completely remove the >>>> movmisalign path, and nothing would happen. >>>> probably. except maybe for a performance regression. >>> >>> In this place probably yes. But we can also fix it to use the proper mode and >>> properly do the offset adjustment. But just adding a bounds check looks >>> broken to me. >>> >>> Note that there may have been a correctness reason for this code in the >>> light of the IPA-SRA code. Maybe Martin remembers. >>> >> >> The misalignp path was added by you during the 4.7 development to fix >> PR 50444 which was indeed about expansion of a SRA generated statement >> >> MEM[(struct Engine *)e_1(D) + 40B].m = SR.18_17; >> >> If I disable this path on the 4.7 branch, the testcase is compiled >> incorrectly and aborts when run, apparently at least the 4.7's >> combination of expand_normal and store_field cannot cope with it. >> >> The path no longer tests the testcase though, because the component >> ref is not present in trunk, the LHS is now just >> >> MEM[(struct Engine *)e_3(D) + 40B] >> >> and so it is now handled just fine by the misaligned mem-ref case at >> the beginning of expand_assignment. > > I tried to remove the misaligned mem-ref case at the beginning of the > expand_assignment, just to see how it fails. I did this on trunk. > > But still all testcases pass, including pr50444.c... > > How can this be? Not sure. Can you try reverting the fix itself and bisect when the testcase will start to pass? (maybe the testcase passed even without the fix?) Richard. >>> If removing the movmisalign handling inside the handled-component >>> case in expand_assignment works out (make sure to also test a >>> strict-alignment target) then that is probably fine. >>> >> >> I think we'd also better check that we do have a test where we expand >> a COMPONENT_REF encapsulating a misaligned MEM_REF and a misaligned >> MEM_REF that is mem_ref_refers_to_non_mem_p. >> >> I'm now going through all the new comments in bugzilla and the >> testcases to see if I can still be of any help. >> >> Martin ^ permalink raw reply [flat|nested] 105+ messages in thread
* RE: [PATCH, PR 57748] Check for out of bounds access 2013-09-11 14:47 ` Richard Biener @ 2013-09-12 21:07 ` Bernd Edlinger 2013-09-13 9:37 ` Eric Botcazou 2013-09-15 19:08 ` Bernd Edlinger 1 sibling, 1 reply; 105+ messages in thread From: Bernd Edlinger @ 2013-09-12 21:07 UTC (permalink / raw) To: Richard Biener; +Cc: Martin Jambor, GCC Patches [-- Attachment #1: Type: text/plain, Size: 2456 bytes --] On Wed, 11 Sep 2013 15:43:53, Richard Biener wrote: > On Wed, Sep 11, 2013 at 3:41 PM, Bernd Edlinger > <bernd.edlinger@hotmail.de> wrote: >> On Tue, 10 Sep 2013 21:32:29, Martin Jambor wrote: >>> The misalignp path was added by you during the 4.7 development to fix >>> PR 50444 which was indeed about expansion of a SRA generated statement >>> >>> MEM[(struct Engine *)e_1(D) + 40B].m = SR.18_17; >>> >>> If I disable this path on the 4.7 branch, the testcase is compiled >>> incorrectly and aborts when run, apparently at least the 4.7's >>> combination of expand_normal and store_field cannot cope with it. >>> >>> The path no longer tests the testcase though, because the component >>> ref is not present in trunk, the LHS is now just >>> >>> MEM[(struct Engine *)e_3(D) + 40B] >>> >>> and so it is now handled just fine by the misaligned mem-ref case at >>> the beginning of expand_assignment. >> >> I tried to remove the misaligned mem-ref case at the beginning of the >> expand_assignment, just to see how it fails. I did this on trunk. >> >> But still all testcases pass, including pr50444.c... >> >> How can this be? > > Not sure. Can you try reverting the fix itself and bisect when the testcase > will start to pass? (maybe the testcase passed even without the fix?) > > Richard. What I found out is this: If the movmisalign_optab is replaced by mov_optab it does still generate correct code. In 4.9, 4.8 and 4.7 too. The reason is that the back-end accesses MEM_ALIGN(to_rtx) in mov_optab and movmisalign_optab to decide if movdqa or movdqu is needed. While it is straight forward to remove the movmisalign path in 4.9 and 4.8, this is not so simple in the 4.7 branch. The reason is that 4.7 uses "to_rtx = expand_normal (tem);" while 4.8 and 4.9 use "to_rtx = expand_expr (tem, NULL_RTX, VOIDmode, EXPAND_WRITE);" which does almost the same, but returns the misaligned rtx instead of an register with the value of the structure. And the generated code without the misalign path fails simply because the assignment goes to the register instead of the structure. So the problem is: there is no EXPAND_WRITE/EXPAND_MEMORY in 4.7... A possible patch for 4.7 would be like the attached (untested) patch. With this pr50444.c, and pr57748-1..3.c would pass, but not pr57748-4.c as the read side would still be wrong, but back-porting this would be even more ugly :( Bernd. [-- Attachment #2: patch-pr57748-4_7.diff --] [-- Type: application/octet-stream, Size: 2305 bytes --] Index: gcc/expr.c =================================================================== --- gcc/expr.c (Revision 202295) +++ gcc/expr.c (Arbeitskopie) @@ -4641,8 +4641,6 @@ int unsignedp; int volatilep = 0; tree tem; - bool misalignp; - rtx mem = NULL_RTX; push_temp_slots (); tem = get_inner_reference (to, &bitsize, &bitpos, &offset, &mode1, @@ -4664,14 +4662,10 @@ { enum machine_mode address_mode; rtx op0; - struct expand_operand ops[2]; addr_space_t as = TYPE_ADDR_SPACE (TREE_TYPE (TREE_TYPE (TREE_OPERAND (tem, 0)))); tree base = TREE_OPERAND (tem, 0); - misalignp = true; - to_rtx = gen_reg_rtx (mode); - address_mode = targetm.addr_space.address_mode (as); op0 = expand_expr (base, NULL_RTX, VOIDmode, EXPAND_NORMAL); op0 = convert_memory_address_addr_space (address_mode, op0, as); @@ -4682,28 +4676,14 @@ op0 = simplify_gen_binary (PLUS, address_mode, op0, off); } op0 = memory_address_addr_space (mode, op0, as); - mem = gen_rtx_MEM (mode, op0); - set_mem_attributes (mem, tem, 0); - set_mem_addr_space (mem, as); + to_rtx = gen_rtx_MEM (mode, op0); + set_mem_attributes (to_rtx, tem, 0); + set_mem_addr_space (to_rtx, as); if (TREE_THIS_VOLATILE (tem)) - MEM_VOLATILE_P (mem) = 1; - - /* If the misaligned store doesn't overwrite all bits, perform - rmw cycle on MEM. */ - if (bitsize != GET_MODE_BITSIZE (mode)) - { - create_input_operand (&ops[0], to_rtx, mode); - create_fixed_operand (&ops[1], mem); - /* The movmisalign<mode> pattern cannot fail, else the assignment - would silently be omitted. */ - expand_insn (icode, 2, ops); - - mem = copy_rtx (mem); - } + MEM_VOLATILE_P (to_rtx) = 1; } else { - misalignp = false; to_rtx = expand_normal (tem); } @@ -4851,17 +4831,6 @@ nontemporal); } - if (misalignp) - { - struct expand_operand ops[2]; - - create_fixed_operand (&ops[0], mem); - create_input_operand (&ops[1], to_rtx, mode); - /* The movmisalign<mode> pattern cannot fail, else the assignment - would silently be omitted. */ - expand_insn (icode, 2, ops); - } - if (result) preserve_temp_slots (result); free_temp_slots (); ^ permalink raw reply [flat|nested] 105+ messages in thread
* Re: [PATCH, PR 57748] Check for out of bounds access 2013-09-12 21:07 ` Bernd Edlinger @ 2013-09-13 9:37 ` Eric Botcazou 2013-09-13 9:48 ` Bernd Edlinger 0 siblings, 1 reply; 105+ messages in thread From: Eric Botcazou @ 2013-09-13 9:37 UTC (permalink / raw) To: Bernd Edlinger; +Cc: gcc-patches, Richard Biener, Martin Jambor > While it is straight forward to remove the movmisalign path in 4.9 and 4.8, > this is not so simple in the 4.7 branch. The reason is that 4.7 uses > "to_rtx = expand_normal (tem);" while 4.8 and 4.9 use > "to_rtx = expand_expr (tem, NULL_RTX, VOIDmode, EXPAND_WRITE);" > which does almost the same, but returns the misaligned rtx instead of > an register with the value of the structure. And the generated code without > the misalign path fails simply because the assignment goes to the register > instead of the structure. > > So the problem is: there is no EXPAND_WRITE/EXPAND_MEMORY in 4.7... > > A possible patch for 4.7 would be like the attached (untested) patch. Let's simply declare this as WONTFIX on the 4.7 branch. -- Eric Botcazou ^ permalink raw reply [flat|nested] 105+ messages in thread
* RE: [PATCH, PR 57748] Check for out of bounds access 2013-09-13 9:37 ` Eric Botcazou @ 2013-09-13 9:48 ` Bernd Edlinger 0 siblings, 0 replies; 105+ messages in thread From: Bernd Edlinger @ 2013-09-13 9:48 UTC (permalink / raw) To: Eric Botcazou; +Cc: gcc-patches, Richard Biener, Martin Jambor >> While it is straight forward to remove the movmisalign path in 4.9 and 4.8, >> this is not so simple in the 4.7 branch. The reason is that 4.7 uses >> "to_rtx = expand_normal (tem);" while 4.8 and 4.9 use >> "to_rtx = expand_expr (tem, NULL_RTX, VOIDmode, EXPAND_WRITE);" >> which does almost the same, but returns the misaligned rtx instead of >> an register with the value of the structure. And the generated code without >> the misalign path fails simply because the assignment goes to the register >> instead of the structure. >> >> So the problem is: there is no EXPAND_WRITE/EXPAND_MEMORY in 4.7... >> >> A possible patch for 4.7 would be like the attached (untested) patch. > > Let's simply declare this as WONTFIX on the 4.7 branch. > > -- > Eric Botcazou I absolutely agree with you. This was only meant as a theoretical exercise. I was just nervous, if removing the misalign path is the right fix here, because as Martin pointed out that SRA behaves quite differently in the 4.7 branch, and pr50444.c does test nothing in 4.8 and trunk. The result is: yes. Removing the misalign path will be OK on trunk. Bernd. ^ permalink raw reply [flat|nested] 105+ messages in thread
* RE: [PATCH, PR 57748] Check for out of bounds access 2013-09-11 14:47 ` Richard Biener 2013-09-12 21:07 ` Bernd Edlinger @ 2013-09-15 19:08 ` Bernd Edlinger 2013-09-17 0:05 ` Martin Jambor 2013-09-17 11:07 ` [PATCH, PR 57748] Check for out of bounds access Richard Biener 1 sibling, 2 replies; 105+ messages in thread From: Bernd Edlinger @ 2013-09-15 19:08 UTC (permalink / raw) To: Richard Biener; +Cc: Martin Jambor, GCC Patches [-- Attachment #1: Type: text/plain, Size: 679 bytes --] Hello Richard, attached is my second attempt at fixing PR 57748. This time the movmisalign path is completely removed and a similar bug in the read handling of misaligned structures with a non-BLKmode is fixed too. There are several new test cases for the different possible failure modes. This patch was boot-strapped and regression tested on x86_64-unknown-linux-gnu and i686-pc-linux-gnu. Additionally I generated eCos and an eCos-application (on ARMv5 using packed structures) with an arm-eabi cross compiler, and looked for differences in the disassembled code with and without this patch, but there were none. OK for trunk? Regards Bernd. [-- Attachment #2: changelog-pr57748.txt --] [-- Type: text/plain, Size: 519 bytes --] 2013-09-15 Bernd Edlinger <bernd.edlinger@hotmail.de> PR middle-end/57748 * expr.c (expand_assignment): Remove misalignp code path. Check for bitregion in offset arithmetic. (expand_expr_real_1): Use EXAND_MEMORY on base object. testsuite: PR middle-end/57748 * gcc.dg/torture/pr57748-1.c: New test. * gcc.dg/torture/pr57748-2.c: New test. * gcc.dg/torture/pr57748-3.c: New test. * gcc.dg/torture/pr57748-3a.c: New test. * gcc.dg/torture/pr57748-4.c: New test. * gcc.dg/torture/pr57748-4a.c: New test. [-- Attachment #3: patch-pr57748.diff --] [-- Type: application/octet-stream, Size: 8061 bytes --] --- gcc/expr.c 2013-08-06 00:09:45.000000000 +0200 +++ gcc/expr.c 2013-09-10 08:23:09.570951685 +0200 @@ -4691,8 +4691,6 @@ expand_assignment (tree to, tree from, b int unsignedp; int volatilep = 0; tree tem; - bool misalignp; - rtx mem = NULL_RTX; push_temp_slots (); tem = get_inner_reference (to, &bitsize, &bitpos, &offset, &mode1, @@ -4702,40 +4700,7 @@ expand_assignment (tree to, tree from, b && DECL_BIT_FIELD_TYPE (TREE_OPERAND (to, 1))) get_bit_range (&bitregion_start, &bitregion_end, to, &bitpos, &offset); - /* If we are going to use store_bit_field and extract_bit_field, - make sure to_rtx will be safe for multiple use. */ - mode = TYPE_MODE (TREE_TYPE (tem)); - if (TREE_CODE (tem) == MEM_REF - && mode != BLKmode - && ((align = get_object_alignment (tem)) - < GET_MODE_ALIGNMENT (mode)) - && ((icode = optab_handler (movmisalign_optab, mode)) - != CODE_FOR_nothing)) - { - struct expand_operand ops[2]; - - misalignp = true; - to_rtx = gen_reg_rtx (mode); - mem = expand_expr (tem, NULL_RTX, VOIDmode, EXPAND_WRITE); - - /* If the misaligned store doesn't overwrite all bits, perform - rmw cycle on MEM. */ - if (bitsize != GET_MODE_BITSIZE (mode)) - { - create_input_operand (&ops[0], to_rtx, mode); - create_fixed_operand (&ops[1], mem); - /* The movmisalign<mode> pattern cannot fail, else the assignment - would silently be omitted. */ - expand_insn (icode, 2, ops); - - mem = copy_rtx (mem); - } - } - else - { - misalignp = false; - to_rtx = expand_expr (tem, NULL_RTX, VOIDmode, EXPAND_WRITE); - } + to_rtx = expand_expr (tem, NULL_RTX, VOIDmode, EXPAND_WRITE); /* If the bitfield is volatile, we want to access it in the field's mode, not the computed mode. @@ -4773,6 +4738,8 @@ expand_assignment (tree to, tree from, b if (MEM_P (to_rtx) && GET_MODE (to_rtx) == BLKmode && GET_MODE (XEXP (to_rtx, 0)) != VOIDmode + && bitregion_start == 0 + && bitregion_end == 0 && bitsize > 0 && (bitpos % bitsize) == 0 && (bitsize % GET_MODE_ALIGNMENT (mode1)) == 0 @@ -4874,17 +4841,6 @@ expand_assignment (tree to, tree from, b get_alias_set (to), nontemporal); } - if (misalignp) - { - struct expand_operand ops[2]; - - create_fixed_operand (&ops[0], mem); - create_input_operand (&ops[1], to_rtx, mode); - /* The movmisalign<mode> pattern cannot fail, else the assignment - would silently be omitted. */ - expand_insn (icode, 2, ops); - } - if (result) preserve_temp_slots (result); pop_temp_slots (); @@ -9905,7 +9861,7 @@ expand_expr_real_1 (tree exp, rtx target && modifier != EXPAND_STACK_PARM ? target : NULL_RTX), VOIDmode, - modifier == EXPAND_SUM ? EXPAND_NORMAL : modifier); + EXPAND_MEMORY); /* If the bitfield is volatile, we want to access it in the field's mode, not the computed mode. --- gcc/testsuite/gcc.dg/torture/pr57748-1.c 1970-01-01 01:00:00.000000000 +0100 +++ gcc/testsuite/gcc.dg/torture/pr57748-1.c 2013-09-06 08:38:03.718686940 +0200 @@ -0,0 +1,49 @@ +/* PR middle-end/57748 */ +/* { dg-do run } */ +/* ICE in expand_assignment: + misalignp == true, !MEM_P (to_rtx), offset != 0, + => gcc_assert (TREE_CODE (offset) == INTEGER_CST) */ + +#include <stdlib.h> + +extern void abort (void); + +typedef long long V + __attribute__ ((vector_size (2 * sizeof (long long)), may_alias)); + +typedef struct S { V a; V b[0]; } P __attribute__((aligned (1))); + +struct __attribute__((packed)) T { char c; P s; }; + +void __attribute__((noinline, noclone)) +check (struct T *t) +{ + if (t->s.b[0][0] != 3 || t->s.b[0][1] != 4) + abort (); +} + +int __attribute__((noinline, noclone)) +get_i (void) +{ + return 0; +} + +void __attribute__((noinline, noclone)) +foo (P *p) +{ + V a = { 3, 4 }; + int i = get_i (); + p->b[i] = a; +} + +int +main () +{ + struct T *t = (struct T *) calloc (128, 1); + + foo (&t->s); + check (t); + + free (t); + return 0; +} --- gcc/testsuite/gcc.dg/torture/pr57748-2.c 1970-01-01 01:00:00.000000000 +0100 +++ gcc/testsuite/gcc.dg/torture/pr57748-2.c 2013-09-06 08:38:03.718686940 +0200 @@ -0,0 +1,43 @@ +/* PR middle-end/57748 */ +/* { dg-do run } */ +/* wrong code in expand_assignment: + misalignp == true, !MEM_P (to_rtx), + offset == 0, bitpos >= GET_MODE_PRECISION, + => result = NULL. */ + +#include <stdlib.h> + +extern void abort (void); + +typedef long long V + __attribute__ ((vector_size (2 * sizeof (long long)), may_alias)); + +typedef struct S { V a; V b[0]; } P __attribute__((aligned (1))); + +struct __attribute__((packed)) T { char c; P s; }; + +void __attribute__((noinline, noclone)) +check (struct T *t) +{ + if (t->s.b[0][0] != 3 || t->s.b[0][1] != 4) + abort (); +} + +void __attribute__((noinline, noclone)) +foo (P *p) +{ + V a = { 3, 4 }; + p->b[0] = a; +} + +int +main () +{ + struct T *t = (struct T *) calloc (128, 1); + + foo (&t->s); + check (t); + + free (t); + return 0; +} --- gcc/testsuite/gcc.dg/torture/pr57748-3.c 1970-01-01 01:00:00.000000000 +0100 +++ gcc/testsuite/gcc.dg/torture/pr57748-3.c 2013-09-13 12:46:34.456009224 +0200 @@ -0,0 +1,48 @@ +/* PR middle-end/57748 */ +/* { dg-do run } */ +/* data store race in expand_assignment: + misalignp == true, !MEM_P (to_rtx), + offset == 0, bitsize < GET_MODE_BITSIZE, + => rmw cycle on MEM. */ + +extern void abort (void); + +typedef long long V + __attribute__ ((vector_size (2 * sizeof (long long)), may_alias)); + +union x +{ + long long a; + float b; +} __attribute__((aligned (1))); + +struct s +{ + union x xx[0]; + V x; +} __attribute__((packed)); + +void __attribute__((noinline, noclone)) +check (union x *xx) +{ + if (xx[0].b != 3.14F || xx[1].a != 0x123456789ABCDEF) + abort (); +} + +void __attribute__((noinline, noclone)) +foo (struct s * x) +{ + x->xx[0].a = -1; + x->xx[0].b = 3.14F; + x->x[1] = 0x123456789ABCDEF; +} + +struct s ss; + +int +main () +{ + foo (&ss); + check (ss.xx); + return 0; +} --- gcc/testsuite/gcc.dg/torture/pr57748-3a.c 1970-01-01 01:00:00.000000000 +0100 +++ gcc/testsuite/gcc.dg/torture/pr57748-3a.c 2013-09-13 12:44:47.140007819 +0200 @@ -0,0 +1,7 @@ +/* PR middle-end/57748 */ +/* { dg-do compile } */ +/* { dg-options "-msse2" } */ +/* { dg-require-effective-target sse2 } */ +/* { dg-final { scan-assembler-not "movdqu" } } */ +/* { dg-final { scan-assembler-not "movdqa" } } */ +#include "pr57748-3.c" --- gcc/testsuite/gcc.dg/torture/pr57748-4.c 1970-01-01 01:00:00.000000000 +0100 +++ gcc/testsuite/gcc.dg/torture/pr57748-4.c 2013-09-13 12:46:13.412008952 +0200 @@ -0,0 +1,49 @@ +/* PR middle-end/57748 */ +/* { dg-do run } */ +/* wrong code in expand_expr_real_1: + read whole structure instead of only one member. */ + +extern void abort (void); + +typedef long long V + __attribute__ ((vector_size (2 * sizeof (long long)), may_alias)); + +union x +{ + long long a; + float b; +} __attribute__((aligned (1))); + +struct s +{ + union x xx[0]; + V x; +} __attribute__((packed)); + +void __attribute__((noinline, noclone)) +check (struct s *x) +{ + if (x->xx[0].b != 3.14F || x->xx[1].a != 0x123456789ABCDEF) + abort (); + if (x->xx[2].b != 3.14F || x->xx[3].a != 0x123456789ABCDEF) + abort (); +} + +void __attribute__((noinline, noclone)) +foo (struct s * x) +{ + x->xx[0].a = -1; + x->xx[0].b = 3.14F; + x->x[1] = 0x123456789ABCDEF; +} + +struct s ss[2]; + +int +main () +{ + foo (ss); + foo (ss+1); + check (ss); + return 0; +} --- gcc/testsuite/gcc.dg/torture/pr57748-4a.c 1970-01-01 01:00:00.000000000 +0100 +++ gcc/testsuite/gcc.dg/torture/pr57748-4a.c 2013-09-13 12:46:02.812008813 +0200 @@ -0,0 +1,7 @@ +/* PR middle-end/57748 */ +/* { dg-do compile } */ +/* { dg-options "-msse2" } */ +/* { dg-require-effective-target sse2 } */ +/* { dg-final { scan-assembler-not "movdqu" } } */ +/* { dg-final { scan-assembler-not "movdqa" } } */ +#include "pr57748-4.c" ^ permalink raw reply [flat|nested] 105+ messages in thread
* Re: [PATCH, PR 57748] Check for out of bounds access 2013-09-15 19:08 ` Bernd Edlinger @ 2013-09-17 0:05 ` Martin Jambor 2013-09-17 10:32 ` Bernd Edlinger 2013-10-22 14:08 ` Bernd Edlinger 2013-09-17 11:07 ` [PATCH, PR 57748] Check for out of bounds access Richard Biener 1 sibling, 2 replies; 105+ messages in thread From: Martin Jambor @ 2013-09-17 0:05 UTC (permalink / raw) To: Bernd Edlinger; +Cc: Richard Biener, GCC Patches [-- Attachment #1: Type: text/plain, Size: 3446 bytes --] Hi, On Sun, Sep 15, 2013 at 06:55:17PM +0200, Bernd Edlinger wrote: > Hello Richard, > > attached is my second attempt at fixing PR 57748. This time the > movmisalign path is completely removed and a similar bug in the read > handling of misaligned structures with a non-BLKmode is fixed > too. There are several new test cases for the different possible > failure modes. I think the third and fourth testcases are undefined as the description of zero-length arrays extension clearly says the whole thing only makes sense when used as the last field of the outermost-aggregate type. I have not really understood what the third testcase is supposed to test but I did not try too much. Instead of the fourth testcase, you can demonstrate the need for your change in expand_expr_real_1 by augmenting the original testcase a little like in attached pr57748-m1.c. The hunk in expand_expr_real_1 can prove problematic if at any point we need to pass some other modifier to the expansion of tem. I'll try to see if I can come up with a testcase tomorrow. But perhaps we never do (and can hope we never will) and then it would be sort of OKish (note that I cannot approve anything) even though it can pessimize unaligned access paths (by not using movmisalign_optab even when perfectly possible - which is always when there is no zero sized array). It really just shows how evil non-BLKmode structures with zero-sized arrays are and how they complicate things. The expansion of component_refs is reasonably built around the assumption that we'd expand the structure in its mode in the most efficient manner and then chuck the correct part out of it, but here we need to tell the expansion of the structure to hold itself back because we'll be looking outside of the structure (as specified by mode). I'm not sure to what extent the hunk adding tests for bitregion_start and bitregion_end being zero is connected to this issue. I do not see any of the testcases exercising that path. If it is indeed another problem, I think it should be submitted (and potentially committed) as a separate patch, preferably with a testcase. Having said all that, I think that removing the misalignp path from expand_assignment altogether is a good idea. I have verified that when the expander is now presented with basically the same thing that 4.7 choked on, expand_expr (..., EXPAND_WRITE) can cope with it (see attached file c.c) and doing that simplifies this complex code path. Thanks, Martin > > This patch was boot-strapped and regression tested on x86_64-unknown-linux-gnu > and i686-pc-linux-gnu. > > Additionally I generated eCos and an eCos-application (on ARMv5 using packed > structures) with an arm-eabi cross compiler, and looked for differences in the > disassembled code with and without this patch, but there were none. > > OK for trunk? > > Regards > Bernd. > 2013-09-15 Bernd Edlinger <bernd.edlinger@hotmail.de> > > PR middle-end/57748 > * expr.c (expand_assignment): Remove misalignp code path. > Check for bitregion in offset arithmetic. > (expand_expr_real_1): Use EXAND_MEMORY on base object. > > testsuite: > > PR middle-end/57748 > * gcc.dg/torture/pr57748-1.c: New test. > * gcc.dg/torture/pr57748-2.c: New test. > * gcc.dg/torture/pr57748-3.c: New test. > * gcc.dg/torture/pr57748-3a.c: New test. > * gcc.dg/torture/pr57748-4.c: New test. > * gcc.dg/torture/pr57748-4a.c: New test. > [-- Attachment #2: pr57748-m1.c --] [-- Type: text/x-c, Size: 842 bytes --] /* PR middle-end/57748 */ /* { dg-do run } */ #include <stdlib.h> extern void abort (void); typedef long long V __attribute__ ((vector_size (2 * sizeof (long long)), may_alias)); typedef struct S { V a; V b[0]; } P __attribute__((aligned (1))); struct __attribute__((packed)) T { char c; P s; }; void __attribute__((noinline, noclone)) check (struct T *t) { if (t->s.b[0][0] != 3 || t->s.b[0][1] != 4) abort (); } void __attribute__((noinline, noclone)) check_1 (P *p) { if (p->b[0][0] != 3 || p->b[0][1] != 4) abort (); } int __attribute__((noinline, noclone)) get_i (void) { return 0; } void __attribute__((noinline, noclone)) foo (P *p) { V a = { 3, 4 }; int i = get_i(); p->b[i] = a; } int main () { struct T *t = (struct T *) malloc (128); foo (&t->s); check (t); check_1 (&t->s); return 0; } [-- Attachment #3: c.c --] [-- Type: text/x-c, Size: 421 bytes --] #include <stdlib.h> extern void abort (void); typedef long long V __attribute__ ((vector_size (2 * sizeof (long long)), may_alias)); typedef struct S { V a; } P __attribute__((aligned (1))); struct __attribute__((packed)) T { char c; P s; }; void __attribute__((noinline, noclone)) foo (P *p) { V a = { 3, 4 }; p->a = a; } int main () { struct T *t = (struct T *) malloc (128); foo (&t->s); return 0; } ^ permalink raw reply [flat|nested] 105+ messages in thread
* RE: [PATCH, PR 57748] Check for out of bounds access 2013-09-17 0:05 ` Martin Jambor @ 2013-09-17 10:32 ` Bernd Edlinger 2013-10-22 14:08 ` Bernd Edlinger 1 sibling, 0 replies; 105+ messages in thread From: Bernd Edlinger @ 2013-09-17 10:32 UTC (permalink / raw) To: Martin Jambor; +Cc: Richard Biener, GCC Patches Hi Martin, On Tue, 17 Sep 2013 01:09:45, Martin Jambor wrote: > Hi, > > On Sun, Sep 15, 2013 at 06:55:17PM +0200, Bernd Edlinger wrote: >> Hello Richard, >> >> attached is my second attempt at fixing PR 57748. This time the >> movmisalign path is completely removed and a similar bug in the read >> handling of misaligned structures with a non-BLKmode is fixed >> too. There are several new test cases for the different possible >> failure modes. > > I think the third and fourth testcases are undefined as the > description of zero-length arrays extension clearly says the whole > thing only makes sense when used as the last field of the > outermost-aggregate type. I have not really understood what the third > testcase is supposed to test but I did not try too much. Instead of > the fourth testcase, you can demonstrate the need for your change in > expand_expr_real_1 by augmenting the original testcase a little like > in attached pr57748-m1.c. The third test case tries to demonstrate the possible write data store race (by checking the assembler output). But you are right, this example is probably not valid C at all. I was actually worried about unions with non-BLK mode and a movmisalign optab handler. When you look at stor-layout.c (compute_record_mode) you'll see, that in the case of a union usually an integer mode is chosen, which is exactly the same size as the whole union. And just by chance this does not have a movmisalign optab. Therefore I tried to cheat with that zero-sized array, which should probably be rejected at stor-layout.c in the first place. When I tried to make a test case out of it, the bug on the read side hit me as a total surprise... > The hunk in expand_expr_real_1 can prove problematic if at any point > we need to pass some other modifier to the expansion of tem. I'll try > to see if I can come up with a testcase tomorrow. But perhaps we > never do (and can hope we never will) and then it would be sort of > OKish (note that I cannot approve anything) even though it can > pessimize unaligned access paths (by not using movmisalign_optab even > when perfectly possible - which is always when there is no zero sized > array). It really just shows how evil non-BLKmode structures with > zero-sized arrays are and how they complicate things. The expansion > of component_refs is reasonably built around the assumption that we'd > expand the structure in its mode in the most efficient manner and then > chuck the correct part out of it, but here we need to tell the > expansion of the structure to hold itself back because we'll be > looking outside of the structure (as specified by mode). I too am under the very strong impression that this was not the intention of the design to use a non-BLKmode on a structure with zero-sized arrays. > I'm not sure to what extent the hunk adding tests for bitregion_start > and bitregion_end being zero is connected to this issue. I do not see > any of the testcases exercising that path. If it is indeed another > problem, I think it should be submitted (and potentially committed) as > a separate patch, preferably with a testcase. Yes, you're probably right. I was unable to find a test case where this code path executes with bitregions. As I said, it maybe possible to prove that bitregion_start and bitregion_end == 0 if the other conditions are satisfied. What is obvious, that it would cause problems to set bitpos=0 when bitregion_start/end is pointing elsewhere. It is however much easier to prove that not going into that code path would not cause any problems if bitregion_start/end is not zero. So this was just for safer programming, but probably no real bug. Thanks, Bernd. > Having said all that, I think that removing the misalignp path from > expand_assignment altogether is a good idea. I have verified that > when the expander is now presented with basically the same thing that > 4.7 choked on, expand_expr (..., EXPAND_WRITE) can cope with it (see > attached file c.c) and doing that simplifies this complex code path. > > Thanks, > > Martin > >> >> This patch was boot-strapped and regression tested on x86_64-unknown-linux-gnu >> and i686-pc-linux-gnu. >> >> Additionally I generated eCos and an eCos-application (on ARMv5 using packed >> structures) with an arm-eabi cross compiler, and looked for differences in the >> disassembled code with and without this patch, but there were none. >> >> OK for trunk? >> >> Regards >> Bernd. > >> 2013-09-15 Bernd Edlinger <bernd.edlinger@hotmail.de> >> >> PR middle-end/57748 >> * expr.c (expand_assignment): Remove misalignp code path. >> Check for bitregion in offset arithmetic. >> (expand_expr_real_1): Use EXAND_MEMORY on base object. >> >> testsuite: >> >> PR middle-end/57748 >> * gcc.dg/torture/pr57748-1.c: New test. >> * gcc.dg/torture/pr57748-2.c: New test. >> * gcc.dg/torture/pr57748-3.c: New test. >> * gcc.dg/torture/pr57748-3a.c: New test. >> * gcc.dg/torture/pr57748-4.c: New test. >> * gcc.dg/torture/pr57748-4a.c: New test. >> > > ^ permalink raw reply [flat|nested] 105+ messages in thread
* RE: [PATCH, PR 57748] Check for out of bounds access 2013-09-17 0:05 ` Martin Jambor 2013-09-17 10:32 ` Bernd Edlinger @ 2013-10-22 14:08 ` Bernd Edlinger 2013-10-23 16:02 ` Richard Biener 2013-11-06 15:08 ` [PATCH, PR 57748] Check for out of bounds access, Part 3 Bernd Edlinger 1 sibling, 2 replies; 105+ messages in thread From: Bernd Edlinger @ 2013-10-22 14:08 UTC (permalink / raw) To: Martin Jambor; +Cc: Richard Biener, GCC Patches, Eric Botcazou [-- Attachment #1: Type: text/plain, Size: 1972 bytes --] Hi, On Tue, 17 Sep 2013 01:09:45, Martin Jambor wrote: >> @@ -4773,6 +4738,8 @@ expand_assignment (tree to, tree from, b >> if (MEM_P (to_rtx) >> && GET_MODE (to_rtx) == BLKmode >> && GET_MODE (XEXP (to_rtx, 0)) != VOIDmode >> + && bitregion_start == 0 >> + && bitregion_end == 0 >> && bitsize> 0 >> && (bitpos % bitsize) == 0 >> && (bitsize % GET_MODE_ALIGNMENT (mode1)) == 0 >> > ... > > I'm not sure to what extent the hunk adding tests for bitregion_start > and bitregion_end being zero is connected to this issue. I do not see > any of the testcases exercising that path. If it is indeed another > problem, I think it should be submitted (and potentially committed) as > a separate patch, preferably with a testcase. > Meanwhile I am able to give an example where that code is executed with bitpos = 64, bitsize=32, bitregion_start = 32, bitregion_end = 95. Afterwards bitpos=0, bitsize=32, which is completely outside bitregion_start=32, bitregion_end=95. However this can only be seen in the debugger, as the store_field goes thru a code path that does not look at bitregion_start/end. Well that is at least extremely ugly, and I would not be sure, that I cannot come up with a sample that crashes or creates wrong code. Currently I think that maybe the best way to fix that would be this: --- gcc/expr.c 2013-10-21 08:27:09.546035668 +0200 +++ gcc/expr.c 2013-10-22 15:19:56.749476525 +0200 @@ -4762,6 +4762,9 @@ expand_assignment (tree to, tree from, b && MEM_ALIGN (to_rtx) == GET_MODE_ALIGNMENT (mode1)) { to_rtx = adjust_address (to_rtx, mode1, bitpos / BITS_PER_UNIT); + bitregion_start = 0; + if (bitregion_end>= (unsigned HOST_WIDE_INT) bitpos) + bitregion_end -= bitpos; bitpos = 0; } Any suggestions? Regards Bernd. [-- Attachment #2: t1.c --] [-- Type: text/plain, Size: 276 bytes --] extern void abort (void); struct x{ int a; int :32; volatile int b:32; }; struct s { int a,b,c,d; struct x xx[1]; }; struct s ss; volatile int k; int main() { ss.xx[k].b = 1; // asm volatile("":::"memory"); if ( ss.xx[k].b != 1) abort (); return 0; } ^ permalink raw reply [flat|nested] 105+ messages in thread
* Re: [PATCH, PR 57748] Check for out of bounds access 2013-10-22 14:08 ` Bernd Edlinger @ 2013-10-23 16:02 ` Richard Biener 2013-10-24 0:09 ` Bernd Edlinger 2013-10-24 8:44 ` Eric Botcazou 2013-11-06 15:08 ` [PATCH, PR 57748] Check for out of bounds access, Part 3 Bernd Edlinger 1 sibling, 2 replies; 105+ messages in thread From: Richard Biener @ 2013-10-23 16:02 UTC (permalink / raw) To: Bernd Edlinger; +Cc: Martin Jambor, GCC Patches, Eric Botcazou On Tue, Oct 22, 2013 at 3:50 PM, Bernd Edlinger <bernd.edlinger@hotmail.de> wrote: > Hi, > > On Tue, 17 Sep 2013 01:09:45, Martin Jambor wrote: >>> @@ -4773,6 +4738,8 @@ expand_assignment (tree to, tree from, b >>> if (MEM_P (to_rtx) >>> && GET_MODE (to_rtx) == BLKmode >>> && GET_MODE (XEXP (to_rtx, 0)) != VOIDmode >>> + && bitregion_start == 0 >>> + && bitregion_end == 0 >>> && bitsize> 0 >>> && (bitpos % bitsize) == 0 >>> && (bitsize % GET_MODE_ALIGNMENT (mode1)) == 0 >>> >> ... >> >> I'm not sure to what extent the hunk adding tests for bitregion_start >> and bitregion_end being zero is connected to this issue. I do not see >> any of the testcases exercising that path. If it is indeed another >> problem, I think it should be submitted (and potentially committed) as >> a separate patch, preferably with a testcase. >> > > Meanwhile I am able to give an example where that code is executed > with bitpos = 64, bitsize=32, bitregion_start = 32, bitregion_end = 95. > > Afterwards bitpos=0, bitsize=32, which is completely outside > bitregion_start=32, bitregion_end=95. > > However this can only be seen in the debugger, as the store_field > goes thru a code path that does not look at bitregion_start/end. > > Well that is at least extremely ugly, and I would not be sure, that > I cannot come up with a sample that crashes or creates wrong code. > > Currently I think that maybe the best way to fix that would be this: > > --- gcc/expr.c 2013-10-21 08:27:09.546035668 +0200 > +++ gcc/expr.c 2013-10-22 15:19:56.749476525 +0200 > @@ -4762,6 +4762,9 @@ expand_assignment (tree to, tree from, b > && MEM_ALIGN (to_rtx) == GET_MODE_ALIGNMENT (mode1)) > { > to_rtx = adjust_address (to_rtx, mode1, bitpos / BITS_PER_UNIT); > + bitregion_start = 0; > + if (bitregion_end>= (unsigned HOST_WIDE_INT) bitpos) > + bitregion_end -= bitpos; > bitpos = 0; > } > > Any suggestions? if bitregion_start/end are used after the adjust_address call then they have to be adjusted (or bitpos left in place). In fact why we apply byte-parts of bitpos here only if offset != 0 is weird. OTOH this code is _very_ old... what happens if you remove the whole case? Richard. > > > Regards > Bernd. ^ permalink raw reply [flat|nested] 105+ messages in thread
* RE: [PATCH, PR 57748] Check for out of bounds access 2013-10-23 16:02 ` Richard Biener @ 2013-10-24 0:09 ` Bernd Edlinger 2013-10-24 8:44 ` Eric Botcazou 1 sibling, 0 replies; 105+ messages in thread From: Bernd Edlinger @ 2013-10-24 0:09 UTC (permalink / raw) To: Richard Biener; +Cc: Martin Jambor, GCC Patches, Eric Botcazou [-- Attachment #1: Type: text/plain, Size: 1106 bytes --] On, Wed, 23 Oct 2013 17:36:41Richard Biener wrote: > > if bitregion_start/end are used after the adjust_address call then they have > to be adjusted (or bitpos left in place). In fact why we apply byte-parts of > bitpos here only if offset != 0 is weird. OTOH this code is _very_ old... > what happens if you remove the whole case? > > Richard. > If I remove that code completely... Than changes nothing ARM at -O2. and on x86 at -O2 this changes: .cfi_startproc movl k, %eax leal (%eax,%eax,2), %eax - leal ss+8(,%eax,4), %eax - movl $1, 16(%eax) + leal ss+16(,%eax,4), %eax + movl $1, 8(%eax) movl k, %eax leal (%eax,%eax,2), %eax - leal ss+8(,%eax,4), %eax - movl 16(%eax), %eax + leal ss+16(,%eax,4), %eax + movl 8(%eax), %eax cmpl $1, %eax jne .L5 xorl %eax, %eax that does not really make any difference. So removing that code looks like a nice alternative. What do you think? Bernd. [-- Attachment #2: patch-pr57748-3.diff --] [-- Type: application/octet-stream, Size: 1607 bytes --] Index: gcc/expr.c =================================================================== --- gcc/expr.c (revision 203898) +++ gcc/expr.c (working copy) @@ -4752,20 +4752,6 @@ if (GET_MODE (offset_rtx) != address_mode) offset_rtx = convert_to_mode (address_mode, offset_rtx, 0); - /* A constant address in TO_RTX can have VOIDmode, we must not try - to call force_reg for that case. Avoid that case. */ - if (MEM_P (to_rtx) - && GET_MODE (to_rtx) == BLKmode - && GET_MODE (XEXP (to_rtx, 0)) != VOIDmode - && bitsize > 0 - && (bitpos % bitsize) == 0 - && (bitsize % GET_MODE_ALIGNMENT (mode1)) == 0 - && MEM_ALIGN (to_rtx) == GET_MODE_ALIGNMENT (mode1)) - { - to_rtx = adjust_address (to_rtx, mode1, bitpos / BITS_PER_UNIT); - bitpos = 0; - } - to_rtx = offset_address (to_rtx, offset_rtx, highest_pow2_factor_for_target (to, offset)); @@ -9981,19 +9967,6 @@ if (GET_MODE (offset_rtx) != address_mode) offset_rtx = convert_to_mode (address_mode, offset_rtx, 0); - if (GET_MODE (op0) == BLKmode - /* A constant address in OP0 can have VOIDmode, we must - not try to call force_reg in that case. */ - && GET_MODE (XEXP (op0, 0)) != VOIDmode - && bitsize != 0 - && (bitpos % bitsize) == 0 - && (bitsize % GET_MODE_ALIGNMENT (mode1)) == 0 - && MEM_ALIGN (op0) == GET_MODE_ALIGNMENT (mode1)) - { - op0 = adjust_address (op0, mode1, bitpos / BITS_PER_UNIT); - bitpos = 0; - } - op0 = offset_address (op0, offset_rtx, highest_pow2_factor (offset)); } ^ permalink raw reply [flat|nested] 105+ messages in thread
* Re: [PATCH, PR 57748] Check for out of bounds access 2013-10-23 16:02 ` Richard Biener 2013-10-24 0:09 ` Bernd Edlinger @ 2013-10-24 8:44 ` Eric Botcazou 2013-10-24 10:06 ` Richard Biener 1 sibling, 1 reply; 105+ messages in thread From: Eric Botcazou @ 2013-10-24 8:44 UTC (permalink / raw) To: Richard Biener; +Cc: gcc-patches, Bernd Edlinger, Martin Jambor > if bitregion_start/end are used after the adjust_address call then they have > to be adjusted (or bitpos left in place). In fact why we apply byte-parts > of bitpos here only if offset != 0 is weird. Presumably to be able to do arithmetic on symbols when the offset is variable, which can save one addition in the final code. -- Eric Botcazou ^ permalink raw reply [flat|nested] 105+ messages in thread
* Re: [PATCH, PR 57748] Check for out of bounds access 2013-10-24 8:44 ` Eric Botcazou @ 2013-10-24 10:06 ` Richard Biener 2013-10-24 10:22 ` Bernd Edlinger 2013-10-25 10:40 ` Eric Botcazou 0 siblings, 2 replies; 105+ messages in thread From: Richard Biener @ 2013-10-24 10:06 UTC (permalink / raw) To: Eric Botcazou; +Cc: GCC Patches, Bernd Edlinger, Martin Jambor On Thu, Oct 24, 2013 at 10:37 AM, Eric Botcazou <ebotcazou@adacore.com> wrote: >> if bitregion_start/end are used after the adjust_address call then they have >> to be adjusted (or bitpos left in place). In fact why we apply byte-parts >> of bitpos here only if offset != 0 is weird. > > Presumably to be able to do arithmetic on symbols when the offset is variable, > which can save one addition in the final code. Doesn't that also apply to arithmetic on symbols when the offset is NULL? But yes, the codegen example posted shows this kind of difference (though it doesn't seem to save anything for that case). I'd have expected a more explicit guarding of this case, like with MEM_P (to_rtx) && SYMBOL_REF_P (XEXP (to_rtx, 0)) though, eventually even looking whether the resulting address is legitimate. But ... doesn't forwprop fix this up later anyway? Either way, bitregion_start/end is clearly wrong after we hit this case. I'm always fast approving removal of "odd" code (less-code-is-better doctrine...), but in this case maybe the code can be improved instead. The comment before it is also odd and likely only applies to later added restrictions. Just to quote it again: if (offset != 0) { ... /* A constant address in TO_RTX can have VOIDmode, we must not try to call force_reg for that case. Avoid that case. */ if (MEM_P (to_rtx) && GET_MODE (to_rtx) == BLKmode && GET_MODE (XEXP (to_rtx, 0)) != VOIDmode && bitsize > 0 && (bitpos % bitsize) == 0 && (bitsize % GET_MODE_ALIGNMENT (mode1)) == 0 && MEM_ALIGN (to_rtx) == GET_MODE_ALIGNMENT (mode1)) { to_rtx = adjust_address (to_rtx, mode1, bitpos / BITS_PER_UNIT); bitpos = 0; } to_rtx = offset_address (to_rtx, offset_rtx, highest_pow2_factor_for_target (to, offset)); } Thanks, Richard. > -- > Eric Botcazou ^ permalink raw reply [flat|nested] 105+ messages in thread
* RE: [PATCH, PR 57748] Check for out of bounds access 2013-10-24 10:06 ` Richard Biener @ 2013-10-24 10:22 ` Bernd Edlinger 2013-10-25 10:40 ` Eric Botcazou 1 sibling, 0 replies; 105+ messages in thread From: Bernd Edlinger @ 2013-10-24 10:22 UTC (permalink / raw) To: Richard Biener, Eric Botcazou; +Cc: GCC Patches, Martin Jambor Hi, On Thu, 24 Oct 2013 11:56:52, Richard Biener wrote: > > On Thu, Oct 24, 2013 at 10:37 AM, Eric Botcazou <ebotcazou@adacore.com> wrote: >>> if bitregion_start/end are used after the adjust_address call then they have >>> to be adjusted (or bitpos left in place). In fact why we apply byte-parts >>> of bitpos here only if offset != 0 is weird. >> >> Presumably to be able to do arithmetic on symbols when the offset is variable, >> which can save one addition in the final code. > > Doesn't that also apply to arithmetic on symbols when the offset is NULL? > But yes, the codegen example posted shows this kind of difference > (though it doesn't seem to save anything for that case). I'd have expected > a more explicit guarding of this case, like with MEM_P (to_rtx) > && SYMBOL_REF_P (XEXP (to_rtx, 0)) though, eventually even looking > whether the resulting address is legitimate. But ... doesn't forwprop > fix this up later anyway? > > Either way, bitregion_start/end is clearly wrong after we hit this case. > I'm always fast approving removal of "odd" code (less-code-is-better > doctrine...), but in this case maybe the code can be improved instead. > The comment before it is also odd and likely only applies to later > added restrictions. Just to quote it again: > > if (offset != 0) > { > ... > /* A constant address in TO_RTX can have VOIDmode, we must not try > to call force_reg for that case. Avoid that case. */ > if (MEM_P (to_rtx) > && GET_MODE (to_rtx) == BLKmode > && GET_MODE (XEXP (to_rtx, 0)) != VOIDmode > && bitsize> 0 > && (bitpos % bitsize) == 0 > && (bitsize % GET_MODE_ALIGNMENT (mode1)) == 0 > && MEM_ALIGN (to_rtx) == GET_MODE_ALIGNMENT (mode1)) > { > to_rtx = adjust_address (to_rtx, mode1, bitpos / BITS_PER_UNIT); > bitpos = 0; > } > > to_rtx = offset_address (to_rtx, offset_rtx, > highest_pow2_factor_for_target (to, > offset)); > } > In the initial commit from 1998 where this was introduced that block contained an explicit force_reg call, but not that comment. Bernd. > > Thanks, > Richard. > >> -- >> Eric Botcazou ^ permalink raw reply [flat|nested] 105+ messages in thread
* Re: [PATCH, PR 57748] Check for out of bounds access 2013-10-24 10:06 ` Richard Biener 2013-10-24 10:22 ` Bernd Edlinger @ 2013-10-25 10:40 ` Eric Botcazou 1 sibling, 0 replies; 105+ messages in thread From: Eric Botcazou @ 2013-10-25 10:40 UTC (permalink / raw) To: Richard Biener; +Cc: gcc-patches, Bernd Edlinger, Martin Jambor > Doesn't that also apply to arithmetic on symbols when the offset is NULL? This can presumably be retrofitted when the offset is null or constant. > But yes, the codegen example posted shows this kind of difference > (though it doesn't seem to save anything for that case). I'd have expected > a more explicit guarding of this case, like with MEM_P (to_rtx) > && SYMBOL_REF_P (XEXP (to_rtx, 0)) though, eventually even looking > whether the resulting address is legitimate. But ... doesn't forwprop > fix this up later anyway? Not clear IMO, it would need to reassociate. > The comment before it is also odd and likely only applies to later > added restrictions. Just to quote it again: > > if (offset != 0) > { > ... > /* A constant address in TO_RTX can have VOIDmode, we must not try > to call force_reg for that case. Avoid that case. */ if (MEM_P (to_rtx) > && GET_MODE (to_rtx) == BLKmode > && GET_MODE (XEXP (to_rtx, 0)) != VOIDmode > && bitsize > 0 > && (bitpos % bitsize) == 0 > && (bitsize % GET_MODE_ALIGNMENT (mode1)) == 0 > && MEM_ALIGN (to_rtx) == GET_MODE_ALIGNMENT (mode1)) > { > to_rtx = adjust_address (to_rtx, mode1, bitpos / > BITS_PER_UNIT); bitpos = 0; > } > > to_rtx = offset_address (to_rtx, offset_rtx, > highest_pow2_factor_for_target (to, > offset)); > } Yes, the comment is out-of-sync and not very informative. -- Eric Botcazou ^ permalink raw reply [flat|nested] 105+ messages in thread
* RE: [PATCH, PR 57748] Check for out of bounds access, Part 3 2013-10-22 14:08 ` Bernd Edlinger 2013-10-23 16:02 ` Richard Biener @ 2013-11-06 15:08 ` Bernd Edlinger 2013-12-03 13:27 ` [PE-POST] Adjust Bit-region in expand_assignment Bernd Edlinger 1 sibling, 1 reply; 105+ messages in thread From: Bernd Edlinger @ 2013-11-06 15:08 UTC (permalink / raw) To: Richard Biener; +Cc: GCC Patches, Eric Botcazou, Martin Jambor [-- Attachment #1: Type: text/plain, Size: 3209 bytes --] > Hi, > > On Tue, 17 Sep 2013 01:09:45, Martin Jambor wrote: >>> @@ -4773,6 +4738,8 @@ expand_assignment (tree to, tree from, b >>> if (MEM_P (to_rtx) >>> && GET_MODE (to_rtx) == BLKmode >>> && GET_MODE (XEXP (to_rtx, 0)) != VOIDmode >>> + && bitregion_start == 0 >>> + && bitregion_end == 0 >>> && bitsize> 0 >>> && (bitpos % bitsize) == 0 >>> && (bitsize % GET_MODE_ALIGNMENT (mode1)) == 0 >>> >> ... >> >> I'm not sure to what extent the hunk adding tests for bitregion_start >> and bitregion_end being zero is connected to this issue. I do not see >> any of the testcases exercising that path. If it is indeed another >> problem, I think it should be submitted (and potentially committed) as >> a separate patch, preferably with a testcase. >> > > Meanwhile I am able to give an example where that code is executed > with bitpos = 64, bitsize=32, bitregion_start = 32, bitregion_end = 95. > > Afterwards bitpos=0, bitsize=32, which is completely outside > bitregion_start=32, bitregion_end=95. > > However this can only be seen in the debugger, as the store_field > goes thru a code path that does not look at bitregion_start/end. > > Well that is at least extremely ugly, and I would not be sure, that > I cannot come up with a sample that crashes or creates wrong code. > > Currently I think that maybe the best way to fix that would be this: > > --- gcc/expr.c 2013-10-21 08:27:09.546035668 +0200 > +++ gcc/expr.c 2013-10-22 15:19:56.749476525 +0200 > @@ -4762,6 +4762,9 @@ expand_assignment (tree to, tree from, b > && MEM_ALIGN (to_rtx) == GET_MODE_ALIGNMENT (mode1)) > { > to_rtx = adjust_address (to_rtx, mode1, bitpos / BITS_PER_UNIT); > + bitregion_start = 0; > + if (bitregion_end>= (unsigned HOST_WIDE_INT) bitpos) > + bitregion_end -= bitpos; > bitpos = 0; > } > > Any suggestions? > > > > Regards > Bernd. well, as already discussed, the following example executes the above memory block, and leaves bitregion_start/end in an undefined state: extern void abort (void); struct x{ int a; int :32; volatile int b:32; }; struct s { int a,b,c,d; struct x xx[1]; }; struct s ss; volatile int k; int main() { ss.xx[k].b = 1; // asm volatile("":::"memory"); if ( ss.xx[k].b != 1) abort (); return 0; } Although this does not cause malfunction at the time, I'd propose to play safe, and update the bitregion_start/bitregion_end. Additionally I'd propose to remove this comment in expand_assignment and expand_expr_real_1: "A constant address in TO_RTX can have VOIDmode, we must not try to call force_reg for that case. Avoid that case." This comment is completely out of sync: There is no longer any force_reg in that if-block, and a constant address in TO_RTX has SImode or DImode in GET_MODE (XEXP (to_rtx, 0)) I do not know how to make it a VOIDmode, therefore the comment does not help either. Boot-strapped and regression-tested on x86_64-linux-gnu. OK for trunk? Regards Bernd. [-- Attachment #2: changelog-pr57748-3.txt --] [-- Type: text/plain, Size: 216 bytes --] 2013-11-06 Bernd Edlinger <bernd.edlinger@hotmail.de> PR middle-end/57748 * expr.c (expand_assignment): Remove bogus comment. Update bitregion_start/bitregion_end. (expand_expr_real_1): Remove bogus comment. [-- Attachment #3: patch-pr57748-3.diff --] [-- Type: application/octet-stream, Size: 1254 bytes --] --- gcc/expr.c.jj 2013-10-31 14:57:05.000000000 +0100 +++ gcc/expr.c 2013-11-06 14:48:59.095970841 +0100 @@ -4756,8 +4756,6 @@ expand_assignment (tree to, tree from, b if (GET_MODE (offset_rtx) != address_mode) offset_rtx = convert_to_mode (address_mode, offset_rtx, 0); - /* A constant address in TO_RTX can have VOIDmode, we must not try - to call force_reg for that case. Avoid that case. */ if (MEM_P (to_rtx) && GET_MODE (to_rtx) == BLKmode && GET_MODE (XEXP (to_rtx, 0)) != VOIDmode @@ -4767,6 +4765,9 @@ expand_assignment (tree to, tree from, b && MEM_ALIGN (to_rtx) == GET_MODE_ALIGNMENT (mode1)) { to_rtx = adjust_address (to_rtx, mode1, bitpos / BITS_PER_UNIT); + bitregion_start = 0; + if (bitregion_end >= (unsigned HOST_WIDE_INT) bitpos) + bitregion_end -= bitpos; bitpos = 0; } @@ -9926,8 +9927,6 @@ expand_expr_real_1 (tree exp, rtx target offset_rtx = convert_to_mode (address_mode, offset_rtx, 0); if (GET_MODE (op0) == BLKmode - /* A constant address in OP0 can have VOIDmode, we must - not try to call force_reg in that case. */ && GET_MODE (XEXP (op0, 0)) != VOIDmode && bitsize != 0 && (bitpos % bitsize) == 0 ^ permalink raw reply [flat|nested] 105+ messages in thread
* [PE-POST] Adjust Bit-region in expand_assignment 2013-11-06 15:08 ` [PATCH, PR 57748] Check for out of bounds access, Part 3 Bernd Edlinger @ 2013-12-03 13:27 ` Bernd Edlinger 2013-12-04 5:55 ` Jeff Law 0 siblings, 1 reply; 105+ messages in thread From: Bernd Edlinger @ 2013-12-03 13:27 UTC (permalink / raw) To: Richard Biener, Jeff Law; +Cc: gcc-patches, Jakub Jelinek [-- Attachment #1: Type: text/plain, Size: 2643 bytes --] Hi, I almost forgot about this (rather simple) one. It falls in the category "Mostly Harmless", but it would be nice to have the bitregion_start/end consistent in all cases, even when it does currently not cause any mal-function. this was: > Subject: RE: [PATCH, PR 57748] Check for out of bounds access, Part 3 > Date: Wed, 6 Nov 2013 15:40:23 +0100 > >> Meanwhile I am able to give an example where that code is executed >> with bitpos = 64, bitsize=32, bitregion_start = 32, bitregion_end = 95. >> >> Afterwards bitpos=0, bitsize=32, which is completely outside >> bitregion_start=32, bitregion_end=95. >> >> However this can only be seen in the debugger, as the store_field >> goes thru a code path that does not look at bitregion_start/end. >> >> Well that is at least extremely ugly, and I would not be sure, that >> I cannot come up with a sample that crashes or creates wrong code. >> >> Currently I think that maybe the best way to fix that would be this: >> >> --- gcc/expr.c 2013-10-21 08:27:09.546035668 +0200 >> +++ gcc/expr.c 2013-10-22 15:19:56.749476525 +0200 >> @@ -4762,6 +4762,9 @@ expand_assignment (tree to, tree from, b >> && MEM_ALIGN (to_rtx) == GET_MODE_ALIGNMENT (mode1)) >> { >> to_rtx = adjust_address (to_rtx, mode1, bitpos / BITS_PER_UNIT); >> + bitregion_start = 0; >> + if (bitregion_end>= (unsigned HOST_WIDE_INT) bitpos) >> + bitregion_end -= bitpos; >> bitpos = 0; >> } >> > > well, as already discussed, the following example executes the above memory block, > and leaves bitregion_start/end in an undefined state: > extern void abort (void); struct x{ int a; int :32; volatile int b:32; }; struct s { int a,b,c,d; struct x xx[1]; }; struct s ss; volatile int k; int main() { ss.xx[k].b = 1; // asm volatile("":::"memory"); if ( ss.xx[k].b != 1) abort (); return 0; } > Although this does not cause malfunction at the time, I'd propose to play safe, > and update the bitregion_start/bitregion_end. Additionally I'd propose to remove > this comment in expand_assignment and expand_expr_real_1: > > "A constant address in TO_RTX can have VOIDmode, we must not try > to call force_reg for that case. Avoid that case." > > This comment is completely out of sync: There is no longer any force_reg in that if-block, > and a constant address in TO_RTX has SImode or DImode in GET_MODE (XEXP (to_rtx, 0)) > I do not know how to make it a VOIDmode, therefore the comment does not help either. > > Boot-strapped and regression-tested on x86_64-linux-gnu. OK for trunk? Regards Bernd. [-- Attachment #2: changelog-pr57748-3.txt --] [-- Type: text/plain, Size: 216 bytes --] 2013-11-06 Bernd Edlinger <bernd.edlinger@hotmail.de> PR middle-end/57748 * expr.c (expand_assignment): Remove bogus comment. Update bitregion_start/bitregion_end. (expand_expr_real_1): Remove bogus comment. [-- Attachment #3: patch-pr57748-3.diff --] [-- Type: application/octet-stream, Size: 1254 bytes --] --- gcc/expr.c.jj 2013-10-31 14:57:05.000000000 +0100 +++ gcc/expr.c 2013-11-06 14:48:59.095970841 +0100 @@ -4756,8 +4756,6 @@ expand_assignment (tree to, tree from, b if (GET_MODE (offset_rtx) != address_mode) offset_rtx = convert_to_mode (address_mode, offset_rtx, 0); - /* A constant address in TO_RTX can have VOIDmode, we must not try - to call force_reg for that case. Avoid that case. */ if (MEM_P (to_rtx) && GET_MODE (to_rtx) == BLKmode && GET_MODE (XEXP (to_rtx, 0)) != VOIDmode @@ -4767,6 +4765,9 @@ expand_assignment (tree to, tree from, b && MEM_ALIGN (to_rtx) == GET_MODE_ALIGNMENT (mode1)) { to_rtx = adjust_address (to_rtx, mode1, bitpos / BITS_PER_UNIT); + bitregion_start = 0; + if (bitregion_end >= (unsigned HOST_WIDE_INT) bitpos) + bitregion_end -= bitpos; bitpos = 0; } @@ -9926,8 +9927,6 @@ expand_expr_real_1 (tree exp, rtx target offset_rtx = convert_to_mode (address_mode, offset_rtx, 0); if (GET_MODE (op0) == BLKmode - /* A constant address in OP0 can have VOIDmode, we must - not try to call force_reg in that case. */ && GET_MODE (XEXP (op0, 0)) != VOIDmode && bitsize != 0 && (bitpos % bitsize) == 0 ^ permalink raw reply [flat|nested] 105+ messages in thread
* Re: [PE-POST] Adjust Bit-region in expand_assignment 2013-12-03 13:27 ` [PE-POST] Adjust Bit-region in expand_assignment Bernd Edlinger @ 2013-12-04 5:55 ` Jeff Law 2013-12-04 7:50 ` Bernd Edlinger 0 siblings, 1 reply; 105+ messages in thread From: Jeff Law @ 2013-12-04 5:55 UTC (permalink / raw) To: Bernd Edlinger, Richard Biener; +Cc: gcc-patches, Jakub Jelinek On 12/03/13 06:27, Bernd Edlinger wrote: >> This comment is completely out of sync: There is no longer any force_reg in that if-block, >> and a constant address in TO_RTX has SImode or DImode in GET_MODE (XEXP (to_rtx, 0)) >> I do not know how to make it a VOIDmode, therefore the comment does not help either. I thought that comment looked familiar... That's because it was mine... The way that was triggered in the past can be found in this ancient posting: http://gcc.gnu.org/ml/gcc-patches/1999-03n/msg00654.html The code went through a major revamp in 2002 which removed the force_reg calls without updating/removing the comment. Additionally, the way we represent and thus ultimately expand the memory reference has changed in ways that make it harder, if not impossible to have a constant address at these points. Even if were to hack up the expanders to force a constant address rather than a REG it's still nontrivial to get into that code with a constant address. I wouldn't be terribly surprised to find all kinds of dead code in the expanders. So the comment clearly needs to get zapped. As for the consistency of bitregion_start/bitregion_end, I'm just not familiar enough with this code or the issues for the C++ memory model to comment. jeff ^ permalink raw reply [flat|nested] 105+ messages in thread
* RE: [PE-POST] Adjust Bit-region in expand_assignment 2013-12-04 5:55 ` Jeff Law @ 2013-12-04 7:50 ` Bernd Edlinger 2013-12-06 4:13 ` Jeff Law 0 siblings, 1 reply; 105+ messages in thread From: Bernd Edlinger @ 2013-12-04 7:50 UTC (permalink / raw) To: Jeff Law, Richard Biener; +Cc: gcc-patches, Jakub Jelinek On Tue, 3 Dec 2013 22:55:32, Jef Law wrote: > > On 12/03/13 06:27, Bernd Edlinger wrote: >>> This comment is completely out of sync: There is no longer any force_reg in that if-block, >>> and a constant address in TO_RTX has SImode or DImode in GET_MODE (XEXP (to_rtx, 0)) >>> I do not know how to make it a VOIDmode, therefore the comment does not help either. > I thought that comment looked familiar... That's because it was mine... > > The way that was triggered in the past can be found in this ancient posting: > > http://gcc.gnu.org/ml/gcc-patches/1999-03n/msg00654.html > > The code went through a major revamp in 2002 which removed the force_reg > calls without updating/removing the comment. > > Additionally, the way we represent and thus ultimately expand the memory > reference has changed in ways that make it harder, if not impossible to > have a constant address at these points. Even if were to hack up the > expanders to force a constant address rather than a REG it's still > nontrivial to get into that code with a constant address. > > I wouldn't be terribly surprised to find all kinds of dead code in the > expanders. > > So the comment clearly needs to get zapped. > > As for the consistency of bitregion_start/bitregion_end, I'm just not > familiar enough with this code or the issues for the C++ memory model to > comment. > > jeff Thanks for this info. Regarding the consistency of bitregion_start/end , they should either both be zero, or bitregion_start <= bitpos && bitpos+bitsize-1 <= bitregion_end of course bitregion_start/end should be on byte-boundarys. So if I set bitpos=0, I must move bitregion_start/end accordingly. Of course bitregion_start can not become negative. Therefore I set it to zero, store_bit_field would never try to write at negative offsets anyway. This stuff with the bit region was introduced recently, and this if-block has been overlooked then. Thanks Bernd. ^ permalink raw reply [flat|nested] 105+ messages in thread
* Re: [PE-POST] Adjust Bit-region in expand_assignment 2013-12-04 7:50 ` Bernd Edlinger @ 2013-12-06 4:13 ` Jeff Law 2013-12-06 8:03 ` Bernd Edlinger 0 siblings, 1 reply; 105+ messages in thread From: Jeff Law @ 2013-12-06 4:13 UTC (permalink / raw) To: Bernd Edlinger, Richard Biener; +Cc: gcc-patches, Jakub Jelinek On 12/04/13 00:49, Bernd Edlinger wrote: > > Regarding the consistency of bitregion_start/end , > > they should either both be zero, or > > bitregion_start <= bitpos && bitpos+bitsize-1 <= bitregion_end Presumably to satisfy the consecutive bitfields are a single memory location stuff from C++11. Thus the bitregion representation (C++11) must totally encompass the original COMPONENT_REF. I can certainly see how that holds immediately after the call to get_bit_range. When we adjust the address, we're just accounting for the bit position (bitpos). ie, if bitpos was 16 and TO_RTX was (plus (reg) (32)). We change TO_RTX to (plus (reg) (48)). This is ultimately meant to simplify the resulting insns we generate by folding the bitpos adjustment into the address computation. In effect, this results in accessing a subobject rather than the full object. Presumably this is kosher for C++11's memory model (I really don't know). *If* it is OK to access the subobject like this in C++11's memory model, then is is necessary for bitregion_{start,end} to encompass the original object, or should it be made consistent with the bitpos/bitsize? And that seems to me to be the fundamental question. What is really the purpose of the bitregion_{start,end} representation? If it must represent the C++ object, then ISTM we don't want to mess with it. If it doesn't, then why did we bother building this alternate representation to begin with? Jeff ^ permalink raw reply [flat|nested] 105+ messages in thread
* RE: [PE-POST] Adjust Bit-region in expand_assignment 2013-12-06 4:13 ` Jeff Law @ 2013-12-06 8:03 ` Bernd Edlinger 2013-12-06 9:49 ` Richard Biener 0 siblings, 1 reply; 105+ messages in thread From: Bernd Edlinger @ 2013-12-06 8:03 UTC (permalink / raw) To: Jeff Law, Richard Biener; +Cc: gcc-patches, Jakub Jelinek Hi, On Thu, 5 Dec 2013 21:12:54, Jeff Law wrote: > > On 12/04/13 00:49, Bernd Edlinger wrote: >> >> Regarding the consistency of bitregion_start/end , >> >> they should either both be zero, or >> >> bitregion_start <= bitpos && bitpos+bitsize-1 <= bitregion_end > Presumably to satisfy the consecutive bitfields are a single memory > location stuff from C++11. Thus the bitregion representation (C++11) > must totally encompass the original COMPONENT_REF. I can certainly see > how that holds immediately after the call to get_bit_range. > > When we adjust the address, we're just accounting for the bit position > (bitpos). ie, if bitpos was 16 and TO_RTX was (plus (reg) (32)). We > change TO_RTX to (plus (reg) (48)). This is ultimately meant to > simplify the resulting insns we generate by folding the bitpos > adjustment into the address computation. In effect, this results in > accessing a subobject rather than the full object. Presumably this is > kosher for C++11's memory model (I really don't know). > > *If* it is OK to access the subobject like this in C++11's memory model, > then is is necessary for bitregion_{start,end} to encompass the original > object, or should it be made consistent with the bitpos/bitsize? And > that seems to me to be the fundamental question. What is really the > purpose of the bitregion_{start,end} representation? If it must > represent the C++ object, then ISTM we don't want to mess with it. If > it doesn't, then why did we bother building this alternate > representation to begin with? > Yes, that is correct. let's assume bitpos = 16, and bitsize = 16, then we have bitregion_start = 16 and bitregion_end = 31. The to_rtx points to the start of the object. to_rtx = adjust_address (to_rtx, mode1, bitpos / BITS_PER_UNIT) makes to_rtx point to two bytes from the beginning. that is compensated by bitpos = 0. So now [to_rtx, bitpos, bitsize] means the same thing than before. What's wrong is that bitregion_start is still 16 and bitregion_end is still 31 in that example. The correct values would be bitregion_start = 0 and bitregion_end = 15. that's what this new statement is meant to do: bitregion_start = 0; if (bitregion_end>= (unsigned HOST_WIDE_INT) bitpos) bitregion_end -= bitpos; I need the "if" because bitregion_end could be 0, and in that case I want bitregion_end to stay 0. Thanks Bernd. > > Jeff ^ permalink raw reply [flat|nested] 105+ messages in thread
* Re: [PE-POST] Adjust Bit-region in expand_assignment 2013-12-06 8:03 ` Bernd Edlinger @ 2013-12-06 9:49 ` Richard Biener 0 siblings, 0 replies; 105+ messages in thread From: Richard Biener @ 2013-12-06 9:49 UTC (permalink / raw) To: Bernd Edlinger; +Cc: Jeff Law, gcc-patches, Jakub Jelinek On Fri, Dec 6, 2013 at 9:02 AM, Bernd Edlinger <bernd.edlinger@hotmail.de> wrote: > Hi, > > On Thu, 5 Dec 2013 21:12:54, Jeff Law wrote: >> >> On 12/04/13 00:49, Bernd Edlinger wrote: >>> >>> Regarding the consistency of bitregion_start/end , >>> >>> they should either both be zero, or >>> >>> bitregion_start <= bitpos && bitpos+bitsize-1 <= bitregion_end >> Presumably to satisfy the consecutive bitfields are a single memory >> location stuff from C++11. Thus the bitregion representation (C++11) >> must totally encompass the original COMPONENT_REF. I can certainly see >> how that holds immediately after the call to get_bit_range. >> >> When we adjust the address, we're just accounting for the bit position >> (bitpos). ie, if bitpos was 16 and TO_RTX was (plus (reg) (32)). We >> change TO_RTX to (plus (reg) (48)). This is ultimately meant to >> simplify the resulting insns we generate by folding the bitpos >> adjustment into the address computation. In effect, this results in >> accessing a subobject rather than the full object. Presumably this is >> kosher for C++11's memory model (I really don't know). >> >> *If* it is OK to access the subobject like this in C++11's memory model, >> then is is necessary for bitregion_{start,end} to encompass the original >> object, or should it be made consistent with the bitpos/bitsize? And >> that seems to me to be the fundamental question. What is really the >> purpose of the bitregion_{start,end} representation? If it must >> represent the C++ object, then ISTM we don't want to mess with it. If >> it doesn't, then why did we bother building this alternate >> representation to begin with? >> > > Yes, that is correct. let's assume bitpos = 16, and bitsize = 16, > then we have bitregion_start = 16 and bitregion_end = 31. > The to_rtx points to the start of the object. > > to_rtx = adjust_address (to_rtx, mode1, bitpos / BITS_PER_UNIT) > > makes to_rtx point to two bytes from the beginning. > that is compensated by > > bitpos = 0. > > So now [to_rtx, bitpos, bitsize] means the same thing than before. > What's wrong is that bitregion_start is still 16 and bitregion_end is still 31 > in that example. > The correct values would be bitregion_start = 0 and bitregion_end = 15. > that's what this new statement is meant to do: > > bitregion_start = 0; > if (bitregion_end>= (unsigned HOST_WIDE_INT) bitpos) > bitregion_end -= bitpos; > > I need the "if" because bitregion_end could be 0, and in that case > I want bitregion_end to stay 0. The patch is ok. Thanks, Richard. > > Thanks > Bernd. > >> >> Jeff ^ permalink raw reply [flat|nested] 105+ messages in thread
* Re: [PATCH, PR 57748] Check for out of bounds access 2013-09-15 19:08 ` Bernd Edlinger 2013-09-17 0:05 ` Martin Jambor @ 2013-09-17 11:07 ` Richard Biener 2013-09-17 11:41 ` Richard Biener 1 sibling, 1 reply; 105+ messages in thread From: Richard Biener @ 2013-09-17 11:07 UTC (permalink / raw) To: Bernd Edlinger; +Cc: Martin Jambor, GCC Patches On Sun, Sep 15, 2013 at 6:55 PM, Bernd Edlinger <bernd.edlinger@hotmail.de> wrote: > Hello Richard, > > attached is my second attempt at fixing PR 57748. This time the movmisalign > path is completely removed and a similar bug in the read handling of misaligned > structures with a non-BLKmode is fixed too. There are several new test cases for the > different possible failure modes. > > This patch was boot-strapped and regression tested on x86_64-unknown-linux-gnu > and i686-pc-linux-gnu. > > Additionally I generated eCos and an eCos-application (on ARMv5 using packed > structures) with an arm-eabi cross compiler, and looked for differences in the > disassembled code with and without this patch, but there were none. > > OK for trunk? I agree that the existing movmisaling path that you remove is simply bogus, so removing it looks fine to me. Can you give rationale to @@ -4773,6 +4738,8 @@ expand_assignment (tree to, tree from, b if (MEM_P (to_rtx) && GET_MODE (to_rtx) == BLKmode && GET_MODE (XEXP (to_rtx, 0)) != VOIDmode + && bitregion_start == 0 + && bitregion_end == 0 && bitsize > 0 && (bitpos % bitsize) == 0 && (bitsize % GET_MODE_ALIGNMENT (mode1)) == 0 and especially to @@ -9905,7 +9861,7 @@ expand_expr_real_1 (tree exp, rtx target && modifier != EXPAND_STACK_PARM ? target : NULL_RTX), VOIDmode, - modifier == EXPAND_SUM ? EXPAND_NORMAL : modifier); + EXPAND_MEMORY); /* If the bitfield is volatile, we want to access it in the field's mode, not the computed mode. which AFAIK makes "memory" expansion of loads/stores from/to registers change (fail? go through stack memory?) - see handling of non-MEM return values from that expand_expr call. That is, do you see anything break with just removing the movmisalign path? I'd rather install that (with the new testcases that then pass) separately as this is a somewhat fragile area and being able to more selectively bisect/backport would be nice. Thanks, Richard. > Regards > Bernd. ^ permalink raw reply [flat|nested] 105+ messages in thread
* Re: [PATCH, PR 57748] Check for out of bounds access 2013-09-17 11:07 ` [PATCH, PR 57748] Check for out of bounds access Richard Biener @ 2013-09-17 11:41 ` Richard Biener 2013-09-17 12:48 ` Bernd Edlinger 2013-09-24 6:34 ` [PATCH, PR 57748] Check for out of bounds access, Part 2 Bernd Edlinger 0 siblings, 2 replies; 105+ messages in thread From: Richard Biener @ 2013-09-17 11:41 UTC (permalink / raw) To: Bernd Edlinger; +Cc: Martin Jambor, GCC Patches On Tue, Sep 17, 2013 at 12:00 PM, Richard Biener <richard.guenther@gmail.com> wrote: > On Sun, Sep 15, 2013 at 6:55 PM, Bernd Edlinger > <bernd.edlinger@hotmail.de> wrote: >> Hello Richard, >> >> attached is my second attempt at fixing PR 57748. This time the movmisalign >> path is completely removed and a similar bug in the read handling of misaligned >> structures with a non-BLKmode is fixed too. There are several new test cases for the >> different possible failure modes. >> >> This patch was boot-strapped and regression tested on x86_64-unknown-linux-gnu >> and i686-pc-linux-gnu. >> >> Additionally I generated eCos and an eCos-application (on ARMv5 using packed >> structures) with an arm-eabi cross compiler, and looked for differences in the >> disassembled code with and without this patch, but there were none. >> >> OK for trunk? > > I agree that the existing movmisaling path that you remove is simply bogus, so > removing it looks fine to me. Can you give rationale to > > @@ -4773,6 +4738,8 @@ expand_assignment (tree to, tree from, b > if (MEM_P (to_rtx) > && GET_MODE (to_rtx) == BLKmode > && GET_MODE (XEXP (to_rtx, 0)) != VOIDmode > + && bitregion_start == 0 > + && bitregion_end == 0 > && bitsize > 0 > && (bitpos % bitsize) == 0 > && (bitsize % GET_MODE_ALIGNMENT (mode1)) == 0 > > and especially to > > @@ -9905,7 +9861,7 @@ expand_expr_real_1 (tree exp, rtx target > && modifier != EXPAND_STACK_PARM > ? target : NULL_RTX), > VOIDmode, > - modifier == EXPAND_SUM ? EXPAND_NORMAL : modifier); > + EXPAND_MEMORY); > > /* If the bitfield is volatile, we want to access it in the > field's mode, not the computed mode. > > which AFAIK makes "memory" expansion of loads/stores from/to registers > change (fail? go through stack memory?) - see handling of non-MEM return > values from that expand_expr call. In particular this seems to disable all movmisalign handling for MEM_REFs wrapped in component references which looks wrong. I was playing with typedef long long V __attribute__ ((vector_size (2 * sizeof (long long)), may_alias)); struct S { long long a[11]; V v; }__attribute__((aligned(8),packed)) ; struct S a, *b = &a; V v, w; int main() { v = b->v; b->v = w; return 0; } (use -fno-common) and I see that we use unaligned stores too often (even with a properly aligned MEM). The above at least shows movmisalign opportunities wrapped in component-refs. > That is, do you see anything break with just removing the movmisalign path? > I'd rather install that (with the new testcases that then pass) separately as > this is a somewhat fragile area and being able to more selectively > bisect/backport > would be nice. > > Thanks, > Richard. > >> Regards >> Bernd. ^ permalink raw reply [flat|nested] 105+ messages in thread
* RE: [PATCH, PR 57748] Check for out of bounds access 2013-09-17 11:41 ` Richard Biener @ 2013-09-17 12:48 ` Bernd Edlinger 2013-09-24 11:40 ` Richard Biener 2013-09-24 6:34 ` [PATCH, PR 57748] Check for out of bounds access, Part 2 Bernd Edlinger 1 sibling, 1 reply; 105+ messages in thread From: Bernd Edlinger @ 2013-09-17 12:48 UTC (permalink / raw) To: Richard Biener; +Cc: Martin Jambor, GCC Patches [-- Attachment #1: Type: text/plain, Size: 4893 bytes --] On Tue, 17 Sep 2013 12:45:40, Richard Biener wrote: > > On Tue, Sep 17, 2013 at 12:00 PM, Richard Biener > <richard.guenther@gmail.com> wrote: >> On Sun, Sep 15, 2013 at 6:55 PM, Bernd Edlinger >> <bernd.edlinger@hotmail.de> wrote: >>> Hello Richard, >>> >>> attached is my second attempt at fixing PR 57748. This time the movmisalign >>> path is completely removed and a similar bug in the read handling of misaligned >>> structures with a non-BLKmode is fixed too. There are several new test cases for the >>> different possible failure modes. >>> >>> This patch was boot-strapped and regression tested on x86_64-unknown-linux-gnu >>> and i686-pc-linux-gnu. >>> >>> Additionally I generated eCos and an eCos-application (on ARMv5 using packed >>> structures) with an arm-eabi cross compiler, and looked for differences in the >>> disassembled code with and without this patch, but there were none. >>> >>> OK for trunk? >> >> I agree that the existing movmisaling path that you remove is simply bogus, so >> removing it looks fine to me. Can you give rationale to >> >> @@ -4773,6 +4738,8 @@ expand_assignment (tree to, tree from, b >> if (MEM_P (to_rtx) >> && GET_MODE (to_rtx) == BLKmode >> && GET_MODE (XEXP (to_rtx, 0)) != VOIDmode >> + && bitregion_start == 0 >> + && bitregion_end == 0 >> && bitsize> 0 >> && (bitpos % bitsize) == 0 >> && (bitsize % GET_MODE_ALIGNMENT (mode1)) == 0 OK, as already said, I think it could be dangerous to set bitpos=0 without considering bitregion_start/end, but I think it may be possible that this can not happen, because if bitsize is a multiple if ALIGNMENT, and bitpos is a multiple of bitsize, we probably do not have a bit-field at all. And of course I have no test case that fails without this hunk. Maybe it would be better to add an assertion here like: { gcc_assert (bitregion_start == 0 && bitregion_end == 0); to_rtx = adjust_address (to_rtx, mode1, bitpos / BITS_PER_UNIT); bitpos = 0; } >> and especially to >> >> @@ -9905,7 +9861,7 @@ expand_expr_real_1 (tree exp, rtx target >> && modifier != EXPAND_STACK_PARM >> ? target : NULL_RTX), >> VOIDmode, >> - modifier == EXPAND_SUM ? EXPAND_NORMAL : modifier); >> + EXPAND_MEMORY); >> >> /* If the bitfield is volatile, we want to access it in the >> field's mode, not the computed mode. >> >> which AFAIK makes "memory" expansion of loads/stores from/to registers >> change (fail? go through stack memory?) - see handling of non-MEM return >> values from that expand_expr call. I wanted to make the expansion of MEM_REF and TARGET_MEM_REF not go thru the final misalign handling, which is guarded by "if (modifier != EXPAND_WRITE && modifier != EXPAND_MEMORY && ..." What we want here is most likely EXPAND_MEMORY, which returns a memory context if possible. Could you specify more explicitly what you mean with "handling of non-MEM return values from that expand_expr call", then I could try finding test cases for that. > In particular this seems to disable all movmisalign handling for MEM_REFs > wrapped in component references which looks wrong. I was playing with > > typedef long long V > __attribute__ ((vector_size (2 * sizeof (long long)), may_alias)); > > struct S { long long a[11]; V v; }__attribute__((aligned(8),packed)) ; > struct S a, *b = &a; > V v, w; > > int main() > { > v = b->v; > b->v = w; > return 0; > } > > (use -fno-common) and I see that we use unaligned stores too often > (even with a properly aligned MEM). > > The above at least shows movmisalign opportunities wrapped in component-refs. hmm, interesting. This does not compile differently with or without this patch. I have another observation, regarding the testcase pr50444.c: method: .LFB4: .cfi_startproc movq 32(%rdi), %rax testq %rax, %rax jne .L7 addl $1, 16(%rdi) movl $3, %eax movq %rax, 32(%rdi) movdqu 16(%rdi), %xmm0 pxor (%rdi), %xmm0 movdqu %xmm0, 40(%rdi) here the first movdqu could as well be movdqa, because 16+rdi is 128-bit aligned. In the ctor method a movdqa is used, but the SRA is very pessimistic and generates an unaligned MEM_REF. Also this example does not compile any different with this patch. >> That is, do you see anything break with just removing the movmisalign path? >> I'd rather install that (with the new testcases that then pass) separately as >> this is a somewhat fragile area and being able to more selectively >> bisect/backport >> would be nice. No, I think that is a good idea. Attached the first part of the patch, that does only remove the movmisalign path. Should I apply this one after regression testing? Bernd. >> Thanks, >> Richard. >> >>> Regards >>> Bernd. [-- Attachment #2: changelog-pr57748.txt --] [-- Type: text/plain, Size: 254 bytes --] 2013-09-17 Bernd Edlinger <bernd.edlinger@hotmail.de> PR middle-end/57748 * expr.c (expand_assignment): Remove misalignp code path. testsuite: PR middle-end/57748 * gcc.dg/torture/pr57748-1.c: New test. * gcc.dg/torture/pr57748-2.c: New test. [-- Attachment #3: patch-pr57748.diff --] [-- Type: application/octet-stream, Size: 4437 bytes --] --- gcc/expr.c 2013-09-12 15:03:18.000000000 +0200 +++ gcc/expr.c 2013-09-17 13:13:45.762823753 +0200 @@ -4709,8 +4709,6 @@ expand_assignment (tree to, tree from, b int unsignedp; int volatilep = 0; tree tem; - bool misalignp; - rtx mem = NULL_RTX; push_temp_slots (); tem = get_inner_reference (to, &bitsize, &bitpos, &offset, &mode1, @@ -4720,40 +4718,7 @@ expand_assignment (tree to, tree from, b && DECL_BIT_FIELD_TYPE (TREE_OPERAND (to, 1))) get_bit_range (&bitregion_start, &bitregion_end, to, &bitpos, &offset); - /* If we are going to use store_bit_field and extract_bit_field, - make sure to_rtx will be safe for multiple use. */ - mode = TYPE_MODE (TREE_TYPE (tem)); - if (TREE_CODE (tem) == MEM_REF - && mode != BLKmode - && ((align = get_object_alignment (tem)) - < GET_MODE_ALIGNMENT (mode)) - && ((icode = optab_handler (movmisalign_optab, mode)) - != CODE_FOR_nothing)) - { - struct expand_operand ops[2]; - - misalignp = true; - to_rtx = gen_reg_rtx (mode); - mem = expand_expr (tem, NULL_RTX, VOIDmode, EXPAND_WRITE); - - /* If the misaligned store doesn't overwrite all bits, perform - rmw cycle on MEM. */ - if (bitsize != GET_MODE_BITSIZE (mode)) - { - create_input_operand (&ops[0], to_rtx, mode); - create_fixed_operand (&ops[1], mem); - /* The movmisalign<mode> pattern cannot fail, else the assignment - would silently be omitted. */ - expand_insn (icode, 2, ops); - - mem = copy_rtx (mem); - } - } - else - { - misalignp = false; - to_rtx = expand_expr (tem, NULL_RTX, VOIDmode, EXPAND_WRITE); - } + to_rtx = expand_expr (tem, NULL_RTX, VOIDmode, EXPAND_WRITE); /* If the bitfield is volatile, we want to access it in the field's mode, not the computed mode. @@ -4892,17 +4857,6 @@ expand_assignment (tree to, tree from, b get_alias_set (to), nontemporal); } - if (misalignp) - { - struct expand_operand ops[2]; - - create_fixed_operand (&ops[0], mem); - create_input_operand (&ops[1], to_rtx, mode); - /* The movmisalign<mode> pattern cannot fail, else the assignment - would silently be omitted. */ - expand_insn (icode, 2, ops); - } - if (result) preserve_temp_slots (result); pop_temp_slots (); --- gcc/testsuite/gcc.dg/torture/pr57748-1.c 1970-01-01 01:00:00.000000000 +0100 +++ gcc/testsuite/gcc.dg/torture/pr57748-1.c 2013-09-06 08:38:03.718686940 +0200 @@ -0,0 +1,49 @@ +/* PR middle-end/57748 */ +/* { dg-do run } */ +/* ICE in expand_assignment: + misalignp == true, !MEM_P (to_rtx), offset != 0, + => gcc_assert (TREE_CODE (offset) == INTEGER_CST) */ + +#include <stdlib.h> + +extern void abort (void); + +typedef long long V + __attribute__ ((vector_size (2 * sizeof (long long)), may_alias)); + +typedef struct S { V a; V b[0]; } P __attribute__((aligned (1))); + +struct __attribute__((packed)) T { char c; P s; }; + +void __attribute__((noinline, noclone)) +check (struct T *t) +{ + if (t->s.b[0][0] != 3 || t->s.b[0][1] != 4) + abort (); +} + +int __attribute__((noinline, noclone)) +get_i (void) +{ + return 0; +} + +void __attribute__((noinline, noclone)) +foo (P *p) +{ + V a = { 3, 4 }; + int i = get_i (); + p->b[i] = a; +} + +int +main () +{ + struct T *t = (struct T *) calloc (128, 1); + + foo (&t->s); + check (t); + + free (t); + return 0; +} --- gcc/testsuite/gcc.dg/torture/pr57748-2.c 1970-01-01 01:00:00.000000000 +0100 +++ gcc/testsuite/gcc.dg/torture/pr57748-2.c 2013-09-06 08:38:03.718686940 +0200 @@ -0,0 +1,43 @@ +/* PR middle-end/57748 */ +/* { dg-do run } */ +/* wrong code in expand_assignment: + misalignp == true, !MEM_P (to_rtx), + offset == 0, bitpos >= GET_MODE_PRECISION, + => result = NULL. */ + +#include <stdlib.h> + +extern void abort (void); + +typedef long long V + __attribute__ ((vector_size (2 * sizeof (long long)), may_alias)); + +typedef struct S { V a; V b[0]; } P __attribute__((aligned (1))); + +struct __attribute__((packed)) T { char c; P s; }; + +void __attribute__((noinline, noclone)) +check (struct T *t) +{ + if (t->s.b[0][0] != 3 || t->s.b[0][1] != 4) + abort (); +} + +void __attribute__((noinline, noclone)) +foo (P *p) +{ + V a = { 3, 4 }; + p->b[0] = a; +} + +int +main () +{ + struct T *t = (struct T *) calloc (128, 1); + + foo (&t->s); + check (t); + + free (t); + return 0; +} ^ permalink raw reply [flat|nested] 105+ messages in thread
* Re: [PATCH, PR 57748] Check for out of bounds access 2013-09-17 12:48 ` Bernd Edlinger @ 2013-09-24 11:40 ` Richard Biener 2013-09-24 11:56 ` Bernd Edlinger 0 siblings, 1 reply; 105+ messages in thread From: Richard Biener @ 2013-09-24 11:40 UTC (permalink / raw) To: Bernd Edlinger; +Cc: Martin Jambor, GCC Patches On Tue, Sep 17, 2013 at 2:08 PM, Bernd Edlinger <bernd.edlinger@hotmail.de> wrote: > On Tue, 17 Sep 2013 12:45:40, Richard Biener wrote: >> >> On Tue, Sep 17, 2013 at 12:00 PM, Richard Biener >> <richard.guenther@gmail.com> wrote: >>> On Sun, Sep 15, 2013 at 6:55 PM, Bernd Edlinger >>> <bernd.edlinger@hotmail.de> wrote: >>>> Hello Richard, >>>> >>>> attached is my second attempt at fixing PR 57748. This time the movmisalign >>>> path is completely removed and a similar bug in the read handling of misaligned >>>> structures with a non-BLKmode is fixed too. There are several new test cases for the >>>> different possible failure modes. >>>> >>>> This patch was boot-strapped and regression tested on x86_64-unknown-linux-gnu >>>> and i686-pc-linux-gnu. >>>> >>>> Additionally I generated eCos and an eCos-application (on ARMv5 using packed >>>> structures) with an arm-eabi cross compiler, and looked for differences in the >>>> disassembled code with and without this patch, but there were none. >>>> >>>> OK for trunk? >>> >>> I agree that the existing movmisaling path that you remove is simply bogus, so >>> removing it looks fine to me. Can you give rationale to >>> >>> @@ -4773,6 +4738,8 @@ expand_assignment (tree to, tree from, b >>> if (MEM_P (to_rtx) >>> && GET_MODE (to_rtx) == BLKmode >>> && GET_MODE (XEXP (to_rtx, 0)) != VOIDmode >>> + && bitregion_start == 0 >>> + && bitregion_end == 0 >>> && bitsize> 0 >>> && (bitpos % bitsize) == 0 >>> && (bitsize % GET_MODE_ALIGNMENT (mode1)) == 0 > > OK, as already said, I think it could be dangerous to set bitpos=0 without > considering bitregion_start/end, but I think it may be possible that this > can not happen, because if bitsize is a multiple if ALIGNMENT, and > bitpos is a multiple of bitsize, we probably do not have a bit-field at all. > And of course I have no test case that fails without this hunk. > Maybe it would be better to add an assertion here like: > > { > gcc_assert (bitregion_start == 0 && bitregion_end == 0); > to_rtx = adjust_address (to_rtx, mode1, bitpos / BITS_PER_UNIT); > bitpos = 0; > } > >>> and especially to >>> >>> @@ -9905,7 +9861,7 @@ expand_expr_real_1 (tree exp, rtx target >>> && modifier != EXPAND_STACK_PARM >>> ? target : NULL_RTX), >>> VOIDmode, >>> - modifier == EXPAND_SUM ? EXPAND_NORMAL : modifier); >>> + EXPAND_MEMORY); >>> >>> /* If the bitfield is volatile, we want to access it in the >>> field's mode, not the computed mode. >>> >>> which AFAIK makes "memory" expansion of loads/stores from/to registers >>> change (fail? go through stack memory?) - see handling of non-MEM return >>> values from that expand_expr call. > > I wanted to make the expansion of MEM_REF and TARGET_MEM_REF > not go thru the final misalign handling, which is guarded by > "if (modifier != EXPAND_WRITE && modifier != EXPAND_MEMORY && ..." > > What we want here is most likely EXPAND_MEMORY, which returns a > memory context if possible. > > Could you specify more explicitly what you mean with "handling of non-MEM return > values from that expand_expr call", then I could try finding test cases for > that. > > >> In particular this seems to disable all movmisalign handling for MEM_REFs >> wrapped in component references which looks wrong. I was playing with >> >> typedef long long V >> __attribute__ ((vector_size (2 * sizeof (long long)), may_alias)); >> >> struct S { long long a[11]; V v; }__attribute__((aligned(8),packed)) ; >> struct S a, *b = &a; >> V v, w; >> >> int main() >> { >> v = b->v; >> b->v = w; >> return 0; >> } >> >> (use -fno-common) and I see that we use unaligned stores too often >> (even with a properly aligned MEM). >> >> The above at least shows movmisalign opportunities wrapped in component-refs. > > hmm, interesting. This does not compile differently with or without this patch. > > I have another observation, regarding the testcase pr50444.c: > > method: > .LFB4: > .cfi_startproc > movq 32(%rdi), %rax > testq %rax, %rax > jne .L7 > addl $1, 16(%rdi) > movl $3, %eax > movq %rax, 32(%rdi) > movdqu 16(%rdi), %xmm0 > pxor (%rdi), %xmm0 > movdqu %xmm0, 40(%rdi) > > here the first movdqu could as well be movdqa, because 16+rdi is 128-bit aligned. > In the ctor method a movdqa is used, but the SRA is very pessimistic and generates > an unaligned MEM_REF. Also this example does not compile any different with this patch. > > >>> That is, do you see anything break with just removing the movmisalign path? >>> I'd rather install that (with the new testcases that then pass) separately as >>> this is a somewhat fragile area and being able to more selectively >>> bisect/backport >>> would be nice. > > No, I think that is a good idea. > > Attached the first part of the patch, that does only remove the movmisalign path. > > Should I apply this one after regression testing? It seems you already have...? Richard. > Bernd. > >>> Thanks, >>> Richard. >>> >>>> Regards >>>> Bernd. ^ permalink raw reply [flat|nested] 105+ messages in thread
* RE: [PATCH, PR 57748] Check for out of bounds access 2013-09-24 11:40 ` Richard Biener @ 2013-09-24 11:56 ` Bernd Edlinger 0 siblings, 0 replies; 105+ messages in thread From: Bernd Edlinger @ 2013-09-24 11:56 UTC (permalink / raw) To: Richard Biener; +Cc: Martin Jambor, GCC Patches On Tue, 24 Sep 2013 13:13:09, Richard Biener wrote: >>>> That is, do you see anything break with just removing the movmisalign path? >>>> I'd rather install that (with the new testcases that then pass) separately as >>>> this is a somewhat fragile area and being able to more selectively >>>> bisect/backport >>>> would be nice. >> >> No, I think that is a good idea. >> >> Attached the first part of the patch, that does only remove the movmisalign path. >> >> Should I apply this one after regression testing? > > It seems you already have...? > > Richard. > yes, did I misunderstand this message? --- Comment #40 from rguenther at suse dot de <rguenther at suse dot de> --- On Wed, 18 Sep 2013, bernd.edlinger at hotmail dot de wrote: > http://gcc.gnu.org/bugzilla/show_bug.cgi?id=57748 > > --- Comment #38 from Bernd Edlinger <bernd.edlinger at hotmail dot de> --- > Richard, > > I've split up the patch as requested: > > Part 1 was posted here, but not yet approved: > http://gcc.gnu.org/ml/gcc-patches/2013-09/msg01292.html > > Just for the record, part 1 has been bootstrapped and regression tested. > > For part 2: > For simplicity I'd propose to use simply pass EXPAND_MEMORY here. > These misaligned uses are quite rare hopefully. > > I will replace my test cases 3+4 with Martin's test case, > maybe without the get_i() because otherwise the test will die > from the ICE before the check runs. > > Will do this after Part 1 if you agree... The issue is that we added the movmisaling-on-component-ref path for _correctness_ reasons. Now, if all misaligned accesses end up being expanded using BLKmode moves then it probably works ok (but then they are going to be horribly inefficent and wouldn't have triggered the movmisaling path anyway ...). But I'm willing to make the experiment - we've got plenty (well ...) time to watch out for fallout of this change (and it does simplify code, something I always like ;)) >> Bernd. >> >>>> Thanks, >>>> Richard. >>>> >>>>> Regards >>>>> Bernd. ^ permalink raw reply [flat|nested] 105+ messages in thread
* [PATCH, PR 57748] Check for out of bounds access, Part 2 2013-09-17 11:41 ` Richard Biener 2013-09-17 12:48 ` Bernd Edlinger @ 2013-09-24 6:34 ` Bernd Edlinger 2013-09-24 10:31 ` Richard Biener 1 sibling, 1 reply; 105+ messages in thread From: Bernd Edlinger @ 2013-09-24 6:34 UTC (permalink / raw) To: Richard Biener; +Cc: Martin Jambor, GCC Patches [-- Attachment #1: Type: text/plain, Size: 624 bytes --] Hi, with the attached patch the read-side of the out of bounds accesses are fixed. There is a single new test case pr57748-3.c that is derived from Martin's test case. The test case does only test the read access and does not depend on part 1 of the patch. This patch was boot-strapped and regression tested on x86_64-unknown-linux-gnu. Additionally I generated eCos and an eCos-application (on ARMv5 using packed structures) with an arm-eabi cross compiler, and looked for differences in the disassembled code with and without this patch, but there were none. OK for trunk? Regards Bernd. [-- Attachment #2: changelog-pr57748-2.txt --] [-- Type: text/plain, Size: 219 bytes --] 2013-09-24 Bernd Edlinger <bernd.edlinger@hotmail.de> PR middle-end/57748 * expr.c (expand_expr_real_1): Use EXAND_MEMORY on base object. testsuite/ PR middle-end/57748 * gcc.dg/torture/pr57748-3.c: New test. [-- Attachment #3: patch-pr57748-2.diff --] [-- Type: application/octet-stream, Size: 1399 bytes --] Index: gcc/expr.c =================================================================== --- gcc/expr.c (revision 202778) +++ gcc/expr.c (working copy) @@ -9878,7 +9878,7 @@ && modifier != EXPAND_STACK_PARM ? target : NULL_RTX), VOIDmode, - modifier == EXPAND_SUM ? EXPAND_NORMAL : modifier); + EXPAND_MEMORY); /* If the bitfield is volatile, we want to access it in the field's mode, not the computed mode. Index: gcc/testsuite/gcc.dg/torture/pr57748-3.c =================================================================== --- gcc/testsuite/gcc.dg/torture/pr57748-3.c (revision 0) +++ gcc/testsuite/gcc.dg/torture/pr57748-3.c (revision 0) @@ -0,0 +1,40 @@ +/* PR middle-end/57748 */ +/* { dg-do run } */ +/* wrong code in expand_expr_real_1. */ + +#include <stdlib.h> + +extern void abort (void); + +typedef long long V + __attribute__ ((vector_size (2 * sizeof (long long)), may_alias)); + +typedef struct S { V a; V b[0]; } P __attribute__((aligned (1))); + +struct __attribute__((packed)) T { char c; P s; }; + +void __attribute__((noinline, noclone)) +check (P *p) +{ + if (p->b[0][0] != 3 || p->b[0][1] != 4) + abort (); +} + +void __attribute__((noinline, noclone)) +foo (struct T *t) +{ + V a = { 3, 4 }; + t->s.b[0] = a; +} + +int +main () +{ + struct T *t = (struct T *) calloc (128, 1); + + foo (t); + check (&t->s); + + free (t); + return 0; +} ^ permalink raw reply [flat|nested] 105+ messages in thread
* Re: [PATCH, PR 57748] Check for out of bounds access, Part 2 2013-09-24 6:34 ` [PATCH, PR 57748] Check for out of bounds access, Part 2 Bernd Edlinger @ 2013-09-24 10:31 ` Richard Biener 2013-09-24 14:46 ` Eric Botcazou 2013-09-24 18:51 ` Martin Jambor 0 siblings, 2 replies; 105+ messages in thread From: Richard Biener @ 2013-09-24 10:31 UTC (permalink / raw) To: Bernd Edlinger, Eric Botcazou; +Cc: Martin Jambor, GCC Patches On Tue, Sep 24, 2013 at 4:52 AM, Bernd Edlinger <bernd.edlinger@hotmail.de> wrote: > Hi, > > with the attached patch the read-side of the out of bounds accesses are fixed. > There is a single new test case pr57748-3.c that is derived from Martin's test case. > The test case does only test the read access and does not depend on part 1 of the > patch. > > This patch was boot-strapped and regression tested on x86_64-unknown-linux-gnu. > > Additionally I generated eCos and an eCos-application (on ARMv5 using packed > structures) with an arm-eabi cross compiler, and looked for differences in the > disassembled code with and without this patch, but there were none. > > OK for trunk? Index: gcc/expr.c =================================================================== --- gcc/expr.c (revision 202778) +++ gcc/expr.c (working copy) @@ -9878,7 +9878,7 @@ && modifier != EXPAND_STACK_PARM ? target : NULL_RTX), VOIDmode, - modifier == EXPAND_SUM ? EXPAND_NORMAL : modifier); + EXPAND_MEMORY); /* If the bitfield is volatile, we want to access it in the field's mode, not the computed mode. context suggests that we may arrive with EXPAND_STACK_PARM here which is a correctness modifier (see its docs). But I'm not too familiar with the details of the various expand modifiers, Eric may be though. That said, I still believe that fixing the misalign path in expand_assignment would be better than trying to avoid it. For this testcase the issue is again that expand_assignment passes the wrong mode/target to the movmisalign optab. Richard. > > Regards > Bernd. ^ permalink raw reply [flat|nested] 105+ messages in thread
* Re: [PATCH, PR 57748] Check for out of bounds access, Part 2 2013-09-24 10:31 ` Richard Biener @ 2013-09-24 14:46 ` Eric Botcazou 2013-09-24 18:51 ` Martin Jambor 1 sibling, 0 replies; 105+ messages in thread From: Eric Botcazou @ 2013-09-24 14:46 UTC (permalink / raw) To: Richard Biener; +Cc: gcc-patches, Bernd Edlinger, Martin Jambor > Index: gcc/expr.c > =================================================================== > --- gcc/expr.c (revision 202778) > +++ gcc/expr.c (working copy) > @@ -9878,7 +9878,7 @@ > && modifier != EXPAND_STACK_PARM > ? target : NULL_RTX), > VOIDmode, > - modifier == EXPAND_SUM ? EXPAND_NORMAL : modifier); > + EXPAND_MEMORY); > > /* If the bitfield is volatile, we want to access it in the > field's mode, not the computed mode. > > context suggests that we may arrive with EXPAND_STACK_PARM here > which is a correctness modifier (see its docs). But I'm not too familiar > with the details of the various expand modifiers, Eric may be though. Yes, this change looks far too bold and is presumably papering over the underlying issue... > That said, I still believe that fixing the misalign path in > expand_assignment would be better than trying to avoid it. For this > testcase the issue is again that expand_assignment passes the wrong > mode/target to the > movmisalign optab. ...then let's just fix the movmisalign stuff. -- Eric Botcazou ^ permalink raw reply [flat|nested] 105+ messages in thread
* Re: [PATCH, PR 57748] Check for out of bounds access, Part 2 2013-09-24 10:31 ` Richard Biener 2013-09-24 14:46 ` Eric Botcazou @ 2013-09-24 18:51 ` Martin Jambor 2013-09-25 9:51 ` Richard Biener 2013-09-25 13:22 ` Bernd Edlinger 1 sibling, 2 replies; 105+ messages in thread From: Martin Jambor @ 2013-09-24 18:51 UTC (permalink / raw) To: Richard Biener; +Cc: Bernd Edlinger, Eric Botcazou, GCC Patches Hi, On Tue, Sep 24, 2013 at 12:02:17PM +0200, Richard Biener wrote: > On Tue, Sep 24, 2013 at 4:52 AM, Bernd Edlinger > <bernd.edlinger@hotmail.de> wrote: > > Hi, > > > > with the attached patch the read-side of the out of bounds accesses are fixed. > > There is a single new test case pr57748-3.c that is derived from Martin's test case. > > The test case does only test the read access and does not depend on part 1 of the > > patch. > > > > This patch was boot-strapped and regression tested on x86_64-unknown-linux-gnu. > > > > Additionally I generated eCos and an eCos-application (on ARMv5 using packed > > structures) with an arm-eabi cross compiler, and looked for differences in the > > disassembled code with and without this patch, but there were none. > > > > OK for trunk? > > Index: gcc/expr.c > =================================================================== > --- gcc/expr.c (revision 202778) > +++ gcc/expr.c (working copy) > @@ -9878,7 +9878,7 @@ > && modifier != EXPAND_STACK_PARM > ? target : NULL_RTX), > VOIDmode, > - modifier == EXPAND_SUM ? EXPAND_NORMAL : modifier); > + EXPAND_MEMORY); > > /* If the bitfield is volatile, we want to access it in the > field's mode, not the computed mode. > > context suggests that we may arrive with EXPAND_STACK_PARM here > which is a correctness modifier (see its docs). But I'm not too familiar > with the details of the various expand modifiers, Eric may be though. > > That said, I still believe that fixing the misalign path in expand_assignment > would be better than trying to avoid it. For this testcase the issue is > again that expand_assignment passes the wrong mode/target to the > movmisalign optab. Perhaps I'm stating the obvious, but this is supposed to address a separate bug in the expansion of the RHS (as opposed to the first bug which was in the expansion of the LHS), and so we would have to make expand_assignment to also examine potential misalignments in the RHS, which it so far does not do, despite its complexity. Having said that, I also dislike the patch, but I am quite convinced that if we allow non-BLK structures with zero sized arrays, the fix will be ugly - but I'll be glad to be shown I've been wrong. Martin ^ permalink raw reply [flat|nested] 105+ messages in thread
* Re: [PATCH, PR 57748] Check for out of bounds access, Part 2 2013-09-24 18:51 ` Martin Jambor @ 2013-09-25 9:51 ` Richard Biener 2013-09-25 14:56 ` Martin Jambor 2013-09-25 13:22 ` Bernd Edlinger 1 sibling, 1 reply; 105+ messages in thread From: Richard Biener @ 2013-09-25 9:51 UTC (permalink / raw) To: Richard Biener, Bernd Edlinger, Eric Botcazou, GCC Patches On Tue, Sep 24, 2013 at 8:06 PM, Martin Jambor <mjambor@suse.cz> wrote: > Hi, > > On Tue, Sep 24, 2013 at 12:02:17PM +0200, Richard Biener wrote: >> On Tue, Sep 24, 2013 at 4:52 AM, Bernd Edlinger >> <bernd.edlinger@hotmail.de> wrote: >> > Hi, >> > >> > with the attached patch the read-side of the out of bounds accesses are fixed. >> > There is a single new test case pr57748-3.c that is derived from Martin's test case. >> > The test case does only test the read access and does not depend on part 1 of the >> > patch. >> > >> > This patch was boot-strapped and regression tested on x86_64-unknown-linux-gnu. >> > >> > Additionally I generated eCos and an eCos-application (on ARMv5 using packed >> > structures) with an arm-eabi cross compiler, and looked for differences in the >> > disassembled code with and without this patch, but there were none. >> > >> > OK for trunk? >> >> Index: gcc/expr.c >> =================================================================== >> --- gcc/expr.c (revision 202778) >> +++ gcc/expr.c (working copy) >> @@ -9878,7 +9878,7 @@ >> && modifier != EXPAND_STACK_PARM >> ? target : NULL_RTX), >> VOIDmode, >> - modifier == EXPAND_SUM ? EXPAND_NORMAL : modifier); >> + EXPAND_MEMORY); >> >> /* If the bitfield is volatile, we want to access it in the >> field's mode, not the computed mode. >> >> context suggests that we may arrive with EXPAND_STACK_PARM here >> which is a correctness modifier (see its docs). But I'm not too familiar >> with the details of the various expand modifiers, Eric may be though. >> >> That said, I still believe that fixing the misalign path in expand_assignment >> would be better than trying to avoid it. For this testcase the issue is >> again that expand_assignment passes the wrong mode/target to the >> movmisalign optab. > > Perhaps I'm stating the obvious, but this is supposed to address a > separate bug in the expansion of the RHS (as opposed to the first bug > which was in the expansion of the LHS), and so we would have to make > expand_assignment to also examine potential misalignments in the RHS, > which it so far does not do, despite its complexity. > > Having said that, I also dislike the patch, but I am quite convinced > that if we allow non-BLK structures with zero sized arrays, the fix > will be ugly - but I'll be glad to be shown I've been wrong. I don't think the issues have anything to do with zero sized arrays or non-BLK structures. The issue is just we are feeding movmisaling with the wrong mode (the mode of the base object) if we are expanding a base object which is unaligned and has non-BLK mode. So what we maybe need is another expand modifier that tells us to not use movmisalign when expanding the base object. Or we need to stop expanding the base object with VOIDmode and instead pass down the mode of the access (TYPE_MODE (TREE_TYPE (exp)) which will probably confuse other code. So eventually not handling the misaligned case by expansion of the base but inlined similar to how it was in expand_assignment would be needed here. Richard. > Martin ^ permalink raw reply [flat|nested] 105+ messages in thread
* Re: [PATCH, PR 57748] Check for out of bounds access, Part 2 2013-09-25 9:51 ` Richard Biener @ 2013-09-25 14:56 ` Martin Jambor 2013-09-26 9:34 ` Bernd Edlinger 0 siblings, 1 reply; 105+ messages in thread From: Martin Jambor @ 2013-09-25 14:56 UTC (permalink / raw) To: Richard Biener; +Cc: Bernd Edlinger, Eric Botcazou, GCC Patches Hi, On Wed, Sep 25, 2013 at 11:05:21AM +0200, Richard Biener wrote: > On Tue, Sep 24, 2013 at 8:06 PM, Martin Jambor <mjambor@suse.cz> wrote: > > Hi, > > > > On Tue, Sep 24, 2013 at 12:02:17PM +0200, Richard Biener wrote: > >> On Tue, Sep 24, 2013 at 4:52 AM, Bernd Edlinger > >> <bernd.edlinger@hotmail.de> wrote: > >> > Hi, > >> > > >> > with the attached patch the read-side of the out of bounds accesses are fixed. > >> > There is a single new test case pr57748-3.c that is derived from Martin's test case. > >> > The test case does only test the read access and does not depend on part 1 of the > >> > patch. > >> > > >> > This patch was boot-strapped and regression tested on x86_64-unknown-linux-gnu. > >> > > >> > Additionally I generated eCos and an eCos-application (on ARMv5 using packed > >> > structures) with an arm-eabi cross compiler, and looked for differences in the > >> > disassembled code with and without this patch, but there were none. > >> > > >> > OK for trunk? > >> > >> Index: gcc/expr.c > >> =================================================================== > >> --- gcc/expr.c (revision 202778) > >> +++ gcc/expr.c (working copy) > >> @@ -9878,7 +9878,7 @@ > >> && modifier != EXPAND_STACK_PARM > >> ? target : NULL_RTX), > >> VOIDmode, > >> - modifier == EXPAND_SUM ? EXPAND_NORMAL : modifier); > >> + EXPAND_MEMORY); > >> > >> /* If the bitfield is volatile, we want to access it in the > >> field's mode, not the computed mode. > >> > >> context suggests that we may arrive with EXPAND_STACK_PARM here > >> which is a correctness modifier (see its docs). But I'm not too familiar > >> with the details of the various expand modifiers, Eric may be though. > >> > >> That said, I still believe that fixing the misalign path in expand_assignment > >> would be better than trying to avoid it. For this testcase the issue is > >> again that expand_assignment passes the wrong mode/target to the > >> movmisalign optab. > > > > Perhaps I'm stating the obvious, but this is supposed to address a > > separate bug in the expansion of the RHS (as opposed to the first bug > > which was in the expansion of the LHS), and so we would have to make > > expand_assignment to also examine potential misalignments in the RHS, > > which it so far does not do, despite its complexity. > > > > Having said that, I also dislike the patch, but I am quite convinced > > that if we allow non-BLK structures with zero sized arrays, the fix > > will be ugly - but I'll be glad to be shown I've been wrong. > > I don't think the issues have anything to do with zero sized arrays > or non-BLK structures. The issue is just we are feeding movmisaling > with the wrong mode (the mode of the base object) if we are expanding > a base object which is unaligned and has non-BLK mode. I disagree. Consider a slightly modified testcase: #include <stdlib.h> typedef long long V __attribute__ ((vector_size (2 * sizeof (long long)), may_alias)); #if 1 typedef struct S { V a; V b[0]; } P __attribute__((aligned (1))); struct __attribute__((packed)) T { char c; P s; }; #else typedef struct S { V a; V b[0]; } P; struct T { char c; P s; }; #endif void __attribute__((noinline, noclone)) good_value (V b) { if (b[0] != 3 || b[1] != 4) __builtin_abort (); } void __attribute__((noinline, noclone)) check (P *p) { good_value (p->b[0]); } int main () { struct T *t = (struct T *) calloc (128, 1); V a = { 3, 4 }; t->s.b[0] = a; check (&t->s); free (t); return 0; } The problem is the expansion of the memory load in function check. All involved modes, the one of the base structure and of the loaded component, are V2DI so even if we somehow mixed them up, in this example it should not matter, yet the unaligned load gives wrong results. I'm still convinced that the problem is that we have a V2DImode structure which is larger that the mode tells and we want to load the data from outside of its mode. That is only happening because zero sized arrays. > > So what we maybe need is another expand modifier that tells us > to not use movmisalign when expanding the base object. In that case we can just as well use EXPAND_MEMORY. If so, I'd do that only when there is a zero sized array involved in order not to avoid using movmisalign when we can. > Or we need to stop expanding the base object with VOIDmode and > instead pass down the mode of the access (TYPE_MODE (TREE_TYPE > (exp)) which will probably confuse other code. Well, because I think the problem is not (just) mixing up modes, I don't think this will help either. > So eventually not > handling the misaligned case by expansion of the base but inlined > similar to how it was in expand_assignment would be needed here. At least now I fail to see how this would be different from copying a large portion of expand_expr_real_1 (all of the MEM_REF part without the movmisalign bit) and calling that when we detect "this case" whatever we eventually agree it is. Martin ^ permalink raw reply [flat|nested] 105+ messages in thread
* RE: [PATCH, PR 57748] Check for out of bounds access, Part 2 2013-09-25 14:56 ` Martin Jambor @ 2013-09-26 9:34 ` Bernd Edlinger 2013-09-26 11:18 ` Eric Botcazou 0 siblings, 1 reply; 105+ messages in thread From: Bernd Edlinger @ 2013-09-26 9:34 UTC (permalink / raw) To: Martin Jambor, Richard Biener; +Cc: Eric Botcazou, GCC Patches Hi, On Wed, 25 Sep 2013 16:01:02, Martin Jambor wrote: > Hi, > > On Wed, Sep 25, 2013 at 11:05:21AM +0200, Richard Biener wrote: >> On Tue, Sep 24, 2013 at 8:06 PM, Martin Jambor <mjambor@suse.cz> wrote: >>> Hi, >>> >>> On Tue, Sep 24, 2013 at 12:02:17PM +0200, Richard Biener wrote: >>>> On Tue, Sep 24, 2013 at 4:52 AM, Bernd Edlinger >>>> <bernd.edlinger@hotmail.de> wrote: >>>>> Hi, >>>>> >>>>> with the attached patch the read-side of the out of bounds accesses are fixed. >>>>> There is a single new test case pr57748-3.c that is derived from Martin's test case. >>>>> The test case does only test the read access and does not depend on part 1 of the >>>>> patch. >>>>> >>>>> This patch was boot-strapped and regression tested on x86_64-unknown-linux-gnu. >>>>> >>>>> Additionally I generated eCos and an eCos-application (on ARMv5 using packed >>>>> structures) with an arm-eabi cross compiler, and looked for differences in the >>>>> disassembled code with and without this patch, but there were none. >>>>> >>>>> OK for trunk? >>>> >>>> Index: gcc/expr.c >>>> =================================================================== >>>> --- gcc/expr.c (revision 202778) >>>> +++ gcc/expr.c (working copy) >>>> @@ -9878,7 +9878,7 @@ >>>> && modifier != EXPAND_STACK_PARM >>>> ? target : NULL_RTX), >>>> VOIDmode, >>>> - modifier == EXPAND_SUM ? EXPAND_NORMAL : modifier); >>>> + EXPAND_MEMORY); >>>> >>>> /* If the bitfield is volatile, we want to access it in the >>>> field's mode, not the computed mode. >>>> >>>> context suggests that we may arrive with EXPAND_STACK_PARM here >>>> which is a correctness modifier (see its docs). But I'm not too familiar >>>> with the details of the various expand modifiers, Eric may be though. >>>> >>>> That said, I still believe that fixing the misalign path in expand_assignment >>>> would be better than trying to avoid it. For this testcase the issue is >>>> again that expand_assignment passes the wrong mode/target to the >>>> movmisalign optab. >>> >>> Perhaps I'm stating the obvious, but this is supposed to address a >>> separate bug in the expansion of the RHS (as opposed to the first bug >>> which was in the expansion of the LHS), and so we would have to make >>> expand_assignment to also examine potential misalignments in the RHS, >>> which it so far does not do, despite its complexity. >>> >>> Having said that, I also dislike the patch, but I am quite convinced >>> that if we allow non-BLK structures with zero sized arrays, the fix >>> will be ugly - but I'll be glad to be shown I've been wrong. >> >> I don't think the issues have anything to do with zero sized arrays >> or non-BLK structures. The issue is just we are feeding movmisaling >> with the wrong mode (the mode of the base object) if we are expanding >> a base object which is unaligned and has non-BLK mode. > > I disagree. Consider a slightly modified testcase: > > #include <stdlib.h> > typedef long long V > __attribute__ ((vector_size (2 * sizeof (long long)), may_alias)); > > #if 1 > typedef struct S { V a; V b[0]; } P __attribute__((aligned (1))); > struct __attribute__((packed)) T { char c; P s; }; > #else > typedef struct S { V a; V b[0]; } P; > struct T { char c; P s; }; > #endif > > void __attribute__((noinline, noclone)) > good_value (V b) > { > if (b[0] != 3 || b[1] != 4) > __builtin_abort (); > } > > void __attribute__((noinline, noclone)) > check (P *p) > { > good_value (p->b[0]); > } > > int > main () > { > struct T *t = (struct T *) calloc (128, 1); > V a = { 3, 4 }; > t->s.b[0] = a; > check (&t->s); > free (t); > return 0; > } > > The problem is the expansion of the memory load in function check. > All involved modes, the one of the base structure and of the loaded > component, are V2DI so even if we somehow mixed them up, in this > example it should not matter, yet the unaligned load gives wrong > results. > > I'm still convinced that the problem is that we have a V2DImode > structure which is larger that the mode tells and we want to load the > data from outside of its mode. That is only happening because zero > sized arrays. Yes, this is another good example, and it passes vector values on the stack to a function. Again my patch produces working code, while the current trunk produces just completely _insane_ code. And again, this is not only a problem of structures with zero-sized arrays at the end. Remember my previous example code: On ARM (or anything with STRICT_ALIGNMENT) this union has the same problems: /* PR middle-end/57748 */ /* arm-eabi-gcc -mcpu=cortex-a9 -O3 */ #include <stdlib.h> union x { short a[2]; char x[4]; } __attribute__((packed, aligned(4))) ; typedef volatile union x *s; void __attribute__((noinline, noclone)) check (void) { s xx=(s)(0x80000002); /* although volatile xx->x[3] reads 4 bytes here */ if (xx->x[3] != 3) abort (); } void __attribute__((noinline, noclone)) foo (void) { s xx=(s)(0x80000002); xx->x[3] = 3; } int main () { foo (); check (); return 0; } >> >> So what we maybe need is another expand modifier that tells us >> to not use movmisalign when expanding the base object. > > In that case we can just as well use EXPAND_MEMORY. If so, I'd do > that only when there is a zero sized array involved in order not to > avoid using movmisalign when we can. > >> Or we need to stop expanding the base object with VOIDmode and >> instead pass down the mode of the access (TYPE_MODE (TREE_TYPE >> (exp)) which will probably confuse other code. > > Well, because I think the problem is not (just) mixing up modes, I > don't think this will help either. > >> So eventually not >> handling the misaligned case by expansion of the base but inlined >> similar to how it was in expand_assignment would be needed here. > > At least now I fail to see how this would be different from copying a > large portion of expand_expr_real_1 (all of the MEM_REF part without > the movmisalign bit) and calling that when we detect "this case" > whatever we eventually agree it is. > > Martin So I still think my patch does the right thing. The rationale is: = expand_expr (tem, (TREE_CODE (TREE_TYPE (tem)) == UNION_TYPE && COMPLETE_TYPE_P (TREE_TYPE (tem)) && (TREE_CODE (TYPE_SIZE (TREE_TYPE (tem))) != INTEGER_CST) && modifier != EXPAND_STACK_PARM ? target : NULL_RTX), VOIDmode, EXPAND_MEMORY); returns the address of the structure in question, we can add offset, bitoffset, and access the memory in the right mode and alignment information is passed to the backend via MEM_ALIGN (op0). Passing EXPAND_STACK_PARM would explicitly do the wrong thing, as this is not the final result but only an intermediate value. As long as MEM_ALIGN(op0) is right it does not matter if we use mov_optab or movmisalign_optab. If _that_ is a bug, then the back-ends worked around it already for years, and I don't see any reason for changing that now. Bernd. ^ permalink raw reply [flat|nested] 105+ messages in thread
* Re: [PATCH, PR 57748] Check for out of bounds access, Part 2 2013-09-26 9:34 ` Bernd Edlinger @ 2013-09-26 11:18 ` Eric Botcazou 2013-09-26 12:42 ` Bernd Edlinger 0 siblings, 1 reply; 105+ messages in thread From: Eric Botcazou @ 2013-09-26 11:18 UTC (permalink / raw) To: Bernd Edlinger; +Cc: gcc-patches, Martin Jambor, Richard Biener > So I still think my patch does the right thing. > > The rationale is: > > = expand_expr (tem, > (TREE_CODE (TREE_TYPE (tem)) == UNION_TYPE > && COMPLETE_TYPE_P (TREE_TYPE (tem)) > && (TREE_CODE (TYPE_SIZE (TREE_TYPE (tem))) > != INTEGER_CST) > && modifier != EXPAND_STACK_PARM > ? target : NULL_RTX), > VOIDmode, > EXPAND_MEMORY); > > returns the address of the structure in question, > we can add offset, bitoffset, and access the memory > in the right mode and alignment information is > passed to the backend via MEM_ALIGN (op0). But there are conceptually no reasons to require a MEM here. Look at all the code just below the block. Given how hard it is to eliminate spills to memory in RTL once they are generated, this shouldn't be taken lightly. -- Eric Botcazou ^ permalink raw reply [flat|nested] 105+ messages in thread
* RE: [PATCH, PR 57748] Check for out of bounds access, Part 2 2013-09-26 11:18 ` Eric Botcazou @ 2013-09-26 12:42 ` Bernd Edlinger 2013-09-27 8:45 ` Eric Botcazou 0 siblings, 1 reply; 105+ messages in thread From: Bernd Edlinger @ 2013-09-26 12:42 UTC (permalink / raw) To: Eric Botcazou; +Cc: gcc-patches, Martin Jambor, Richard Biener Hi, On Thu, 26 Sep 2013 11:34:02, Eric Botcazou wrote: > >> So I still think my patch does the right thing. >> >> The rationale is: >> >> = expand_expr (tem, >> (TREE_CODE (TREE_TYPE (tem)) == UNION_TYPE >> && COMPLETE_TYPE_P (TREE_TYPE (tem)) >> && (TREE_CODE (TYPE_SIZE (TREE_TYPE (tem))) >> != INTEGER_CST) >> && modifier != EXPAND_STACK_PARM >> ? target : NULL_RTX), >> VOIDmode, >> EXPAND_MEMORY); >> >> returns the address of the structure in question, >> we can add offset, bitoffset, and access the memory >> in the right mode and alignment information is >> passed to the backend via MEM_ALIGN (op0). > > But there are conceptually no reasons to require a MEM here. Look at all the > code just below the block. Given how hard it is to eliminate spills to memory > in RTL once they are generated, this shouldn't be taken lightly. > > -- > Eric Botcazou Sure, but the modifier is not meant to force something into memory, especially when it is already in an register. Remember, we are only talking of structures here, and we only want to access one member. It is more the other way round: It says: "You do not have to load the value in a register, if it is already in memory I'm happy" At least in my understanding. Bernd. ^ permalink raw reply [flat|nested] 105+ messages in thread
* Re: [PATCH, PR 57748] Check for out of bounds access, Part 2 2013-09-26 12:42 ` Bernd Edlinger @ 2013-09-27 8:45 ` Eric Botcazou 2013-10-03 0:37 ` Bernd Edlinger 0 siblings, 1 reply; 105+ messages in thread From: Eric Botcazou @ 2013-09-27 8:45 UTC (permalink / raw) To: Bernd Edlinger; +Cc: gcc-patches, Martin Jambor, Richard Biener > Sure, but the modifier is not meant to force something into memory, > especially when it is already in an register. Remember, we are only > talking of structures here, and we only want to access one member. > > It is more the other way round: > It says: "You do not have to load the value in a register, if it is already > in memory I'm happy" EXPAND_MEMORY means we are interested in a memory result, even if the memory is constant and we could have propagated a constant value. */ We definitely want to propagate constant values here, look at the code below. And it already lists explicit cases where we really need to splill to memory. -- Eric Botcazou ^ permalink raw reply [flat|nested] 105+ messages in thread
* RE: [PATCH, PR 57748] Check for out of bounds access, Part 2 2013-09-27 8:45 ` Eric Botcazou @ 2013-10-03 0:37 ` Bernd Edlinger 2013-10-08 8:02 ` Eric Botcazou 0 siblings, 1 reply; 105+ messages in thread From: Bernd Edlinger @ 2013-10-03 0:37 UTC (permalink / raw) To: Eric Botcazou; +Cc: gcc-patches, Martin Jambor, Richard Biener [-- Attachment #1: Type: text/plain, Size: 2820 bytes --] Hi Eric, On Fri, 27 Sep 2013 10:36:57, Eric Botcazou wrote: > >> Sure, but the modifier is not meant to force something into memory, >> especially when it is already in an register. Remember, we are only >> talking of structures here, and we only want to access one member. >> >> It is more the other way round: >> It says: "You do not have to load the value in a register, if it is already >> in memory I'm happy" > > EXPAND_MEMORY means we are interested in a memory result, even if > the memory is constant and we could have propagated a constant value. */ > > We definitely want to propagate constant values here, look at the code below. > And it already lists explicit cases where we really need to splill to memory. > > -- > Eric Botcazou I'd like to continue this discussion by proposing this updated patch. I have now added a new value "EXPAND_REFERENCE" to the expand_modifier enumeration. It is almost like EXPAND_MEMORY but it does not interfere with constant values. I have done the same modification to VIEW_CONVERT_EXPR too, because this is a possible inner reference, itself. It is however inherently hard to test around this code. To understand this patch it is good to know what type of object the return value "tem" of get_inner_reference can be. From the program logic at get_inner_reference it is clear that the return value may *not* be BIT_FIELD_REF, COMPONENT_REF, ARRAY_REF, ARRAY_RANGE_REF, REALPART_EXPR, IMAGPART_EXPR. The result may be VIEW_CONVERT_EXPR only on a STRICT_ALIGNMENT target. This is probably further restricted because exp is gimplified. Usually the result will be a MEM_REF or a SSA_NAME of the memory where the structure is to be found. When you look at where EXPAND_MEMORY is handled you see it is special-cased in TARGET_MEM_REF, MEM_REF, ARRAY_REF, COMPONENT_REF, BIT_FIELD_REF, ARRAY_RANGE_REF. At TARGET_MEM_REF, MEM_REF, VIEW_CONVERT_EXPR, it should be the same if EXPAND_MEMORY, EXPAND_WRITE or EXPAND_REFERENCE is given: If it is an unaligned memory, we just return the unaligned reference. This was missing for VIEW_CONVERT_EXPR, and unfortunately I have no test case, because it is only a problem for STRICT_ALIGNMENT targets, and even there it will certainly be really hard to find test cases that exercise this code. In ARRAY_REF, COMPONENT_REF, BIT_FIELD_REF, ARRAY_RANGE_REF we do not have to touch the handling of the outer modifier. However we pass EXPAND_REFERENCE to the inner object, which should not be a recursive use of any ARRAY_REF, COMPONENT_REF, BIT_FIELD_REF, ARRAY_RANGE_REF. TARGET_MEM_REF, MEM_REF and VIEW_CONVERT_EXPR know how to handle EXPAND_REFERENCE, anything else handles it like EXPAND_NORMAL. OK, what do you think of it now? Thanks Bernd. [-- Attachment #2: changelog-pr57748-2.txt --] [-- Type: text/plain, Size: 284 bytes --] 2013-10-03 Bernd Edlinger <bernd.edlinger@hotmail.de> PR middle-end/57748 * expr.h (expand_modifier): New enum value EXPAND_REFERENCE. * expr.c (expand_expr_real_1): Use EXAND_REFERENCE on base object. testsuite/ PR middle-end/57748 * gcc.dg/torture/pr57748-3.c: New test. [-- Attachment #3: patch-pr57748-2.diff --] [-- Type: application/octet-stream, Size: 4286 bytes --] Index: gcc/expr.c =================================================================== --- gcc/expr.c (revision 203044) +++ gcc/expr.c (working copy) @@ -9573,6 +9573,7 @@ expand_expr_real_1 (tree exp, rtx target, enum mac align = get_object_alignment (exp); if (modifier != EXPAND_WRITE && modifier != EXPAND_MEMORY + && modifier != EXPAND_REFERENCE && mode != BLKmode && align < GET_MODE_ALIGNMENT (mode) /* If the target does not have special handling for unaligned @@ -9653,6 +9654,7 @@ expand_expr_real_1 (tree exp, rtx target, enum mac MEM_VOLATILE_P (temp) = 1; if (modifier != EXPAND_WRITE && modifier != EXPAND_MEMORY + && modifier != EXPAND_REFERENCE && mode != BLKmode && align < GET_MODE_ALIGNMENT (mode)) { @@ -9886,7 +9888,7 @@ expand_expr_real_1 (tree exp, rtx target, enum mac && modifier != EXPAND_STACK_PARM ? target : NULL_RTX), VOIDmode, - modifier == EXPAND_SUM ? EXPAND_NORMAL : modifier); + EXPAND_REFERENCE); /* If the bitfield is volatile, we want to access it in the field's mode, not the computed mode. @@ -10245,7 +10247,7 @@ expand_expr_real_1 (tree exp, rtx target, enum mac && modifier != EXPAND_STACK_PARM ? target : NULL_RTX), VOIDmode, - modifier == EXPAND_SUM ? EXPAND_NORMAL : modifier); + EXPAND_REFERENCE); if (MEM_P (orig_op0)) { @@ -10339,7 +10341,10 @@ expand_expr_real_1 (tree exp, rtx target, enum mac op0 = copy_rtx (op0); set_mem_align (op0, MAX (MEM_ALIGN (op0), TYPE_ALIGN (type))); } - else if (mode != BLKmode + else if (modifier != EXPAND_WRITE + && modifier != EXPAND_MEMORY + && modifier != EXPAND_REFERENCE + && mode != BLKmode && MEM_ALIGN (op0) < GET_MODE_ALIGNMENT (mode) /* If the target does have special handling for unaligned loads of mode then use them. */ @@ -10360,6 +10365,9 @@ expand_expr_real_1 (tree exp, rtx target, enum mac return reg; } else if (STRICT_ALIGNMENT + && modifier != EXPAND_WRITE + && modifier != EXPAND_MEMORY + && modifier != EXPAND_REFERENCE && mode != BLKmode && MEM_ALIGN (op0) < GET_MODE_ALIGNMENT (mode)) { Index: gcc/expr.h =================================================================== --- gcc/expr.h (revision 203044) +++ gcc/expr.h (working copy) @@ -41,10 +41,13 @@ along with GCC; see the file COPYING3. If not see is a constant that is not a legitimate address. EXPAND_WRITE means we are only going to write to the resulting rtx. EXPAND_MEMORY means we are interested in a memory result, even if - the memory is constant and we could have propagated a constant value. */ + the memory is constant and we could have propagated a constant value, + or the memory is unaligned on a STRICT_ALIGNMENT target. + EXPAND_REFERENCE is similar to EXPAND_MEMORY, used internally to expand + the inner reference of a component. */ enum expand_modifier {EXPAND_NORMAL = 0, EXPAND_STACK_PARM, EXPAND_SUM, EXPAND_CONST_ADDRESS, EXPAND_INITIALIZER, EXPAND_WRITE, - EXPAND_MEMORY}; + EXPAND_MEMORY, EXPAND_REFERENCE}; /* Prevent the compiler from deferring stack pops. See inhibit_defer_pop for more information. */ Index: gcc/testsuite/gcc.dg/torture/pr57748-3.c =================================================================== --- gcc/testsuite/gcc.dg/torture/pr57748-3.c (revision 0) +++ gcc/testsuite/gcc.dg/torture/pr57748-3.c (revision 0) @@ -0,0 +1,40 @@ +/* PR middle-end/57748 */ +/* { dg-do run } */ +/* wrong code in expand_expr_real_1. */ + +#include <stdlib.h> + +extern void abort (void); + +typedef long long V + __attribute__ ((vector_size (2 * sizeof (long long)), may_alias)); + +typedef struct S { V a; V b[0]; } P __attribute__((aligned (1))); + +struct __attribute__((packed)) T { char c; P s; }; + +void __attribute__((noinline, noclone)) +check (P *p) +{ + if (p->b[0][0] != 3 || p->b[0][1] != 4) + abort (); +} + +void __attribute__((noinline, noclone)) +foo (struct T *t) +{ + V a = { 3, 4 }; + t->s.b[0] = a; +} + +int +main () +{ + struct T *t = (struct T *) calloc (128, 1); + + foo (t); + check (&t->s); + + free (t); + return 0; +} ^ permalink raw reply [flat|nested] 105+ messages in thread
* Re: [PATCH, PR 57748] Check for out of bounds access, Part 2 2013-10-03 0:37 ` Bernd Edlinger @ 2013-10-08 8:02 ` Eric Botcazou 2013-10-08 9:22 ` Bernd Edlinger 0 siblings, 1 reply; 105+ messages in thread From: Eric Botcazou @ 2013-10-08 8:02 UTC (permalink / raw) To: Bernd Edlinger; +Cc: gcc-patches, Martin Jambor, Richard Biener > OK, what do you think of it now? My take on this is that the Proper Fix(tm) has been posted by Martin: http://gcc.gnu.org/ml/gcc-patches/2013-08/msg00082.html IMO it's a no-brainer, modulo the ABI concern. Everything else is more or less clever stuff to paper over this original compute_record_mode bug. We are lying to the expander by pretending that the object has V2DImode since it's larger and thus cannot be manipulated in this mode; everything is clearly downhill from there. If we don't want to properly fix the bug then let's put a hack in the expander, possibly using EXPAND_MEMORY, but it should trigger _only_ for structures with zero-sized arrays and non-BLKmode and be preceded by a big ??? comment explaining why it is deemed necessary. -- Eric Botcazou ^ permalink raw reply [flat|nested] 105+ messages in thread
* RE: [PATCH, PR 57748] Check for out of bounds access, Part 2 2013-10-08 8:02 ` Eric Botcazou @ 2013-10-08 9:22 ` Bernd Edlinger 2013-10-08 21:04 ` Eric Botcazou 0 siblings, 1 reply; 105+ messages in thread From: Bernd Edlinger @ 2013-10-08 9:22 UTC (permalink / raw) To: Eric Botcazou; +Cc: gcc-patches, Martin Jambor, Richard Biener Hi, On Tue, 8 Oct 2013 10:01:37, Eric Botcazou wrote: > >> OK, what do you think of it now? > > My take on this is that the Proper Fix(tm) has been posted by Martin: > http://gcc.gnu.org/ml/gcc-patches/2013-08/msg00082.html > IMO it's a no-brainer, modulo the ABI concern. Everything else is more or > less clever stuff to paper over this original compute_record_mode bug. > > We are lying to the expander by pretending that the object has V2DImode since > it's larger and thus cannot be manipulated in this mode; everything is clearly > downhill from there. If we don't want to properly fix the bug then let's put > a hack in the expander, possibly using EXPAND_MEMORY, but it should trigger > _only_ for structures with zero-sized arrays and non-BLKmode and be preceded > by a big ??? comment explaining why it is deemed necessary. > > -- > Eric Botcazou I agree, that assigning a non-BLKmode to structures with zero-sized arrays should be considered a bug. And it should be checked that there is only ONE zero-sized array. And it should be checked that it is only allowed at the end of the structure. Otherwise we have something like a union instead of a structure, which will break the code in tree-ssa-alias.c ! And again, this is not only a problem of structures with zero-sized arrays at the end. Remember my previous example code: On ARM (or anything with STRICT_ALIGNMENT) this union has the same problems: /* PR middle-end/57748 */ /* arm-eabi-gcc -mcpu=cortex-a9 -O3 */ #include <stdlib.h> union x { short a[2]; char x[4]; } __attribute__((packed, aligned(4))) ; typedef volatile union x *s; void __attribute__((noinline, noclone)) check (void) { s xx=(s)(0x80000002); /* although volatile xx->x[3] reads 4 bytes here */ if (xx->x[3] != 3) abort (); } void __attribute__((noinline, noclone)) foo (void) { s xx=(s)(0x80000002); xx->x[3] = 3; } int main () { foo (); check (); return 0; } This union has a UINT32 mode, look at compute_record_mode! Because of this example I still think that the expander should know what we intend to do with the base object. Regards Bernd. ^ permalink raw reply [flat|nested] 105+ messages in thread
* Re: [PATCH, PR 57748] Check for out of bounds access, Part 2 2013-10-08 9:22 ` Bernd Edlinger @ 2013-10-08 21:04 ` Eric Botcazou 2013-10-08 23:03 ` Bernd Edlinger 0 siblings, 1 reply; 105+ messages in thread From: Eric Botcazou @ 2013-10-08 21:04 UTC (permalink / raw) To: Bernd Edlinger; +Cc: gcc-patches, Martin Jambor, Richard Biener > I agree, that assigning a non-BLKmode to structures with zero-sized arrays > should be considered a bug. Fine, then let's apply Martin's patch, on mainline at least. > And again, this is not only a problem of structures with zero-sized > arrays at the end. Remember my previous example code: > On ARM (or anything with STRICT_ALIGNMENT) this union has the > same problems: > > /* PR middle-end/57748 */ > /* arm-eabi-gcc -mcpu=cortex-a9 -O3 */ > #include <stdlib.h> > > union x > { > short a[2]; > char x[4]; > } __attribute__((packed, aligned(4))) ; > typedef volatile union x *s; > > void __attribute__((noinline, noclone)) > check (void) > { > s xx=(s)(0x80000002); > /* although volatile xx->x[3] reads 4 bytes here */ > if (xx->x[3] != 3) > abort (); > } > > void __attribute__((noinline, noclone)) > foo (void) > { > s xx=(s)(0x80000002); > xx->x[3] = 3; > } > > int > main () > { > foo (); > check (); > return 0; > } But this testcase is invalid on STRICT_ALIGNMENT platforms: xx is pointer to a type with 4-byte alignment so its value must be a multiple of 4. -- Eric Botcazou ^ permalink raw reply [flat|nested] 105+ messages in thread
* RE: [PATCH, PR 57748] Check for out of bounds access, Part 2 2013-10-08 21:04 ` Eric Botcazou @ 2013-10-08 23:03 ` Bernd Edlinger 2013-10-11 17:27 ` Eric Botcazou 2013-10-22 11:02 ` Bernd Edlinger 0 siblings, 2 replies; 105+ messages in thread From: Bernd Edlinger @ 2013-10-08 23:03 UTC (permalink / raw) To: Eric Botcazou; +Cc: gcc-patches, Martin Jambor, Richard Biener Hi, On Tue, 8 Oct 2013 22:50:21, Eric Botcazou wrote: > >> I agree, that assigning a non-BLKmode to structures with zero-sized arrays >> should be considered a bug. > > Fine, then let's apply Martin's patch, on mainline at least. > That would definitely be a good move. Maybe someone should approve it? > But this testcase is invalid on STRICT_ALIGNMENT platforms: xx is pointer to a > type with 4-byte alignment so its value must be a multiple of 4. Then you probably win. But I still have some doubts. I had to use this silly alignment/pack(4) to circumvent this statement in compute_record_mode: /* If structure's known alignment is less than what the scalar mode would need, and it matters, then stick with BLKmode. */ if (TYPE_MODE (type) != BLKmode && STRICT_ALIGNMENT && ! (TYPE_ALIGN (type)>= BIGGEST_ALIGNMENT || TYPE_ALIGN (type)>= GET_MODE_ALIGNMENT (TYPE_MODE (type)))) { /* If this is the only reason this type is BLKmode, then don't force containing types to be BLKmode. */ TYPE_NO_FORCE_BLK (type) = 1; SET_TYPE_MODE (type, BLKmode); } But there are at least two targets where STRICT_ALIGNMENT = 0 and SLOW_UNALIGNED_ACCESS != 0: rs6000 and alpha. This example with a byte-aligned structure will on one of these targets likely execute this code path in expand_expr_real_1/case MEM_REF: else if (SLOW_UNALIGNED_ACCESS (mode, align)) temp = extract_bit_field (temp, GET_MODE_BITSIZE (mode), 0, TYPE_UNSIGNED (TREE_TYPE (exp)), (modifier == EXPAND_STACK_PARM ? NULL_RTX : target), mode, mode); This looks wrong, but unfortunately I cannot test on these targets... Regards Bernd. ^ permalink raw reply [flat|nested] 105+ messages in thread
* Re: [PATCH, PR 57748] Check for out of bounds access, Part 2 2013-10-08 23:03 ` Bernd Edlinger @ 2013-10-11 17:27 ` Eric Botcazou 2013-10-13 8:22 ` Bernd Edlinger 2013-10-22 11:02 ` Bernd Edlinger 1 sibling, 1 reply; 105+ messages in thread From: Eric Botcazou @ 2013-10-11 17:27 UTC (permalink / raw) To: Bernd Edlinger; +Cc: gcc-patches, Martin Jambor, Richard Biener > That would definitely be a good move. Maybe someone should approve it? Yes, but I agree that we ought to restrict it to trailing zero-sized arrays. That would help to allay Jakub's concerns about possible ABI fallouts. -- Eric Botcazou ^ permalink raw reply [flat|nested] 105+ messages in thread
* RE: [PATCH, PR 57748] Check for out of bounds access, Part 2 2013-10-11 17:27 ` Eric Botcazou @ 2013-10-13 8:22 ` Bernd Edlinger 2013-10-13 12:29 ` Eric Botcazou 0 siblings, 1 reply; 105+ messages in thread From: Bernd Edlinger @ 2013-10-13 8:22 UTC (permalink / raw) To: Eric Botcazou; +Cc: gcc-patches, Martin Jambor, Richard Biener Hi, >> That would definitely be a good move. Maybe someone should approve it? > > Yes, but I agree that we ought to restrict it to trailing zero-sized arrays. > That would help to allay Jakub's concerns about possible ABI fallouts. > > -- > Eric Botcazou Other uses of zero-sized arrays in structures and unions are at least questionable, and should be rejected. While this construct produces an error: struct s { int a[]; float b; }; error: flexible array member not at end of struct This does not even produce a waning: struct s { int a[0]; float b; }; Would you agree that this "error: flexible array member" should also be emitted for a zero-sized array member, maybe as "error: zero-sized array member not at end of struct"? Regards Bernd. ^ permalink raw reply [flat|nested] 105+ messages in thread
* Re: [PATCH, PR 57748] Check for out of bounds access, Part 2 2013-10-13 8:22 ` Bernd Edlinger @ 2013-10-13 12:29 ` Eric Botcazou 2013-10-13 12:30 ` Bernd Edlinger 0 siblings, 1 reply; 105+ messages in thread From: Eric Botcazou @ 2013-10-13 12:29 UTC (permalink / raw) To: Bernd Edlinger; +Cc: gcc-patches, Martin Jambor, Richard Biener > Would you agree that this "error: flexible array member" > should also be emitted for a zero-sized array member, > maybe as "error: zero-sized array member not at end of struct"? I would have answered yes when zero-sized arrays where introduced, but it's far less clear a couple of decades later IMO. -- Eric Botcazou ^ permalink raw reply [flat|nested] 105+ messages in thread
* RE: [PATCH, PR 57748] Check for out of bounds access, Part 2 2013-10-13 12:29 ` Eric Botcazou @ 2013-10-13 12:30 ` Bernd Edlinger 2013-10-13 14:06 ` Eric Botcazou 0 siblings, 1 reply; 105+ messages in thread From: Bernd Edlinger @ 2013-10-13 12:30 UTC (permalink / raw) To: Eric Botcazou; +Cc: gcc-patches, Martin Jambor, Richard Biener [-- Attachment #1: Type: text/plain, Size: 620 bytes --] Hi Eric, >> Would you agree that this "error: flexible array member" >> should also be emitted for a zero-sized array member, >> maybe as "error: zero-sized array member not at end of struct"? > > I would have answered yes when zero-sized arrays where introduced, but it's > far less clear a couple of decades later IMO. But if zero-sized arrays everywhere in a structure is valid C, then the attached test case is a valid test case. And it will break your patch for PR58570 at -O1 and above, because you can no longer assume that different array members are not an alias. Regards Bernd. [-- Attachment #2: pr58570-1.c --] [-- Type: text/plain, Size: 268 bytes --] int printf (const char *, ...); struct S { char a[0]; short b[1]; }; int e = 1, i; static struct S d; int main () { if (e) { d.b[i]=!d.b[i]; //0->1 d.a[i]=!d.a[i]; //1->0 d.b[i]=!d.b[i]; //0->1 } printf ("%d\n", d.b[0]); return 0; } ^ permalink raw reply [flat|nested] 105+ messages in thread
* Re: [PATCH, PR 57748] Check for out of bounds access, Part 2 2013-10-13 12:30 ` Bernd Edlinger @ 2013-10-13 14:06 ` Eric Botcazou 0 siblings, 0 replies; 105+ messages in thread From: Eric Botcazou @ 2013-10-13 14:06 UTC (permalink / raw) To: Bernd Edlinger; +Cc: gcc-patches, Martin Jambor, Richard Biener > But if zero-sized arrays everywhere in a structure is valid C, > then the attached test case is a valid test case. Not necessarily, you can write the declaration but you cannot index the array, i.e. this is undefined behavior. And there is nothing new, distinct fields have been disambiguated in alias.c for ages. -- Eric Botcazou ^ permalink raw reply [flat|nested] 105+ messages in thread
* RE: [PATCH, PR 57748] Check for out of bounds access, Part 2 2013-10-08 23:03 ` Bernd Edlinger 2013-10-11 17:27 ` Eric Botcazou @ 2013-10-22 11:02 ` Bernd Edlinger 2013-10-23 16:14 ` Richard Biener 1 sibling, 1 reply; 105+ messages in thread From: Bernd Edlinger @ 2013-10-22 11:02 UTC (permalink / raw) To: Eric Botcazou; +Cc: gcc-patches, Martin Jambor, Richard Biener [-- Attachment #1: Type: text/plain, Size: 3080 bytes --] Hi, > On Tue, 8 Oct 2013 22:50:21, Eric Botcazou wrote: >> >>> I agree, that assigning a non-BLKmode to structures with zero-sized arrays >>> should be considered a bug. >> >> Fine, then let's apply Martin's patch, on mainline at least. >> > > That would definitely be a good move. Maybe someone should approve it? > >> But this testcase is invalid on STRICT_ALIGNMENT platforms: xx is pointer to a >> type with 4-byte alignment so its value must be a multiple of 4. > > Then you probably win. But I still have some doubts. > > I had to use this silly alignment/pack(4) to circumvent this statement > in compute_record_mode: > > /* If structure's known alignment is less than what the scalar > mode would need, and it matters, then stick with BLKmode. */ > if (TYPE_MODE (type) != BLKmode > && STRICT_ALIGNMENT > && ! (TYPE_ALIGN (type)>= BIGGEST_ALIGNMENT > || TYPE_ALIGN (type)>= GET_MODE_ALIGNMENT (TYPE_MODE (type)))) > { > /* If this is the only reason this type is BLKmode, then > don't force containing types to be BLKmode. */ > TYPE_NO_FORCE_BLK (type) = 1; > SET_TYPE_MODE (type, BLKmode); > } > > But there are at least two targets where STRICT_ALIGNMENT = 0 > and SLOW_UNALIGNED_ACCESS != 0: rs6000 and alpha. > > This example with a byte-aligned structure will on one of these targets > likely execute this code path in expand_expr_real_1/case MEM_REF: > > else if (SLOW_UNALIGNED_ACCESS (mode, align)) > temp = extract_bit_field (temp, GET_MODE_BITSIZE (mode), > 0, TYPE_UNSIGNED (TREE_TYPE (exp)), > (modifier == EXPAND_STACK_PARM > ? NULL_RTX : target), > mode, mode); > > This looks wrong, but unfortunately I cannot test on these targets... > Hmm, well, the condition that would be necessary to execute that code path would be STRICT_ALIGNMENT = 0 and SLOW_UNALIGNED_ACCESS != 0 for any integer mode. The only target that is close to hit this "bug" is rs6000: #define STRICT_ALIGNMENT 0 #define SLOW_UNALIGNED_ACCESS(MODE, ALIGN) \ (STRICT_ALIGNMENT \ || (((MODE) == SFmode || (MODE) == DFmode || (MODE) == TFmode \ || (MODE) == SDmode || (MODE) == DDmode || (MODE) == TDmode) \ && (ALIGN) < 32) \ || (VECTOR_MODE_P ((MODE)) && (((int)(ALIGN)) < VECTOR_ALIGN (MODE)))) but, luckily this is 0 for all integer modes. So I am now convinced, there won't be any valid example with unions that executes this code path. Therefore I updated Martin's previous patch, to meet Eric's request: That is to only handle zero-sized arrays at the end of the structure. Boot-strapped and regression-tested on x86_64-linux-gnu. Ok for trunk? Regards Bernd. [-- Attachment #2: changelog-pr57748-2.txt --] [-- Type: text/plain, Size: 351 bytes --] 2013-10-22 Martin Jambor <mjambor@suse.cz> Bernd Edlinger <bernd.edlinger@hotmail.de> PR middle-end/57748 * stor-layout.c (compute_record_mode): Treat trailing zero-sized array fields like incomplete types. testsuite: 2013-10-22 Bernd Edlinger <bernd.edlinger@hotmail.de> PR middle-end/57748 * gcc.dg/torture/pr57748-3.c: New test. [-- Attachment #3: patch-pr57748-2.diff --] [-- Type: application/octet-stream, Size: 1499 bytes --] --- gcc/stor-layout.c 2013-10-21 08:27:09.546035668 +0200 +++ gcc/stor-layout.c 2013-10-22 10:46:49.233261818 +0200 @@ -1600,7 +1600,10 @@ compute_record_mode (tree type) && integer_zerop (TYPE_SIZE (TREE_TYPE (field))))) || ! host_integerp (bit_position (field), 1) || DECL_SIZE (field) == 0 - || ! host_integerp (DECL_SIZE (field), 1)) + || ! host_integerp (DECL_SIZE (field), 1) + || (TREE_CODE (TREE_TYPE (field)) == ARRAY_TYPE + && tree_low_cst (DECL_SIZE (field), 1) == 0 + && simple_cst_equal (TYPE_SIZE (type), bit_position (field)))) return; /* If this field is the whole struct, remember its mode so --- gcc/testsuite/gcc.dg/torture/pr57748-3.c (revision 0) +++ gcc/testsuite/gcc.dg/torture/pr57748-3.c (revision 0) @@ -0,0 +1,40 @@ +/* PR middle-end/57748 */ +/* { dg-do run } */ +/* wrong code in expand_expr_real_1. */ + +#include <stdlib.h> + +extern void abort (void); + +typedef long long V + __attribute__ ((vector_size (2 * sizeof (long long)), may_alias)); + +typedef struct S { V a; V b[0]; } P __attribute__((aligned (1))); + +struct __attribute__((packed)) T { char c; P s; }; + +void __attribute__((noinline, noclone)) +check (P *p) +{ + if (p->b[0][0] != 3 || p->b[0][1] != 4) + abort (); +} + +void __attribute__((noinline, noclone)) +foo (struct T *t) +{ + V a = { 3, 4 }; + t->s.b[0] = a; +} + +int +main () +{ + struct T *t = (struct T *) calloc (128, 1); + + foo (t); + check (&t->s); + + free (t); + return 0; +} ^ permalink raw reply [flat|nested] 105+ messages in thread
* Re: [PATCH, PR 57748] Check for out of bounds access, Part 2 2013-10-22 11:02 ` Bernd Edlinger @ 2013-10-23 16:14 ` Richard Biener 2013-10-23 17:25 ` Martin Jambor 2013-10-23 17:45 ` Eric Botcazou 0 siblings, 2 replies; 105+ messages in thread From: Richard Biener @ 2013-10-23 16:14 UTC (permalink / raw) To: Bernd Edlinger; +Cc: Eric Botcazou, gcc-patches, Martin Jambor On Tue, Oct 22, 2013 at 12:25 PM, Bernd Edlinger <bernd.edlinger@hotmail.de> wrote: > Hi, > >> On Tue, 8 Oct 2013 22:50:21, Eric Botcazou wrote: >>> >>>> I agree, that assigning a non-BLKmode to structures with zero-sized arrays >>>> should be considered a bug. >>> >>> Fine, then let's apply Martin's patch, on mainline at least. >>> >> >> That would definitely be a good move. Maybe someone should approve it? >> >>> But this testcase is invalid on STRICT_ALIGNMENT platforms: xx is pointer to a >>> type with 4-byte alignment so its value must be a multiple of 4. >> >> Then you probably win. But I still have some doubts. >> >> I had to use this silly alignment/pack(4) to circumvent this statement >> in compute_record_mode: >> >> /* If structure's known alignment is less than what the scalar >> mode would need, and it matters, then stick with BLKmode. */ >> if (TYPE_MODE (type) != BLKmode >> && STRICT_ALIGNMENT >> && ! (TYPE_ALIGN (type)>= BIGGEST_ALIGNMENT >> || TYPE_ALIGN (type)>= GET_MODE_ALIGNMENT (TYPE_MODE (type)))) >> { >> /* If this is the only reason this type is BLKmode, then >> don't force containing types to be BLKmode. */ >> TYPE_NO_FORCE_BLK (type) = 1; >> SET_TYPE_MODE (type, BLKmode); >> } >> >> But there are at least two targets where STRICT_ALIGNMENT = 0 >> and SLOW_UNALIGNED_ACCESS != 0: rs6000 and alpha. >> >> This example with a byte-aligned structure will on one of these targets >> likely execute this code path in expand_expr_real_1/case MEM_REF: >> >> else if (SLOW_UNALIGNED_ACCESS (mode, align)) >> temp = extract_bit_field (temp, GET_MODE_BITSIZE (mode), >> 0, TYPE_UNSIGNED (TREE_TYPE (exp)), >> (modifier == EXPAND_STACK_PARM >> ? NULL_RTX : target), >> mode, mode); >> >> This looks wrong, but unfortunately I cannot test on these targets... >> > > Hmm, well, > > the condition that would be necessary to execute that code path > would be > > STRICT_ALIGNMENT = 0 > and SLOW_UNALIGNED_ACCESS != 0 for any integer mode. > > The only target that is close to hit this "bug" is rs6000: > > #define STRICT_ALIGNMENT 0 > > #define SLOW_UNALIGNED_ACCESS(MODE, ALIGN) \ > (STRICT_ALIGNMENT \ > || (((MODE) == SFmode || (MODE) == DFmode || (MODE) == TFmode \ > || (MODE) == SDmode || (MODE) == DDmode || (MODE) == TDmode) \ > && (ALIGN) < 32) \ > || (VECTOR_MODE_P ((MODE)) && (((int)(ALIGN)) < VECTOR_ALIGN (MODE)))) > > but, luckily this is 0 for all integer modes. > > So I am now convinced, there won't be any valid example with unions that > executes this code path. > > Therefore I updated Martin's previous patch, to meet Eric's request: > That is to only handle zero-sized arrays at the end of the structure. That looks backwards. Why should struct { V i; V j[0]; } have a different mode than struct { V j[0]; V i; } ? And why should the same issue not exist for struct { V a[1]; } which is also "flexible enough" that we support accesses beyond it via a pointer? That struct also has V2DImode. And this is all because /* If this field is the whole struct, remember its mode so that, say, we can put a double in a class into a DF register instead of forcing it to live in the stack. */ if (simple_cst_equal (TYPE_SIZE (type), DECL_SIZE (field))) mode = DECL_MODE (field); which is IMHO ok. > Boot-strapped and regression-tested on x86_64-linux-gnu. > > Ok for trunk? Well, I'm not so sure. And if so then I'd prefer martins original patch, rejecting all zero-sized fields. But then only if you consider it a "real" field. Of course I blame those that added the zero-sized array extension for all this mess ... maybe we can reduce it by rejecting zero-sized arrays that are not at the end of a structure - which means we can demote them to flexible arrays with a NULL TYPE_SIZE which would completely side-step this issue in stor-layout.c. Richard. > Regards > Bernd. ^ permalink raw reply [flat|nested] 105+ messages in thread
* Re: [PATCH, PR 57748] Check for out of bounds access, Part 2 2013-10-23 16:14 ` Richard Biener @ 2013-10-23 17:25 ` Martin Jambor 2013-10-23 18:05 ` Eric Botcazou 2013-10-24 8:20 ` Bernd Edlinger 2013-10-23 17:45 ` Eric Botcazou 1 sibling, 2 replies; 105+ messages in thread From: Martin Jambor @ 2013-10-23 17:25 UTC (permalink / raw) To: Richard Biener; +Cc: Bernd Edlinger, Eric Botcazou, gcc-patches Hi, On Wed, Oct 23, 2013 at 06:00:43PM +0200, Richard Biener wrote: > ... > ? And why should the same issue not exist for > > struct { V a[1]; } > indeed, it does and it's simple to trigger (on x86_64): ---------------------------------------- /* { dg-do run } */ #include <stdlib.h> typedef long long V __attribute__ ((vector_size (2 * sizeof (long long)), may_alias)); #if 1 typedef struct S {V b[1]; } P __attribute__((aligned (1))); struct __attribute__((packed)) T { char c; P s; }; #else typedef struct S {V b[1]; } P; struct T { char c; P s; }; #endif void __attribute__((noinline, noclone)) good_value (V b) { if (b[0] != 3 || b[1] != 4) __builtin_abort (); } void __attribute__((noinline, noclone)) check (P *p) { good_value (p->b[1]); } int main () { struct T *t = (struct T *) calloc (128, 1); V a = { 3, 4 }; t->s.b[1] = a; check (&t->s); free (t); return 0; } ---------------------------------------- While I was willing to discount the zero sized array as an insufficiently specified oddity, this seems to be much more serious and potentially common. It seems we really need to be able to detect these out-of-bounds situations and tell lower levels of expander that "whatever mode you think you are expanding, it is actually BLK mode." It's uglier than I thought. Martin > which is also "flexible enough" that we support accesses beyond it > via a pointer? That struct also has V2DImode. And this is all > because > > /* If this field is the whole struct, remember its mode so > that, say, we can put a double in a class into a DF > register instead of forcing it to live in the stack. */ > if (simple_cst_equal (TYPE_SIZE (type), DECL_SIZE (field))) > mode = DECL_MODE (field); > > which is IMHO ok. > > > Boot-strapped and regression-tested on x86_64-linux-gnu. > > > > Ok for trunk? > > Well, I'm not so sure. And if so then I'd prefer martins original > patch, rejecting all zero-sized fields. But then only if you > consider it a "real" field. > > Of course I blame those that added the zero-sized array extension > for all this mess ... maybe we can reduce it by rejecting > zero-sized arrays that are not at the end of a structure - which means > we can demote them to flexible arrays with a NULL TYPE_SIZE > which would completely side-step this issue in stor-layout.c. > > Richard. > > > Regards > > Bernd. ^ permalink raw reply [flat|nested] 105+ messages in thread
* Re: [PATCH, PR 57748] Check for out of bounds access, Part 2 2013-10-23 17:25 ` Martin Jambor @ 2013-10-23 18:05 ` Eric Botcazou 2013-10-24 8:20 ` Bernd Edlinger 1 sibling, 0 replies; 105+ messages in thread From: Eric Botcazou @ 2013-10-23 18:05 UTC (permalink / raw) To: Martin Jambor; +Cc: gcc-patches, Richard Biener, Bernd Edlinger > While I was willing to discount the zero sized array as an > insufficiently specified oddity, this seems to be much more serious > and potentially common. It seems we really need to be able to detect > these out-of-bounds situations and tell lower levels of expander that > "whatever mode you think you are expanding, it is actually BLK mode." Please let's not enter this hazardous business. We just need to draw a line somewhere and clearly state what we support in terms of out-of-bounds access. -- Eric Botcazou ^ permalink raw reply [flat|nested] 105+ messages in thread
* RE: [PATCH, PR 57748] Check for out of bounds access, Part 2 2013-10-23 17:25 ` Martin Jambor 2013-10-23 18:05 ` Eric Botcazou @ 2013-10-24 8:20 ` Bernd Edlinger 2013-10-24 9:16 ` Eric Botcazou 2013-10-24 11:14 ` Richard Biener 1 sibling, 2 replies; 105+ messages in thread From: Bernd Edlinger @ 2013-10-24 8:20 UTC (permalink / raw) To: Martin Jambor, Richard Biener; +Cc: Eric Botcazou, gcc-patches Hi Martin, On Wed, 23 Oct 2013 19:11:06, Martin Jambor wrote: > On Wed, Oct 23, 2013 at 06:00:43PM +0200, Richard Biener wrote: >> > > ... > >> ? And why should the same issue not exist for >> >> struct { V a[1]; } >> > > indeed, it does and it's simple to trigger (on x86_64): > > ---------------------------------------- > /* { dg-do run } */ > > #include <stdlib.h> > > typedef long long V > __attribute__ ((vector_size (2 * sizeof (long long)), may_alias)); > > #if 1 > typedef struct S {V b[1]; } P __attribute__((aligned (1))); > struct __attribute__((packed)) T { char c; P s; }; > #else > typedef struct S {V b[1]; } P; > struct T { char c; P s; }; > #endif > > void __attribute__((noinline, noclone)) > good_value (V b) > { > if (b[0] != 3 || b[1] != 4) > __builtin_abort (); > } > > void __attribute__((noinline, noclone)) > check (P *p) > { > good_value (p->b[1]); > } > > int > main () > { > struct T *t = (struct T *) calloc (128, 1); > V a = { 3, 4 }; > t->s.b[1] = a; > check (&t->s); > free (t); > return 0; > } > ---------------------------------------- > > While I was willing to discount the zero sized array as an > insufficiently specified oddity, this seems to be much more serious > and potentially common. It seems we really need to be able to detect > these out-of-bounds situations and tell lower levels of expander that > "whatever mode you think you are expanding, it is actually BLK mode." > > It's uglier than I thought. > > Martin > Deja-vu... Thanks for this test case. This definitely destroys the idea to fix this in stor-layout.c I think that is common practice to write array[1]; at the end of the structure, and use it as a flexible array. The compute_record_mode has no way to decide if that is going to be a flexible array or not. Sorry Eric, but now I have no other choice than to go back to my previous version of part 2: http://gcc.gnu.org/ml/gcc-patches/2013-10/msg00222.html I'd just add Martin's new test case as 57748-4.c. Bernd. ^ permalink raw reply [flat|nested] 105+ messages in thread
* Re: [PATCH, PR 57748] Check for out of bounds access, Part 2 2013-10-24 8:20 ` Bernd Edlinger @ 2013-10-24 9:16 ` Eric Botcazou 2013-10-24 10:00 ` Bernd Edlinger 2013-10-24 10:50 ` Richard Biener 2013-10-24 11:14 ` Richard Biener 1 sibling, 2 replies; 105+ messages in thread From: Eric Botcazou @ 2013-10-24 9:16 UTC (permalink / raw) To: Bernd Edlinger; +Cc: gcc-patches, Martin Jambor, Richard Biener > I think that is common practice to write array[1]; at the end of the > structure, and use it as a flexible array. The compute_record_mode has no > way to decide if that is going to be a flexible array or not. > > Sorry Eric, but now I have no other choice than to go back to my previous > version of part 2: > > http://gcc.gnu.org/ml/gcc-patches/2013-10/msg00222.html Why? Just set BLKmode in this case as well. -- Eric Botcazou ^ permalink raw reply [flat|nested] 105+ messages in thread
* RE: [PATCH, PR 57748] Check for out of bounds access, Part 2 2013-10-24 9:16 ` Eric Botcazou @ 2013-10-24 10:00 ` Bernd Edlinger 2013-10-24 10:16 ` Eric Botcazou 2013-10-24 10:50 ` Richard Biener 1 sibling, 1 reply; 105+ messages in thread From: Bernd Edlinger @ 2013-10-24 10:00 UTC (permalink / raw) To: Eric Botcazou; +Cc: gcc-patches, Martin Jambor, Richard Biener >> I think that is common practice to write array[1]; at the end of the >> structure, and use it as a flexible array. The compute_record_mode has no >> way to decide if that is going to be a flexible array or not. >> >> Sorry Eric, but now I have no other choice than to go back to my previous >> version of part 2: >> >> http://gcc.gnu.org/ml/gcc-patches/2013-10/msg00222.html > > Why? Just set BLKmode in this case as well. Because of the ABI-change? > > -- > Eric Botcazou ^ permalink raw reply [flat|nested] 105+ messages in thread
* Re: [PATCH, PR 57748] Check for out of bounds access, Part 2 2013-10-24 10:00 ` Bernd Edlinger @ 2013-10-24 10:16 ` Eric Botcazou 0 siblings, 0 replies; 105+ messages in thread From: Eric Botcazou @ 2013-10-24 10:16 UTC (permalink / raw) To: Bernd Edlinger; +Cc: gcc-patches, Martin Jambor, Richard Biener > Because of the ABI-change? While concerns about accidental ABI changes are real, they shouldn't be overstated either. We have been saying for longer than a decade that the back-ends must not use the type mode to implement calling conventions and other external interfaces. -- Eric Botcazou ^ permalink raw reply [flat|nested] 105+ messages in thread
* Re: [PATCH, PR 57748] Check for out of bounds access, Part 2 2013-10-24 9:16 ` Eric Botcazou 2013-10-24 10:00 ` Bernd Edlinger @ 2013-10-24 10:50 ` Richard Biener 2013-10-24 13:09 ` Bernd Edlinger 1 sibling, 1 reply; 105+ messages in thread From: Richard Biener @ 2013-10-24 10:50 UTC (permalink / raw) To: Eric Botcazou; +Cc: Bernd Edlinger, GCC Patches, Martin Jambor On Thu, Oct 24, 2013 at 10:48 AM, Eric Botcazou <ebotcazou@adacore.com> wrote: >> I think that is common practice to write array[1]; at the end of the >> structure, and use it as a flexible array. The compute_record_mode has no >> way to decide if that is going to be a flexible array or not. >> >> Sorry Eric, but now I have no other choice than to go back to my previous >> version of part 2: >> >> http://gcc.gnu.org/ml/gcc-patches/2013-10/msg00222.html > > Why? Just set BLKmode in this case as well. Works for me if it works ABI-wise (which you say it should unless the backend is buggy). Note that means mode_for_array should unconditionally return BLKmode. Richard. > -- > Eric Botcazou ^ permalink raw reply [flat|nested] 105+ messages in thread
* RE: [PATCH, PR 57748] Check for out of bounds access, Part 2 2013-10-24 10:50 ` Richard Biener @ 2013-10-24 13:09 ` Bernd Edlinger 2013-10-24 13:16 ` Richard Biener 2013-10-24 13:20 ` Jakub Jelinek 0 siblings, 2 replies; 105+ messages in thread From: Bernd Edlinger @ 2013-10-24 13:09 UTC (permalink / raw) To: Richard Biener, Eric Botcazou; +Cc: GCC Patches, Martin Jambor On Thu, 24 Oct 2013 12:18:43, Richard Biener wrote: > > On Thu, Oct 24, 2013 at 10:48 AM, Eric Botcazou <ebotcazou@adacore.com> wrote: >>> I think that is common practice to write array[1]; at the end of the >>> structure, and use it as a flexible array. The compute_record_mode has no >>> way to decide if that is going to be a flexible array or not. >>> >>> Sorry Eric, but now I have no other choice than to go back to my previous >>> version of part 2: >>> >>> http://gcc.gnu.org/ml/gcc-patches/2013-10/msg00222.html >> >> Why? Just set BLKmode in this case as well. > > Works for me if it works ABI-wise (which you say it should unless the > backend is buggy). Note that means mode_for_array should unconditionally > return BLKmode. Did you just propose: --- stor-layout.c.orig 2013-10-22 10:46:49.233261818 +0200 +++ stor-layout.c 2013-10-24 14:54:00.425259062 +0200 @@ -471,27 +471,7 @@ static enum machine_mode mode_for_array (tree elem_type, tree size) { - tree elem_size; - unsigned HOST_WIDE_INT int_size, int_elem_size; - bool limit_p; - - /* One-element arrays get the component type's mode. */ - elem_size = TYPE_SIZE (elem_type); - if (simple_cst_equal (size, elem_size)) - return TYPE_MODE (elem_type); - - limit_p = true; - if (host_integerp (size, 1) && host_integerp (elem_size, 1)) - { - int_size = tree_low_cst (size, 1); - int_elem_size = tree_low_cst (elem_size, 1); - if (int_elem_size> 0 - && int_size % int_elem_size == 0 - && targetm.array_mode_supported_p (TYPE_MODE (elem_type), - int_size / int_elem_size)) - limit_p = false; - } - return mode_for_size_tree (size, MODE_INT, limit_p); + return BLKmode; } ??? > Richard. > >> -- >> Eric Botcazou ^ permalink raw reply [flat|nested] 105+ messages in thread
* Re: [PATCH, PR 57748] Check for out of bounds access, Part 2 2013-10-24 13:09 ` Bernd Edlinger @ 2013-10-24 13:16 ` Richard Biener 2013-10-24 13:38 ` Bernd Edlinger 2013-10-25 7:05 ` Bernd Edlinger 2013-10-24 13:20 ` Jakub Jelinek 1 sibling, 2 replies; 105+ messages in thread From: Richard Biener @ 2013-10-24 13:16 UTC (permalink / raw) To: Bernd Edlinger; +Cc: Eric Botcazou, GCC Patches, Martin Jambor On Thu, Oct 24, 2013 at 2:55 PM, Bernd Edlinger <bernd.edlinger@hotmail.de> wrote: > On Thu, 24 Oct 2013 12:18:43, Richard Biener wrote: >> >> On Thu, Oct 24, 2013 at 10:48 AM, Eric Botcazou <ebotcazou@adacore.com> wrote: >>>> I think that is common practice to write array[1]; at the end of the >>>> structure, and use it as a flexible array. The compute_record_mode has no >>>> way to decide if that is going to be a flexible array or not. >>>> >>>> Sorry Eric, but now I have no other choice than to go back to my previous >>>> version of part 2: >>>> >>>> http://gcc.gnu.org/ml/gcc-patches/2013-10/msg00222.html >>> >>> Why? Just set BLKmode in this case as well. >> >> Works for me if it works ABI-wise (which you say it should unless the >> backend is buggy). Note that means mode_for_array should unconditionally >> return BLKmode. > > Did you just propose: > > --- stor-layout.c.orig 2013-10-22 10:46:49.233261818 +0200 > +++ stor-layout.c 2013-10-24 14:54:00.425259062 +0200 > @@ -471,27 +471,7 @@ > static enum machine_mode > mode_for_array (tree elem_type, tree size) > { > - tree elem_size; > - unsigned HOST_WIDE_INT int_size, int_elem_size; > - bool limit_p; > - > - /* One-element arrays get the component type's mode. */ > - elem_size = TYPE_SIZE (elem_type); > - if (simple_cst_equal (size, elem_size)) > - return TYPE_MODE (elem_type); > - > - limit_p = true; > - if (host_integerp (size, 1) && host_integerp (elem_size, 1)) > - { > - int_size = tree_low_cst (size, 1); > - int_elem_size = tree_low_cst (elem_size, 1); > - if (int_elem_size> 0 > - && int_size % int_elem_size == 0 > - && targetm.array_mode_supported_p (TYPE_MODE (elem_type), > - int_size / int_elem_size)) > - limit_p = false; > - } > - return mode_for_size_tree (size, MODE_INT, limit_p); > + return BLKmode; > } > > ??? Yes. Does it work? Richard. > >> Richard. >> >>> -- >>> Eric Botcazou ^ permalink raw reply [flat|nested] 105+ messages in thread
* RE: [PATCH, PR 57748] Check for out of bounds access, Part 2 2013-10-24 13:16 ` Richard Biener @ 2013-10-24 13:38 ` Bernd Edlinger 2013-10-25 7:05 ` Bernd Edlinger 1 sibling, 0 replies; 105+ messages in thread From: Bernd Edlinger @ 2013-10-24 13:38 UTC (permalink / raw) To: Richard Biener; +Cc: Eric Botcazou, GCC Patches, Martin Jambor, Jakub Jelinek >> Did you just propose: >> >> --- stor-layout.c.orig 2013-10-22 10:46:49.233261818 +0200 >> +++ stor-layout.c 2013-10-24 14:54:00.425259062 +0200 >> @@ -471,27 +471,7 @@ >> static enum machine_mode >> mode_for_array (tree elem_type, tree size) >> { >> - tree elem_size; >> - unsigned HOST_WIDE_INT int_size, int_elem_size; >> - bool limit_p; >> - >> - /* One-element arrays get the component type's mode. */ >> - elem_size = TYPE_SIZE (elem_type); >> - if (simple_cst_equal (size, elem_size)) >> - return TYPE_MODE (elem_type); >> - >> - limit_p = true; >> - if (host_integerp (size, 1) && host_integerp (elem_size, 1)) >> - { >> - int_size = tree_low_cst (size, 1); >> - int_elem_size = tree_low_cst (elem_size, 1); >> - if (int_elem_size> 0 >> - && int_size % int_elem_size == 0 >> - && targetm.array_mode_supported_p (TYPE_MODE (elem_type), >> - int_size / int_elem_size)) >> - limit_p = false; >> - } >> - return mode_for_size_tree (size, MODE_INT, limit_p); >> + return BLKmode; >> } >> >> ??? > > Yes. Does it work? > > Richard. > I will give it a try. I could also explicitly catch the case "struct { a[x]; };" in compute_record_mode. That might work too. But one way or the other that fix will be ugly. Note: struct Y { char c[1]; char c2; }; is "invalid" even if the expander would not fail, because the code in tree-ssa-alias.c will not see the alias, between c[2] and c2, that works only for the last array. So that is no ICE but all generated code at -O1 and higher will be wrong. Bernd. ^ permalink raw reply [flat|nested] 105+ messages in thread
* RE: [PATCH, PR 57748] Check for out of bounds access, Part 2 2013-10-24 13:16 ` Richard Biener 2013-10-24 13:38 ` Bernd Edlinger @ 2013-10-25 7:05 ` Bernd Edlinger 2013-10-25 9:29 ` Richard Biener 1 sibling, 1 reply; 105+ messages in thread From: Bernd Edlinger @ 2013-10-25 7:05 UTC (permalink / raw) To: Richard Biener; +Cc: Eric Botcazou, GCC Patches, Martin Jambor, Jakub Jelinek Hi Richard, >> Did you just propose: >> >> --- stor-layout.c.orig 2013-10-22 10:46:49.233261818 +0200 >> +++ stor-layout.c 2013-10-24 14:54:00.425259062 +0200 >> @@ -471,27 +471,7 @@ >> static enum machine_mode >> mode_for_array (tree elem_type, tree size) >> { >> - tree elem_size; >> - unsigned HOST_WIDE_INT int_size, int_elem_size; >> - bool limit_p; >> - >> - /* One-element arrays get the component type's mode. */ >> - elem_size = TYPE_SIZE (elem_type); >> - if (simple_cst_equal (size, elem_size)) >> - return TYPE_MODE (elem_type); >> - >> - limit_p = true; >> - if (host_integerp (size, 1) && host_integerp (elem_size, 1)) >> - { >> - int_size = tree_low_cst (size, 1); >> - int_elem_size = tree_low_cst (elem_size, 1); >> - if (int_elem_size> 0 >> - && int_size % int_elem_size == 0 >> - && targetm.array_mode_supported_p (TYPE_MODE (elem_type), >> - int_size / int_elem_size)) >> - limit_p = false; >> - } >> - return mode_for_size_tree (size, MODE_INT, limit_p); >> + return BLKmode; >> } >> >> ??? > > Yes. Does it work? > > Richard. > No. PASS: gcc.target/i386/pr14289-1.c (test for errors, line 10) FAIL: gcc.target/i386/pr14289-1.c (test for excess errors) Excess errors: /home/ed/gnu/gcc-4.9-20131013/gcc/testsuite/gcc.target/i386/pr14289-1.c:5:14: error: data type of 'a' isn't suitable for a register Does that look like an ABI-Change? the test case uses: register int a[2] asm("ebx"); Bernd. ^ permalink raw reply [flat|nested] 105+ messages in thread
* Re: [PATCH, PR 57748] Check for out of bounds access, Part 2 2013-10-25 7:05 ` Bernd Edlinger @ 2013-10-25 9:29 ` Richard Biener 2013-10-25 10:40 ` Bernd Edlinger 0 siblings, 1 reply; 105+ messages in thread From: Richard Biener @ 2013-10-25 9:29 UTC (permalink / raw) To: Bernd Edlinger; +Cc: Eric Botcazou, GCC Patches, Martin Jambor, Jakub Jelinek On Fri, Oct 25, 2013 at 8:29 AM, Bernd Edlinger <bernd.edlinger@hotmail.de> wrote: > Hi Richard, > > >>> Did you just propose: >>> >>> --- stor-layout.c.orig 2013-10-22 10:46:49.233261818 +0200 >>> +++ stor-layout.c 2013-10-24 14:54:00.425259062 +0200 >>> @@ -471,27 +471,7 @@ >>> static enum machine_mode >>> mode_for_array (tree elem_type, tree size) >>> { >>> - tree elem_size; >>> - unsigned HOST_WIDE_INT int_size, int_elem_size; >>> - bool limit_p; >>> - >>> - /* One-element arrays get the component type's mode. */ >>> - elem_size = TYPE_SIZE (elem_type); >>> - if (simple_cst_equal (size, elem_size)) >>> - return TYPE_MODE (elem_type); >>> - >>> - limit_p = true; >>> - if (host_integerp (size, 1) && host_integerp (elem_size, 1)) >>> - { >>> - int_size = tree_low_cst (size, 1); >>> - int_elem_size = tree_low_cst (elem_size, 1); >>> - if (int_elem_size> 0 >>> - && int_size % int_elem_size == 0 >>> - && targetm.array_mode_supported_p (TYPE_MODE (elem_type), >>> - int_size / int_elem_size)) >>> - limit_p = false; >>> - } >>> - return mode_for_size_tree (size, MODE_INT, limit_p); >>> + return BLKmode; >>> } >>> >>> ??? >> >> Yes. Does it work? >> >> Richard. >> > > No. > > PASS: gcc.target/i386/pr14289-1.c (test for errors, line 10) > FAIL: gcc.target/i386/pr14289-1.c (test for excess errors) > Excess errors: > /home/ed/gnu/gcc-4.9-20131013/gcc/testsuite/gcc.target/i386/pr14289-1.c:5:14: error: data type of 'a' isn't suitable for a register > > Does that look like an ABI-Change? > > the test case uses: > register int a[2] asm("ebx"); Eh ... even register struct { int i; int a[0]; } asm ("ebx"); works. Also with int a[1] but not with a[2]. So just handling trailing arrays makes this case regress as well. Now I'd call this use questionable ... but we've likely supported that for decades and cannot change that now. Back to fixing everything in expand. Richard. > Bernd. ^ permalink raw reply [flat|nested] 105+ messages in thread
* RE: [PATCH, PR 57748] Check for out of bounds access, Part 2 2013-10-25 9:29 ` Richard Biener @ 2013-10-25 10:40 ` Bernd Edlinger 2013-10-25 11:10 ` Richard Biener 0 siblings, 1 reply; 105+ messages in thread From: Bernd Edlinger @ 2013-10-25 10:40 UTC (permalink / raw) To: Richard Biener; +Cc: Eric Botcazou, GCC Patches, Martin Jambor, Jakub Jelinek [-- Attachment #1: Type: text/plain, Size: 2479 bytes --] Hi, > Eh ... even > > register struct { int i; int a[0]; } asm ("ebx"); > > works. Also with int a[1] but not with a[2]. So just handling trailing > arrays makes this case regress as well. > > Now I'd call this use questionable ... but we've likely supported that > for decades and cannot change that now. > > Back to fixing everything in expand. > > Richard. > Ok, finally you asked for it. Here is my previous version of that patch again. I have now added a new value "EXPAND_REFERENCE" to the expand_modifier enumeration. It is almost like EXPAND_MEMORY but it does not interfere with constant values. I have done the same modification to VIEW_CONVERT_EXPR too, because this is a possible inner reference, itself. It is however inherently hard to test around this code. To understand this patch it is good to know what type of object the return value "tem" of get_inner_reference can be. From the program logic at get_inner_reference it is clear that the return value may *not* be BIT_FIELD_REF, COMPONENT_REF, ARRAY_REF, ARRAY_RANGE_REF, REALPART_EXPR, IMAGPART_EXPR. The result may be VIEW_CONVERT_EXPR only on a STRICT_ALIGNMENT target. This is probably further restricted because exp is gimplified. Usually the result will be a MEM_REF or a SSA_NAME of the memory where the structure is to be found. When you look at where EXPAND_MEMORY is handled you see it is special-cased in TARGET_MEM_REF, MEM_REF, ARRAY_REF, COMPONENT_REF, BIT_FIELD_REF, ARRAY_RANGE_REF. At TARGET_MEM_REF, MEM_REF, VIEW_CONVERT_EXPR, it should be the same if EXPAND_MEMORY, EXPAND_WRITE or EXPAND_REFERENCE is given: If it is an unaligned memory, we just return the unaligned reference. This was missing for VIEW_CONVERT_EXPR, and unfortunately I have no test case, because it is only a problem for STRICT_ALIGNMENT targets, and even there it will certainly be really hard to find test cases that exercise this code. In ARRAY_REF, COMPONENT_REF, BIT_FIELD_REF, ARRAY_RANGE_REF we do not have to touch the handling of the outer modifier. However we pass EXPAND_REFERENCE to the inner object, which should not be a recursive use of any ARRAY_REF, COMPONENT_REF, BIT_FIELD_REF, ARRAY_RANGE_REF. TARGET_MEM_REF, MEM_REF and VIEW_CONVERT_EXPR know how to handle EXPAND_REFERENCE, anything else handles it like EXPAND_NORMAL. Boot-strapped and regression-tested on x86_64-linux-gnu OK for trunk? Thanks Bernd. [-- Attachment #2: changelog-pr57748-2.txt --] [-- Type: text/plain, Size: 381 bytes --] 2013-10-25 Bernd Edlinger <bernd.edlinger@hotmail.de> PR middle-end/57748 * expr.h (expand_modifier): New enum value EXPAND_REFERENCE. * expr.c (expand_expr_real_1): Use EXAND_REFERENCE on base object. testsuite: 2013-10-25 Bernd Edlinger <bernd.edlinger@hotmail.de> PR middle-end/57748 * gcc.dg/torture/pr57748-3.c: New test. * gcc.dg/torture/pr57748-4.c: New test. [-- Attachment #3: patch-pr57748-2.diff --] [-- Type: application/octet-stream, Size: 5240 bytes --] Index: gcc/expr.c =================================================================== --- gcc/expr.c (revision 203044) +++ gcc/expr.c (working copy) @@ -9573,6 +9573,7 @@ expand_expr_real_1 (tree exp, rtx target, enum mac align = get_object_alignment (exp); if (modifier != EXPAND_WRITE && modifier != EXPAND_MEMORY + && modifier != EXPAND_REFERENCE && mode != BLKmode && align < GET_MODE_ALIGNMENT (mode) /* If the target does not have special handling for unaligned @@ -9653,6 +9654,7 @@ expand_expr_real_1 (tree exp, rtx target, enum mac MEM_VOLATILE_P (temp) = 1; if (modifier != EXPAND_WRITE && modifier != EXPAND_MEMORY + && modifier != EXPAND_REFERENCE && mode != BLKmode && align < GET_MODE_ALIGNMENT (mode)) { @@ -9886,7 +9888,7 @@ expand_expr_real_1 (tree exp, rtx target, enum mac && modifier != EXPAND_STACK_PARM ? target : NULL_RTX), VOIDmode, - modifier == EXPAND_SUM ? EXPAND_NORMAL : modifier); + EXPAND_REFERENCE); /* If the bitfield is volatile, we want to access it in the field's mode, not the computed mode. @@ -10245,7 +10247,7 @@ expand_expr_real_1 (tree exp, rtx target, enum mac && modifier != EXPAND_STACK_PARM ? target : NULL_RTX), VOIDmode, - modifier == EXPAND_SUM ? EXPAND_NORMAL : modifier); + EXPAND_REFERENCE); if (MEM_P (orig_op0)) { @@ -10339,7 +10341,10 @@ expand_expr_real_1 (tree exp, rtx target, enum mac op0 = copy_rtx (op0); set_mem_align (op0, MAX (MEM_ALIGN (op0), TYPE_ALIGN (type))); } - else if (mode != BLKmode + else if (modifier != EXPAND_WRITE + && modifier != EXPAND_MEMORY + && modifier != EXPAND_REFERENCE + && mode != BLKmode && MEM_ALIGN (op0) < GET_MODE_ALIGNMENT (mode) /* If the target does have special handling for unaligned loads of mode then use them. */ @@ -10360,6 +10365,9 @@ expand_expr_real_1 (tree exp, rtx target, enum mac return reg; } else if (STRICT_ALIGNMENT + && modifier != EXPAND_WRITE + && modifier != EXPAND_MEMORY + && modifier != EXPAND_REFERENCE && mode != BLKmode && MEM_ALIGN (op0) < GET_MODE_ALIGNMENT (mode)) { Index: gcc/expr.h =================================================================== --- gcc/expr.h (revision 203044) +++ gcc/expr.h (working copy) @@ -41,10 +41,13 @@ along with GCC; see the file COPYING3. If not see is a constant that is not a legitimate address. EXPAND_WRITE means we are only going to write to the resulting rtx. EXPAND_MEMORY means we are interested in a memory result, even if - the memory is constant and we could have propagated a constant value. */ + the memory is constant and we could have propagated a constant value, + or the memory is unaligned on a STRICT_ALIGNMENT target. + EXPAND_REFERENCE is similar to EXPAND_MEMORY, used internally to expand + the inner reference of a component. */ enum expand_modifier {EXPAND_NORMAL = 0, EXPAND_STACK_PARM, EXPAND_SUM, EXPAND_CONST_ADDRESS, EXPAND_INITIALIZER, EXPAND_WRITE, - EXPAND_MEMORY}; + EXPAND_MEMORY, EXPAND_REFERENCE}; /* Prevent the compiler from deferring stack pops. See inhibit_defer_pop for more information. */ Index: gcc/testsuite/gcc.dg/torture/pr57748-3.c =================================================================== --- gcc/testsuite/gcc.dg/torture/pr57748-3.c (revision 0) +++ gcc/testsuite/gcc.dg/torture/pr57748-3.c (revision 0) @@ -0,0 +1,40 @@ +/* PR middle-end/57748 */ +/* { dg-do run } */ +/* wrong code in expand_expr_real_1. */ + +#include <stdlib.h> + +extern void abort (void); + +typedef long long V + __attribute__ ((vector_size (2 * sizeof (long long)), may_alias)); + +typedef struct S { V a; V b[0]; } P __attribute__((aligned (1))); + +struct __attribute__((packed)) T { char c; P s; }; + +void __attribute__((noinline, noclone)) +check (P *p) +{ + if (p->b[0][0] != 3 || p->b[0][1] != 4) + abort (); +} + +void __attribute__((noinline, noclone)) +foo (struct T *t) +{ + V a = { 3, 4 }; + t->s.b[0] = a; +} + +int +main () +{ + struct T *t = (struct T *) calloc (128, 1); + + foo (t); + check (&t->s); + + free (t); + return 0; +} Index: gcc/testsuite/gcc.dg/torture/pr57748-4.c =================================================================== --- gcc/testsuite/gcc.dg/torture/pr57748-4.c (revision 0) +++ gcc/testsuite/gcc.dg/torture/pr57748-4.c (revision 0) @@ -0,0 +1,38 @@ +/* PR middle-end/57748 */ +/* { dg-do run } */ +/* wrong code in expand_expr_real_1. */ + +#include <stdlib.h> + +extern void abort (void); + +typedef long long V + __attribute__ ((vector_size (2 * sizeof (long long)), may_alias)); + +typedef struct S { V b[1]; } P __attribute__((aligned (1))); + +struct __attribute__((packed)) T { char c; P s; }; + +void __attribute__((noinline, noclone)) +good_value (V b) +{ + if (b[0] != 3 || b[1] != 4) + abort (); +} + +void __attribute__((noinline, noclone)) +check (P *p) +{ + good_value (p->b[1]); +} + +int +main () +{ + struct T *t = (struct T *) calloc (128, 1); + V a = { 3, 4 }; + t->s.b[1] = a; + check (&t->s); + free (t); + return 0; +} ^ permalink raw reply [flat|nested] 105+ messages in thread
* Re: [PATCH, PR 57748] Check for out of bounds access, Part 2 2013-10-25 10:40 ` Bernd Edlinger @ 2013-10-25 11:10 ` Richard Biener 2013-10-25 14:01 ` Martin Jambor ` (2 more replies) 0 siblings, 3 replies; 105+ messages in thread From: Richard Biener @ 2013-10-25 11:10 UTC (permalink / raw) To: Bernd Edlinger; +Cc: Eric Botcazou, GCC Patches, Martin Jambor, Jakub Jelinek On Fri, Oct 25, 2013 at 12:02 PM, Bernd Edlinger <bernd.edlinger@hotmail.de> wrote: > Hi, > >> Eh ... even >> >> register struct { int i; int a[0]; } asm ("ebx"); >> >> works. Also with int a[1] but not with a[2]. So just handling trailing >> arrays makes this case regress as well. >> >> Now I'd call this use questionable ... but we've likely supported that >> for decades and cannot change that now. >> >> Back to fixing everything in expand. >> >> Richard. >> > > Ok, finally you asked for it. > > Here is my previous version of that patch again. > > I have now added a new value "EXPAND_REFERENCE" to the expand_modifier > enumeration. It is almost like EXPAND_MEMORY but it does not interfere with > constant values. > > I have done the same modification to VIEW_CONVERT_EXPR too, because > this is a possible inner reference, itself. It is however inherently hard to > test around this code. > > To understand this patch it is good to know what type of object the > return value "tem" of get_inner_reference can be. > > From the program logic at get_inner_reference it is clear that the > return value may *not* be BIT_FIELD_REF, COMPONENT_REF, ARRAY_REF, > ARRAY_RANGE_REF, REALPART_EXPR, IMAGPART_EXPR. The result may > be VIEW_CONVERT_EXPR only on a STRICT_ALIGNMENT target. This is probably > further restricted because exp is gimplified. > > Usually the result will be a MEM_REF or a SSA_NAME of the memory where > the structure is to be found. > > When you look at where EXPAND_MEMORY is handled you see it is special-cased > in TARGET_MEM_REF, MEM_REF, ARRAY_REF, COMPONENT_REF, BIT_FIELD_REF, > ARRAY_RANGE_REF. > > At TARGET_MEM_REF, MEM_REF, VIEW_CONVERT_EXPR, it should be the > same if EXPAND_MEMORY, EXPAND_WRITE or EXPAND_REFERENCE is given: > If it is an unaligned memory, we just return the unaligned reference. > > This was missing for VIEW_CONVERT_EXPR, and unfortunately I have no test case, > because it is only a problem for STRICT_ALIGNMENT targets, and even there it will > certainly be really hard to find test cases that exercise this code. > > In ARRAY_REF, COMPONENT_REF, BIT_FIELD_REF, ARRAY_RANGE_REF > we do not have to touch the handling of the outer modifier. However we pass > EXPAND_REFERENCE to the inner object, which should not be a recursive > use of any ARRAY_REF, COMPONENT_REF, BIT_FIELD_REF, ARRAY_RANGE_REF. > > TARGET_MEM_REF, MEM_REF and VIEW_CONVERT_EXPR know how to handle > EXPAND_REFERENCE, anything else handles it like EXPAND_NORMAL. > > > Boot-strapped and regression-tested on x86_64-linux-gnu > OK for trunk? You point to a weak spot in expansion - that it handles creating the base MEM to offset with handled components by recursing into the case that handles bare MEM_REFs. This makes the bare MEM_REF handling code somewhat awkward (it's the one to assign mem-attrs which are later adjusted for example). Maybe a better appropach than adding yet another expand modifier would be to split out the "base MEM" expansion part out of the bare MEM_REF handling code so we can call that instead of recursing. In this light - instead of a new expand modifier don't you want an actual flag that specifies we are coming from a call that wants to expand a base? That is, allow EXPAND_SUM but with the recursion flag set? Finally I think the recursion into the VIEW_CONVERT_EXPR case is only there because of the keep_aligning flag of get_inner_reference which should be obsolete now that we properly handle its effects in get_object_alignment. So you wouldn't need to adjust this path if we finally can get rid of that. What do others think? Thanks, Richard. > Thanks > Bernd. ^ permalink raw reply [flat|nested] 105+ messages in thread
* Re: [PATCH, PR 57748] Check for out of bounds access, Part 2 2013-10-25 11:10 ` Richard Biener @ 2013-10-25 14:01 ` Martin Jambor 2013-10-27 20:21 ` [PATCH] Remove "keep_aligning" from get_inner_reference Bernd Edlinger 2013-11-07 13:23 ` [PATCH, PR 57748] Check for out of bounds access, Part 2 Bernd Edlinger 2 siblings, 0 replies; 105+ messages in thread From: Martin Jambor @ 2013-10-25 14:01 UTC (permalink / raw) To: Richard Biener; +Cc: Bernd Edlinger, Eric Botcazou, GCC Patches, Jakub Jelinek Hi, On Fri, Oct 25, 2013 at 12:51:13PM +0200, Richard Biener wrote: > On Fri, Oct 25, 2013 at 12:02 PM, Bernd Edlinger > <bernd.edlinger@hotmail.de> wrote: > > Hi, > > > >> Eh ... even > >> > >> register struct { int i; int a[0]; } asm ("ebx"); > >> > >> works. Also with int a[1] but not with a[2]. So just handling trailing > >> arrays makes this case regress as well. > >> > >> Now I'd call this use questionable ... but we've likely supported that > >> for decades and cannot change that now. > >> > >> Back to fixing everything in expand. > >> > >> Richard. > >> > > > > Ok, finally you asked for it. > > > > Here is my previous version of that patch again. > > > > I have now added a new value "EXPAND_REFERENCE" to the expand_modifier > > enumeration. It is almost like EXPAND_MEMORY but it does not interfere with > > constant values. > > > > I have done the same modification to VIEW_CONVERT_EXPR too, because > > this is a possible inner reference, itself. It is however inherently hard to > > test around this code. > > > > To understand this patch it is good to know what type of object the > > return value "tem" of get_inner_reference can be. > > > > From the program logic at get_inner_reference it is clear that the > > return value may *not* be BIT_FIELD_REF, COMPONENT_REF, ARRAY_REF, > > ARRAY_RANGE_REF, REALPART_EXPR, IMAGPART_EXPR. The result may > > be VIEW_CONVERT_EXPR only on a STRICT_ALIGNMENT target. This is probably > > further restricted because exp is gimplified. > > > > Usually the result will be a MEM_REF or a SSA_NAME of the memory where > > the structure is to be found. > > > > When you look at where EXPAND_MEMORY is handled you see it is special-cased > > in TARGET_MEM_REF, MEM_REF, ARRAY_REF, COMPONENT_REF, BIT_FIELD_REF, > > ARRAY_RANGE_REF. > > > > At TARGET_MEM_REF, MEM_REF, VIEW_CONVERT_EXPR, it should be the > > same if EXPAND_MEMORY, EXPAND_WRITE or EXPAND_REFERENCE is given: > > If it is an unaligned memory, we just return the unaligned reference. > > > > This was missing for VIEW_CONVERT_EXPR, and unfortunately I have no test case, > > because it is only a problem for STRICT_ALIGNMENT targets, and even there it will > > certainly be really hard to find test cases that exercise this code. > > > > In ARRAY_REF, COMPONENT_REF, BIT_FIELD_REF, ARRAY_RANGE_REF > > we do not have to touch the handling of the outer modifier. However we pass > > EXPAND_REFERENCE to the inner object, which should not be a recursive > > use of any ARRAY_REF, COMPONENT_REF, BIT_FIELD_REF, ARRAY_RANGE_REF. > > > > TARGET_MEM_REF, MEM_REF and VIEW_CONVERT_EXPR know how to handle > > EXPAND_REFERENCE, anything else handles it like EXPAND_NORMAL. > > > > > > Boot-strapped and regression-tested on x86_64-linux-gnu > > OK for trunk? > > You point to a weak spot in expansion - that it handles creating > the base MEM to offset with handled components by recursing > into the case that handles bare MEM_REFs. This makes the > bare MEM_REF handling code somewhat awkward (it's the > one to assign mem-attrs which are later adjusted for example). > > Maybe a better appropach than adding yet another expand > modifier would be to split out the "base MEM" expansion part > out of the bare MEM_REF handling code so we can call that > instead of recursing. I think that we should seize every easy opportunity to break up expand_expr* functions into smaller ones with nicer names and easier to understand semantics. So I think is a good idea. Thanks, Martin > > In this light - instead of a new expand modifier don't you want > an actual flag that specifies we are coming from a call that > wants to expand a base? That is, allow EXPAND_SUM > but with the recursion flag set? > > Finally I think the recursion into the VIEW_CONVERT_EXPR case > is only there because of the keep_aligning flag of get_inner_reference > which should be obsolete now that we properly handle its effects > in get_object_alignment. So you wouldn't need to adjust this path > if we finally can get rid of that. > > What do others think? > > Thanks, > Richard. > > > Thanks > > Bernd. ^ permalink raw reply [flat|nested] 105+ messages in thread
* [PATCH] Remove "keep_aligning" from get_inner_reference 2013-10-25 11:10 ` Richard Biener 2013-10-25 14:01 ` Martin Jambor @ 2013-10-27 20:21 ` Bernd Edlinger 2013-11-26 12:37 ` Richard Biener 2013-11-27 11:28 ` Eric Botcazou 2013-11-07 13:23 ` [PATCH, PR 57748] Check for out of bounds access, Part 2 Bernd Edlinger 2 siblings, 2 replies; 105+ messages in thread From: Bernd Edlinger @ 2013-10-27 20:21 UTC (permalink / raw) To: Richard Biener; +Cc: Eric Botcazou, GCC Patches, Martin Jambor, Jakub Jelinek [-- Attachment #1: Type: text/plain, Size: 739 bytes --] Hi, On Fri, 25 Oct 2013 12:51:13, Richard Biener wrote: > Finally I think the recursion into the VIEW_CONVERT_EXPR case > is only there because of the keep_aligning flag of get_inner_reference > which should be obsolete now that we properly handle its effects > in get_object_alignment. So you wouldn't need to adjust this path > if we finally can get rid of that. I think you are right, this flag is no longer necessary, and removing this code path would simplify everything. Therefore I'd like to propose to remove the "keep_aligning" parameter of get_inner_reference as a split-out patch. Boot-strapped (with languages=all,ada,go) and regression-tested on x86_64-linux-gnu. Ok for trunk? Thanks Bernd. [-- Attachment #2: changelog-inner-reference.txt --] [-- Type: text/plain, Size: 1546 bytes --] 2013-10-27 Bernd Edlinger <bernd.edlinger@hotmail.de> Remove parameter keep_aligning from get_inner_reference. * tree.h (get_inner_reference): Adjust header. * expr.c (get_inner_reference): Remove parameter keep_aligning. (get_bit_range, expand_assignment, expand_expr_addr_expr_1, expand_expr_real_1): Adjust. * asan.c (instrument_derefs): Adjust. * builtins.c (get_object_alignment_2): Adjust. Remove handling of VIEW_CONVERT_EXPR. * cfgexpand.c (expand_debug_expr): Adjust. * dbxout.c (dbxout_expand_expr): Adjust. * dwarf2out.c (loc_list_for_address_of_addr_expr_of_indirect_ref, loc_list_from_tree, fortran_common): Adjust. * fold-const.c (optimize_bit_field_compare, decode_field_reference, fold_unary_loc, fold_comparison, split_address_to_core_and_offset): Adjust. * gimple-ssa-strength-reduction.c (slsr_process_ref): Adjust. * simplifx-rtx.c (delegitimize_mem_from_attrs): Adjust. * tree-affine.c (tree_to_aff_combination, get_inner_reference_aff): Adjust. * tree-data-ref.c (split_constant_offset_1, dr_analyze_innermost): Adjust. * tree-vect-data-refs.c (vect_check_gather, vect_analyze_data_refs): Adjust. * tree-scalar-evolution.c (interpret_rhs_expr): Adjust. * tree-ssa-loop-ivopts.c (may_be_unaligned_p, split_address_cost): Adjust. * tsan.c (instrument_expr): Adjust. * ada/gcc-interface/decl.c (elaborate_expression_1): Adjust. * ada/gcc-interface/trans.c (Attribute_to_gnu): Adjust. * ada/gcc-interface/utils2.c (build_unary_op): Adjust. * config/mips/mips.c (r10k_safe_mem_expr_p): Adjust. [-- Attachment #3: patch-inner-reference.diff --] [-- Type: application/octet-stream, Size: 19213 bytes --] Index: gcc/simplify-rtx.c =================================================================== --- gcc/simplify-rtx.c (revision 204101) +++ gcc/simplify-rtx.c (working copy) @@ -295,7 +295,7 @@ delegitimize_mem_from_attrs (rtx x) int unsignedp, volatilep = 0; decl = get_inner_reference (decl, &bitsize, &bitpos, &toffset, - &mode, &unsignedp, &volatilep, false); + &mode, &unsignedp, &volatilep); if (bitsize != GET_MODE_BITSIZE (mode) || (bitpos % BITS_PER_UNIT) || (toffset && !host_integerp (toffset, 0))) Index: gcc/fold-const.c =================================================================== --- gcc/fold-const.c (revision 204101) +++ gcc/fold-const.c (working copy) @@ -3479,7 +3479,7 @@ optimize_bit_field_compare (location_t loc, enum t do anything if the inner expression is a PLACEHOLDER_EXPR since we then will no longer be able to replace it. */ linner = get_inner_reference (lhs, &lbitsize, &lbitpos, &offset, &lmode, - &lunsignedp, &lvolatilep, false); + &lunsignedp, &lvolatilep); if (linner == lhs || lbitsize == GET_MODE_BITSIZE (lmode) || lbitsize < 0 || offset != 0 || TREE_CODE (linner) == PLACEHOLDER_EXPR || lvolatilep) return 0; @@ -3489,7 +3489,7 @@ optimize_bit_field_compare (location_t loc, enum t /* If this is not a constant, we can only do something if bit positions, sizes, and signedness are the same. */ rinner = get_inner_reference (rhs, &rbitsize, &rbitpos, &offset, &rmode, - &runsignedp, &rvolatilep, false); + &runsignedp, &rvolatilep); if (rinner == rhs || lbitpos != rbitpos || lbitsize != rbitsize || lunsignedp != runsignedp || offset != 0 @@ -3663,7 +3663,7 @@ decode_field_reference (location_t loc, tree exp, } inner = get_inner_reference (exp, pbitsize, pbitpos, &offset, pmode, - punsignedp, pvolatilep, false); + punsignedp, pvolatilep); if ((inner == exp && and_mask == 0) || *pbitsize < 0 || offset != 0 || TREE_CODE (inner) == PLACEHOLDER_EXPR) @@ -8047,7 +8047,7 @@ fold_unary_loc (location_t loc, enum tree_code cod int unsignedp, volatilep; tree base = TREE_OPERAND (op0, 0); base = get_inner_reference (base, &bitsize, &bitpos, &offset, - &mode, &unsignedp, &volatilep, false); + &mode, &unsignedp, &volatilep); /* If the reference was to a (constant) zero offset, we can use the address of the base if it has the same base type as the result type and the pointer type is unqualified. */ @@ -9061,7 +9061,7 @@ fold_comparison (location_t loc, enum tree_code co { base0 = get_inner_reference (TREE_OPERAND (arg0, 0), &bitsize, &bitpos0, &offset0, &mode, - &unsignedp, &volatilep, false); + &unsignedp, &volatilep); if (TREE_CODE (base0) == INDIRECT_REF) base0 = TREE_OPERAND (base0, 0); else @@ -9095,7 +9095,7 @@ fold_comparison (location_t loc, enum tree_code co { base1 = get_inner_reference (TREE_OPERAND (arg1, 0), &bitsize, &bitpos1, &offset1, &mode, - &unsignedp, &volatilep, false); + &unsignedp, &volatilep); if (TREE_CODE (base1) == INDIRECT_REF) base1 = TREE_OPERAND (base1, 0); else @@ -16977,8 +16977,7 @@ split_address_to_core_and_offset (tree exp, if (TREE_CODE (exp) == ADDR_EXPR) { core = get_inner_reference (TREE_OPERAND (exp, 0), &bitsize, pbitpos, - poffset, &mode, &unsignedp, &volatilep, - false); + poffset, &mode, &unsignedp, &volatilep); core = build_fold_addr_expr_loc (loc, core); } else Index: gcc/config/mips/mips.c =================================================================== --- gcc/config/mips/mips.c (revision 204101) +++ gcc/config/mips/mips.c (working copy) @@ -14925,7 +14925,7 @@ r10k_safe_mem_expr_p (tree expr, HOST_WIDE_INT off int unsigned_p, volatile_p; inner = get_inner_reference (expr, &bitsize, &bitoffset, &var_offset, &mode, - &unsigned_p, &volatile_p, false); + &unsigned_p, &volatile_p); if (!DECL_P (inner) || !DECL_SIZE_UNIT (inner) || var_offset) return false; Index: gcc/tree-scalar-evolution.c =================================================================== --- gcc/tree-scalar-evolution.c (revision 204101) +++ gcc/tree-scalar-evolution.c (working copy) @@ -1649,7 +1649,7 @@ interpret_rhs_expr (struct loop *loop, gimple at_s base = get_inner_reference (TREE_OPERAND (rhs1, 0), &bitsize, &bitpos, &offset, - &mode, &unsignedp, &volatilep, false); + &mode, &unsignedp, &volatilep); if (TREE_CODE (base) == MEM_REF) { Index: gcc/cfgexpand.c =================================================================== --- gcc/cfgexpand.c (revision 204101) +++ gcc/cfgexpand.c (working copy) @@ -3026,7 +3026,7 @@ expand_debug_expr (tree exp) tree offset; int volatilep = 0; tree tem = get_inner_reference (exp, &bitsize, &bitpos, &offset, - &mode1, &unsignedp, &volatilep, false); + &mode1, &unsignedp, &volatilep); rtx orig_op0; if (bitsize == 0) Index: gcc/tree-data-ref.c =================================================================== --- gcc/tree-data-ref.c (revision 204101) +++ gcc/tree-data-ref.c (working copy) @@ -612,7 +612,7 @@ split_constant_offset_1 (tree type, tree op0, enum op0 = TREE_OPERAND (op0, 0); base = get_inner_reference (op0, &pbitsize, &pbitpos, &poffset, - &pmode, &punsignedp, &pvolatilep, false); + &pmode, &punsignedp, &pvolatilep); if (pbitpos % BITS_PER_UNIT != 0) return false; @@ -762,7 +762,7 @@ dr_analyze_innermost (struct data_reference *dr, s fprintf (dump_file, "analyze_innermost: "); base = get_inner_reference (ref, &pbitsize, &pbitpos, &poffset, - &pmode, &punsignedp, &pvolatilep, false); + &pmode, &punsignedp, &pvolatilep); gcc_assert (base != NULL_TREE); if (pbitpos % BITS_PER_UNIT != 0) Index: gcc/tree.h =================================================================== --- gcc/tree.h (revision 204101) +++ gcc/tree.h (working copy) @@ -4139,8 +4139,7 @@ handled_component_p (const_tree t) the access position and size. */ extern tree get_inner_reference (tree, HOST_WIDE_INT *, HOST_WIDE_INT *, - tree *, enum machine_mode *, int *, int *, - bool); + tree *, enum machine_mode *, int *, int *); /* Return a tree of sizetype representing the size, in bytes, of the element of EXP, an ARRAY_REF or an ARRAY_RANGE_REF. */ Index: gcc/builtins.c =================================================================== --- gcc/builtins.c (revision 204101) +++ gcc/builtins.c (working copy) @@ -315,7 +315,7 @@ get_object_alignment_2 (tree exp, unsigned int *al /* Get the innermost object and the constant (bitpos) and possibly variable (offset) offset of the access. */ exp = get_inner_reference (exp, &bitsize, &bitpos, &offset, - &mode, &unsignedp, &volatilep, true); + &mode, &unsignedp, &volatilep); /* Extract alignment information from the innermost object and possibly adjust bitpos and offset. */ @@ -346,10 +346,6 @@ get_object_alignment_2 (tree exp, unsigned int *al align = DECL_ALIGN (exp); known_alignment = true; } - else if (TREE_CODE (exp) == VIEW_CONVERT_EXPR) - { - align = TYPE_ALIGN (TREE_TYPE (exp)); - } else if (TREE_CODE (exp) == INDIRECT_REF || TREE_CODE (exp) == MEM_REF || TREE_CODE (exp) == TARGET_MEM_REF) Index: gcc/expr.c =================================================================== --- gcc/expr.c (revision 204101) +++ gcc/expr.c (working copy) @@ -4551,7 +4551,7 @@ get_bit_range (unsigned HOST_WIDE_INT *bitstart, int unsignedp; int volatilep = 0; get_inner_reference (TREE_OPERAND (exp, 0), &rbitsize, &rbitpos, - &roffset, &rmode, &unsignedp, &volatilep, false); + &roffset, &rmode, &unsignedp, &volatilep); if ((rbitpos % BITS_PER_UNIT) != 0) { *bitstart = *bitend = 0; @@ -4716,7 +4716,7 @@ expand_assignment (tree to, tree from, bool nontem push_temp_slots (); tem = get_inner_reference (to, &bitsize, &bitpos, &offset, &mode1, - &unsignedp, &volatilep, true); + &unsignedp, &volatilep); if (TREE_CODE (to) == COMPONENT_REF && DECL_BIT_FIELD_TYPE (TREE_OPERAND (to, 1))) @@ -6520,27 +6520,13 @@ store_field (rtx target, HOST_WIDE_INT bitsize, HO If the field describes a variable-sized object, *PMODE is set to BLKmode and *PBITSIZE is set to -1. An access cannot be made in - this case, but the address of the object can be found. + this case, but the address of the object can be found. */ - If KEEP_ALIGNING is true and the target is STRICT_ALIGNMENT, we don't - look through nodes that serve as markers of a greater alignment than - the one that can be deduced from the expression. These nodes make it - possible for front-ends to prevent temporaries from being created by - the middle-end on alignment considerations. For that purpose, the - normal operating mode at high-level is to always pass FALSE so that - the ultimate containing object is really returned; moreover, the - associated predicate handled_component_p will always return TRUE - on these nodes, thus indicating that they are essentially handled - by get_inner_reference. TRUE should only be passed when the caller - is scanning the expression in order to build another representation - and specifically knows how to handle these nodes; as such, this is - the normal operating mode in the RTL expanders. */ - tree get_inner_reference (tree exp, HOST_WIDE_INT *pbitsize, HOST_WIDE_INT *pbitpos, tree *poffset, enum machine_mode *pmode, int *punsignedp, - int *pvolatilep, bool keep_aligning) + int *pvolatilep) { tree size_tree = 0; enum machine_mode mode = VOIDmode; @@ -6660,14 +6646,6 @@ get_inner_reference (tree exp, HOST_WIDE_INT *pbit break; case VIEW_CONVERT_EXPR: - if (keep_aligning && STRICT_ALIGNMENT - && (TYPE_ALIGN (TREE_TYPE (exp)) - > TYPE_ALIGN (TREE_TYPE (TREE_OPERAND (exp, 0)))) - && (TYPE_ALIGN (TREE_TYPE (TREE_OPERAND (exp, 0))) - < BIGGEST_ALIGNMENT) - && (TYPE_ALIGN_OK (TREE_TYPE (exp)) - || TYPE_ALIGN_OK (TREE_TYPE (TREE_OPERAND (exp, 0))))) - goto done; break; case MEM_REF: @@ -7592,7 +7570,7 @@ expand_expr_addr_expr_1 (tree exp, rtx target, enu they won't change the final object whose address will be returned (they actually exist only for that purpose). */ inner = get_inner_reference (exp, &bitsize, &bitpos, &offset, - &mode1, &unsignedp, &volatilep, false); + &mode1, &unsignedp, &volatilep); break; } @@ -9869,7 +9847,7 @@ expand_expr_real_1 (tree exp, rtx target, enum mac tree offset; int volatilep = 0, must_force_mem; tree tem = get_inner_reference (exp, &bitsize, &bitpos, &offset, - &mode1, &unsignedp, &volatilep, true); + &mode1, &unsignedp, &volatilep); rtx orig_op0, memloc; bool mem_attrs_from_type = false; @@ -10230,8 +10208,7 @@ expand_expr_real_1 (tree exp, rtx target, enum mac int volatilep = 0; tree tem = get_inner_reference (treeop0, &bitsize, &bitpos, - &offset, &mode1, &unsignedp, &volatilep, - true); + &offset, &mode1, &unsignedp, &volatilep); rtx orig_op0; /* ??? We should work harder and deal with non-zero offsets. */ Index: gcc/tsan.c =================================================================== --- gcc/tsan.c (revision 204101) +++ gcc/tsan.c (working copy) @@ -113,7 +113,7 @@ instrument_expr (gimple_stmt_iterator gsi, tree ex enum machine_mode mode; int volatilep = 0, unsignedp = 0; base = get_inner_reference (expr, &bitsize, &bitpos, &offset, - &mode, &unsignedp, &volatilep, false); + &mode, &unsignedp, &volatilep); /* No need to instrument accesses to decls that don't escape, they can't escape to other threads then. */ Index: gcc/asan.c =================================================================== --- gcc/asan.c (revision 204101) +++ gcc/asan.c (working copy) @@ -1445,7 +1445,7 @@ instrument_derefs (gimple_stmt_iterator *iter, tre enum machine_mode mode; int volatilep = 0, unsignedp = 0; get_inner_reference (t, &bitsize, &bitpos, &offset, - &mode, &unsignedp, &volatilep, false); + &mode, &unsignedp, &volatilep); if (bitpos % (size_in_bytes * BITS_PER_UNIT) || bitsize != size_in_bytes * BITS_PER_UNIT) { Index: gcc/gimple-ssa-strength-reduction.c =================================================================== --- gcc/gimple-ssa-strength-reduction.c (revision 204101) +++ gcc/gimple-ssa-strength-reduction.c (working copy) @@ -931,7 +931,7 @@ slsr_process_ref (gimple gs) return; base = get_inner_reference (ref_expr, &bitsize, &bitpos, &offset, &mode, - &unsignedp, &volatilep, false); + &unsignedp, &volatilep); index = double_int::from_uhwi (bitpos); if (!restructure_reference (&base, &offset, &index, &type)) Index: gcc/tree-affine.c =================================================================== --- gcc/tree-affine.c (revision 204101) +++ gcc/tree-affine.c (working copy) @@ -317,8 +317,7 @@ tree_to_aff_combination (tree expr, tree type, aff return; } core = get_inner_reference (TREE_OPERAND (expr, 0), &bitsize, &bitpos, - &toffset, &mode, &unsignedp, &volatilep, - false); + &toffset, &mode, &unsignedp, &volatilep); if (bitpos % BITS_PER_UNIT != 0) break; aff_combination_const (comb, type, @@ -886,7 +885,7 @@ get_inner_reference_aff (tree ref, aff_tree *addr, int uns, vol; aff_tree tmp; tree base = get_inner_reference (ref, &bitsize, &bitpos, &toff, &mode, - &uns, &vol, false); + &uns, &vol); tree base_addr = build_fold_addr_expr (base); /* ADDR = &BASE + TOFF + BITPOS / BITS_PER_UNIT. */ Index: gcc/ada/gcc-interface/utils2.c =================================================================== --- gcc/ada/gcc-interface/utils2.c (revision 204101) +++ gcc/ada/gcc-interface/utils2.c (working copy) @@ -1309,8 +1309,7 @@ build_unary_op (enum tree_code op_code, tree resul int unsignedp, volatilep; inner = get_inner_reference (operand, &bitsize, &bitpos, &offset, - &mode, &unsignedp, &volatilep, - false); + &mode, &unsignedp, &volatilep); /* If INNER is a padding type whose field has a self-referential size, convert to that inner type. We know the offset is zero Index: gcc/ada/gcc-interface/trans.c =================================================================== --- gcc/ada/gcc-interface/trans.c (revision 204101) +++ gcc/ada/gcc-interface/trans.c (working copy) @@ -2061,7 +2061,7 @@ Attribute_to_gnu (Node_Id gnat_node, tree *gnu_res && TREE_CODE (gnu_prefix) == FIELD_DECL)); get_inner_reference (gnu_prefix, &bitsize, &bitpos, &gnu_offset, - &mode, &unsignedp, &volatilep, false); + &mode, &unsignedp, &volatilep); if (TREE_CODE (gnu_prefix) == COMPONENT_REF) { Index: gcc/ada/gcc-interface/decl.c =================================================================== --- gcc/ada/gcc-interface/decl.c (revision 204101) +++ gcc/ada/gcc-interface/decl.c (working copy) @@ -6263,7 +6263,7 @@ elaborate_expression_1 (tree gnu_expr, Entity_Id g int unsignedp, volatilep; inner = get_inner_reference (inner, &bitsize, &bitpos, &offset, - &mode, &unsignedp, &volatilep, false); + &mode, &unsignedp, &volatilep); /* If the offset is variable, err on the side of caution. */ if (offset) inner = NULL_TREE; Index: gcc/tree-vect-data-refs.c =================================================================== --- gcc/tree-vect-data-refs.c (revision 204101) +++ gcc/tree-vect-data-refs.c (working copy) @@ -2762,7 +2762,7 @@ vect_check_gather (gimple stmt, loop_vec_info loop SSA_NAME OFF and put the loop invariants into a tree BASE that can be gimplified before the loop. */ base = get_inner_reference (DR_REF (dr), &pbitsize, &pbitpos, &off, - &pmode, &punsignedp, &pvolatilep, false); + &pmode, &punsignedp, &pvolatilep); gcc_assert (base != NULL_TREE && (pbitpos % BITS_PER_UNIT) == 0); if (TREE_CODE (base) == MEM_REF) @@ -3258,7 +3258,7 @@ again: } outer_base = get_inner_reference (inner_base, &pbitsize, &pbitpos, - &poffset, &pmode, &punsignedp, &pvolatilep, false); + &poffset, &pmode, &punsignedp, &pvolatilep); gcc_assert (outer_base != NULL_TREE); if (pbitpos % BITS_PER_UNIT != 0) Index: gcc/tree-ssa-loop-ivopts.c =================================================================== --- gcc/tree-ssa-loop-ivopts.c (revision 204101) +++ gcc/tree-ssa-loop-ivopts.c (working copy) @@ -1655,7 +1655,7 @@ may_be_unaligned_p (tree ref, tree step) does to check whether the object must be loaded by parts when STRICT_ALIGNMENT is true. */ base = get_inner_reference (ref, &bitsize, &bitpos, &toffset, &mode, - &unsignedp, &volatilep, true); + &unsignedp, &volatilep); base_type = TREE_TYPE (base); base_align = get_object_alignment (base); base_align = MAX (base_align, TYPE_ALIGN (base_type)); @@ -3687,7 +3687,7 @@ split_address_cost (struct ivopts_data *data, int unsignedp, volatilep; core = get_inner_reference (addr, &bitsize, &bitpos, &toffset, &mode, - &unsignedp, &volatilep, false); + &unsignedp, &volatilep); if (toffset != 0 || bitpos % BITS_PER_UNIT != 0 Index: gcc/dwarf2out.c =================================================================== --- gcc/dwarf2out.c (revision 204101) +++ gcc/dwarf2out.c (working copy) @@ -13929,7 +13929,7 @@ loc_list_for_address_of_addr_expr_of_indirect_ref obj = get_inner_reference (TREE_OPERAND (loc, 0), &bitsize, &bitpos, &offset, &mode, - &unsignedp, &volatilep, false); + &unsignedp, &volatilep); STRIP_NOPS (obj); if (bitpos % BITS_PER_UNIT) { @@ -14206,7 +14206,7 @@ loc_list_from_tree (tree loc, int want_address) int unsignedp, volatilep = 0; obj = get_inner_reference (loc, &bitsize, &bitpos, &offset, &mode, - &unsignedp, &volatilep, false); + &unsignedp, &volatilep); gcc_assert (obj != loc); @@ -15516,7 +15516,7 @@ fortran_common (tree decl, HOST_WIDE_INT *value) return NULL_TREE; cvar = get_inner_reference (val_expr, &bitsize, &bitpos, &offset, - &mode, &unsignedp, &volatilep, true); + &mode, &unsignedp, &volatilep); if (cvar == NULL_TREE || TREE_CODE (cvar) != VAR_DECL Index: gcc/dbxout.c =================================================================== --- gcc/dbxout.c (revision 204101) +++ gcc/dbxout.c (working copy) @@ -2509,7 +2509,7 @@ dbxout_expand_expr (tree expr) rtx x; tem = get_inner_reference (expr, &bitsize, &bitpos, &offset, - &mode, &unsignedp, &volatilep, true); + &mode, &unsignedp, &volatilep); x = dbxout_expand_expr (tem); if (x == NULL || !MEM_P (x)) ^ permalink raw reply [flat|nested] 105+ messages in thread
* Re: [PATCH] Remove "keep_aligning" from get_inner_reference 2013-10-27 20:21 ` [PATCH] Remove "keep_aligning" from get_inner_reference Bernd Edlinger @ 2013-11-26 12:37 ` Richard Biener 2013-11-27 11:28 ` Eric Botcazou 1 sibling, 0 replies; 105+ messages in thread From: Richard Biener @ 2013-11-26 12:37 UTC (permalink / raw) To: Bernd Edlinger; +Cc: Eric Botcazou, GCC Patches, Martin Jambor, Jakub Jelinek On Sun, Oct 27, 2013 at 5:01 PM, Bernd Edlinger <bernd.edlinger@hotmail.de> wrote: > Hi, > > On Fri, 25 Oct 2013 12:51:13, Richard Biener wrote: >> Finally I think the recursion into the VIEW_CONVERT_EXPR case >> is only there because of the keep_aligning flag of get_inner_reference >> which should be obsolete now that we properly handle its effects >> in get_object_alignment. So you wouldn't need to adjust this path >> if we finally can get rid of that. > > I think you are right, this flag is no longer necessary, and removing > this code path would simplify everything. Therefore I'd like to propose > to remove the "keep_aligning" parameter of get_inner_reference as > a split-out patch. > > Boot-strapped (with languages=all,ada,go) and > regression-tested on x86_64-linux-gnu. > Ok for trunk? Ok. Thanks, Richard. > Thanks > Bernd. ^ permalink raw reply [flat|nested] 105+ messages in thread
* Re: [PATCH] Remove "keep_aligning" from get_inner_reference 2013-10-27 20:21 ` [PATCH] Remove "keep_aligning" from get_inner_reference Bernd Edlinger 2013-11-26 12:37 ` Richard Biener @ 2013-11-27 11:28 ` Eric Botcazou 2013-11-27 12:24 ` Bernd Edlinger 2013-11-27 13:30 ` Richard Biener 1 sibling, 2 replies; 105+ messages in thread From: Eric Botcazou @ 2013-11-27 11:28 UTC (permalink / raw) To: Bernd Edlinger; +Cc: gcc-patches, Richard Biener, Martin Jambor, Jakub Jelinek > I think you are right, this flag is no longer necessary, and removing > this code path would simplify everything. Therefore I'd like to propose > to remove the "keep_aligning" parameter of get_inner_reference as > a split-out patch. > > Boot-strapped (with languages=all,ada,go) and > regression-tested on x86_64-linux-gnu. I don't understand how you can commit a patch that changes something only on strict-alignment platforms and test it only on x86-64. This change *must* be tested with Ada on a strict-alignment platform, that's the only combination for which it is exercised. If you cannot do that, then please back it out. More generally speaking, it's not acceptable to make cleanup changes like that in the RTL expander without extreme care, which of course starts with proper testing. The patch should not have been approved either for that reason. -- Eric Botcazou ^ permalink raw reply [flat|nested] 105+ messages in thread
* RE: [PATCH] Remove "keep_aligning" from get_inner_reference 2013-11-27 11:28 ` Eric Botcazou @ 2013-11-27 12:24 ` Bernd Edlinger 2013-11-27 12:33 ` Eric Botcazou 2013-11-27 13:30 ` Richard Biener 1 sibling, 1 reply; 105+ messages in thread From: Bernd Edlinger @ 2013-11-27 12:24 UTC (permalink / raw) To: Eric Botcazou; +Cc: gcc-patches, Richard Biener, Martin Jambor, Jakub Jelinek Hi, On 27 Nov 2013 10:43:59, Eric Botcazou wrote: > >> I think you are right, this flag is no longer necessary, and removing >> this code path would simplify everything. Therefore I'd like to propose >> to remove the "keep_aligning" parameter of get_inner_reference as >> a split-out patch. >> >> Boot-strapped (with languages=all,ada,go) and >> regression-tested on x86_64-linux-gnu. > > I don't understand how you can commit a patch that changes something only on > strict-alignment platforms and test it only on x86-64. This change *must* be > tested with Ada on a strict-alignment platform, that's the only combination Well, I did that. Apologies for not mentioning that. > for which it is exercised. If you cannot do that, then please back it out. > > More generally speaking, it's not acceptable to make cleanup changes like that > in the RTL expander without extreme care, which of course starts with proper > testing. The patch should not have been approved either for that reason. > > -- > Eric Botcazou The change on the ada interface is actually not critical, because all invocations of get_inner_reference there used keep_aligning == false, as did the majority of all other invocations. What changes with that patch, is that get_inner_reference(...., true) could return a VIEW_CONVERT_EXPR, which is now obsolete. If it is causing any trouble, I can revert that change of course. Thanks Bernd. ^ permalink raw reply [flat|nested] 105+ messages in thread
* Re: [PATCH] Remove "keep_aligning" from get_inner_reference 2013-11-27 12:24 ` Bernd Edlinger @ 2013-11-27 12:33 ` Eric Botcazou 0 siblings, 0 replies; 105+ messages in thread From: Eric Botcazou @ 2013-11-27 12:33 UTC (permalink / raw) To: Bernd Edlinger; +Cc: gcc-patches, Richard Biener, Martin Jambor, Jakub Jelinek > Well, I did that. Apologies for not mentioning that. OK, on which strict-alignment platform did you test it with Ada enabled? > The change on the ada interface is actually not critical, because all > invocations of get_inner_reference there used keep_aligning == false, as > did the majority of all other invocations. Sure, but that's not the point... > What changes with that patch, is that get_inner_reference(...., true) could > return a VIEW_CONVERT_EXPR, which is now obsolete. ...that's what needs to be properly verified indeed. > If it is causing any trouble, I can revert that change of course. You might want to take a look at PR middle-end/17746, it took about 3 months almost a decade ago to find something plausible to fix this fundamental issue for Ada on strict-aligmnent platforms so I'd rather not go through this again. -- Eric Botcazou ^ permalink raw reply [flat|nested] 105+ messages in thread
* Re: [PATCH] Remove "keep_aligning" from get_inner_reference 2013-11-27 11:28 ` Eric Botcazou 2013-11-27 12:24 ` Bernd Edlinger @ 2013-11-27 13:30 ` Richard Biener 2013-11-27 15:10 ` Bernd Edlinger ` (2 more replies) 1 sibling, 3 replies; 105+ messages in thread From: Richard Biener @ 2013-11-27 13:30 UTC (permalink / raw) To: Eric Botcazou; +Cc: Bernd Edlinger, GCC Patches, Martin Jambor, Jakub Jelinek On Wed, Nov 27, 2013 at 10:43 AM, Eric Botcazou <ebotcazou@adacore.com> wrote: >> I think you are right, this flag is no longer necessary, and removing >> this code path would simplify everything. Therefore I'd like to propose >> to remove the "keep_aligning" parameter of get_inner_reference as >> a split-out patch. >> >> Boot-strapped (with languages=all,ada,go) and >> regression-tested on x86_64-linux-gnu. > > I don't understand how you can commit a patch that changes something only on > strict-alignment platforms and test it only on x86-64. This change *must* be > tested with Ada on a strict-alignment platform, that's the only combination > for which it is exercised. If you cannot do that, then please back it out. > > More generally speaking, it's not acceptable to make cleanup changes like that > in the RTL expander without extreme care, which of course starts with proper > testing. The patch should not have been approved either for that reason. I'm fine with reverting it for now (you were in CC of the patch submission but silent on it, I asked for the patch to start simplifying the way mems are expanded - ultimately to avoid the recursion and mem-attribute compute by the recursion). We can come back during stage1. get_object_alignment should be able to properly handle this case if you call it on the full reference in the normal_inner_ref: case. All the weird duplicate code on the VIEW_CONVERT_EXPR case should IMHO go. Richard. > -- > Eric Botcazou ^ permalink raw reply [flat|nested] 105+ messages in thread
* RE: [PATCH] Remove "keep_aligning" from get_inner_reference 2013-11-27 13:30 ` Richard Biener @ 2013-11-27 15:10 ` Bernd Edlinger 2013-11-27 16:25 ` Eric Botcazou 2014-04-22 7:55 ` Bernd Edlinger 2 siblings, 0 replies; 105+ messages in thread From: Bernd Edlinger @ 2013-11-27 15:10 UTC (permalink / raw) To: Richard Biener, Eric Botcazou; +Cc: GCC Patches, Martin Jambor, Jakub Jelinek On Wed, 27 Nov 2013 12:47:19, Richard Biener wrote: > > On Wed, Nov 27, 2013 at 10:43 AM, Eric Botcazou <ebotcazou@adacore.com> wrote: >>> I think you are right, this flag is no longer necessary, and removing >>> this code path would simplify everything. Therefore I'd like to propose >>> to remove the "keep_aligning" parameter of get_inner_reference as >>> a split-out patch. >>> >>> Boot-strapped (with languages=all,ada,go) and >>> regression-tested on x86_64-linux-gnu. >> >> I don't understand how you can commit a patch that changes something only on >> strict-alignment platforms and test it only on x86-64. This change *must* be >> tested with Ada on a strict-alignment platform, that's the only combination >> for which it is exercised. If you cannot do that, then please back it out. >> >> More generally speaking, it's not acceptable to make cleanup changes like that >> in the RTL expander without extreme care, which of course starts with proper >> testing. The patch should not have been approved either for that reason. > > I'm fine with reverting it for now (you were in CC of the patch submission > but silent on it, I asked for the patch to start simplifying the way > mems are expanded - ultimately to avoid the recursion and mem-attribute > compute by the recursion). > Ok, then I'll revert this patch in the evening. Bernd. > We can come back during stage1. > > get_object_alignment should be able to properly handle this case > if you call it on the full reference in the normal_inner_ref: case. > All the weird duplicate code on the VIEW_CONVERT_EXPR case > should IMHO go. > > Richard. > >> -- >> Eric Botcazou ^ permalink raw reply [flat|nested] 105+ messages in thread
* Re: [PATCH] Remove "keep_aligning" from get_inner_reference 2013-11-27 13:30 ` Richard Biener 2013-11-27 15:10 ` Bernd Edlinger @ 2013-11-27 16:25 ` Eric Botcazou 2013-11-27 16:33 ` Richard Biener 2014-04-22 7:55 ` Bernd Edlinger 2 siblings, 1 reply; 105+ messages in thread From: Eric Botcazou @ 2013-11-27 16:25 UTC (permalink / raw) To: Richard Biener; +Cc: gcc-patches, Bernd Edlinger, Martin Jambor, Jakub Jelinek > I'm fine with reverting it for now (you were in CC of the patch submission > but silent on it, I asked for the patch to start simplifying the way > mems are expanded - ultimately to avoid the recursion and mem-attribute > compute by the recursion). Because I'm totally lost in this thread and its many sub-threads. > We can come back during stage1. Sure, let's do that instead and not enter stage #3 with hazardous changes. > get_object_alignment should be able to properly handle this case > if you call it on the full reference in the normal_inner_ref: case. How exactly? Once you flatten everything with get_inner_reference at the beginning, the TYPE_ALIGN_OK flag on the VIEW_CONVERT_EXPR is lost. > All the weird duplicate code on the VIEW_CONVERT_EXPR case > should IMHO go. What has changed since 2004 exactly? If you do a grep for TYPE_ALIGN_OK on 4.1 and 4.9 trees, you get exactly the same 4 occurrences in the middle-end. -- Eric Botcazou ^ permalink raw reply [flat|nested] 105+ messages in thread
* Re: [PATCH] Remove "keep_aligning" from get_inner_reference 2013-11-27 16:25 ` Eric Botcazou @ 2013-11-27 16:33 ` Richard Biener 2013-11-27 16:43 ` Eric Botcazou 0 siblings, 1 reply; 105+ messages in thread From: Richard Biener @ 2013-11-27 16:33 UTC (permalink / raw) To: Eric Botcazou; +Cc: GCC Patches, Bernd Edlinger, Martin Jambor, Jakub Jelinek On Wed, Nov 27, 2013 at 1:29 PM, Eric Botcazou <ebotcazou@adacore.com> wrote: >> I'm fine with reverting it for now (you were in CC of the patch submission >> but silent on it, I asked for the patch to start simplifying the way >> mems are expanded - ultimately to avoid the recursion and mem-attribute >> compute by the recursion). > > Because I'm totally lost in this thread and its many sub-threads. > >> We can come back during stage1. > > Sure, let's do that instead and not enter stage #3 with hazardous changes. > >> get_object_alignment should be able to properly handle this case >> if you call it on the full reference in the normal_inner_ref: case. > > How exactly? Once you flatten everything with get_inner_reference at the > beginning, the TYPE_ALIGN_OK flag on the VIEW_CONVERT_EXPR is lost. Well, I want tem = get_inner_reference (from, ...); op = expand_expr (tem); ... set_mem_attrs (op, from); instead of setting mem_attrs from 'tem' by some obfuscated means of recursing through multiple levels of expanding the memory reference. That is, completely refactor this stuff as it has become so non-obvious what happens. >> All the weird duplicate code on the VIEW_CONVERT_EXPR case >> should IMHO go. > > What has changed since 2004 exactly? If you do a grep for TYPE_ALIGN_OK on > 4.1 and 4.9 trees, you get exactly the same 4 occurrences in the middle-end. Ah, get_object_alignment used keep_aligning ... Richard. > -- > Eric Botcazou ^ permalink raw reply [flat|nested] 105+ messages in thread
* Re: [PATCH] Remove "keep_aligning" from get_inner_reference 2013-11-27 16:33 ` Richard Biener @ 2013-11-27 16:43 ` Eric Botcazou 0 siblings, 0 replies; 105+ messages in thread From: Eric Botcazou @ 2013-11-27 16:43 UTC (permalink / raw) To: Richard Biener; +Cc: gcc-patches, Bernd Edlinger, Martin Jambor, Jakub Jelinek > Ah, get_object_alignment used keep_aligning ... Yes, the patch contains the rather explicit hunks: Index: gcc/builtins.c =================================================================== --- gcc/builtins.c (revision 204101) +++ gcc/builtins.c (working copy) @@ -315,7 +315,7 @@ get_object_alignment_2 (tree exp, unsigned int *al /* Get the innermost object and the constant (bitpos) and possibly variable (offset) offset of the access. */ exp = get_inner_reference (exp, &bitsize, &bitpos, &offset, - &mode, &unsignedp, &volatilep, true); + &mode, &unsignedp, &volatilep); /* Extract alignment information from the innermost object and possibly adjust bitpos and offset. */ @@ -346,10 +346,6 @@ get_object_alignment_2 (tree exp, unsigned int *al align = DECL_ALIGN (exp); known_alignment = true; } - else if (TREE_CODE (exp) == VIEW_CONVERT_EXPR) - { - align = TYPE_ALIGN (TREE_TYPE (exp)); - } else if (TREE_CODE (exp) == INDIRECT_REF || TREE_CODE (exp) == MEM_REF || TREE_CODE (exp) == TARGET_MEM_REF) -- Eric Botcazou ^ permalink raw reply [flat|nested] 105+ messages in thread
* RE: [PATCH] Remove "keep_aligning" from get_inner_reference 2013-11-27 13:30 ` Richard Biener 2013-11-27 15:10 ` Bernd Edlinger 2013-11-27 16:25 ` Eric Botcazou @ 2014-04-22 7:55 ` Bernd Edlinger 2014-04-22 8:11 ` Eric Botcazou 2 siblings, 1 reply; 105+ messages in thread From: Bernd Edlinger @ 2014-04-22 7:55 UTC (permalink / raw) To: Richard Biener, Eric Botcazou; +Cc: GCC Patches, Martin Jambor, Jakub Jelinek [-- Attachment #1: Type: text/plain, Size: 1972 bytes --] Hi, On Wed, 27 Nov 2013 12:47:19, Richard Biener wrote: > > On Wed, Nov 27, 2013 at 10:43 AM, Eric Botcazou <ebotcazou@adacore.com> wrote: >>> I think you are right, this flag is no longer necessary, and removing >>> this code path would simplify everything. Therefore I'd like to propose >>> to remove the "keep_aligning" parameter of get_inner_reference as >>> a split-out patch. >>> >>> Boot-strapped (with languages=all,ada,go) and >>> regression-tested on x86_64-linux-gnu. >> >> I don't understand how you can commit a patch that changes something only on >> strict-alignment platforms and test it only on x86-64. This change *must* be >> tested with Ada on a strict-alignment platform, that's the only combination >> for which it is exercised. If you cannot do that, then please back it out. >> >> More generally speaking, it's not acceptable to make cleanup changes like that >> in the RTL expander without extreme care, which of course starts with proper >> testing. The patch should not have been approved either for that reason. > > I'm fine with reverting it for now (you were in CC of the patch submission > but silent on it, I asked for the patch to start simplifying the way > mems are expanded - ultimately to avoid the recursion and mem-attribute > compute by the recursion). > > We can come back during stage1. > Well, it's stage1 again. I still have that already-approved patch, updated to current trunk. I've successfully boot-strapped it on armv7-linux-gnueabihf with all languages enabled, including Ada. The test suite runs cleanly without any drop-outs. Is it OK to commit now, or are there objections? Thanks Bernd. > get_object_alignment should be able to properly handle this case > if you call it on the full reference in the normal_inner_ref: case. > All the weird duplicate code on the VIEW_CONVERT_EXPR case > should IMHO go. > > Richard. > >> -- >> Eric Botcazou [-- Attachment #2: changelog-inner-reference.txt --] [-- Type: text/plain, Size: 1634 bytes --] 2014-04-16 Bernd Edlinger <bernd.edlinger@hotmail.de> Remove parameter keep_aligning from get_inner_reference. * tree.h (get_inner_reference): Adjust header. * expr.c (get_inner_reference): Remove parameter keep_aligning. (get_bit_range, expand_assignment, expand_expr_addr_expr_1, expand_expr_real_1): Adjust. * asan.c (instrument_derefs): Adjust. * builtins.c (get_object_alignment_2): Adjust. Remove handling of VIEW_CONVERT_EXPR. * cfgexpand.c (expand_debug_expr): Adjust. * dbxout.c (dbxout_expand_expr): Adjust. * dwarf2out.c (loc_list_for_address_of_addr_expr_of_indirect_ref, loc_list_from_tree, fortran_common): Adjust. * fold-const.c (optimize_bit_field_compare, decode_field_reference, fold_unary_loc, fold_comparison, split_address_to_core_and_offset): Adjust. * gimple-ssa-strength-reduction.c (slsr_process_ref): Adjust. * simplifx-rtx.c (delegitimize_mem_from_attrs): Adjust. * tree-affine.c (tree_to_aff_combination, get_inner_reference_aff): Adjust. * tree-data-ref.c (split_constant_offset_1, dr_analyze_innermost): Adjust. * tree-vect-data-refs.c (vect_check_gather, vect_analyze_data_refs): Adjust. * tree-scalar-evolution.c (interpret_rhs_expr): Adjust. * tree-ssa-loop-ivopts.c ( split_address_cost): Adjust. * tsan.c (instrument_expr): Adjust. * config/mips/mips.c (r10k_safe_mem_expr_p): Adjust. ada: 2014-04-16 Bernd Edlinger <bernd.edlinger@hotmail.de> Remove parameter keep_aligning from get_inner_reference. * gcc-interface/decl.c (elaborate_expression_1): Adjust. * gcc-interface/trans.c (Attribute_to_gnu): Adjust. * gcc-interface/utils2.c (build_unary_op): Adjust. [-- Attachment #3: patch-inner-reference.diff --] [-- Type: application/octet-stream, Size: 18974 bytes --] diff -pur gcc/ada/gcc-interface/decl.c gcc/ada/gcc-interface/decl.c --- gcc/ada/gcc-interface/decl.c 2014-01-25 11:42:04.000000000 +0100 +++ gcc/ada/gcc-interface/decl.c 2014-04-15 09:39:15.273336672 +0200 @@ -6301,7 +6301,7 @@ elaborate_expression_1 (tree gnu_expr, E int unsignedp, volatilep; inner = get_inner_reference (inner, &bitsize, &bitpos, &offset, - &mode, &unsignedp, &volatilep, false); + &mode, &unsignedp, &volatilep); /* If the offset is variable, err on the side of caution. */ if (offset) inner = NULL_TREE; diff -pur gcc/ada/gcc-interface/trans.c gcc/ada/gcc-interface/trans.c --- gcc/ada/gcc-interface/trans.c 2014-02-25 17:14:58.000000000 +0100 +++ gcc/ada/gcc-interface/trans.c 2014-04-15 09:39:15.281336643 +0200 @@ -2094,7 +2094,7 @@ Attribute_to_gnu (Node_Id gnat_node, tre && TREE_CODE (gnu_prefix) == FIELD_DECL)); get_inner_reference (gnu_prefix, &bitsize, &bitpos, &gnu_offset, - &mode, &unsignedp, &volatilep, false); + &mode, &unsignedp, &volatilep); if (TREE_CODE (gnu_prefix) == COMPONENT_REF) { diff -pur gcc/ada/gcc-interface/utils2.c gcc/ada/gcc-interface/utils2.c --- gcc/ada/gcc-interface/utils2.c 2014-02-23 17:26:32.000000000 +0100 +++ gcc/ada/gcc-interface/utils2.c 2014-04-15 09:39:15.281336643 +0200 @@ -1312,8 +1312,7 @@ build_unary_op (enum tree_code op_code, int unsignedp, volatilep; inner = get_inner_reference (operand, &bitsize, &bitpos, &offset, - &mode, &unsignedp, &volatilep, - false); + &mode, &unsignedp, &volatilep); /* If INNER is a padding type whose field has a self-referential size, convert to that inner type. We know the offset is zero diff -pur gcc/asan.c gcc/asan.c --- gcc/asan.c 2014-01-09 08:31:05.000000000 +0100 +++ gcc/asan.c 2014-04-15 09:39:15.301336568 +0200 @@ -1605,7 +1605,7 @@ instrument_derefs (gimple_stmt_iterator enum machine_mode mode; int volatilep = 0, unsignedp = 0; tree inner = get_inner_reference (t, &bitsize, &bitpos, &offset, - &mode, &unsignedp, &volatilep, false); + &mode, &unsignedp, &volatilep); if (bitpos % (size_in_bytes * BITS_PER_UNIT) || bitsize != size_in_bytes * BITS_PER_UNIT) { diff -pur gcc/builtins.c gcc/builtins.c --- gcc/builtins.c 2014-03-18 12:31:04.000000000 +0100 +++ gcc/builtins.c 2014-04-15 09:39:15.205336931 +0200 @@ -327,7 +327,7 @@ get_object_alignment_2 (tree exp, unsign /* Get the innermost object and the constant (bitpos) and possibly variable (offset) offset of the access. */ exp = get_inner_reference (exp, &bitsize, &bitpos, &offset, - &mode, &unsignedp, &volatilep, true); + &mode, &unsignedp, &volatilep); /* Extract alignment information from the innermost object and possibly adjust bitpos and offset. */ @@ -358,10 +358,6 @@ get_object_alignment_2 (tree exp, unsign align = DECL_ALIGN (exp); known_alignment = true; } - else if (TREE_CODE (exp) == VIEW_CONVERT_EXPR) - { - align = TYPE_ALIGN (TREE_TYPE (exp)); - } else if (TREE_CODE (exp) == INDIRECT_REF || TREE_CODE (exp) == MEM_REF || TREE_CODE (exp) == TARGET_MEM_REF) diff -pur gcc/cfgexpand.c gcc/cfgexpand.c --- gcc/cfgexpand.c 2014-03-20 12:35:22.000000000 +0100 +++ gcc/cfgexpand.c 2014-04-15 09:39:15.345336402 +0200 @@ -3954,7 +3954,7 @@ expand_debug_expr (tree exp) tree offset; int volatilep = 0; tree tem = get_inner_reference (exp, &bitsize, &bitpos, &offset, - &mode1, &unsignedp, &volatilep, false); + &mode1, &unsignedp, &volatilep); rtx orig_op0; if (bitsize == 0) diff -pur gcc/config/mips/mips.c gcc/config/mips/mips.c --- gcc/config/mips/mips.c 2014-03-08 10:27:23.000000000 +0100 +++ gcc/config/mips/mips.c 2014-04-15 09:39:15.365336327 +0200 @@ -15078,7 +15078,7 @@ r10k_safe_mem_expr_p (tree expr, unsigne int unsigned_p, volatile_p; inner = get_inner_reference (expr, &bitsize, &bitoffset, &var_offset, &mode, - &unsigned_p, &volatile_p, false); + &unsigned_p, &volatile_p); if (!DECL_P (inner) || !DECL_SIZE_UNIT (inner) || var_offset) return false; diff -pur gcc/dbxout.c gcc/dbxout.c --- gcc/dbxout.c 2014-01-02 23:23:26.000000000 +0100 +++ gcc/dbxout.c 2014-04-15 09:39:15.241336794 +0200 @@ -2511,7 +2511,7 @@ dbxout_expand_expr (tree expr) rtx x; tem = get_inner_reference (expr, &bitsize, &bitpos, &offset, - &mode, &unsignedp, &volatilep, true); + &mode, &unsignedp, &volatilep); x = dbxout_expand_expr (tem); if (x == NULL || !MEM_P (x)) diff -pur gcc/dwarf2out.c gcc/dwarf2out.c --- gcc/dwarf2out.c 2014-04-04 18:10:07.000000000 +0200 +++ gcc/dwarf2out.c 2014-04-15 09:39:15.253336749 +0200 @@ -13971,7 +13971,7 @@ loc_list_for_address_of_addr_expr_of_ind obj = get_inner_reference (TREE_OPERAND (loc, 0), &bitsize, &bitpos, &offset, &mode, - &unsignedp, &volatilep, false); + &unsignedp, &volatilep); STRIP_NOPS (obj); if (bitpos % BITS_PER_UNIT) { @@ -14248,7 +14248,7 @@ loc_list_from_tree (tree loc, int want_a int unsignedp, volatilep = 0; obj = get_inner_reference (loc, &bitsize, &bitpos, &offset, &mode, - &unsignedp, &volatilep, false); + &unsignedp, &volatilep); gcc_assert (obj != loc); @@ -15558,7 +15558,7 @@ fortran_common (tree decl, HOST_WIDE_INT return NULL_TREE; cvar = get_inner_reference (val_expr, &bitsize, &bitpos, &offset, - &mode, &unsignedp, &volatilep, true); + &mode, &unsignedp, &volatilep); if (cvar == NULL_TREE || TREE_CODE (cvar) != VAR_DECL diff -pur gcc/expr.c gcc/expr.c --- gcc/expr.c 2014-04-11 13:52:14.000000000 +0200 +++ gcc/expr.c 2014-04-15 09:39:15.261336719 +0200 @@ -4665,7 +4665,7 @@ get_bit_range (unsigned HOST_WIDE_INT *b int unsignedp; int volatilep = 0; get_inner_reference (TREE_OPERAND (exp, 0), &rbitsize, &rbitpos, - &roffset, &rmode, &unsignedp, &volatilep, false); + &roffset, &rmode, &unsignedp, &volatilep); if ((rbitpos % BITS_PER_UNIT) != 0) { *bitstart = *bitend = 0; @@ -4818,7 +4818,7 @@ expand_assignment (tree to, tree from, b push_temp_slots (); tem = get_inner_reference (to, &bitsize, &bitpos, &offset, &mode1, - &unsignedp, &volatilep, true); + &unsignedp, &volatilep); /* Make sure bitpos is not negative, it can wreak havoc later. */ if (bitpos < 0) @@ -6674,27 +6674,13 @@ store_field (rtx target, HOST_WIDE_INT b If the field describes a variable-sized object, *PMODE is set to BLKmode and *PBITSIZE is set to -1. An access cannot be made in - this case, but the address of the object can be found. - - If KEEP_ALIGNING is true and the target is STRICT_ALIGNMENT, we don't - look through nodes that serve as markers of a greater alignment than - the one that can be deduced from the expression. These nodes make it - possible for front-ends to prevent temporaries from being created by - the middle-end on alignment considerations. For that purpose, the - normal operating mode at high-level is to always pass FALSE so that - the ultimate containing object is really returned; moreover, the - associated predicate handled_component_p will always return TRUE - on these nodes, thus indicating that they are essentially handled - by get_inner_reference. TRUE should only be passed when the caller - is scanning the expression in order to build another representation - and specifically knows how to handle these nodes; as such, this is - the normal operating mode in the RTL expanders. */ + this case, but the address of the object can be found. */ tree get_inner_reference (tree exp, HOST_WIDE_INT *pbitsize, HOST_WIDE_INT *pbitpos, tree *poffset, enum machine_mode *pmode, int *punsignedp, - int *pvolatilep, bool keep_aligning) + int *pvolatilep) { tree size_tree = 0; enum machine_mode mode = VOIDmode; @@ -6814,14 +6800,6 @@ get_inner_reference (tree exp, HOST_WIDE break; case VIEW_CONVERT_EXPR: - if (keep_aligning && STRICT_ALIGNMENT - && (TYPE_ALIGN (TREE_TYPE (exp)) - > TYPE_ALIGN (TREE_TYPE (TREE_OPERAND (exp, 0)))) - && (TYPE_ALIGN (TREE_TYPE (TREE_OPERAND (exp, 0))) - < BIGGEST_ALIGNMENT) - && (TYPE_ALIGN_OK (TREE_TYPE (exp)) - || TYPE_ALIGN_OK (TREE_TYPE (TREE_OPERAND (exp, 0))))) - goto done; break; case MEM_REF: @@ -7686,7 +7664,7 @@ expand_expr_addr_expr_1 (tree exp, rtx t they won't change the final object whose address will be returned (they actually exist only for that purpose). */ inner = get_inner_reference (exp, &bitsize, &bitpos, &offset, - &mode1, &unsignedp, &volatilep, false); + &mode1, &unsignedp, &volatilep); break; } @@ -9988,7 +9966,7 @@ expand_expr_real_1 (tree exp, rtx target tree offset; int volatilep = 0, must_force_mem; tree tem = get_inner_reference (exp, &bitsize, &bitpos, &offset, - &mode1, &unsignedp, &volatilep, true); + &mode1, &unsignedp, &volatilep); rtx orig_op0, memloc; bool mem_attrs_from_type = false; @@ -10346,8 +10324,7 @@ expand_expr_real_1 (tree exp, rtx target int volatilep = 0; tree tem = get_inner_reference (treeop0, &bitsize, &bitpos, - &offset, &mode1, &unsignedp, &volatilep, - true); + &offset, &mode1, &unsignedp, &volatilep); rtx orig_op0; /* ??? We should work harder and deal with non-zero offsets. */ diff -pur gcc/fold-const.c gcc/fold-const.c --- gcc/fold-const.c 2014-01-02 23:23:26.000000000 +0100 +++ gcc/fold-const.c 2014-04-15 09:39:15.221336869 +0200 @@ -3503,7 +3503,7 @@ optimize_bit_field_compare (location_t l do anything if the inner expression is a PLACEHOLDER_EXPR since we then will no longer be able to replace it. */ linner = get_inner_reference (lhs, &lbitsize, &lbitpos, &offset, &lmode, - &lunsignedp, &lvolatilep, false); + &lunsignedp, &lvolatilep); if (linner == lhs || lbitsize == GET_MODE_BITSIZE (lmode) || lbitsize < 0 || offset != 0 || TREE_CODE (linner) == PLACEHOLDER_EXPR || lvolatilep) return 0; @@ -3513,7 +3513,7 @@ optimize_bit_field_compare (location_t l /* If this is not a constant, we can only do something if bit positions, sizes, and signedness are the same. */ rinner = get_inner_reference (rhs, &rbitsize, &rbitpos, &offset, &rmode, - &runsignedp, &rvolatilep, false); + &runsignedp, &rvolatilep); if (rinner == rhs || lbitpos != rbitpos || lbitsize != rbitsize || lunsignedp != runsignedp || offset != 0 @@ -3687,7 +3687,7 @@ decode_field_reference (location_t loc, } inner = get_inner_reference (exp, pbitsize, pbitpos, &offset, pmode, - punsignedp, pvolatilep, false); + punsignedp, pvolatilep); if ((inner == exp && and_mask == 0) || *pbitsize < 0 || offset != 0 || TREE_CODE (inner) == PLACEHOLDER_EXPR) @@ -8071,7 +8071,7 @@ fold_unary_loc (location_t loc, enum tre int unsignedp, volatilep; tree base = TREE_OPERAND (op0, 0); base = get_inner_reference (base, &bitsize, &bitpos, &offset, - &mode, &unsignedp, &volatilep, false); + &mode, &unsignedp, &volatilep); /* If the reference was to a (constant) zero offset, we can use the address of the base if it has the same base type as the result type and the pointer type is unqualified. */ @@ -9096,7 +9096,7 @@ fold_comparison (location_t loc, enum tr { base0 = get_inner_reference (TREE_OPERAND (arg0, 0), &bitsize, &bitpos0, &offset0, &mode, - &unsignedp, &volatilep, false); + &unsignedp, &volatilep); if (TREE_CODE (base0) == INDIRECT_REF) base0 = TREE_OPERAND (base0, 0); else @@ -9130,7 +9130,7 @@ fold_comparison (location_t loc, enum tr { base1 = get_inner_reference (TREE_OPERAND (arg1, 0), &bitsize, &bitpos1, &offset1, &mode, - &unsignedp, &volatilep, false); + &unsignedp, &volatilep); if (TREE_CODE (base1) == INDIRECT_REF) base1 = TREE_OPERAND (base1, 0); else @@ -16999,8 +16999,7 @@ split_address_to_core_and_offset (tree e if (TREE_CODE (exp) == ADDR_EXPR) { core = get_inner_reference (TREE_OPERAND (exp, 0), &bitsize, pbitpos, - poffset, &mode, &unsignedp, &volatilep, - false); + poffset, &mode, &unsignedp, &volatilep); core = build_fold_addr_expr_loc (loc, core); } else diff -pur gcc/gimple-ssa-strength-reduction.c gcc/gimple-ssa-strength-reduction.c --- gcc/gimple-ssa-strength-reduction.c 2014-04-03 00:07:30.000000000 +0200 +++ gcc/gimple-ssa-strength-reduction.c 2014-04-15 09:39:15.313336522 +0200 @@ -1006,7 +1006,7 @@ slsr_process_ref (gimple gs) return; base = get_inner_reference (ref_expr, &bitsize, &bitpos, &offset, &mode, - &unsignedp, &volatilep, false); + &unsignedp, &volatilep); index = double_int::from_uhwi (bitpos); if (!restructure_reference (&base, &offset, &index, &type)) diff -pur gcc/simplify-rtx.c gcc/simplify-rtx.c --- gcc/simplify-rtx.c 2014-01-02 23:23:26.000000000 +0100 +++ gcc/simplify-rtx.c 2014-04-15 09:39:15.349336388 +0200 @@ -296,7 +296,7 @@ delegitimize_mem_from_attrs (rtx x) int unsignedp, volatilep = 0; decl = get_inner_reference (decl, &bitsize, &bitpos, &toffset, - &mode, &unsignedp, &volatilep, false); + &mode, &unsignedp, &volatilep); if (bitsize != GET_MODE_BITSIZE (mode) || (bitpos % BITS_PER_UNIT) || (toffset && !tree_fits_shwi_p (toffset))) diff -pur gcc/tree-affine.c gcc/tree-affine.c --- gcc/tree-affine.c 2014-01-02 23:23:26.000000000 +0100 +++ gcc/tree-affine.c 2014-04-15 09:39:15.333336448 +0200 @@ -325,8 +325,7 @@ tree_to_aff_combination (tree expr, tree return; } core = get_inner_reference (TREE_OPERAND (expr, 0), &bitsize, &bitpos, - &toffset, &mode, &unsignedp, &volatilep, - false); + &toffset, &mode, &unsignedp, &volatilep); if (bitpos % BITS_PER_UNIT != 0) break; aff_combination_const (comb, type, @@ -895,7 +894,7 @@ get_inner_reference_aff (tree ref, aff_t int uns, vol; aff_tree tmp; tree base = get_inner_reference (ref, &bitsize, &bitpos, &toff, &mode, - &uns, &vol, false); + &uns, &vol); tree base_addr = build_fold_addr_expr (base); /* ADDR = &BASE + TOFF + BITPOS / BITS_PER_UNIT. */ diff -pur gcc/tree-data-ref.c gcc/tree-data-ref.c --- gcc/tree-data-ref.c 2014-02-04 14:08:00.000000000 +0100 +++ gcc/tree-data-ref.c 2014-04-15 09:39:15.321336493 +0200 @@ -619,7 +619,7 @@ split_constant_offset_1 (tree type, tree op0 = TREE_OPERAND (op0, 0); base = get_inner_reference (op0, &pbitsize, &pbitpos, &poffset, - &pmode, &punsignedp, &pvolatilep, false); + &pmode, &punsignedp, &pvolatilep); if (pbitpos % BITS_PER_UNIT != 0) return false; @@ -769,7 +769,7 @@ dr_analyze_innermost (struct data_refere fprintf (dump_file, "analyze_innermost: "); base = get_inner_reference (ref, &pbitsize, &pbitpos, &poffset, - &pmode, &punsignedp, &pvolatilep, false); + &pmode, &punsignedp, &pvolatilep); gcc_assert (base != NULL_TREE); if (pbitpos % BITS_PER_UNIT != 0) diff -pur gcc/tree.h gcc/tree.h --- gcc/tree.h 2014-03-21 12:52:50.000000000 +0100 +++ gcc/tree.h 2014-04-15 09:39:15.169337064 +0200 @@ -4530,8 +4530,7 @@ extern tree build_personality_function ( look for the ultimate containing object, which is returned and specify the access position and size. */ extern tree get_inner_reference (tree, HOST_WIDE_INT *, HOST_WIDE_INT *, - tree *, enum machine_mode *, int *, int *, - bool); + tree *, enum machine_mode *, int *, int *); /* Return a tree representing the lower bound of the array mentioned in EXP, an ARRAY_REF or an ARRAY_RANGE_REF. */ diff -pur gcc/tree-scalar-evolution.c gcc/tree-scalar-evolution.c --- gcc/tree-scalar-evolution.c 2014-01-13 20:14:03.000000000 +0100 +++ gcc/tree-scalar-evolution.c 2014-04-15 09:39:15.193336972 +0200 @@ -1733,7 +1733,7 @@ interpret_rhs_expr (struct loop *loop, g base = get_inner_reference (TREE_OPERAND (rhs1, 0), &bitsize, &bitpos, &offset, - &mode, &unsignedp, &volatilep, false); + &mode, &unsignedp, &volatilep); if (TREE_CODE (base) == MEM_REF) { diff -pur gcc/tree-ssa-loop-ivopts.c gcc/tree-ssa-loop-ivopts.c --- gcc/tree-ssa-loop-ivopts.c 2014-04-07 16:03:55.000000000 +0200 +++ gcc/tree-ssa-loop-ivopts.c 2014-04-15 09:39:15.241336794 +0200 @@ -3776,7 +3776,7 @@ split_address_cost (struct ivopts_data * int unsignedp, volatilep; core = get_inner_reference (addr, &bitsize, &bitpos, &toffset, &mode, - &unsignedp, &volatilep, false); + &unsignedp, &volatilep); if (toffset != 0 || bitpos % BITS_PER_UNIT != 0 diff -pur gcc/tree-vect-data-refs.c gcc/tree-vect-data-refs.c --- gcc/tree-vect-data-refs.c 2014-02-21 14:18:54.000000000 +0100 +++ gcc/tree-vect-data-refs.c 2014-04-15 09:40:47.068991277 +0200 @@ -2990,7 +2990,7 @@ vect_check_gather (gimple stmt, loop_vec SSA_NAME OFF and put the loop invariants into a tree BASE that can be gimplified before the loop. */ base = get_inner_reference (base, &pbitsize, &pbitpos, &off, - &pmode, &punsignedp, &pvolatilep, false); + &pmode, &punsignedp, &pvolatilep); gcc_assert (base != NULL_TREE && (pbitpos % BITS_PER_UNIT) == 0); if (TREE_CODE (base) == MEM_REF) @@ -3543,7 +3543,7 @@ again: } outer_base = get_inner_reference (inner_base, &pbitsize, &pbitpos, - &poffset, &pmode, &punsignedp, &pvolatilep, false); + &poffset, &pmode, &punsignedp, &pvolatilep); gcc_assert (outer_base != NULL_TREE); if (pbitpos % BITS_PER_UNIT != 0) diff -pur gcc/tsan.c gcc/tsan.c --- gcc/tsan.c 2014-01-08 10:06:27.000000000 +0100 +++ gcc/tsan.c 2014-04-15 09:39:15.293336598 +0200 @@ -121,7 +121,7 @@ instrument_expr (gimple_stmt_iterator gs enum machine_mode mode; int volatilep = 0, unsignedp = 0; base = get_inner_reference (expr, &bitsize, &bitpos, &offset, - &mode, &unsignedp, &volatilep, false); + &mode, &unsignedp, &volatilep); /* No need to instrument accesses to decls that don't escape, they can't escape to other threads then. */ diff -pur gcc/ubsan.c gcc/ubsan.c --- gcc/ubsan.c 2014-03-26 20:33:40.000000000 +0100 +++ gcc/ubsan.c 2014-04-15 09:55:40.357745684 +0200 @@ -797,7 +797,7 @@ instrument_bool_enum_load (gimple_stmt_i enum machine_mode mode; int volatilep = 0, unsignedp = 0; tree base = get_inner_reference (rhs, &bitsize, &bitpos, &offset, &mode, - &unsignedp, &volatilep, false); + &unsignedp, &volatilep); tree utype = build_nonstandard_integer_type (modebitsize, 1); if ((TREE_CODE (base) == VAR_DECL && DECL_HARD_REGISTER (base)) ^ permalink raw reply [flat|nested] 105+ messages in thread
* Re: [PATCH] Remove "keep_aligning" from get_inner_reference 2014-04-22 7:55 ` Bernd Edlinger @ 2014-04-22 8:11 ` Eric Botcazou 2014-04-22 8:33 ` Bernd Edlinger 0 siblings, 1 reply; 105+ messages in thread From: Eric Botcazou @ 2014-04-22 8:11 UTC (permalink / raw) To: Bernd Edlinger; +Cc: gcc-patches, Richard Biener, Martin Jambor, Jakub Jelinek > I still have that already-approved patch, updated to current trunk. > I've successfully boot-strapped it on armv7-linux-gnueabihf with > all languages enabled, including Ada. > The test suite runs cleanly without any drop-outs. Thanks for the testing. > Is it OK to commit now, or are there objections? I think that the patch is either incomplete or wrong, in the sense that it will break TYPE_ALIGN_OK support, unless this support is totally obsolete, in which case it ought to be totally removed instead of just partially. The Ada testsuite in the compiler isn't exhaustive enough to give any guarantee so I will need to conduct more testing. Can you sit on the patch a few weeks? -- Eric Botcazou ^ permalink raw reply [flat|nested] 105+ messages in thread
* RE: [PATCH] Remove "keep_aligning" from get_inner_reference 2014-04-22 8:11 ` Eric Botcazou @ 2014-04-22 8:33 ` Bernd Edlinger 2014-04-22 9:36 ` Eric Botcazou 0 siblings, 1 reply; 105+ messages in thread From: Bernd Edlinger @ 2014-04-22 8:33 UTC (permalink / raw) To: Eric Botcazou; +Cc: gcc-patches, Richard Biener, Martin Jambor, Jakub Jelinek Hi Eric, On Tue, 22 Apr 2014 10:09:28, Eric Botcazou wrote: > >> I still have that already-approved patch, updated to current trunk. >> I've successfully boot-strapped it on armv7-linux-gnueabihf with >> all languages enabled, including Ada. >> The test suite runs cleanly without any drop-outs. > > Thanks for the testing. > >> Is it OK to commit now, or are there objections? > > I think that the patch is either incomplete or wrong, in the sense that it > will break TYPE_ALIGN_OK support, unless this support is totally obsolete, in > which case it ought to be totally removed instead of just partially. The Ada > testsuite in the compiler isn't exhaustive enough to give any guarantee so I > will need to conduct more testing. Can you sit on the patch a few weeks? > Sure, and thanks again for your help. I was not able to find any difference on the generated code with or without that patch. Bernd. > -- > Eric Botcazou ^ permalink raw reply [flat|nested] 105+ messages in thread
* Re: [PATCH] Remove "keep_aligning" from get_inner_reference 2014-04-22 8:33 ` Bernd Edlinger @ 2014-04-22 9:36 ` Eric Botcazou 2014-05-02 6:18 ` Jeff Law 0 siblings, 1 reply; 105+ messages in thread From: Eric Botcazou @ 2014-04-22 9:36 UTC (permalink / raw) To: Bernd Edlinger; +Cc: gcc-patches, Richard Biener, Martin Jambor, Jakub Jelinek > Sure, and thanks again for your help. Thanks! > I was not able to find any difference on the generated code with > or without that patch. Yes, my gut feeling is that TYPE_ALIGN_OK is really obsolete now. It is set in a single place in the compiler (gcc-interface/decl.c:gnat_to_gnu_entity): /* Tell the middle-end that objects of tagged types are guaranteed to be properly aligned. This is necessary because conversions to the class-wide type are translated into conversions to the root type, which can be less aligned than some of its derived types. */ if (Is_Tagged_Type (gnat_entity) || Is_Class_Wide_Equivalent_Type (gnat_entity)) TYPE_ALIGN_OK (gnu_type) = 1; but we changed the way these conversions are done some time ago. -- Eric Botcazou ^ permalink raw reply [flat|nested] 105+ messages in thread
* Re: [PATCH] Remove "keep_aligning" from get_inner_reference 2014-04-22 9:36 ` Eric Botcazou @ 2014-05-02 6:18 ` Jeff Law 2014-05-05 8:00 ` Richard Biener 0 siblings, 1 reply; 105+ messages in thread From: Jeff Law @ 2014-05-02 6:18 UTC (permalink / raw) To: Eric Botcazou, Bernd Edlinger Cc: gcc-patches, Richard Biener, Martin Jambor, Jakub Jelinek On 04/22/14 03:25, Eric Botcazou wrote: >> Sure, and thanks again for your help. > > Thanks! > >> I was not able to find any difference on the generated code with >> or without that patch. > > Yes, my gut feeling is that TYPE_ALIGN_OK is really obsolete now. It is set > in a single place in the compiler (gcc-interface/decl.c:gnat_to_gnu_entity): > > /* Tell the middle-end that objects of tagged types are guaranteed to > be properly aligned. This is necessary because conversions to the > class-wide type are translated into conversions to the root type, > which can be less aligned than some of its derived types. */ > if (Is_Tagged_Type (gnat_entity) > || Is_Class_Wide_Equivalent_Type (gnat_entity)) > TYPE_ALIGN_OK (gnu_type) = 1; > > but we changed the way these conversions are done some time ago. So does this remove the last concern around Bernd's patch? Jeff ^ permalink raw reply [flat|nested] 105+ messages in thread
* Re: [PATCH] Remove "keep_aligning" from get_inner_reference 2014-05-02 6:18 ` Jeff Law @ 2014-05-05 8:00 ` Richard Biener 2014-05-05 20:25 ` Mike Stump 2014-05-14 7:30 ` Eric Botcazou 0 siblings, 2 replies; 105+ messages in thread From: Richard Biener @ 2014-05-05 8:00 UTC (permalink / raw) To: Jeff Law Cc: Eric Botcazou, Bernd Edlinger, GCC Patches, Martin Jambor, Jakub Jelinek On Fri, May 2, 2014 at 8:18 AM, Jeff Law <law@redhat.com> wrote: > On 04/22/14 03:25, Eric Botcazou wrote: >>> >>> Sure, and thanks again for your help. >> >> >> Thanks! >> >>> I was not able to find any difference on the generated code with >>> or without that patch. >> >> >> Yes, my gut feeling is that TYPE_ALIGN_OK is really obsolete now. It is >> set >> in a single place in the compiler >> (gcc-interface/decl.c:gnat_to_gnu_entity): >> >> /* Tell the middle-end that objects of tagged types are guaranteed >> to >> be properly aligned. This is necessary because conversions to >> the >> class-wide type are translated into conversions to the root type, >> which can be less aligned than some of its derived types. */ >> if (Is_Tagged_Type (gnat_entity) >> || Is_Class_Wide_Equivalent_Type (gnat_entity)) >> TYPE_ALIGN_OK (gnu_type) = 1; >> >> but we changed the way these conversions are done some time ago. > > So does this remove the last concern around Bernd's patch? And can we remove TYPE_ALIGN_OK as followup? (ISTR it's used by obj-c/c++ as well, but I can't find such use) Thanks, Richard. > Jeff > ^ permalink raw reply [flat|nested] 105+ messages in thread
* Re: [PATCH] Remove "keep_aligning" from get_inner_reference 2014-05-05 8:00 ` Richard Biener @ 2014-05-05 20:25 ` Mike Stump 2014-05-14 7:30 ` Eric Botcazou 1 sibling, 0 replies; 105+ messages in thread From: Mike Stump @ 2014-05-05 20:25 UTC (permalink / raw) To: Richard Biener Cc: Jeff Law, Eric Botcazou, Bernd Edlinger, GCC Patches, Martin Jambor, Jakub Jelinek On May 5, 2014, at 1:00 AM, Richard Biener <richard.guenther@gmail.com> wrote: > And can we remove TYPE_ALIGN_OK as followup? (ISTR it's used > by obj-c/c++ as well, but I can't find such use) I didn’t find any current hint… the only landmine I found was: ./gcc/config/pa/pa.c:1878: /* Using TYPE_ALIGN_OK is rather conservative as ./gcc/config/pa/pa.c:1880: align = (TYPE_ALIGN_OK (type) ? TYPE_ALIGN (type) ^ permalink raw reply [flat|nested] 105+ messages in thread
* Re: [PATCH] Remove "keep_aligning" from get_inner_reference 2014-05-05 8:00 ` Richard Biener 2014-05-05 20:25 ` Mike Stump @ 2014-05-14 7:30 ` Eric Botcazou 2014-05-14 9:06 ` Bernd Edlinger 1 sibling, 1 reply; 105+ messages in thread From: Eric Botcazou @ 2014-05-14 7:30 UTC (permalink / raw) To: Richard Biener Cc: gcc-patches, Jeff Law, Bernd Edlinger, Martin Jambor, Jakub Jelinek > > So does this remove the last concern around Bernd's patch? > > And can we remove TYPE_ALIGN_OK as followup? (ISTR it's used > by obj-c/c++ as well, but I can't find such use) Probably but, as previously indicated, I need to do some testing first. -- Eric Botcazou ^ permalink raw reply [flat|nested] 105+ messages in thread
* RE: [PATCH] Remove "keep_aligning" from get_inner_reference 2014-05-14 7:30 ` Eric Botcazou @ 2014-05-14 9:06 ` Bernd Edlinger 0 siblings, 0 replies; 105+ messages in thread From: Bernd Edlinger @ 2014-05-14 9:06 UTC (permalink / raw) To: Eric Botcazou, Richard Biener Cc: gcc-patches, Jeff Law, Martin Jambor, Jakub Jelinek Hi Eric, On Wed, 14 May 2014 09:28:55, Eric Botcazou wrote: > >>> So does this remove the last concern around Bernd's patch? >> >> And can we remove TYPE_ALIGN_OK as followup? (ISTR it's used >> by obj-c/c++ as well, but I can't find such use) > > Probably but, as previously indicated, I need to do some testing first. > > -- > Eric Botcazou Ok sure, I'll be patient... If I remove this line, the build fails: gcc-interface/decl.c:gnat_to_gnu_entity: /* Tell the middle-end that objects of tagged types are guaranteed to be properly aligned. This is necessary because conversions to the class-wide type are translated into conversions to the root type, which can be less aligned than some of its derived types. */ if (Is_Tagged_Type (gnat_entity) || Is_Class_Wide_Equivalent_Type (gnat_entity)) TYPE_ALIGN_OK (gnu_type) = 1; but only because this bit is read back in the ada/gcc-interface. If I apply my patch, and additionally remove this line in expr.c, which is one of the last references to TYPE_ALIGN_OK in the middle-end: if (TYPE_ALIGN_OK (type)) { /* ??? Copying the MEM without substantially changing it might run afoul of the code handling volatile memory references in store_expr, which assumes that TARGET is returned unmodified if it has been used. */ op0 = copy_rtx (op0); set_mem_align (op0, MAX (MEM_ALIGN (op0), TYPE_ALIGN (type))); } nothing changes. All test cases pass, and again I can not see any difference in the generated code (I compare gcc/ada/*.o with and without patch). So, currently I am under the impression that TYPE_ALIGN_OK has some relevance to the Ada front-end, but it should not be used in the middle-end and certainly not in the back-end. Bernd. ^ permalink raw reply [flat|nested] 105+ messages in thread
* RE: [PATCH, PR 57748] Check for out of bounds access, Part 2 2013-10-25 11:10 ` Richard Biener 2013-10-25 14:01 ` Martin Jambor 2013-10-27 20:21 ` [PATCH] Remove "keep_aligning" from get_inner_reference Bernd Edlinger @ 2013-11-07 13:23 ` Bernd Edlinger 2013-11-07 13:23 ` Bernd Edlinger 2 siblings, 1 reply; 105+ messages in thread From: Bernd Edlinger @ 2013-11-07 13:23 UTC (permalink / raw) To: Richard Biener; +Cc: Eric Botcazou, GCC Patches, Martin Jambor, Jakub Jelinek Hi, On Fri, 25 Oct 2013 12:51:13, Richard Biener wrote: > > On Fri, Oct 25, 2013 at 12:02 PM, Bernd Edlinger > <bernd.edlinger@hotmail.de> wrote: >> Hi, >> >>> Eh ... even >>> >>> register struct { int i; int a[0]; } asm ("ebx"); >>> >>> works. Also with int a[1] but not with a[2]. So just handling trailing >>> arrays makes this case regress as well. >>> >>> Now I'd call this use questionable ... but we've likely supported that >>> for decades and cannot change that now. >>> >>> Back to fixing everything in expand. >>> >>> Richard. >>> >> >> Ok, finally you asked for it. >> >> Here is my previous version of that patch again. >> >> I have now added a new value "EXPAND_REFERENCE" to the expand_modifier >> enumeration. It is almost like EXPAND_MEMORY but it does not interfere with >> constant values. >> >> I have done the same modification to VIEW_CONVERT_EXPR too, because >> this is a possible inner reference, itself. It is however inherently hard to >> test around this code. >> >> To understand this patch it is good to know what type of object the >> return value "tem" of get_inner_reference can be. >> >> From the program logic at get_inner_reference it is clear that the >> return value may *not* be BIT_FIELD_REF, COMPONENT_REF, ARRAY_REF, >> ARRAY_RANGE_REF, REALPART_EXPR, IMAGPART_EXPR. The result may >> be VIEW_CONVERT_EXPR only on a STRICT_ALIGNMENT target. This is probably >> further restricted because exp is gimplified. >> >> Usually the result will be a MEM_REF or a SSA_NAME of the memory where >> the structure is to be found. >> >> When you look at where EXPAND_MEMORY is handled you see it is special-cased >> in TARGET_MEM_REF, MEM_REF, ARRAY_REF, COMPONENT_REF, BIT_FIELD_REF, >> ARRAY_RANGE_REF. >> >> At TARGET_MEM_REF, MEM_REF, VIEW_CONVERT_EXPR, it should be the >> same if EXPAND_MEMORY, EXPAND_WRITE or EXPAND_REFERENCE is given: >> If it is an unaligned memory, we just return the unaligned reference. >> >> This was missing for VIEW_CONVERT_EXPR, and unfortunately I have no test case, >> because it is only a problem for STRICT_ALIGNMENT targets, and even there it will >> certainly be really hard to find test cases that exercise this code. >> >> In ARRAY_REF, COMPONENT_REF, BIT_FIELD_REF, ARRAY_RANGE_REF >> we do not have to touch the handling of the outer modifier. However we pass >> EXPAND_REFERENCE to the inner object, which should not be a recursive >> use of any ARRAY_REF, COMPONENT_REF, BIT_FIELD_REF, ARRAY_RANGE_REF. >> >> TARGET_MEM_REF, MEM_REF and VIEW_CONVERT_EXPR know how to handle >> EXPAND_REFERENCE, anything else handles it like EXPAND_NORMAL. >> >> >> Boot-strapped and regression-tested on x86_64-linux-gnu >> OK for trunk? > > You point to a weak spot in expansion - that it handles creating > the base MEM to offset with handled components by recursing > into the case that handles bare MEM_REFs. This makes the > bare MEM_REF handling code somewhat awkward (it's the > one to assign mem-attrs which are later adjusted for example). > > Maybe a better appropach than adding yet another expand > modifier would be to split out the "base MEM" expansion part > out of the bare MEM_REF handling code so we can call that > instead of recursing. > > In this light - instead of a new expand modifier don't you want > an actual flag that specifies we are coming from a call that > wants to expand a base? That is, allow EXPAND_SUM > but with the recursion flag set? > I think you are right. After some thought, I start to like that idea. This way we have at least much more flexibility, how to handle the inner references correctly, and if I change only the interfaces of expand_expr_real/real_1 that will not be used at too many places, either. > Finally I think the recursion into the VIEW_CONVERT_EXPR case > is only there because of the keep_aligning flag of get_inner_reference > which should be obsolete now that we properly handle its effects > in get_object_alignment. So you wouldn't need to adjust this path > if we finally can get rid of that. > I proposed a patch for that, but did not hear from you: http://gcc.gnu.org/ml/gcc-patches/2013-10/msg02267.html nevertheless, even if the VIEW_CONVERT_EXPR may or may not be an inner reference, the code there should be kept in sync with the normal_inner_ref, and MEM_REF, IMHO. Attached, my updated patch for PR57748, Part 2. Boot-strapped and regression-tested on X86_64-pc-linux-gnu. Ok for trunk? Thanks Bernd. > What do others think? > > Thanks, > Richard. > >> Thanks >> Bernd. ^ permalink raw reply [flat|nested] 105+ messages in thread
* RE: [PATCH, PR 57748] Check for out of bounds access, Part 2 2013-11-07 13:23 ` [PATCH, PR 57748] Check for out of bounds access, Part 2 Bernd Edlinger @ 2013-11-07 13:23 ` Bernd Edlinger 2013-11-19 15:05 ` Bernd Edlinger 0 siblings, 1 reply; 105+ messages in thread From: Bernd Edlinger @ 2013-11-07 13:23 UTC (permalink / raw) To: Richard Biener; +Cc: Eric Botcazou, GCC Patches, Martin Jambor, Jakub Jelinek [-- Attachment #1: Type: text/plain, Size: 4836 bytes --] oops - this time with attachments... > Hi, > > On Fri, 25 Oct 2013 12:51:13, Richard Biener wrote: >> >> On Fri, Oct 25, 2013 at 12:02 PM, Bernd Edlinger >> <bernd.edlinger@hotmail.de> wrote: >>> Hi, >>> >>>> Eh ... even >>>> >>>> register struct { int i; int a[0]; } asm ("ebx"); >>>> >>>> works. Also with int a[1] but not with a[2]. So just handling trailing >>>> arrays makes this case regress as well. >>>> >>>> Now I'd call this use questionable ... but we've likely supported that >>>> for decades and cannot change that now. >>>> >>>> Back to fixing everything in expand. >>>> >>>> Richard. >>>> >>> >>> Ok, finally you asked for it. >>> >>> Here is my previous version of that patch again. >>> >>> I have now added a new value "EXPAND_REFERENCE" to the expand_modifier >>> enumeration. It is almost like EXPAND_MEMORY but it does not interfere with >>> constant values. >>> >>> I have done the same modification to VIEW_CONVERT_EXPR too, because >>> this is a possible inner reference, itself. It is however inherently hard to >>> test around this code. >>> >>> To understand this patch it is good to know what type of object the >>> return value "tem" of get_inner_reference can be. >>> >>> From the program logic at get_inner_reference it is clear that the >>> return value may *not* be BIT_FIELD_REF, COMPONENT_REF, ARRAY_REF, >>> ARRAY_RANGE_REF, REALPART_EXPR, IMAGPART_EXPR. The result may >>> be VIEW_CONVERT_EXPR only on a STRICT_ALIGNMENT target. This is probably >>> further restricted because exp is gimplified. >>> >>> Usually the result will be a MEM_REF or a SSA_NAME of the memory where >>> the structure is to be found. >>> >>> When you look at where EXPAND_MEMORY is handled you see it is special-cased >>> in TARGET_MEM_REF, MEM_REF, ARRAY_REF, COMPONENT_REF, BIT_FIELD_REF, >>> ARRAY_RANGE_REF. >>> >>> At TARGET_MEM_REF, MEM_REF, VIEW_CONVERT_EXPR, it should be the >>> same if EXPAND_MEMORY, EXPAND_WRITE or EXPAND_REFERENCE is given: >>> If it is an unaligned memory, we just return the unaligned reference. >>> >>> This was missing for VIEW_CONVERT_EXPR, and unfortunately I have no test case, >>> because it is only a problem for STRICT_ALIGNMENT targets, and even there it will >>> certainly be really hard to find test cases that exercise this code. >>> >>> In ARRAY_REF, COMPONENT_REF, BIT_FIELD_REF, ARRAY_RANGE_REF >>> we do not have to touch the handling of the outer modifier. However we pass >>> EXPAND_REFERENCE to the inner object, which should not be a recursive >>> use of any ARRAY_REF, COMPONENT_REF, BIT_FIELD_REF, ARRAY_RANGE_REF. >>> >>> TARGET_MEM_REF, MEM_REF and VIEW_CONVERT_EXPR know how to handle >>> EXPAND_REFERENCE, anything else handles it like EXPAND_NORMAL. >>> >>> >>> Boot-strapped and regression-tested on x86_64-linux-gnu >>> OK for trunk? >> >> You point to a weak spot in expansion - that it handles creating >> the base MEM to offset with handled components by recursing >> into the case that handles bare MEM_REFs. This makes the >> bare MEM_REF handling code somewhat awkward (it's the >> one to assign mem-attrs which are later adjusted for example). >> >> Maybe a better appropach than adding yet another expand >> modifier would be to split out the "base MEM" expansion part >> out of the bare MEM_REF handling code so we can call that >> instead of recursing. >> >> In this light - instead of a new expand modifier don't you want >> an actual flag that specifies we are coming from a call that >> wants to expand a base? That is, allow EXPAND_SUM >> but with the recursion flag set? >> > > I think you are right. After some thought, I start to like that idea. > > This way we have at least much more flexibility, how to handle the inner > references correctly, and if I change only the interfaces of expand_expr_real/real_1 > that will not be used at too many places, either. > >> Finally I think the recursion into the VIEW_CONVERT_EXPR case >> is only there because of the keep_aligning flag of get_inner_reference >> which should be obsolete now that we properly handle its effects >> in get_object_alignment. So you wouldn't need to adjust this path >> if we finally can get rid of that. >> > > I proposed a patch for that, but did not hear from you: > http://gcc.gnu.org/ml/gcc-patches/2013-10/msg02267.html > > nevertheless, even if the VIEW_CONVERT_EXPR may or may not be an inner > reference, the code there should be kept in sync with the normal_inner_ref, > and MEM_REF, IMHO. > > Attached, my updated patch for PR57748, Part 2. > > Boot-strapped and regression-tested on X86_64-pc-linux-gnu. > > Ok for trunk? > > > Thanks > Bernd. > >> What do others think? >> >> Thanks, >> Richard. >> >>> Thanks >>> Bernd. [-- Attachment #2: changelog-pr57748-2.txt --] [-- Type: text/plain, Size: 579 bytes --] 2013-11-07 Bernd Edlinger <bernd.edlinger@hotmail.de> PR middle-end/57748 * expr.h (expand_expr_real, expand_expr_real_1): Add new parameter expand_reference. (expand_expr, expand_normal): Adjust. * expr.c (expand_expr_real, expand_expr_real_1): Add new parameter expand_reference. Use expand_reference to expand inner references. (store_expr): Adjust. * cfgexpand.c (expand_call_stmt): Adjust. testsuite: 2013-11-07 Bernd Edlinger <bernd.edlinger@hotmail.de> PR middle-end/57748 * gcc.dg/torture/pr57748-3.c: New test. * gcc.dg/torture/pr57748-4.c: New test. [-- Attachment #3: patch-pr57748-2.diff --] [-- Type: application/octet-stream, Size: 10472 bytes --] Index: gcc/expr.h =================================================================== --- gcc/expr.h (revision 204411) +++ gcc/expr.h (working copy) @@ -41,7 +41,8 @@ along with GCC; see the file COPYING3. If not see is a constant that is not a legitimate address. EXPAND_WRITE means we are only going to write to the resulting rtx. EXPAND_MEMORY means we are interested in a memory result, even if - the memory is constant and we could have propagated a constant value. */ + the memory is constant and we could have propagated a constant value, + or the memory is unaligned on a STRICT_ALIGNMENT target. */ enum expand_modifier {EXPAND_NORMAL = 0, EXPAND_STACK_PARM, EXPAND_SUM, EXPAND_CONST_ADDRESS, EXPAND_INITIALIZER, EXPAND_WRITE, EXPAND_MEMORY}; @@ -428,9 +429,9 @@ extern rtx force_operand (rtx, rtx); /* Work horses for expand_expr. */ extern rtx expand_expr_real (tree, rtx, enum machine_mode, - enum expand_modifier, rtx *); + enum expand_modifier, rtx *, bool); extern rtx expand_expr_real_1 (tree, rtx, enum machine_mode, - enum expand_modifier, rtx *); + enum expand_modifier, rtx *, bool); extern rtx expand_expr_real_2 (sepops, rtx, enum machine_mode, enum expand_modifier); @@ -441,13 +442,13 @@ static inline rtx expand_expr (tree exp, rtx target, enum machine_mode mode, enum expand_modifier modifier) { - return expand_expr_real (exp, target, mode, modifier, NULL); + return expand_expr_real (exp, target, mode, modifier, NULL, false); } static inline rtx expand_normal (tree exp) { - return expand_expr_real (exp, NULL_RTX, VOIDmode, EXPAND_NORMAL, NULL); + return expand_expr_real (exp, NULL_RTX, VOIDmode, EXPAND_NORMAL, NULL, false); } /* At the start of a function, record that we have no previously-pushed Index: gcc/expr.c =================================================================== --- gcc/expr.c (revision 204411) +++ gcc/expr.c (working copy) @@ -5211,7 +5211,7 @@ store_expr (tree exp, rtx target, int call_param_p temp = expand_expr_real (exp, tmp_target, GET_MODE (target), (call_param_p ? EXPAND_STACK_PARM : EXPAND_NORMAL), - &alt_rtl); + &alt_rtl, false); } /* If TEMP is a VOIDmode constant and the mode of the type of EXP is not @@ -7768,11 +7768,14 @@ expand_constructor (tree exp, rtx target, enum exp address, and ALT_RTL is non-NULL, then *ALT_RTL is set to the DECL_RTL of the VAR_DECL. *ALT_RTL is also set if EXP is a COMPOUND_EXPR whose second argument is such a VAR_DECL, and so on - recursively. */ + recursively. + If EXPAND_REFERENCE is true, we are expanding an inner reference. */ + rtx expand_expr_real (tree exp, rtx target, enum machine_mode tmode, - enum expand_modifier modifier, rtx *alt_rtl) + enum expand_modifier modifier, rtx *alt_rtl, + bool expand_reference) { rtx ret; @@ -7784,7 +7787,8 @@ expand_expr_real (tree exp, rtx target, enum machi return ret ? ret : const0_rtx; } - ret = expand_expr_real_1 (exp, target, tmode, modifier, alt_rtl); + ret = expand_expr_real_1 (exp, target, tmode, modifier, alt_rtl, + expand_reference); return ret; } @@ -9095,7 +9099,8 @@ stmt_is_replaceable_p (gimple stmt) rtx expand_expr_real_1 (tree exp, rtx target, enum machine_mode tmode, - enum expand_modifier modifier, rtx *alt_rtl) + enum expand_modifier modifier, rtx *alt_rtl, + bool expand_reference) { rtx op0, op1, temp, decl_rtl; tree type; @@ -9241,7 +9246,7 @@ expand_expr_real_1 (tree exp, rtx target, enum mac set_curr_insn_location (gimple_location (g)); r = expand_expr_real (gimple_assign_rhs_to_tree (g), target, - tmode, modifier, NULL); + tmode, modifier, NULL, false); set_curr_insn_location (saved_loc); if (REG_P (r) && !REG_EXPR (r)) set_reg_attrs_for_decl_rtl (SSA_NAME_VAR (exp), r); @@ -9462,7 +9467,8 @@ expand_expr_real_1 (tree exp, rtx target, enum mac case SAVE_EXPR: { tree val = treeop0; - rtx ret = expand_expr_real_1 (val, target, tmode, modifier, alt_rtl); + rtx ret = expand_expr_real_1 (val, target, tmode, modifier, alt_rtl, + expand_reference); if (!SAVE_EXPR_RESOLVED_P (exp)) { @@ -9520,6 +9526,7 @@ expand_expr_real_1 (tree exp, rtx target, enum mac align = get_object_alignment (exp); if (modifier != EXPAND_WRITE && modifier != EXPAND_MEMORY + && !expand_reference && mode != BLKmode && align < GET_MODE_ALIGNMENT (mode) /* If the target does not have special handling for unaligned @@ -9600,6 +9607,7 @@ expand_expr_real_1 (tree exp, rtx target, enum mac MEM_VOLATILE_P (temp) = 1; if (modifier != EXPAND_WRITE && modifier != EXPAND_MEMORY + && !expand_reference && mode != BLKmode && align < GET_MODE_ALIGNMENT (mode)) { @@ -9825,15 +9833,16 @@ expand_expr_real_1 (tree exp, rtx target, enum mac computation, since it will need a temporary and TARGET is known to have to do. This occurs in unchecked conversion in Ada. */ orig_op0 = op0 - = expand_expr (tem, - (TREE_CODE (TREE_TYPE (tem)) == UNION_TYPE - && COMPLETE_TYPE_P (TREE_TYPE (tem)) - && (TREE_CODE (TYPE_SIZE (TREE_TYPE (tem))) - != INTEGER_CST) - && modifier != EXPAND_STACK_PARM - ? target : NULL_RTX), - VOIDmode, - modifier == EXPAND_SUM ? EXPAND_NORMAL : modifier); + = expand_expr_real (tem, + (TREE_CODE (TREE_TYPE (tem)) == UNION_TYPE + && COMPLETE_TYPE_P (TREE_TYPE (tem)) + && (TREE_CODE (TYPE_SIZE (TREE_TYPE (tem))) + != INTEGER_CST) + && modifier != EXPAND_STACK_PARM + ? target : NULL_RTX), + VOIDmode, + modifier == EXPAND_SUM ? EXPAND_NORMAL : modifier, + NULL, true); /* If the bitfield is volatile, we want to access it in the field's mode, not the computed mode. @@ -10185,14 +10194,15 @@ expand_expr_real_1 (tree exp, rtx target, enum mac { /* See the normal_inner_ref case for the rationale. */ orig_op0 - = expand_expr (tem, - (TREE_CODE (TREE_TYPE (tem)) == UNION_TYPE - && (TREE_CODE (TYPE_SIZE (TREE_TYPE (tem))) - != INTEGER_CST) - && modifier != EXPAND_STACK_PARM - ? target : NULL_RTX), - VOIDmode, - modifier == EXPAND_SUM ? EXPAND_NORMAL : modifier); + = expand_expr_real (tem, + (TREE_CODE (TREE_TYPE (tem)) == UNION_TYPE + && (TREE_CODE (TYPE_SIZE (TREE_TYPE (tem))) + != INTEGER_CST) + && modifier != EXPAND_STACK_PARM + ? target : NULL_RTX), + VOIDmode, + modifier == EXPAND_SUM ? EXPAND_NORMAL : modifier, + NULL, true); if (MEM_P (orig_op0)) { @@ -10286,7 +10296,10 @@ expand_expr_real_1 (tree exp, rtx target, enum mac op0 = copy_rtx (op0); set_mem_align (op0, MAX (MEM_ALIGN (op0), TYPE_ALIGN (type))); } - else if (mode != BLKmode + else if (modifier != EXPAND_WRITE + && modifier != EXPAND_MEMORY + && !expand_reference + && mode != BLKmode && MEM_ALIGN (op0) < GET_MODE_ALIGNMENT (mode) /* If the target does have special handling for unaligned loads of mode then use them. */ @@ -10307,6 +10320,9 @@ expand_expr_real_1 (tree exp, rtx target, enum mac return reg; } else if (STRICT_ALIGNMENT + && modifier != EXPAND_WRITE + && modifier != EXPAND_MEMORY + && !expand_reference && mode != BLKmode && MEM_ALIGN (op0) < GET_MODE_ALIGNMENT (mode)) { @@ -10429,7 +10445,7 @@ expand_expr_real_1 (tree exp, rtx target, enum mac /* WITH_SIZE_EXPR expands to its first argument. The caller should have pulled out the size to use in whatever context it needed. */ return expand_expr_real (treeop0, original_target, tmode, - modifier, alt_rtl); + modifier, alt_rtl, expand_reference); default: return expand_expr_real_2 (&ops, target, tmode, modifier); Index: gcc/cfgexpand.c =================================================================== --- gcc/cfgexpand.c (revision 204411) +++ gcc/cfgexpand.c (working copy) @@ -2189,7 +2189,7 @@ expand_call_stmt (gimple stmt) if (lhs) expand_assignment (lhs, exp, false); else - expand_expr_real_1 (exp, const0_rtx, VOIDmode, EXPAND_NORMAL, NULL); + expand_expr_real_1 (exp, const0_rtx, VOIDmode, EXPAND_NORMAL, NULL, false); mark_transaction_restart_calls (stmt); } Index: gcc/testsuite/gcc.dg/torture/pr57748-3.c =================================================================== --- gcc/testsuite/gcc.dg/torture/pr57748-3.c (revision 0) +++ gcc/testsuite/gcc.dg/torture/pr57748-3.c (revision 0) @@ -0,0 +1,40 @@ +/* PR middle-end/57748 */ +/* { dg-do run } */ +/* wrong code in expand_expr_real_1. */ + +#include <stdlib.h> + +extern void abort (void); + +typedef long long V + __attribute__ ((vector_size (2 * sizeof (long long)), may_alias)); + +typedef struct S { V a; V b[0]; } P __attribute__((aligned (1))); + +struct __attribute__((packed)) T { char c; P s; }; + +void __attribute__((noinline, noclone)) +check (P *p) +{ + if (p->b[0][0] != 3 || p->b[0][1] != 4) + abort (); +} + +void __attribute__((noinline, noclone)) +foo (struct T *t) +{ + V a = { 3, 4 }; + t->s.b[0] = a; +} + +int +main () +{ + struct T *t = (struct T *) calloc (128, 1); + + foo (t); + check (&t->s); + + free (t); + return 0; +} Index: gcc/testsuite/gcc.dg/torture/pr57748-4.c =================================================================== --- gcc/testsuite/gcc.dg/torture/pr57748-4.c (revision 0) +++ gcc/testsuite/gcc.dg/torture/pr57748-4.c (revision 0) @@ -0,0 +1,40 @@ +/* PR middle-end/57748 */ +/* { dg-do run } */ +/* wrong code in expand_expr_real_1. */ + +#include <stdlib.h> + +extern void abort (void); + +typedef long long V + __attribute__ ((vector_size (2 * sizeof (long long)), may_alias)); + +typedef struct S { V b[1]; } P __attribute__((aligned (1))); + +struct __attribute__((packed)) T { char c; P s; }; + +void __attribute__((noinline, noclone)) +check (P *p) +{ + if (p->b[1][0] != 3 || p->b[1][1] != 4) + abort (); +} + +void __attribute__((noinline, noclone)) +foo (struct T *t) +{ + V a = { 3, 4 }; + t->s.b[1] = a; +} + +int +main () +{ + struct T *t = (struct T *) calloc (128, 1); + + foo (t); + check (&t->s); + + free (t); + return 0; +} ^ permalink raw reply [flat|nested] 105+ messages in thread
* [PATCH, PR 57748] Check for out of bounds access, Part 2 2013-11-07 13:23 ` Bernd Edlinger @ 2013-11-19 15:05 ` Bernd Edlinger 2013-11-27 16:22 ` [PING] " Bernd Edlinger 0 siblings, 1 reply; 105+ messages in thread From: Bernd Edlinger @ 2013-11-19 15:05 UTC (permalink / raw) To: Richard Biener; +Cc: Eric Botcazou, GCC Patches, Martin Jambor, Jakub Jelinek [-- Attachment #1: Type: text/plain, Size: 5850 bytes --] Hello, this is a minor update to my previous version of this patch, (using a boolean expand_reference, instead of adding a new expand_modifier enum value): I forgot to pass down the expand_reference value at the second expand_expr call inside the case VIEW_CONVERT_EXPR. Sorry for the inconvenience. @@ -10219,7 +10229,8 @@ expand_expr_real_1 (tree exp, rtx target, enum mac } if (!op0) - op0 = expand_expr (treeop0, NULL_RTX, VOIDmode, modifier); + op0 = expand_expr_real (treeop0, NULL_RTX, VOIDmode, modifier, + NULL, expand_reference); /* If the input and output modes are both the same, we are done. */ if (mode == GET_MODE (op0)) Boot-strapped and regression-tested on X86_64-pc-linux-gnu. Ok for trunk? Thanks Bernd. > Date: Thu, 7 Nov 2013 13:58:55 +0100 > > oops - this time with attachments... > > >> Hi, >> >> On Fri, 25 Oct 2013 12:51:13, Richard Biener wrote: >>> >>> On Fri, Oct 25, 2013 at 12:02 PM, Bernd Edlinger >>> <bernd.edlinger@hotmail.de> wrote: >>>> Hi, >>>> >>>>> Eh ... even >>>>> >>>>> register struct { int i; int a[0]; } asm ("ebx"); >>>>> >>>>> works. Also with int a[1] but not with a[2]. So just handling trailing >>>>> arrays makes this case regress as well. >>>>> >>>>> Now I'd call this use questionable ... but we've likely supported that >>>>> for decades and cannot change that now. >>>>> >>>>> Back to fixing everything in expand. >>>>> >>>>> Richard. >>>>> >>>> >>>> Ok, finally you asked for it. >>>> >>>> Here is my previous version of that patch again. >>>> >>>> I have now added a new value "EXPAND_REFERENCE" to the expand_modifier >>>> enumeration. It is almost like EXPAND_MEMORY but it does not interfere with >>>> constant values. >>>> >>>> I have done the same modification to VIEW_CONVERT_EXPR too, because >>>> this is a possible inner reference, itself. It is however inherently hard to >>>> test around this code. >>>> >>>> To understand this patch it is good to know what type of object the >>>> return value "tem" of get_inner_reference can be. >>>> >>>> From the program logic at get_inner_reference it is clear that the >>>> return value may *not* be BIT_FIELD_REF, COMPONENT_REF, ARRAY_REF, >>>> ARRAY_RANGE_REF, REALPART_EXPR, IMAGPART_EXPR. The result may >>>> be VIEW_CONVERT_EXPR only on a STRICT_ALIGNMENT target. This is probably >>>> further restricted because exp is gimplified. >>>> >>>> Usually the result will be a MEM_REF or a SSA_NAME of the memory where >>>> the structure is to be found. >>>> >>>> When you look at where EXPAND_MEMORY is handled you see it is special-cased >>>> in TARGET_MEM_REF, MEM_REF, ARRAY_REF, COMPONENT_REF, BIT_FIELD_REF, >>>> ARRAY_RANGE_REF. >>>> >>>> At TARGET_MEM_REF, MEM_REF, VIEW_CONVERT_EXPR, it should be the >>>> same if EXPAND_MEMORY, EXPAND_WRITE or EXPAND_REFERENCE is given: >>>> If it is an unaligned memory, we just return the unaligned reference. >>>> >>>> This was missing for VIEW_CONVERT_EXPR, and unfortunately I have no test case, >>>> because it is only a problem for STRICT_ALIGNMENT targets, and even there it will >>>> certainly be really hard to find test cases that exercise this code. >>>> >>>> In ARRAY_REF, COMPONENT_REF, BIT_FIELD_REF, ARRAY_RANGE_REF >>>> we do not have to touch the handling of the outer modifier. However we pass >>>> EXPAND_REFERENCE to the inner object, which should not be a recursive >>>> use of any ARRAY_REF, COMPONENT_REF, BIT_FIELD_REF, ARRAY_RANGE_REF. >>>> >>>> TARGET_MEM_REF, MEM_REF and VIEW_CONVERT_EXPR know how to handle >>>> EXPAND_REFERENCE, anything else handles it like EXPAND_NORMAL. >>>> >>>> >>>> Boot-strapped and regression-tested on x86_64-linux-gnu >>>> OK for trunk? >>> >>> You point to a weak spot in expansion - that it handles creating >>> the base MEM to offset with handled components by recursing >>> into the case that handles bare MEM_REFs. This makes the >>> bare MEM_REF handling code somewhat awkward (it's the >>> one to assign mem-attrs which are later adjusted for example). >>> >>> Maybe a better appropach than adding yet another expand >>> modifier would be to split out the "base MEM" expansion part >>> out of the bare MEM_REF handling code so we can call that >>> instead of recursing. >>> >>> In this light - instead of a new expand modifier don't you want >>> an actual flag that specifies we are coming from a call that >>> wants to expand a base? That is, allow EXPAND_SUM >>> but with the recursion flag set? >>> >> >> I think you are right. After some thought, I start to like that idea. >> >> This way we have at least much more flexibility, how to handle the inner >> references correctly, and if I change only the interfaces of expand_expr_real/real_1 >> that will not be used at too many places, either. >> >>> Finally I think the recursion into the VIEW_CONVERT_EXPR case >>> is only there because of the keep_aligning flag of get_inner_reference >>> which should be obsolete now that we properly handle its effects >>> in get_object_alignment. So you wouldn't need to adjust this path >>> if we finally can get rid of that. >>> >> >> I proposed a patch for that, but did not hear from you: >> http://gcc.gnu.org/ml/gcc-patches/2013-10/msg02267.html >> >> nevertheless, even if the VIEW_CONVERT_EXPR may or may not be an inner >> reference, the code there should be kept in sync with the normal_inner_ref, >> and MEM_REF, IMHO. >> >> Attached, my updated patch for PR57748, Part 2. >> >> Boot-strapped and regression-tested on X86_64-pc-linux-gnu. >> >> Ok for trunk? >> >> >> Thanks >> Bernd. >> >>> What do others think? >>> >>> Thanks, >>> Richard. >>> >>>> Thanks >>>> Bernd. [-- Attachment #2: changelog-pr57748-2.txt --] [-- Type: text/plain, Size: 579 bytes --] 2013-11-07 Bernd Edlinger <bernd.edlinger@hotmail.de> PR middle-end/57748 * expr.h (expand_expr_real, expand_expr_real_1): Add new parameter expand_reference. (expand_expr, expand_normal): Adjust. * expr.c (expand_expr_real, expand_expr_real_1): Add new parameter expand_reference. Use expand_reference to expand inner references. (store_expr): Adjust. * cfgexpand.c (expand_call_stmt): Adjust. testsuite: 2013-11-07 Bernd Edlinger <bernd.edlinger@hotmail.de> PR middle-end/57748 * gcc.dg/torture/pr57748-3.c: New test. * gcc.dg/torture/pr57748-4.c: New test. [-- Attachment #3: patch-pr57748-2.diff --] [-- Type: application/octet-stream, Size: 10855 bytes --] Index: gcc/expr.h =================================================================== --- gcc/expr.h (revision 204411) +++ gcc/expr.h (working copy) @@ -41,7 +41,8 @@ along with GCC; see the file COPYING3. If not see is a constant that is not a legitimate address. EXPAND_WRITE means we are only going to write to the resulting rtx. EXPAND_MEMORY means we are interested in a memory result, even if - the memory is constant and we could have propagated a constant value. */ + the memory is constant and we could have propagated a constant value, + or the memory is unaligned on a STRICT_ALIGNMENT target. */ enum expand_modifier {EXPAND_NORMAL = 0, EXPAND_STACK_PARM, EXPAND_SUM, EXPAND_CONST_ADDRESS, EXPAND_INITIALIZER, EXPAND_WRITE, EXPAND_MEMORY}; @@ -428,9 +429,9 @@ extern rtx force_operand (rtx, rtx); /* Work horses for expand_expr. */ extern rtx expand_expr_real (tree, rtx, enum machine_mode, - enum expand_modifier, rtx *); + enum expand_modifier, rtx *, bool); extern rtx expand_expr_real_1 (tree, rtx, enum machine_mode, - enum expand_modifier, rtx *); + enum expand_modifier, rtx *, bool); extern rtx expand_expr_real_2 (sepops, rtx, enum machine_mode, enum expand_modifier); @@ -441,13 +442,13 @@ static inline rtx expand_expr (tree exp, rtx target, enum machine_mode mode, enum expand_modifier modifier) { - return expand_expr_real (exp, target, mode, modifier, NULL); + return expand_expr_real (exp, target, mode, modifier, NULL, false); } static inline rtx expand_normal (tree exp) { - return expand_expr_real (exp, NULL_RTX, VOIDmode, EXPAND_NORMAL, NULL); + return expand_expr_real (exp, NULL_RTX, VOIDmode, EXPAND_NORMAL, NULL, false); } /* At the start of a function, record that we have no previously-pushed Index: gcc/expr.c =================================================================== --- gcc/expr.c (revision 204411) +++ gcc/expr.c (working copy) @@ -5211,7 +5211,7 @@ store_expr (tree exp, rtx target, int call_param_p temp = expand_expr_real (exp, tmp_target, GET_MODE (target), (call_param_p ? EXPAND_STACK_PARM : EXPAND_NORMAL), - &alt_rtl); + &alt_rtl, false); } /* If TEMP is a VOIDmode constant and the mode of the type of EXP is not @@ -7768,11 +7768,14 @@ expand_constructor (tree exp, rtx target, enum exp address, and ALT_RTL is non-NULL, then *ALT_RTL is set to the DECL_RTL of the VAR_DECL. *ALT_RTL is also set if EXP is a COMPOUND_EXPR whose second argument is such a VAR_DECL, and so on - recursively. */ + recursively. + If EXPAND_REFERENCE is true, we are expanding an inner reference. */ + rtx expand_expr_real (tree exp, rtx target, enum machine_mode tmode, - enum expand_modifier modifier, rtx *alt_rtl) + enum expand_modifier modifier, rtx *alt_rtl, + bool expand_reference) { rtx ret; @@ -7784,7 +7787,8 @@ expand_expr_real (tree exp, rtx target, enum machi return ret ? ret : const0_rtx; } - ret = expand_expr_real_1 (exp, target, tmode, modifier, alt_rtl); + ret = expand_expr_real_1 (exp, target, tmode, modifier, alt_rtl, + expand_reference); return ret; } @@ -9095,7 +9099,8 @@ stmt_is_replaceable_p (gimple stmt) rtx expand_expr_real_1 (tree exp, rtx target, enum machine_mode tmode, - enum expand_modifier modifier, rtx *alt_rtl) + enum expand_modifier modifier, rtx *alt_rtl, + bool expand_reference) { rtx op0, op1, temp, decl_rtl; tree type; @@ -9241,7 +9246,7 @@ expand_expr_real_1 (tree exp, rtx target, enum mac set_curr_insn_location (gimple_location (g)); r = expand_expr_real (gimple_assign_rhs_to_tree (g), target, - tmode, modifier, NULL); + tmode, modifier, NULL, expand_reference); set_curr_insn_location (saved_loc); if (REG_P (r) && !REG_EXPR (r)) set_reg_attrs_for_decl_rtl (SSA_NAME_VAR (exp), r); @@ -9462,7 +9467,8 @@ expand_expr_real_1 (tree exp, rtx target, enum mac case SAVE_EXPR: { tree val = treeop0; - rtx ret = expand_expr_real_1 (val, target, tmode, modifier, alt_rtl); + rtx ret = expand_expr_real_1 (val, target, tmode, modifier, alt_rtl, + expand_reference); if (!SAVE_EXPR_RESOLVED_P (exp)) { @@ -9520,6 +9526,7 @@ expand_expr_real_1 (tree exp, rtx target, enum mac align = get_object_alignment (exp); if (modifier != EXPAND_WRITE && modifier != EXPAND_MEMORY + && !expand_reference && mode != BLKmode && align < GET_MODE_ALIGNMENT (mode) /* If the target does not have special handling for unaligned @@ -9600,6 +9607,7 @@ expand_expr_real_1 (tree exp, rtx target, enum mac MEM_VOLATILE_P (temp) = 1; if (modifier != EXPAND_WRITE && modifier != EXPAND_MEMORY + && !expand_reference && mode != BLKmode && align < GET_MODE_ALIGNMENT (mode)) { @@ -9825,15 +9833,16 @@ expand_expr_real_1 (tree exp, rtx target, enum mac computation, since it will need a temporary and TARGET is known to have to do. This occurs in unchecked conversion in Ada. */ orig_op0 = op0 - = expand_expr (tem, - (TREE_CODE (TREE_TYPE (tem)) == UNION_TYPE - && COMPLETE_TYPE_P (TREE_TYPE (tem)) - && (TREE_CODE (TYPE_SIZE (TREE_TYPE (tem))) - != INTEGER_CST) - && modifier != EXPAND_STACK_PARM - ? target : NULL_RTX), - VOIDmode, - modifier == EXPAND_SUM ? EXPAND_NORMAL : modifier); + = expand_expr_real (tem, + (TREE_CODE (TREE_TYPE (tem)) == UNION_TYPE + && COMPLETE_TYPE_P (TREE_TYPE (tem)) + && (TREE_CODE (TYPE_SIZE (TREE_TYPE (tem))) + != INTEGER_CST) + && modifier != EXPAND_STACK_PARM + ? target : NULL_RTX), + VOIDmode, + modifier == EXPAND_SUM ? EXPAND_NORMAL : modifier, + NULL, true); /* If the bitfield is volatile, we want to access it in the field's mode, not the computed mode. @@ -10185,14 +10194,15 @@ expand_expr_real_1 (tree exp, rtx target, enum mac { /* See the normal_inner_ref case for the rationale. */ orig_op0 - = expand_expr (tem, - (TREE_CODE (TREE_TYPE (tem)) == UNION_TYPE - && (TREE_CODE (TYPE_SIZE (TREE_TYPE (tem))) - != INTEGER_CST) - && modifier != EXPAND_STACK_PARM - ? target : NULL_RTX), - VOIDmode, - modifier == EXPAND_SUM ? EXPAND_NORMAL : modifier); + = expand_expr_real (tem, + (TREE_CODE (TREE_TYPE (tem)) == UNION_TYPE + && (TREE_CODE (TYPE_SIZE (TREE_TYPE (tem))) + != INTEGER_CST) + && modifier != EXPAND_STACK_PARM + ? target : NULL_RTX), + VOIDmode, + modifier == EXPAND_SUM ? EXPAND_NORMAL : modifier, + NULL, true); if (MEM_P (orig_op0)) { @@ -10219,7 +10229,8 @@ expand_expr_real_1 (tree exp, rtx target, enum mac } if (!op0) - op0 = expand_expr (treeop0, NULL_RTX, VOIDmode, modifier); + op0 = expand_expr_real (treeop0, NULL_RTX, VOIDmode, modifier, + NULL, expand_reference); /* If the input and output modes are both the same, we are done. */ if (mode == GET_MODE (op0)) @@ -10286,7 +10297,10 @@ expand_expr_real_1 (tree exp, rtx target, enum mac op0 = copy_rtx (op0); set_mem_align (op0, MAX (MEM_ALIGN (op0), TYPE_ALIGN (type))); } - else if (mode != BLKmode + else if (modifier != EXPAND_WRITE + && modifier != EXPAND_MEMORY + && !expand_reference + && mode != BLKmode && MEM_ALIGN (op0) < GET_MODE_ALIGNMENT (mode) /* If the target does have special handling for unaligned loads of mode then use them. */ @@ -10307,6 +10321,9 @@ expand_expr_real_1 (tree exp, rtx target, enum mac return reg; } else if (STRICT_ALIGNMENT + && modifier != EXPAND_WRITE + && modifier != EXPAND_MEMORY + && !expand_reference && mode != BLKmode && MEM_ALIGN (op0) < GET_MODE_ALIGNMENT (mode)) { @@ -10429,7 +10446,7 @@ expand_expr_real_1 (tree exp, rtx target, enum mac /* WITH_SIZE_EXPR expands to its first argument. The caller should have pulled out the size to use in whatever context it needed. */ return expand_expr_real (treeop0, original_target, tmode, - modifier, alt_rtl); + modifier, alt_rtl, expand_reference); default: return expand_expr_real_2 (&ops, target, tmode, modifier); Index: gcc/cfgexpand.c =================================================================== --- gcc/cfgexpand.c (revision 204411) +++ gcc/cfgexpand.c (working copy) @@ -2189,7 +2189,7 @@ expand_call_stmt (gimple stmt) if (lhs) expand_assignment (lhs, exp, false); else - expand_expr_real_1 (exp, const0_rtx, VOIDmode, EXPAND_NORMAL, NULL); + expand_expr_real_1 (exp, const0_rtx, VOIDmode, EXPAND_NORMAL, NULL, false); mark_transaction_restart_calls (stmt); } Index: gcc/testsuite/gcc.dg/torture/pr57748-3.c =================================================================== --- gcc/testsuite/gcc.dg/torture/pr57748-3.c (revision 0) +++ gcc/testsuite/gcc.dg/torture/pr57748-3.c (revision 0) @@ -0,0 +1,40 @@ +/* PR middle-end/57748 */ +/* { dg-do run } */ +/* wrong code in expand_expr_real_1. */ + +#include <stdlib.h> + +extern void abort (void); + +typedef long long V + __attribute__ ((vector_size (2 * sizeof (long long)), may_alias)); + +typedef struct S { V a; V b[0]; } P __attribute__((aligned (1))); + +struct __attribute__((packed)) T { char c; P s; }; + +void __attribute__((noinline, noclone)) +check (P *p) +{ + if (p->b[0][0] != 3 || p->b[0][1] != 4) + abort (); +} + +void __attribute__((noinline, noclone)) +foo (struct T *t) +{ + V a = { 3, 4 }; + t->s.b[0] = a; +} + +int +main () +{ + struct T *t = (struct T *) calloc (128, 1); + + foo (t); + check (&t->s); + + free (t); + return 0; +} Index: gcc/testsuite/gcc.dg/torture/pr57748-4.c =================================================================== --- gcc/testsuite/gcc.dg/torture/pr57748-4.c (revision 0) +++ gcc/testsuite/gcc.dg/torture/pr57748-4.c (revision 0) @@ -0,0 +1,40 @@ +/* PR middle-end/57748 */ +/* { dg-do run } */ +/* wrong code in expand_expr_real_1. */ + +#include <stdlib.h> + +extern void abort (void); + +typedef long long V + __attribute__ ((vector_size (2 * sizeof (long long)), may_alias)); + +typedef struct S { V b[1]; } P __attribute__((aligned (1))); + +struct __attribute__((packed)) T { char c; P s; }; + +void __attribute__((noinline, noclone)) +check (P *p) +{ + if (p->b[1][0] != 3 || p->b[1][1] != 4) + abort (); +} + +void __attribute__((noinline, noclone)) +foo (struct T *t) +{ + V a = { 3, 4 }; + t->s.b[1] = a; +} + +int +main () +{ + struct T *t = (struct T *) calloc (128, 1); + + foo (t); + check (&t->s); + + free (t); + return 0; +} ^ permalink raw reply [flat|nested] 105+ messages in thread
* [PING] [PATCH, PR 57748] Check for out of bounds access, Part 2 2013-11-19 15:05 ` Bernd Edlinger @ 2013-11-27 16:22 ` Bernd Edlinger 2013-11-27 17:09 ` Richard Biener 2013-11-27 22:30 ` Jeff Law 0 siblings, 2 replies; 105+ messages in thread From: Bernd Edlinger @ 2013-11-27 16:22 UTC (permalink / raw) To: Richard Biener; +Cc: Eric Botcazou, GCC Patches, Martin Jambor, Jakub Jelinek Hi, ping... this patch still open: http://gcc.gnu.org/ml/gcc-patches/2013-11/msg02291.html Note: it does, as it is, _not_ depend on the keep_aligning patch. And it would fix some really nasty wrong code generation issues. Thanks Bernd. > Date: Tue, 19 Nov 2013 15:39:39 +0100 > > Hello, > > > this is a minor update to my previous version of this patch, (using a boolean expand_reference, > instead of adding a new expand_modifier enum value): > > I forgot to pass down the expand_reference value at the second expand_expr call inside the > case VIEW_CONVERT_EXPR. Sorry for the inconvenience. > > > > @@ -10219,7 +10229,8 @@ expand_expr_real_1 (tree exp, rtx target, enum mac > } > > if (!op0) > - op0 = expand_expr (treeop0, NULL_RTX, VOIDmode, modifier); > + op0 = expand_expr_real (treeop0, NULL_RTX, VOIDmode, modifier, > + NULL, expand_reference); > > /* If the input and output modes are both the same, we are done. */ > if (mode == GET_MODE (op0)) > > > Boot-strapped and regression-tested on X86_64-pc-linux-gnu. > > Ok for trunk? > > > Thanks > Bernd. > > >> Date: Thu, 7 Nov 2013 13:58:55 +0100 >> >> oops - this time with attachments... >> >> >>> Hi, >>> >>> On Fri, 25 Oct 2013 12:51:13, Richard Biener wrote: >>>> >>>> On Fri, Oct 25, 2013 at 12:02 PM, Bernd Edlinger >>>> <bernd.edlinger@hotmail.de> wrote: >>>>> Hi, >>>>> >>>>>> Eh ... even >>>>>> >>>>>> register struct { int i; int a[0]; } asm ("ebx"); >>>>>> >>>>>> works. Also with int a[1] but not with a[2]. So just handling trailing >>>>>> arrays makes this case regress as well. >>>>>> >>>>>> Now I'd call this use questionable ... but we've likely supported that >>>>>> for decades and cannot change that now. >>>>>> >>>>>> Back to fixing everything in expand. >>>>>> >>>>>> Richard. >>>>>> >>>>> >>>>> Ok, finally you asked for it. >>>>> >>>>> Here is my previous version of that patch again. >>>>> >>>>> I have now added a new value "EXPAND_REFERENCE" to the expand_modifier >>>>> enumeration. It is almost like EXPAND_MEMORY but it does not interfere with >>>>> constant values. >>>>> >>>>> I have done the same modification to VIEW_CONVERT_EXPR too, because >>>>> this is a possible inner reference, itself. It is however inherently hard to >>>>> test around this code. >>>>> >>>>> To understand this patch it is good to know what type of object the >>>>> return value "tem" of get_inner_reference can be. >>>>> >>>>> From the program logic at get_inner_reference it is clear that the >>>>> return value may *not* be BIT_FIELD_REF, COMPONENT_REF, ARRAY_REF, >>>>> ARRAY_RANGE_REF, REALPART_EXPR, IMAGPART_EXPR. The result may >>>>> be VIEW_CONVERT_EXPR only on a STRICT_ALIGNMENT target. This is probably >>>>> further restricted because exp is gimplified. >>>>> >>>>> Usually the result will be a MEM_REF or a SSA_NAME of the memory where >>>>> the structure is to be found. >>>>> >>>>> When you look at where EXPAND_MEMORY is handled you see it is special-cased >>>>> in TARGET_MEM_REF, MEM_REF, ARRAY_REF, COMPONENT_REF, BIT_FIELD_REF, >>>>> ARRAY_RANGE_REF. >>>>> >>>>> At TARGET_MEM_REF, MEM_REF, VIEW_CONVERT_EXPR, it should be the >>>>> same if EXPAND_MEMORY, EXPAND_WRITE or EXPAND_REFERENCE is given: >>>>> If it is an unaligned memory, we just return the unaligned reference. >>>>> >>>>> This was missing for VIEW_CONVERT_EXPR, and unfortunately I have no test case, >>>>> because it is only a problem for STRICT_ALIGNMENT targets, and even there it will >>>>> certainly be really hard to find test cases that exercise this code. >>>>> >>>>> In ARRAY_REF, COMPONENT_REF, BIT_FIELD_REF, ARRAY_RANGE_REF >>>>> we do not have to touch the handling of the outer modifier. However we pass >>>>> EXPAND_REFERENCE to the inner object, which should not be a recursive >>>>> use of any ARRAY_REF, COMPONENT_REF, BIT_FIELD_REF, ARRAY_RANGE_REF. >>>>> >>>>> TARGET_MEM_REF, MEM_REF and VIEW_CONVERT_EXPR know how to handle >>>>> EXPAND_REFERENCE, anything else handles it like EXPAND_NORMAL. >>>>> >>>>> >>>>> Boot-strapped and regression-tested on x86_64-linux-gnu >>>>> OK for trunk? >>>> >>>> You point to a weak spot in expansion - that it handles creating >>>> the base MEM to offset with handled components by recursing >>>> into the case that handles bare MEM_REFs. This makes the >>>> bare MEM_REF handling code somewhat awkward (it's the >>>> one to assign mem-attrs which are later adjusted for example). >>>> >>>> Maybe a better appropach than adding yet another expand >>>> modifier would be to split out the "base MEM" expansion part >>>> out of the bare MEM_REF handling code so we can call that >>>> instead of recursing. >>>> >>>> In this light - instead of a new expand modifier don't you want >>>> an actual flag that specifies we are coming from a call that >>>> wants to expand a base? That is, allow EXPAND_SUM >>>> but with the recursion flag set? >>>> >>> >>> I think you are right. After some thought, I start to like that idea. >>> >>> This way we have at least much more flexibility, how to handle the inner >>> references correctly, and if I change only the interfaces of expand_expr_real/real_1 >>> that will not be used at too many places, either. >>> >>>> Finally I think the recursion into the VIEW_CONVERT_EXPR case >>>> is only there because of the keep_aligning flag of get_inner_reference >>>> which should be obsolete now that we properly handle its effects >>>> in get_object_alignment. So you wouldn't need to adjust this path >>>> if we finally can get rid of that. >>>> >>> >>> I proposed a patch for that, but did not hear from you: >>> http://gcc.gnu.org/ml/gcc-patches/2013-10/msg02267.html >>> >>> nevertheless, even if the VIEW_CONVERT_EXPR may or may not be an inner >>> reference, the code there should be kept in sync with the normal_inner_ref, >>> and MEM_REF, IMHO. >>> >>> Attached, my updated patch for PR57748, Part 2. >>> >>> Boot-strapped and regression-tested on X86_64-pc-linux-gnu. >>> >>> Ok for trunk? >>> >>> >>> Thanks >>> Bernd. >>> >>>> What do others think? >>>> >>>> Thanks, >>>> Richard. >>>> >>>>> Thanks >>>>> Bernd. ^ permalink raw reply [flat|nested] 105+ messages in thread
* Re: [PING] [PATCH, PR 57748] Check for out of bounds access, Part 2 2013-11-27 16:22 ` [PING] " Bernd Edlinger @ 2013-11-27 17:09 ` Richard Biener 2013-11-27 22:30 ` Jeff Law 1 sibling, 0 replies; 105+ messages in thread From: Richard Biener @ 2013-11-27 17:09 UTC (permalink / raw) To: Bernd Edlinger; +Cc: Eric Botcazou, GCC Patches, Martin Jambor, Jakub Jelinek On Wed, Nov 27, 2013 at 1:29 PM, Bernd Edlinger <bernd.edlinger@hotmail.de> wrote: > Hi, > > ping... > > this patch still open: http://gcc.gnu.org/ml/gcc-patches/2013-11/msg02291.html > > Note: it does, as it is, _not_ depend on the keep_aligning patch. > And it would fix some really nasty wrong code generation issues. I'll come back to all these patches once the late features have all hit stage3 (hopefully next week). We have some time left to fix this and related bugs. Thanks, Richard. > > Thanks > Bernd. > >> Date: Tue, 19 Nov 2013 15:39:39 +0100 >> >> Hello, >> >> >> this is a minor update to my previous version of this patch, (using a boolean expand_reference, >> instead of adding a new expand_modifier enum value): >> >> I forgot to pass down the expand_reference value at the second expand_expr call inside the >> case VIEW_CONVERT_EXPR. Sorry for the inconvenience. >> >> >> >> @@ -10219,7 +10229,8 @@ expand_expr_real_1 (tree exp, rtx target, enum mac >> } >> >> if (!op0) >> - op0 = expand_expr (treeop0, NULL_RTX, VOIDmode, modifier); >> + op0 = expand_expr_real (treeop0, NULL_RTX, VOIDmode, modifier, >> + NULL, expand_reference); >> >> /* If the input and output modes are both the same, we are done. */ >> if (mode == GET_MODE (op0)) >> >> >> Boot-strapped and regression-tested on X86_64-pc-linux-gnu. >> >> Ok for trunk? >> >> >> Thanks >> Bernd. >> >> >>> Date: Thu, 7 Nov 2013 13:58:55 +0100 >>> >>> oops - this time with attachments... >>> >>> >>>> Hi, >>>> >>>> On Fri, 25 Oct 2013 12:51:13, Richard Biener wrote: >>>>> >>>>> On Fri, Oct 25, 2013 at 12:02 PM, Bernd Edlinger >>>>> <bernd.edlinger@hotmail.de> wrote: >>>>>> Hi, >>>>>> >>>>>>> Eh ... even >>>>>>> >>>>>>> register struct { int i; int a[0]; } asm ("ebx"); >>>>>>> >>>>>>> works. Also with int a[1] but not with a[2]. So just handling trailing >>>>>>> arrays makes this case regress as well. >>>>>>> >>>>>>> Now I'd call this use questionable ... but we've likely supported that >>>>>>> for decades and cannot change that now. >>>>>>> >>>>>>> Back to fixing everything in expand. >>>>>>> >>>>>>> Richard. >>>>>>> >>>>>> >>>>>> Ok, finally you asked for it. >>>>>> >>>>>> Here is my previous version of that patch again. >>>>>> >>>>>> I have now added a new value "EXPAND_REFERENCE" to the expand_modifier >>>>>> enumeration. It is almost like EXPAND_MEMORY but it does not interfere with >>>>>> constant values. >>>>>> >>>>>> I have done the same modification to VIEW_CONVERT_EXPR too, because >>>>>> this is a possible inner reference, itself. It is however inherently hard to >>>>>> test around this code. >>>>>> >>>>>> To understand this patch it is good to know what type of object the >>>>>> return value "tem" of get_inner_reference can be. >>>>>> >>>>>> From the program logic at get_inner_reference it is clear that the >>>>>> return value may *not* be BIT_FIELD_REF, COMPONENT_REF, ARRAY_REF, >>>>>> ARRAY_RANGE_REF, REALPART_EXPR, IMAGPART_EXPR. The result may >>>>>> be VIEW_CONVERT_EXPR only on a STRICT_ALIGNMENT target. This is probably >>>>>> further restricted because exp is gimplified. >>>>>> >>>>>> Usually the result will be a MEM_REF or a SSA_NAME of the memory where >>>>>> the structure is to be found. >>>>>> >>>>>> When you look at where EXPAND_MEMORY is handled you see it is special-cased >>>>>> in TARGET_MEM_REF, MEM_REF, ARRAY_REF, COMPONENT_REF, BIT_FIELD_REF, >>>>>> ARRAY_RANGE_REF. >>>>>> >>>>>> At TARGET_MEM_REF, MEM_REF, VIEW_CONVERT_EXPR, it should be the >>>>>> same if EXPAND_MEMORY, EXPAND_WRITE or EXPAND_REFERENCE is given: >>>>>> If it is an unaligned memory, we just return the unaligned reference. >>>>>> >>>>>> This was missing for VIEW_CONVERT_EXPR, and unfortunately I have no test case, >>>>>> because it is only a problem for STRICT_ALIGNMENT targets, and even there it will >>>>>> certainly be really hard to find test cases that exercise this code. >>>>>> >>>>>> In ARRAY_REF, COMPONENT_REF, BIT_FIELD_REF, ARRAY_RANGE_REF >>>>>> we do not have to touch the handling of the outer modifier. However we pass >>>>>> EXPAND_REFERENCE to the inner object, which should not be a recursive >>>>>> use of any ARRAY_REF, COMPONENT_REF, BIT_FIELD_REF, ARRAY_RANGE_REF. >>>>>> >>>>>> TARGET_MEM_REF, MEM_REF and VIEW_CONVERT_EXPR know how to handle >>>>>> EXPAND_REFERENCE, anything else handles it like EXPAND_NORMAL. >>>>>> >>>>>> >>>>>> Boot-strapped and regression-tested on x86_64-linux-gnu >>>>>> OK for trunk? >>>>> >>>>> You point to a weak spot in expansion - that it handles creating >>>>> the base MEM to offset with handled components by recursing >>>>> into the case that handles bare MEM_REFs. This makes the >>>>> bare MEM_REF handling code somewhat awkward (it's the >>>>> one to assign mem-attrs which are later adjusted for example). >>>>> >>>>> Maybe a better appropach than adding yet another expand >>>>> modifier would be to split out the "base MEM" expansion part >>>>> out of the bare MEM_REF handling code so we can call that >>>>> instead of recursing. >>>>> >>>>> In this light - instead of a new expand modifier don't you want >>>>> an actual flag that specifies we are coming from a call that >>>>> wants to expand a base? That is, allow EXPAND_SUM >>>>> but with the recursion flag set? >>>>> >>>> >>>> I think you are right. After some thought, I start to like that idea. >>>> >>>> This way we have at least much more flexibility, how to handle the inner >>>> references correctly, and if I change only the interfaces of expand_expr_real/real_1 >>>> that will not be used at too many places, either. >>>> >>>>> Finally I think the recursion into the VIEW_CONVERT_EXPR case >>>>> is only there because of the keep_aligning flag of get_inner_reference >>>>> which should be obsolete now that we properly handle its effects >>>>> in get_object_alignment. So you wouldn't need to adjust this path >>>>> if we finally can get rid of that. >>>>> >>>> >>>> I proposed a patch for that, but did not hear from you: >>>> http://gcc.gnu.org/ml/gcc-patches/2013-10/msg02267.html >>>> >>>> nevertheless, even if the VIEW_CONVERT_EXPR may or may not be an inner >>>> reference, the code there should be kept in sync with the normal_inner_ref, >>>> and MEM_REF, IMHO. >>>> >>>> Attached, my updated patch for PR57748, Part 2. >>>> >>>> Boot-strapped and regression-tested on X86_64-pc-linux-gnu. >>>> >>>> Ok for trunk? >>>> >>>> >>>> Thanks >>>> Bernd. >>>> >>>>> What do others think? >>>>> >>>>> Thanks, >>>>> Richard. >>>>> >>>>>> Thanks >>>>>> Bernd. ^ permalink raw reply [flat|nested] 105+ messages in thread
* Re: [PING] [PATCH, PR 57748] Check for out of bounds access, Part 2 2013-11-27 16:22 ` [PING] " Bernd Edlinger 2013-11-27 17:09 ` Richard Biener @ 2013-11-27 22:30 ` Jeff Law 2013-11-28 12:36 ` Bernd Edlinger 1 sibling, 1 reply; 105+ messages in thread From: Jeff Law @ 2013-11-27 22:30 UTC (permalink / raw) To: Bernd Edlinger, Richard Biener Cc: Eric Botcazou, GCC Patches, Martin Jambor, Jakub Jelinek On 11/27/13 05:29, Bernd Edlinger wrote: > Hi, > > ping... > > this patch still open: http://gcc.gnu.org/ml/gcc-patches/2013-11/msg02291.html > > Note: it does, as it is, _not_ depend on the keep_aligning patch. > And it would fix some really nasty wrong code generation issues. Is there a testcase for this problem? My recommendation is to start a separate thread which focuses on this issue and only this issue. jeff ^ permalink raw reply [flat|nested] 105+ messages in thread
* RE: [PING] [PATCH, PR 57748] Check for out of bounds access, Part 2 2013-11-27 22:30 ` Jeff Law @ 2013-11-28 12:36 ` Bernd Edlinger 2013-12-03 6:00 ` Jeff Law 0 siblings, 1 reply; 105+ messages in thread From: Bernd Edlinger @ 2013-11-28 12:36 UTC (permalink / raw) To: Jeff Law, Richard Biener Cc: Eric Botcazou, GCC Patches, Martin Jambor, Jakub Jelinek Hi, On Wed, 27 Nov 2013 12:07:16, Jeff Law wrote: > > On 11/27/13 05:29, Bernd Edlinger wrote: >> Hi, >> >> ping... >> >> this patch still open: http://gcc.gnu.org/ml/gcc-patches/2013-11/msg02291.html >> >> Note: it does, as it is, _not_ depend on the keep_aligning patch. >> And it would fix some really nasty wrong code generation issues. > Is there a testcase for this problem? Yes, the patch contains two test cases, one for struct S { V a; V b[0]; } P __attribute__((aligned (1))) and another for struct S { V b[1]; } P __attribute__((aligned (1))) V can be anything that has a movmisalign_optab or is SLOW_UNALIGNED_ACCESS If V::b is used as flexible array, reading p->b[1] gives garbage. We tried hard, to fix this in stor-layout.c by not using the mode of V for struct S, but this created ABI-fallout. So currently the only possible way to fix it seems to be in expansion, by letting expand_real_1 know that we need a memory reference, even if it may be unaligned. > > My recommendation is to start a separate thread which focuses on this > issue and only this issue. > If there are more questions of general interest, please feel free to start in a new thread. > jeff > Thanks Bernd. ^ permalink raw reply [flat|nested] 105+ messages in thread
* Re: [PING] [PATCH, PR 57748] Check for out of bounds access, Part 2 2013-11-28 12:36 ` Bernd Edlinger @ 2013-12-03 6:00 ` Jeff Law 0 siblings, 0 replies; 105+ messages in thread From: Jeff Law @ 2013-12-03 6:00 UTC (permalink / raw) To: Bernd Edlinger, Richard Biener Cc: Eric Botcazou, GCC Patches, Martin Jambor, Jakub Jelinek On 11/28/13 03:24, Bernd Edlinger wrote: > Hi, > > On Wed, 27 Nov 2013 12:07:16, Jeff Law wrote: >> >> On 11/27/13 05:29, Bernd Edlinger wrote: >>> Hi, >>> >>> ping... >>> >>> this patch still open: http://gcc.gnu.org/ml/gcc-patches/2013-11/msg02291.html >>> >>> Note: it does, as it is, _not_ depend on the keep_aligning patch. >>> And it would fix some really nasty wrong code generation issues. >> Is there a testcase for this problem? > > Yes, > the patch contains two test cases, one for > > struct S { V a; V b[0]; } P __attribute__((aligned (1))) > and another for > > struct S { V b[1]; } P __attribute__((aligned (1))) > > > V can be anything that has a movmisalign_optab or is SLOW_UNALIGNED_ACCESS > > If V::b is used as flexible array, reading p->b[1] gives garbage. > > We tried hard, to fix this in stor-layout.c by not using the mode of V > for struct S, but this created ABI-fallout. So currently the only possible > way to fix it seems to be in expansion, by letting expand_real_1 know that > we need a memory reference, even if it may be unaligned. > >> >> My recommendation is to start a separate thread which focuses on this >> issue and only this issue. >> > > If there are more questions of general interest, please feel free to start > in a new thread. Well, my point is there's this thread that deals with multiple issues; the message with the patch itself references prior versions of the patch and sorting out any discussion that relates strictly to the outstanding patch is nontrivial. Hence my request to repost the patch as a new independent thread. Include the testcase and a reference to any current bugzilla bugs. jeff ^ permalink raw reply [flat|nested] 105+ messages in thread
* Re: [PATCH, PR 57748] Check for out of bounds access, Part 2 2013-10-24 13:09 ` Bernd Edlinger 2013-10-24 13:16 ` Richard Biener @ 2013-10-24 13:20 ` Jakub Jelinek 2013-10-24 13:42 ` Richard Biener 1 sibling, 1 reply; 105+ messages in thread From: Jakub Jelinek @ 2013-10-24 13:20 UTC (permalink / raw) To: Bernd Edlinger; +Cc: Richard Biener, Eric Botcazou, GCC Patches, Martin Jambor On Thu, Oct 24, 2013 at 02:55:59PM +0200, Bernd Edlinger wrote: > On Thu, 24 Oct 2013 12:18:43, Richard Biener wrote: > > > > On Thu, Oct 24, 2013 at 10:48 AM, Eric Botcazou <ebotcazou@adacore.com> wrote: > >>> I think that is common practice to write array[1]; at the end of the > >>> structure, and use it as a flexible array. The compute_record_mode has no > >>> way to decide if that is going to be a flexible array or not. > >>> > >>> Sorry Eric, but now I have no other choice than to go back to my previous > >>> version of part 2: > >>> > >>> http://gcc.gnu.org/ml/gcc-patches/2013-10/msg00222.html > >> > >> Why? Just set BLKmode in this case as well. > > > > Works for me if it works ABI-wise (which you say it should unless the > > backend is buggy). Note that means mode_for_array should unconditionally > > return BLKmode. > > Did you just propose: But why would we want to penalize the generated code for this? I mean, if some structure has a flexible array member or something similar to it that we allow to be used as one, if we pass it as arguments, return from functions etc., it will not have any bits beyond those and thus it should be just fine to be passed in registers etc. We can only use those extra bits if either we allocate them on the heap/stack (malloc, alloca, ...) or as a global or automatic variable with initializer that fills in the zero sized array or flexible array member (GNU extensions?), but in either of these cases the DECL_MODE or TYPE_MODE should be irrelevant. So to me this really sounds like a bug in the expansion, certainly not stor-layout. Jakub ^ permalink raw reply [flat|nested] 105+ messages in thread
* Re: [PATCH, PR 57748] Check for out of bounds access, Part 2 2013-10-24 13:20 ` Jakub Jelinek @ 2013-10-24 13:42 ` Richard Biener 0 siblings, 0 replies; 105+ messages in thread From: Richard Biener @ 2013-10-24 13:42 UTC (permalink / raw) To: Jakub Jelinek; +Cc: Bernd Edlinger, Eric Botcazou, GCC Patches, Martin Jambor On Thu, Oct 24, 2013 at 3:13 PM, Jakub Jelinek <jakub@redhat.com> wrote: > On Thu, Oct 24, 2013 at 02:55:59PM +0200, Bernd Edlinger wrote: >> On Thu, 24 Oct 2013 12:18:43, Richard Biener wrote: >> > >> > On Thu, Oct 24, 2013 at 10:48 AM, Eric Botcazou <ebotcazou@adacore.com> wrote: >> >>> I think that is common practice to write array[1]; at the end of the >> >>> structure, and use it as a flexible array. The compute_record_mode has no >> >>> way to decide if that is going to be a flexible array or not. >> >>> >> >>> Sorry Eric, but now I have no other choice than to go back to my previous >> >>> version of part 2: >> >>> >> >>> http://gcc.gnu.org/ml/gcc-patches/2013-10/msg00222.html >> >> >> >> Why? Just set BLKmode in this case as well. >> > >> > Works for me if it works ABI-wise (which you say it should unless the >> > backend is buggy). Note that means mode_for_array should unconditionally >> > return BLKmode. >> >> Did you just propose: > > But why would we want to penalize the generated code for this? > I mean, if some structure has a flexible array member or something similar > to it that we allow to be used as one, if we pass it as arguments, return > from functions etc., it will not have any bits beyond those and thus it > should be just fine to be passed in registers etc. We can only use those > extra bits if either we allocate them on the heap/stack (malloc, alloca, > ...) or as a global or automatic variable with initializer that fills in the > zero sized array or flexible array member (GNU extensions?), but in either > of these cases the DECL_MODE or TYPE_MODE should be irrelevant. > > So to me this really sounds like a bug in the expansion, certainly not > stor-layout. Sure, that was what I was saying all along ... but still, if we want to fix it in stor-layout.c then we have to fix it for all cases there, not just the zero-size array case (which I showed is not the only relevant case). Richard. > Jakub ^ permalink raw reply [flat|nested] 105+ messages in thread
* Re: [PATCH, PR 57748] Check for out of bounds access, Part 2 2013-10-24 8:20 ` Bernd Edlinger 2013-10-24 9:16 ` Eric Botcazou @ 2013-10-24 11:14 ` Richard Biener 2013-10-24 13:13 ` Richard Biener 1 sibling, 1 reply; 105+ messages in thread From: Richard Biener @ 2013-10-24 11:14 UTC (permalink / raw) To: Bernd Edlinger; +Cc: Martin Jambor, Eric Botcazou, gcc-patches On Thu, Oct 24, 2013 at 9:15 AM, Bernd Edlinger <bernd.edlinger@hotmail.de> wrote: > Hi Martin, > > On Wed, 23 Oct 2013 19:11:06, Martin Jambor wrote: >> On Wed, Oct 23, 2013 at 06:00:43PM +0200, Richard Biener wrote: >>> >> >> ... >> >>> ? And why should the same issue not exist for >>> >>> struct { V a[1]; } >>> >> >> indeed, it does and it's simple to trigger (on x86_64): >> >> ---------------------------------------- >> /* { dg-do run } */ >> >> #include <stdlib.h> >> >> typedef long long V >> __attribute__ ((vector_size (2 * sizeof (long long)), may_alias)); >> >> #if 1 >> typedef struct S {V b[1]; } P __attribute__((aligned (1))); >> struct __attribute__((packed)) T { char c; P s; }; >> #else >> typedef struct S {V b[1]; } P; >> struct T { char c; P s; }; >> #endif >> >> void __attribute__((noinline, noclone)) >> good_value (V b) >> { >> if (b[0] != 3 || b[1] != 4) >> __builtin_abort (); >> } >> >> void __attribute__((noinline, noclone)) >> check (P *p) >> { >> good_value (p->b[1]); >> } >> >> int >> main () >> { >> struct T *t = (struct T *) calloc (128, 1); >> V a = { 3, 4 }; >> t->s.b[1] = a; >> check (&t->s); >> free (t); >> return 0; >> } >> ---------------------------------------- >> >> While I was willing to discount the zero sized array as an >> insufficiently specified oddity, this seems to be much more serious >> and potentially common. It seems we really need to be able to detect >> these out-of-bounds situations and tell lower levels of expander that >> "whatever mode you think you are expanding, it is actually BLK mode." >> >> It's uglier than I thought. >> >> Martin >> > > Deja-vu... > > Thanks for this test case. This definitely destroys the idea to fix this in stor-layout.c > > I think that is common practice to write array[1]; at the end of the structure, > and use it as a flexible array. Same for stuff like struct X { char c[4]; }; that currently gets SImode. In alias handling we treat all trailing arrays as flexible, even if they happen to be nested in sub-structs like for struct X { int i; struct Y { char c[4]; } }; too much code out in the wild to disallow this. > The compute_record_mode has no way to > decide if that is going to be a flexible array or not. But it could assign BLKmode to _all_ array types. Richard. > Sorry Eric, but now I have no other choice than to go back to my previous version > of part 2: > > http://gcc.gnu.org/ml/gcc-patches/2013-10/msg00222.html > > I'd just add Martin's new test case as 57748-4.c. > > > Bernd. ^ permalink raw reply [flat|nested] 105+ messages in thread
* Re: [PATCH, PR 57748] Check for out of bounds access, Part 2 2013-10-24 11:14 ` Richard Biener @ 2013-10-24 13:13 ` Richard Biener 0 siblings, 0 replies; 105+ messages in thread From: Richard Biener @ 2013-10-24 13:13 UTC (permalink / raw) To: Bernd Edlinger; +Cc: Martin Jambor, Eric Botcazou, gcc-patches On Thu, Oct 24, 2013 at 12:22 PM, Richard Biener <richard.guenther@gmail.com> wrote: > On Thu, Oct 24, 2013 at 9:15 AM, Bernd Edlinger > <bernd.edlinger@hotmail.de> wrote: >> Hi Martin, >> >> On Wed, 23 Oct 2013 19:11:06, Martin Jambor wrote: >>> On Wed, Oct 23, 2013 at 06:00:43PM +0200, Richard Biener wrote: >>>> >>> >>> ... >>> >>>> ? And why should the same issue not exist for >>>> >>>> struct { V a[1]; } >>>> >>> >>> indeed, it does and it's simple to trigger (on x86_64): >>> >>> ---------------------------------------- >>> /* { dg-do run } */ >>> >>> #include <stdlib.h> >>> >>> typedef long long V >>> __attribute__ ((vector_size (2 * sizeof (long long)), may_alias)); >>> >>> #if 1 >>> typedef struct S {V b[1]; } P __attribute__((aligned (1))); >>> struct __attribute__((packed)) T { char c; P s; }; >>> #else >>> typedef struct S {V b[1]; } P; >>> struct T { char c; P s; }; >>> #endif >>> >>> void __attribute__((noinline, noclone)) >>> good_value (V b) >>> { >>> if (b[0] != 3 || b[1] != 4) >>> __builtin_abort (); >>> } >>> >>> void __attribute__((noinline, noclone)) >>> check (P *p) >>> { >>> good_value (p->b[1]); >>> } >>> >>> int >>> main () >>> { >>> struct T *t = (struct T *) calloc (128, 1); >>> V a = { 3, 4 }; >>> t->s.b[1] = a; >>> check (&t->s); >>> free (t); >>> return 0; >>> } >>> ---------------------------------------- >>> >>> While I was willing to discount the zero sized array as an >>> insufficiently specified oddity, this seems to be much more serious >>> and potentially common. It seems we really need to be able to detect >>> these out-of-bounds situations and tell lower levels of expander that >>> "whatever mode you think you are expanding, it is actually BLK mode." >>> >>> It's uglier than I thought. >>> >>> Martin >>> >> >> Deja-vu... >> >> Thanks for this test case. This definitely destroys the idea to fix this in stor-layout.c >> >> I think that is common practice to write array[1]; at the end of the structure, >> and use it as a flexible array. > > Same for stuff like > > struct X { char c[4]; }; > > that currently gets SImode. In alias handling we treat all trailing > arrays as flexible, even if they happen to be nested in sub-structs like for > > struct X { int i; struct Y { char c[4]; } }; > > too much code out in the wild to disallow this. > >> The compute_record_mode has no way to >> decide if that is going to be a flexible array or not. > > But it could assign BLKmode to _all_ array types. And if it is to prevent ICEs then even struct Y { char c[1]; char c2; } which gets HImode might be used as ((struct Y *)p)->c[1] - invalid but still shouldn't ICE in any way. Richard. > Richard. > >> Sorry Eric, but now I have no other choice than to go back to my previous version >> of part 2: >> >> http://gcc.gnu.org/ml/gcc-patches/2013-10/msg00222.html >> >> I'd just add Martin's new test case as 57748-4.c. >> >> >> Bernd. ^ permalink raw reply [flat|nested] 105+ messages in thread
* Re: [PATCH, PR 57748] Check for out of bounds access, Part 2 2013-10-23 16:14 ` Richard Biener 2013-10-23 17:25 ` Martin Jambor @ 2013-10-23 17:45 ` Eric Botcazou 1 sibling, 0 replies; 105+ messages in thread From: Eric Botcazou @ 2013-10-23 17:45 UTC (permalink / raw) To: Richard Biener; +Cc: gcc-patches, Bernd Edlinger, Martin Jambor > That looks backwards. Why should > > struct { V i; V j[0]; } > > have a different mode than > > struct { V j[0]; V i; } > > ? Because we support out-of-bounds access for the array in the former case and not in the latter case. > And why should the same issue not exist for > > struct { V a[1]; } > > which is also "flexible enough" that we support accesses beyond it > via a pointer? That struct also has V2DImode. And this is all > because > > /* If this field is the whole struct, remember its mode so > that, say, we can put a double in a class into a DF > register instead of forcing it to live in the stack. */ > if (simple_cst_equal (TYPE_SIZE (type), DECL_SIZE (field))) > mode = DECL_MODE (field); > > which is IMHO ok. It's OK *only* if TYPE_SIZE (type) is really the size of all the objects of the type; if it isn't, i.e. if we allow access past TYPE_SIZE (type), then we cannot use the field's mode. So we need to decide where to draw the line. -- Eric Botcazou ^ permalink raw reply [flat|nested] 105+ messages in thread
* RE: [PATCH, PR 57748] Check for out of bounds access, Part 2 2013-09-24 18:51 ` Martin Jambor 2013-09-25 9:51 ` Richard Biener @ 2013-09-25 13:22 ` Bernd Edlinger 1 sibling, 0 replies; 105+ messages in thread From: Bernd Edlinger @ 2013-09-25 13:22 UTC (permalink / raw) To: Martin Jambor, Richard Biener; +Cc: Eric Botcazou, GCC Patches [-- Attachment #1: Type: text/plain, Size: 5422 bytes --] Hmm....., On Tue, 24 Sep 2013 20:06:51, Martin Jambor wrote: > Hi, > > On Tue, Sep 24, 2013 at 12:02:17PM +0200, Richard Biener wrote: >> On Tue, Sep 24, 2013 at 4:52 AM, Bernd Edlinger >> <bernd.edlinger@hotmail.de> wrote: >>> Hi, >>> >>> with the attached patch the read-side of the out of bounds accesses are fixed. >>> There is a single new test case pr57748-3.c that is derived from Martin's test case. >>> The test case does only test the read access and does not depend on part 1 of the >>> patch. >>> >>> This patch was boot-strapped and regression tested on x86_64-unknown-linux-gnu. >>> >>> Additionally I generated eCos and an eCos-application (on ARMv5 using packed >>> structures) with an arm-eabi cross compiler, and looked for differences in the >>> disassembled code with and without this patch, but there were none. >>> >>> OK for trunk? >> >> Index: gcc/expr.c >> =================================================================== >> --- gcc/expr.c (revision 202778) >> +++ gcc/expr.c (working copy) >> @@ -9878,7 +9878,7 @@ >> && modifier != EXPAND_STACK_PARM >> ? target : NULL_RTX), >> VOIDmode, >> - modifier == EXPAND_SUM ? EXPAND_NORMAL : modifier); >> + EXPAND_MEMORY); >> >> /* If the bitfield is volatile, we want to access it in the >> field's mode, not the computed mode. >> >> context suggests that we may arrive with EXPAND_STACK_PARM here >> which is a correctness modifier (see its docs). But I'm not too familiar >> with the details of the various expand modifiers, Eric may be though. " EXPAND_STACK_PARM is used when expanding to a TARGET on the stack for a call parameter. Such targets require special care as we haven't yet marked TARGET so that it's safe from being trashed by libcalls. We don't want to use TARGET for anything but the final result; Intermediate values must go elsewhere. Additionally, calls to emit_block_move will be flagged with BLOCK_OP_CALL_PARM." This should not be a problem: If modifier == EXPAND_STACK_PARM the target is NOT passed down, and thus not giving the modifier either should not cause incorrect code. But I might be wrong... On the other hand, in the case where tem is a unaligned MEM_REF and exp is not exactly the same object as tem, EXPAND_STACK_PARM may exactly do the wrong thing. What I can tell is, that this patch does not change a single bit in the complete GCC boot strap process, stage 2 and stage 3 are binary identical with or without this patch, and that all test cases pass, even the ADA test cases... >> That said, I still believe that fixing the misalign path in expand_assignment >> would be better than trying to avoid it. For this testcase the issue is >> again that expand_assignment passes the wrong mode/target to the >> movmisalign optab. > > Perhaps I'm stating the obvious, but this is supposed to address a > separate bug in the expansion of the RHS (as opposed to the first bug > which was in the expansion of the LHS), and so we would have to make > expand_assignment to also examine potential misalignments in the RHS, > which it so far does not do, despite its complexity. Thanks for pointing that out. This is true. > Having said that, I also dislike the patch, but I am quite convinced > that if we allow non-BLK structures with zero sized arrays, the fix > will be ugly - but I'll be glad to be shown I've been wrong. > > Martin I could of course look at the type of tem, and only mess with the expand modifier in case of a MEM_REF. But I am not sure what to do about the VIEW_CONVERT_EXPR, if the code at normal_inner_ref is wrong, the code at VIEW_CONVERT_EXPR can't possibly be any better, although I have not yet any idea how to write a test case for this: /* ??? We should work harder and deal with non-zero offsets. */ if (!offset && (bitpos % BITS_PER_UNIT) == 0 && bitsize>= 0 && compare_tree_int (TYPE_SIZE (type), bitsize) == 0) { /* See the normal_inner_ref case for the rationale. */ orig_op0 = expand_expr (tem, (TREE_CODE (TREE_TYPE (tem)) == UNION_TYPE && (TREE_CODE (TYPE_SIZE (TREE_TYPE (tem))) != INTEGER_CST) && modifier != EXPAND_STACK_PARM ? target : NULL_RTX), VOIDmode, modifier == EXPAND_SUM ? EXPAND_NORMAL : modifier); Especially for EXPAND_STACK_PARM? If this does really allocate something on a register, then the result will be thrown away, because it is not MEM_P? Right? Note the RHS-Bug can also affect ordinary unions on ARM and all STRICT_ALIGNMENT targets. Please check the attached test case. It may not be obvious at first sight, but the assembler code for check is definitely wrong, because it reads the whole structure, and uses only one byte of it. And that is, not OK because x was volatile... check: @ args = 0, pretend = 0, frame = 0 @ frame_needed = 0, uses_anonymous_args = 0 stmfd sp!, {r3, lr} mov r3, #-2147483648 ldr r3, [r3, #2] @ unaligned mov r3, r3, lsr #24 cmp r3, #3 ldmeqfd sp!, {r3, pc} bl abort Bernd. [-- Attachment #2: pr57748-4.c --] [-- Type: text/plain, Size: 459 bytes --] /* PR middle-end/57748 */ /* arm-eabi-gcc -mcpu=cortex-a9 -O3 */ #include <stdlib.h> union x { short a[2]; char x[4]; } __attribute__((packed, aligned(4))) ; typedef volatile union x *s; void __attribute__((noinline, noclone)) check (void) { s xx=(s)(0x80000002); if (xx->x[3] != 3) abort (); } void __attribute__((noinline, noclone)) foo (void) { s xx=(s)(0x80000002); xx->x[3] = 3; } int main () { foo (); check (); return 0; } ^ permalink raw reply [flat|nested] 105+ messages in thread
* Re: [PATCH, PR 57748] Check for out of bounds access 2013-09-06 7:03 [PATCH, PR 57748] Check for out of bounds access Bernd Edlinger 2013-09-06 7:31 ` Richard Biener @ 2013-09-06 9:29 ` Eric Botcazou 2013-09-06 9:30 ` Jakub Jelinek 1 sibling, 1 reply; 105+ messages in thread From: Eric Botcazou @ 2013-09-06 9:29 UTC (permalink / raw) To: Bernd Edlinger; +Cc: gcc-patches, Richard Biener > this patch fixes the ICE and wrong code issues from PR57748. It contains two > test cases. One for the ICE and one for the wrong code. Both test cases > fail for all gcc versions, and are fixed with this patch. > > Bootstrapped and tested on x86_64-linux without any problems. > > OK for trunk and the 4.8 / 4.7 branch? Please avoid touching the 4.7 branch at this point, this is a sensitive area and the testcases look quite artificial to me. -- Eric Botcazou ^ permalink raw reply [flat|nested] 105+ messages in thread
* Re: [PATCH, PR 57748] Check for out of bounds access 2013-09-06 9:29 ` [PATCH, PR 57748] Check for out of bounds access Eric Botcazou @ 2013-09-06 9:30 ` Jakub Jelinek 2013-09-06 10:30 ` Bernd Edlinger 0 siblings, 1 reply; 105+ messages in thread From: Jakub Jelinek @ 2013-09-06 9:30 UTC (permalink / raw) To: Eric Botcazou; +Cc: Bernd Edlinger, gcc-patches, Richard Biener On Fri, Sep 06, 2013 at 11:28:44AM +0200, Eric Botcazou wrote: > > this patch fixes the ICE and wrong code issues from PR57748. It contains two > > test cases. One for the ICE and one for the wrong code. Both test cases > > fail for all gcc versions, and are fixed with this patch. > > > > Bootstrapped and tested on x86_64-linux without any problems. > > > > OK for trunk and the 4.8 / 4.7 branch? > > Please avoid touching the 4.7 branch at this point, this is a sensitive area > and the testcases look quite artificial to me. Even for 4.8 it needs at least several weeks on the trunk before considering backports of such code. Jakub ^ permalink raw reply [flat|nested] 105+ messages in thread
* RE: [PATCH, PR 57748] Check for out of bounds access 2013-09-06 9:30 ` Jakub Jelinek @ 2013-09-06 10:30 ` Bernd Edlinger 0 siblings, 0 replies; 105+ messages in thread From: Bernd Edlinger @ 2013-09-06 10:30 UTC (permalink / raw) To: Jakub Jelinek, Eric Botcazou; +Cc: gcc-patches, Richard Biener On Fri, 6 Sep 2013 11:30:53, Jakub Jelinek wrote: > On Fri, Sep 06, 2013 at 11:28:44AM +0200, Eric Botcazou wrote: >>> this patch fixes the ICE and wrong code issues from PR57748. It contains two >>> test cases. One for the ICE and one for the wrong code. Both test cases >>> fail for all gcc versions, and are fixed with this patch. >>> >>> Bootstrapped and tested on x86_64-linux without any problems. >>> >>> OK for trunk and the 4.8 / 4.7 branch? >> >> Please avoid touching the 4.7 branch at this point, this is a sensitive area >> and the testcases look quite artificial to me. > > Even for 4.8 it needs at least several weeks on the trunk before considering > backports of such code. > > Jakub That's true, the examples are quite artificial, because it is difficult and quite target-dependent, if there will be a movmisalign optab at all. And the original test case will no longer reproduce on trunk because of this change: 2013-08-08 Bernd Edlinger <bernd.edlinger@hotmail.de> PR target/58065 * config/arm/arm.h (MALLOC_ABI_ALIGNMENT): Define. maybe we should first backport this one. Yesterday someone did that on the linaro branch, but maybe /branches/gcc-4_8-branch should be updated as well? Bernd. ^ permalink raw reply [flat|nested] 105+ messages in thread
end of thread, other threads:[~2014-05-14 9:06 UTC | newest] Thread overview: 105+ messages (download: mbox.gz / follow: Atom feed) -- links below jump to the message on this page -- 2013-09-06 7:03 [PATCH, PR 57748] Check for out of bounds access Bernd Edlinger 2013-09-06 7:31 ` Richard Biener [not found] ` <DUB122-W323D4AAAEA1AFA890BF243E43C0@phx.gbl> [not found] ` <CAFiYyc13wC0jmZ4xELAiL5L5Sbh0yauZWViP2hTdR+H4s0iPSw@mail.gmail.com> [not found] ` <DUB122-W4D571A91831593BA22438E43C0@phx.gbl> 2013-09-06 9:19 ` Richard Biener 2013-09-06 9:30 ` Bernd Edlinger 2013-09-10 21:33 ` Martin Jambor 2013-09-11 14:42 ` Bernd Edlinger 2013-09-11 14:47 ` Richard Biener 2013-09-12 21:07 ` Bernd Edlinger 2013-09-13 9:37 ` Eric Botcazou 2013-09-13 9:48 ` Bernd Edlinger 2013-09-15 19:08 ` Bernd Edlinger 2013-09-17 0:05 ` Martin Jambor 2013-09-17 10:32 ` Bernd Edlinger 2013-10-22 14:08 ` Bernd Edlinger 2013-10-23 16:02 ` Richard Biener 2013-10-24 0:09 ` Bernd Edlinger 2013-10-24 8:44 ` Eric Botcazou 2013-10-24 10:06 ` Richard Biener 2013-10-24 10:22 ` Bernd Edlinger 2013-10-25 10:40 ` Eric Botcazou 2013-11-06 15:08 ` [PATCH, PR 57748] Check for out of bounds access, Part 3 Bernd Edlinger 2013-12-03 13:27 ` [PE-POST] Adjust Bit-region in expand_assignment Bernd Edlinger 2013-12-04 5:55 ` Jeff Law 2013-12-04 7:50 ` Bernd Edlinger 2013-12-06 4:13 ` Jeff Law 2013-12-06 8:03 ` Bernd Edlinger 2013-12-06 9:49 ` Richard Biener 2013-09-17 11:07 ` [PATCH, PR 57748] Check for out of bounds access Richard Biener 2013-09-17 11:41 ` Richard Biener 2013-09-17 12:48 ` Bernd Edlinger 2013-09-24 11:40 ` Richard Biener 2013-09-24 11:56 ` Bernd Edlinger 2013-09-24 6:34 ` [PATCH, PR 57748] Check for out of bounds access, Part 2 Bernd Edlinger 2013-09-24 10:31 ` Richard Biener 2013-09-24 14:46 ` Eric Botcazou 2013-09-24 18:51 ` Martin Jambor 2013-09-25 9:51 ` Richard Biener 2013-09-25 14:56 ` Martin Jambor 2013-09-26 9:34 ` Bernd Edlinger 2013-09-26 11:18 ` Eric Botcazou 2013-09-26 12:42 ` Bernd Edlinger 2013-09-27 8:45 ` Eric Botcazou 2013-10-03 0:37 ` Bernd Edlinger 2013-10-08 8:02 ` Eric Botcazou 2013-10-08 9:22 ` Bernd Edlinger 2013-10-08 21:04 ` Eric Botcazou 2013-10-08 23:03 ` Bernd Edlinger 2013-10-11 17:27 ` Eric Botcazou 2013-10-13 8:22 ` Bernd Edlinger 2013-10-13 12:29 ` Eric Botcazou 2013-10-13 12:30 ` Bernd Edlinger 2013-10-13 14:06 ` Eric Botcazou 2013-10-22 11:02 ` Bernd Edlinger 2013-10-23 16:14 ` Richard Biener 2013-10-23 17:25 ` Martin Jambor 2013-10-23 18:05 ` Eric Botcazou 2013-10-24 8:20 ` Bernd Edlinger 2013-10-24 9:16 ` Eric Botcazou 2013-10-24 10:00 ` Bernd Edlinger 2013-10-24 10:16 ` Eric Botcazou 2013-10-24 10:50 ` Richard Biener 2013-10-24 13:09 ` Bernd Edlinger 2013-10-24 13:16 ` Richard Biener 2013-10-24 13:38 ` Bernd Edlinger 2013-10-25 7:05 ` Bernd Edlinger 2013-10-25 9:29 ` Richard Biener 2013-10-25 10:40 ` Bernd Edlinger 2013-10-25 11:10 ` Richard Biener 2013-10-25 14:01 ` Martin Jambor 2013-10-27 20:21 ` [PATCH] Remove "keep_aligning" from get_inner_reference Bernd Edlinger 2013-11-26 12:37 ` Richard Biener 2013-11-27 11:28 ` Eric Botcazou 2013-11-27 12:24 ` Bernd Edlinger 2013-11-27 12:33 ` Eric Botcazou 2013-11-27 13:30 ` Richard Biener 2013-11-27 15:10 ` Bernd Edlinger 2013-11-27 16:25 ` Eric Botcazou 2013-11-27 16:33 ` Richard Biener 2013-11-27 16:43 ` Eric Botcazou 2014-04-22 7:55 ` Bernd Edlinger 2014-04-22 8:11 ` Eric Botcazou 2014-04-22 8:33 ` Bernd Edlinger 2014-04-22 9:36 ` Eric Botcazou 2014-05-02 6:18 ` Jeff Law 2014-05-05 8:00 ` Richard Biener 2014-05-05 20:25 ` Mike Stump 2014-05-14 7:30 ` Eric Botcazou 2014-05-14 9:06 ` Bernd Edlinger 2013-11-07 13:23 ` [PATCH, PR 57748] Check for out of bounds access, Part 2 Bernd Edlinger 2013-11-07 13:23 ` Bernd Edlinger 2013-11-19 15:05 ` Bernd Edlinger 2013-11-27 16:22 ` [PING] " Bernd Edlinger 2013-11-27 17:09 ` Richard Biener 2013-11-27 22:30 ` Jeff Law 2013-11-28 12:36 ` Bernd Edlinger 2013-12-03 6:00 ` Jeff Law 2013-10-24 13:20 ` Jakub Jelinek 2013-10-24 13:42 ` Richard Biener 2013-10-24 11:14 ` Richard Biener 2013-10-24 13:13 ` Richard Biener 2013-10-23 17:45 ` Eric Botcazou 2013-09-25 13:22 ` Bernd Edlinger 2013-09-06 9:29 ` [PATCH, PR 57748] Check for out of bounds access Eric Botcazou 2013-09-06 9:30 ` Jakub Jelinek 2013-09-06 10:30 ` Bernd Edlinger
This is a public inbox, see mirroring instructions for how to clone and mirror all data and code used for this inbox; as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).