Re: gcc miscompiling duff's device (probaby two different bugs)

2010-03-02 Thread Pjotr Kourzanov
On Tue, 2010-03-02 at 10:24 +, Andrew Haley wrote: 
> On 03/02/2010 09:38 AM, Peter Kourzanov wrote:
> 
> >   I have the following variation on Duff's device that seems to 
> > mis-compile on all GCC versions I can access within a minute (that 
> > is gcc-3.{3,4}, gcc-4.{1,2,3,4} on x86 and gcc-4.3.2 on x86_64). The 
> > symptoms are as follows:
> > 
> > $ gcc-4.4 -o duffbug duffbug.c ; ./duffbug
> > { he��3)
> > { hello world ! }
> > 
> >   As you can observe in the difference between duff4_works() and 
> > duff4_fails(), apparently due to for-loop initializer being externalized
> > vs. specified as the first for-loop expression. It doesn't matter if the
> > 'case 0' is  labeling the for-loop, or the first statement in the 
> > for-loop in case of duff4_works() of course. However, older gcc-3.x do
> > give a warning though if the 'case 0' labels the first statement for 
> > duff4_fails(), since the first expression in the for-loop is then
> > inaccessible. All gcc-4.x versions don't warn, even when supplied with
> > the -Wall flag (which is wrong, hence this *first* bug):
> 
> So, your claim is that gcc should warn about the for loop initializer
> being unreachable.  is that correct?

Exactly. Just like what gcc-3.x does, even without the -Wall flag.

> 
> > $ gcc-4.4 -Wall -o duffbug duffbug.c ; ./duffbug
> > $ gcc-3.4 -Wall -o duffbug duffbug.c ; ./duffbug
> > duffbug.c: In function `duff4_fails':
> > duffbug.c:28: warning: unreachable code at beginning of switch statement
> > 
> >   I think the compiler is generating wrong code for duff4_fails() when
> > 'case 0' labels the for-loop. It somehow skips the first for-loop
> > expression, just as if 'case 0' pointed to the first statement in the
> > for-loop (hence this *second* bug). Haven't checked the assembly
> > though...
> 
> I don't understand.  In what way is the code gcc generates wrong?
> 
> int duff4_fails(char * dst,const char * src,const size_t n)
> {
>   const size_t rem=n % 4, a=rem + (!rem)*4;
>   char * d=dst+=a;
>   const char * s=src+=a;
>   /* gcc bug? dst+=n; */
>   
> switch (rem) {
> case 0:  for(dst+=n;d /*case 0:*/   d[-4]=s[-4];
> case 3:   d[-3]=s[-3];
> case 2:   d[-2]=s[-2];
> case 1:   d[-1]=s[-1];
> }
> }
>   return 0;
> }
> The first time around the loop the initializer (d+=n) is jumped around, so
> d == dst.  At the end of the loop, d+=4, so d > dst.  Therefore the loop
> exits.

  And its wrong since it shouldn't jump around the initializer.  The
following two snippets exhibit the same behaviour:

> case 0:  for(dst+=n;d /*case 0:*/   d[-4]=s[-4];

> /*case 0:*/  for(dst+=n;d case 0:   d[-4]=s[-4];

  Which is wrong IMHO.

Kind regards,

Pjotr



Re: gcc miscompiling duff's device (probaby two different bugs)

2010-03-02 Thread Pjotr Kourzanov
On Tue, 2010-03-02 at 11:27 +0100, Richard Guenther wrote: 
> On Tue, Mar 2, 2010 at 10:38 AM, Peter Kourzanov
>  wrote:
> >
> > Hi guys,
> >
> >  I have the following variation on Duff's device that seems to
> > mis-compile on all GCC versions I can access within a minute (that
> > is gcc-3.{3,4}, gcc-4.{1,2,3,4} on x86 and gcc-4.3.2 on x86_64). The
> > symptoms are as follows:
> >
> > $ gcc-4.4 -o duffbug duffbug.c ; ./duffbug
> > { he��3)
> > { hello world ! }
> >
> >  As you can observe in the difference between duff4_works() and
> > duff4_fails(), apparently due to for-loop initializer being externalized
> > vs. specified as the first for-loop expression. It doesn't matter if the
> > 'case 0' is  labeling the for-loop, or the first statement in the
> > for-loop in case of duff4_works() of course. However, older gcc-3.x do
> > give a warning though if the 'case 0' labels the first statement for
> > duff4_fails(), since the first expression in the for-loop is then
> > inaccessible. All gcc-4.x versions don't warn, even when supplied with
> > the -Wall flag (which is wrong, hence this *first* bug):
> >
> > $ gcc-4.4 -Wall -o duffbug duffbug.c ; ./duffbug
> > $ gcc-3.4 -Wall -o duffbug duffbug.c ; ./duffbug
> > duffbug.c: In function `duff4_fails':
> > duffbug.c:28: warning: unreachable code at beginning of switch statement
> >
> >  I think the compiler is generating wrong code for duff4_fails() when
> > 'case 0' labels the for-loop. It somehow skips the first for-loop
> > expression, just as if 'case 0' pointed to the first statement in the
> > for-loop (hence this *second* bug). Haven't checked the assembly
> > though...
> 
> The routines are not equivalent.  in _works you unconditionally
> do dst += n while in _fails you only do it for rem == 0.

That's right. And about missing warning?

> 
> Richard.
> 
> > Kind regards,
> >
> > Pjotr Kourzanov
> >
> 




Re: gcc miscompiling duff's device (probaby two different bugs)

2010-03-02 Thread Pjotr Kourzanov
On Tue, 2010-03-02 at 10:47 +, Andrew Haley wrote: 
> On 03/02/2010 10:34 AM, Pjotr Kourzanov wrote:
> 
> >> int duff4_fails(char * dst,const char * src,const size_t n)
> >> {
> >>   const size_t rem=n % 4, a=rem + (!rem)*4;
> >>   char * d=dst+=a;
> >>   const char * s=src+=a;
> >>   /* gcc bug? dst+=n; */
> >>   
> >> switch (rem) {
> >> case 0:  for(dst+=n;d >> /*case 0:*/d[-4]=s[-4];
> >> case 3:d[-3]=s[-3];
> >> case 2:d[-2]=s[-2];
> >> case 1:d[-1]=s[-1];
> >>  }
> >> }
> >>return 0;
> >> }
> >> The first time around the loop the initializer (d+=n) is jumped around, so
> >> d == dst.  At the end of the loop, d+=4, so d > dst.  Therefore the loop
> >> exits.
> > 
> >   And its wrong since it shouldn't jump around the initializer.
> 
> Sure it should.  On entry to that loop, rem == 3.

  I agree, this is one of the places where referential transparency
breaks in C. I wouldn't have expected that the compiler could or 
would put the first expression before the switch in this case:

switch (rem) {
  for(dst+=n;d 
> Andrew.
> 




[plugins] binary-level or source-level?

2009-02-11 Thread Pjotr Kourzanov
Dear GCC developers,

  I've been following the plugins discussion and have seen various 
proposals. So far all of them seem to be focusing on plugins as
dynamically linkable libraries (with all associated versioning and
portability ballast). While you could also easily extend that, and
integrate plugins more tightly with the compiler binary as static
libraries (thereby creating customized compilers), I was wondering
whether in future there might be a need to express tighter dependency
between the code and the plugin(s) that the code might require... Or 
at least the dependency between the code and the plugin 
configuration options...

  Should we not have a way to specify a plugin in the source itself?
This could be achieved by tagging a function with a __plugin__
attribute (or a #pragma), exporting the PluginAPI as a bunch of 
built-in functions and having the compiler itself (1) ensure that such
functions only call portable built-ins, and (2) compiling/executing or 
interpreting them as compilation passes. Then, the code can just 
#include a source-level plugin to have it available just for that 
translation unit.

  This is useful for at least one project I am working on...

Regards,

Pjotr Kourzanov







Re: [plugins] binary-level or source-level?

2009-02-11 Thread Pjotr Kourzanov
On Wed, 2009-02-11 at 18:14 -0500, Diego Novillo wrote:
> On Wed, Feb 11, 2009 at 11:46, Pjotr Kourzanov
>  wrote:
> 
> >  Should we not have a way to specify a plugin in the source itself?
> > This could be achieved by tagging a function with a __plugin__
> > attribute (or a #pragma), exporting the PluginAPI as a bunch of
> > built-in functions and having the compiler itself (1) ensure that such
> > functions only call portable built-ins, and (2) compiling/executing or
> > interpreting them as compilation passes. Then, the code can just
> > #include a source-level plugin to have it available just for that
> > translation unit.
> 
> But then, what would be the difference between this and just adding
> your pass to the compiler?  
  
  Well I guess you don't have to rebuild the compiler, once it supports
such JIT plugins. Otherwise you might end up with building lots of 
compilers with only minor differences and getting a Makefile headache.

  Also portability can be improved, since JIT plugins can be made
as portable as any scripting language.

> I'm not sure I understand what this would
> buy you in terms of simplicity.  Perhaps I'm missing something.

  I can imagine a situation when you'll want a set of plugins to apply
only to some specific parts of your code. Or specific plugin options for
some parts, but not others. For such cases, you'd better just #include
an appropriate plugin or supply a parameter via a #pragma to it, rather
than solve these issues in the Makefiles.

  As a bonus, these will have to be distributed in source form, so no 
illegal proprietary gambles are possible. You might get additional
benefits from executing JIT plugins in a restricted or "managed" mode
(only allow usage of some restricted builtins by plugin sourcecode),
rather than just allowing random access to whole compiler workspace.

Pjotr.



gcc bug question regarding error recovery

2008-02-01 Thread Pjotr Kourzanov

Dear gcc developers,

  While trying a code snippet structured as the following code suggests I've
encountered a gcc error recovery bug. Namely, the gcc (versions 4.0-4.3, as well
as 3.2) starts leaking memory (after reporting that a variable-sized object can
not be initialized) and never exists. Strange enough, 3.3 also leaks but still
can exit gracefully. gcc-3.4 and gcc-2.95 both work as expected on this
fragment:

int main() { 

 const int size=10; 

 struct foo { 

 int array[size]; 

 int* p; 

 };// f = { .p=0 }; 




 struct foo f = { .p = 0 }; 


}

  Note that putting size as a #define solves the problem, just as well as 
putting the array to be placed after the pointer.


  I know that initialization of variable-sized object is explicitly prohibited
by C99, but note that the size here is a constant, and that I am trying to 
initialize a struct containing this seemingly variable-sized array.


  I would like to know if its a known bug, and if possible I could file a proper
bug report if this helps...

  I am using Debian-packaged compilers.

Regards,

Pjotr Kourzanov





gcc4.x handling of switch(enum)

2008-04-08 Thread Pjotr Kourzanov

Dear gcc developers,

 I have found a weird discrepancy in error/warning reporting in
GCC4.x. The following fragment:

enum e { A, B, C };
struct u { enum e e:2; };
void bar(struct u u) {
   switch (u.e) {
   case A:;
   }
}

 It does (rightfully) trigger a -Wswitch warning on gcc-3.3 and
gcc-3.4 but not on gcc-4.x.

 Note that the presence of the bitwidth specifier is essential for
this bug. My estimate is that the specifier makes the field to lose
its enum typedness, preventing further passes to from recognising
this (rather important) error.

 This is a bit weird, since giving the specifier a value that does
not match the range of the enum (e.g., :1) does trigger a warning
(`e' is narrower than values of its type).

  I am using Debian-packaged compilers.

Regards,

Pjotr Kourzanov