Reply by Dan Bloomquist●October 14, 20102010-10-14
Microbit_Ubuntu wrote: > Hi David,
>
> Just to drag it all up again (:-), I was glancing at part of this
> thread, and came across your query/question :
>
>
>> Interesting question - should this, or indeed did this, code generate
>> any
>> kind of friendly warning from the compiler?
>>
> Indeed interesting question - and surely a big dilemma for compiler
> designers ?
> I've always - personally - had a strong conviction about compiler
> warnings :
> 1. The more, the merrier :-)
> 2. You can still elect to ignore and/or account for a warning, but you
> can't guess potential problems in the absence of 'em.
> 3. I always endeavour to have zero warning builds.
> 4. This has paid off on brief occasions, where the compiler pointed out
> to me I was being daft for a moment (by taking some warnings serious)
>
> Unfortunately, in these scenarios "excess" warnings could make the
> programmer ignore them more& more. But IMO that's already a lost case
> anyway, because it says something about the programmer's
> discipline/approach to his/her coding.
>
> About zero-warning builds, I personally get irritated a tad when
> inheriting builds with warnings galore - even over (lack of)
> typecasting.
> A bit extreme example I guess, but when building a Linux kernel, how is
> one to actually spot an important warning when you get Hundreds&
> hundreds of warnings already anyway ??
>
> I've still got heaps to learn about C, but warnings I've ploughed
> through over the years to make sense of them (iow make them go away)
> have greatly contributed to further insight into some more intricate C
> issues.
>
> But that's me ..... :-)
> Hi Kris,
I've got to say warnings, all of them on, are just fine. But then, I'm
a
box jockey, my day job. Our product runs some quarter million lines of
source now and I run without a warning, all of them turned on. VS2008.
And I'm using as much Boost lib as I can any more. Major complaint would
be that Billy's intelesence is pretty dumb at times, can't handle some
STL, much less Boost.
Nice when I have so many TODOs that a dangling, if(x); warns, I keep
getting reminded that I have something todo that I really care about.
I hate warnings, I always program them away. I think that is just the
right thing to do if the compiler holds its salt. I've not built a Linux
kernel, not my stuff. But I've built other stuff from the web with GCC
and with a plethora of warnings. It is the fault of the author, it is
just that simple. Most of the stuff I see is like compares with int and
size_t. You either comply with the STL or cast. To leave all those
dangling warnings???? But I can understand that old code on a stricter
compiler just never gets revised. So, what do you do? 99% of the time I
just use it, as is, as I'm corking around. But it will never get into my
day job code.
OT, I'm playing the google challenge in 'my spare time'.
This is just my infrastructure bot, no strategy yet. So I've started
working on bot2 now. When I pound bot1 into the ground, I'll submit. :)
They build with GCC, I build with VS, there are subtle differences and
so far I don't agree with GCC. Nor does the STL from what I see. (it is
about the likes of const on a multiset item. Like, who's container is
it? I'd think it mine... It would be my bad if I modify the compare, so,
leave me alone!)
But then I use GCC as a C compiler for the MSP and so far, I have been
very happy with it, and I've thrown some wild object thinking C at it,
not a problem. This winter I'll be back to thinking msp and will want to
throw real C++ object stuff at it. I'd think that mspgcc4 should do very
well, but wont know till I'll find out. There is like no word on the GCC
group as to where the line is at, if there really is one...
Reply by Microbit_Ubuntu●October 12, 20102010-10-12
Hi David,
Just to drag it all up again (:-), I was glancing at part of this
thread, and came across your query/question :
> Interesting question - should this, or indeed did
this, code generate
> any
> kind of friendly warning from the compiler?
Indeed interesting question - and surely a big dilemma for compiler
designers ?
I've always - personally - had a strong conviction about compiler
warnings :
1. The more, the merrier :-)
2. You can still elect to ignore and/or account for a warning, but you
can't guess potential problems in the absence of 'em.
3. I always endeavour to have zero warning builds.
4. This has paid off on brief occasions, where the compiler pointed out
to me I was being daft for a moment (by taking some warnings serious)
Unfortunately, in these scenarios "excess" warnings could make the
programmer ignore them more & more. But IMO that's already a lost case
anyway, because it says something about the programmer's
discipline/approach to his/her coding.
About zero-warning builds, I personally get irritated a tad when
inheriting builds with warnings galore - even over (lack of)
typecasting.
A bit extreme example I guess, but when building a Linux kernel, how is
one to actually spot an important warning when you get Hundreds &
hundreds of warnings already anyway ??
I've still got heaps to learn about C, but warnings I've ploughed
through over the years to make sense of them (iow make them go away)
have greatly contributed to further insight into some more intricate C
issues.
But that's me ..... :-)
On Tue, 2010-10-05 at 16:41 +0100, david collier wrote: >
> > C is a language with a standard (actually, several standards...).
> > The standards are not perfect, but they are not bad, and they form
> > a contract between the programmer and the compiler writers. IAR do
> > their best to follow these standards, but their compiler can only
> > generate code for programs that also follow the standards. The
> > compiler should not be trying to "guess" what the programmer
> > intended to write - it generates code based on what they /did/
> > write.
> >
> > The original poster wrote code that did not do what he thought it
> > would - that's the programmer's error, not the compiler's.
>
> See that's the thing.... with the optimisation turned off, the code
> DID
> what he wanted.
>
> It was the optimisation process that created code that DIDN'T. You may
> say that IAR would have been within it's rights under the standard to
> generate the optimised code anyway - it still conformed....
>
> I agree by the way, that "for best defensive programming" the code
> should
> not have been written as it was..... and no doubt we've all learned
> something.
>
> I'd still like to get a compiler-writer's reaction to my
suggestion
> that
> the optimiser should treat the assignment of a volatile pointer to
> point
> at a variable as grounds to disable holding that value in a register.
>
> Yes we can all construct situations where that event is disguised from
> the compiler, but in this case it was in plain view.
>
> Interesting question - should this, or indeed did this, code generate
> any
> kind of friendly warning from the compiler?
>
> D
>
> D
>
--
Best regards,
Kris
Reply by Microbit_Ubuntu●October 9, 20102010-10-09
The one thing I never really got about this ongoing thread, was the use
of the pointer (well, lack thereof :-).
The pointer (DMA address) was actually never *dereferenced* in the
example code.
What's a C compiler to do with a pointer - initialised - when the
pointer isn't actually *used* (no access) ??
I thought that this mere fact made the whole excercise so futile.
B rgds
Kris
On Thu, 2010-10-07 at 11:27 +0000, davidbrown563 wrote: >
> --- In m..., "david collier"
> wrote:
> >
> > > Sorry, this is plain wrong. The original was a pointer to
> > > volatile, not a
> > > volatile pointer. Volatile pointers are not common--and the
> > > because the
> > > pointer is volatile, objects dereferenced through that pointer
> must
> > > always
> > > be read or written as the pointer may have changed without the
> > > compiler
> > > being aware of it. No chance for optimizing *p if p is volatile.
> >
> >
> > Yes I agree Paul, it is plain wrong, for the code he originally
> posted.
> >
> > What he was trying to do was to declare the address register in the
> DMA
> > controller as a "volatile pointer".
> >
> > Now I did ask him ( privately ) whether, if he did that declaration
> > properly, the code would work as he hoped.... he tells me it still
> > doesn't.
> >
> > If I write
> >
> > void x( unsigned char c )
> > {
> > volatile char * dma_pointer @ 1234 // or whatever the right syntax
> is
> >
> > dma_pointer = & c ;
> >
> > }
> >
> > I can see that generating code which didn't do what the writer
> intended
> > is legal... the question is... is it maximally helpful?
> >
> > I don't instantly see why it would be unreasonable for the compiler
> to
> > notice that a pointer had been pointed to a thing being held in a
> CPU
> > register, and either re-optimise with the object held in memory, or
> issue
> > a note that the code was clearly non-conforming....
>
> The code is perfectly good, legal C code, and the compiler generates
> appropriate assembly to execute that C code in an efficient way. How
> is the compiler supposed to guess what code the programmer /intended/
> to write, rather than the code that he /actually/ wrote?
>
> >
> > Or are you saying that the optimisation step is so far removed from
> the
> > compilation of the non-optimised code, that it has no clue what was
> > written, it just has a legal set of transformations it is allowed to
> do
> > on that compiled output?
> >
> > D
> > I have no idea about IAR's compilers, but compiling is generally
done
> in passes. Early on you have an analysis pass that builds an code tree
> from the source code. Then you have a series of transformation passes
> and optimisation passes. Then you get the code generation passes,
> followed by some peephole and low-level optimisation passes.
>
> There are occasional situations where the compiler will look for
> particular forms of source code and pass on extra information to the
> later passes to help generate better code, or to guess the
> programmer's intentions. For example, the compiler may notice a phrase
> like "((x & 0x0f) << 4) | ((x & 0xf0) >> 4)" and pass on information
> so that the back-end will use a nibble-swap instruction rather than
> shifts. Or it may notice something like "n = 100; while (n--);" and
> ensure that the optimiser doesn't remove it, on the assumption that
> the programmer wanted a delay loop but didn't know how to write one
> properly.
>
> But cases like this exist when the compiler developers have thought of
> that particular situation, and written code specifically for them. The
> developers are only human - they can't figure out every way someone
> can write incorrect code, and correct it on-the-fly.
>
> >
> >
--
Best regards,
Kris
Reply by davidbrown563●October 7, 20102010-10-07
--- In m..., "david collier" wrote: >
> > Sorry, this is plain wrong. The original was a pointer to
> > volatile, not a
> > volatile pointer. Volatile pointers are not common--and the
> > because the
> > pointer is volatile, objects dereferenced through that pointer must
> > always
> > be read or written as the pointer may have changed without the
> > compiler
> > being aware of it. No chance for optimizing *p if p is volatile.
> Yes I agree Paul, it is plain wrong, for the code he originally posted.
>
> What he was trying to do was to declare the address register in the DMA
> controller as a "volatile pointer".
>
> Now I did ask him ( privately ) whether, if he did that declaration
> properly, the code would work as he hoped.... he tells me it still
> doesn't.
>
> If I write
>
> void x( unsigned char c )
> {
> volatile char * dma_pointer @ 1234 // or whatever the right syntax is
>
> dma_pointer = & c ;
>
> }
>
> I can see that generating code which didn't do what the writer
intended
> is legal... the question is... is it maximally helpful?
>
> I don't instantly see why it would be unreasonable for the compiler to
> notice that a pointer had been pointed to a thing being held in a CPU
> register, and either re-optimise with the object held in memory, or issue
> a note that the code was clearly non-conforming....
The code is perfectly good, legal C code, and the compiler generates appropriate
assembly to execute that C code in an efficient way. How is the compiler
supposed to guess what code the programmer /intended/ to write, rather than the
code that he /actually/ wrote?
>
> Or are you saying that the optimisation step is so far removed from the
> compilation of the non-optimised code, that it has no clue what was
> written, it just has a legal set of transformations it is allowed to do
> on that compiled output?
>
> D
>
I have no idea about IAR's compilers, but compiling is generally done in
passes. Early on you have an analysis pass that builds an code tree from the
source code. Then you have a series of transformation passes and optimisation
passes. Then you get the code generation passes, followed by some peephole and
low-level optimisation passes.
There are occasional situations where the compiler will look for particular
forms of source code and pass on extra information to the later passes to help
generate better code, or to guess the programmer's intentions. For
example, the compiler may notice a phrase like "((x & 0x0f) << 4) | ((x & 0xf0)
>> 4)" and pass on information so that the back-end will use a nibble-swap
instruction rather than shifts. Or it may notice something like "n = 100; while
(n--);" and ensure that the optimiser doesn't remove it, on the assumption
that the programmer wanted a delay loop but didn't know how to write one
properly.
But cases like this exist when the compiler developers have thought of that
particular situation, and written code specifically for them. The developers
are only human - they can't figure out every way someone can write
incorrect code, and correct it on-the-fly. >
>
Reply by david collier●October 6, 20102010-10-06
> Sorry, this is plain wrong. The original was a
pointer to
> volatile, not a
> volatile pointer. Volatile pointers are not common--and the
> because the
> pointer is volatile, objects dereferenced through that pointer must
> always
> be read or written as the pointer may have changed without the
> compiler
> being aware of it. No chance for optimizing *p if p is volatile. Yes I agree Paul, it is plain wrong, for the code he originally
posted.
What he was trying to do was to declare the address register in the DMA
controller as a "volatile pointer".
Now I did ask him ( privately ) whether, if he did that declaration
properly, the code would work as he hoped.... he tells me it still
doesn't.
If I write
void x( unsigned char c )
{
volatile char * dma_pointer @ 1234 // or whatever the right syntax is
dma_pointer = & c ;
}
I can see that generating code which didn't do what the writer intended
is legal... the question is... is it maximally helpful?
I don't instantly see why it would be unreasonable for the compiler to
notice that a pointer had been pointed to a thing being held in a CPU
register, and either re-optimise with the object held in memory, or issue
a note that the code was clearly non-conforming....
Or are you saying that the optimisation step is so far removed from the
compilation of the non-optimised code, that it has no clue what was
written, it just has a legal set of transformations it is allowed to do
on that compiled output?
D
>
> > Interesting question - should this, or indeed did this, code
> > generate any
> > kind of friendly warning from the compiler?
>
> There is no warning to generate, IMO. If you did, I think you'd
> needlessly
> generate a lot of warnings on other valid code so the warning would
> become
> worthless and probably ignored and eventually turned off.
>
> --
> Paul Curtis, Rowley Associates Ltd http://www.rowley.co.uk
> SolderCore arriving Winter 2010! http://www.soldercore.com
>
>
> --
> *Included Files:*
> am2file:001-HTML_Message.html
Reply by davidbrown563●October 6, 20102010-10-06
--- In m..., "david collier" wrote: >
> > C is a language with a standard (actually, several standards...).
> > The standards are not perfect, but they are not bad, and they form
> > a contract between the programmer and the compiler writers. IAR do
> > their best to follow these standards, but their compiler can only
> > generate code for programs that also follow the standards. The
> > compiler should not be trying to "guess" what the programmer
> > intended to write - it generates code based on what they /did/
> > write.
> >
> > The original poster wrote code that did not do what he thought it
> > would - that's the programmer's error, not the compiler's.
>
> See that's the thing.... with the optimisation turned off, the code
DID
> what he wanted.
>
If code stops working when optimisation is turned on or off, then either the
compiler is broken, or the original code was broken. In this case, the compiler
is correct. The fact that it worked without optimisation can almost be called
coincidence - the program was roughly correct, but not fully correct.
> It was the optimisation process that created code
that DIDN'T. You may
> say that IAR would have been within it's rights under the standard to
> generate the optimised code anyway - it still conformed....
I'd go much further than that. When you give flags like -O0 or -O2 to a
compiler, that's just a hint - the compiler is free to put as much or as
little effort into optimisation. The C standard describes a C "virtual
machine", and how the language controls that. As long as the compiler generates
code that gives the same externally visible outcome as the virtual machine, it
is a correct compiler. The only "externally visible" parts of this are volatile
accesses, calls to external code (such as system calls, if they exist on the
system), and externally visible symbols (if the code can be called from the
outside).
In a small embedded system, this boils down to volatile accesses. The compiler
can generate whatever code it likes as long as all volatile reads and writes are
done in the order specified in the program, and with the values expected by the
program.
Labelling different code generations "optimised" or "non-optimised" is just a
convention for the convenience of compiler users and compiler developers to give
an impression of the balance between easy debugging and smaller and faster
code. >
> I agree by the way, that "for best defensive programming" the code should
> not have been written as it was..... and no doubt we've all learned
> something.
>
It's not "defensive programming" - it's /correct/ programming.
Whenever you feel you need to do "defensive programming", you've probably
made a mistake somewhere. "Defensive programming" means it's time to make
a better specification about what parts of your code are doing, or get a clearer
understanding of the programming language, or write your code in a clearer
way.
> I'd still like to get a compiler-writer's
reaction to my suggestion that
> the optimiser should treat the assignment of a volatile pointer to point
> at a variable as grounds to disable holding that value in a register.
>
As Paul said, the pointer is not volatile - it is a pointer to a volatile. But
making a pointer-to-volatile, and setting it to point at something, does not in
any way force that something to be volatile itself.
volatile is a lot easier to understand if you remember that variables or pieces
of data cannot be "volatile". It is only /accesses/ to a piece of data that can
be volatile. When you declare a variable "volatile int v", you are not making
volatile data. You are telling the compiler that it should reserve space for an
int, and that when you access it by the name "v", those accesses should be
volatile. If you then write "int *p = (int*) &v; *p = 123;", then this access
through "p" is /not/ volatile.
> Yes we can all construct situations where that event
is disguised from
> the compiler, but in this case it was in plain view.
>
> Interesting question - should this, or indeed did this, code generate any
> kind of friendly warning from the compiler?
>
The compiler generated correct code for the given source code, and the source
code was clear (but wrong). There is no warning to give. Perhaps a lint
program could spot this sort of situation, but not the compiler.
Reply by david collier●October 5, 20102010-10-05
> C is a language with a standard (actually, several
standards...).
> The standards are not perfect, but they are not bad, and they form
> a contract between the programmer and the compiler writers. IAR do
> their best to follow these standards, but their compiler can only
> generate code for programs that also follow the standards. The
> compiler should not be trying to "guess" what the programmer
> intended to write - it generates code based on what they /did/
> write.
>
> The original poster wrote code that did not do what he thought it
> would - that's the programmer's error, not the compiler's.
See that's the thing.... with the optimisation turned off, the code DID
what he wanted.
It was the optimisation process that created code that DIDN'T. You may
say that IAR would have been within it's rights under the standard to
generate the optimised code anyway - it still conformed....
I agree by the way, that "for best defensive programming" the code should
not have been written as it was..... and no doubt we've all learned
something.
I'd still like to get a compiler-writer's reaction to my suggestion
that
the optimiser should treat the assignment of a volatile pointer to point
at a variable as grounds to disable holding that value in a register.
Yes we can all construct situations where that event is disguised from
the compiler, but in this case it was in plain view.
Interesting question - should this, or indeed did this, code generate any
kind of friendly warning from the compiler?
D
D
Reply by Paul Curtis●October 5, 20102010-10-05
David,
> I'd still like to get a compiler-writer's
reaction to my suggestion that
> the optimiser should treat the assignment of a volatile pointer to point
> at a variable as grounds to disable holding that value in a register.
Sorry, this is plain wrong. The original was a pointer to volatile, not a
volatile pointer. Volatile pointers are not common--and the because the
pointer is volatile, objects dereferenced through that pointer must always
be read or written as the pointer may have changed without the compiler
being aware of it. No chance for optimizing *p if p is volatile.
> Interesting question - should this, or indeed did
this, code generate any
> kind of friendly warning from the compiler?
There is no warning to generate, IMO. If you did, I think you'd
needlessly
generate a lot of warnings on other valid code so the warning would become
worthless and probably ignored and eventually turned off.
Reply by Anders Lindgren●October 5, 20102010-10-05
Hi David!
> Thank you for your illuminating discussion.
You're welcome! > I can see that "not doing this" would add to the
grief of the compiler
> writer.... but can I take it a little further forward?
>
> There is a "reasonable user gripe" here - if the optimiser decides it
> doesn't need to store ch to memory, and that is a reasonable decision
in
> this case, then you might reasonably expect it to un-think it's
> association of the hole on the stack with ch. At which point ptr=&ch
> would become a problem for it to compile, and it would have to do
> something - probably wind the optimisation level down one and re-process
> the current procedure from the top. I don't know if I call it a
compiler
> bug, but it does manage to create a pointer to a location which does not,
> and will not, contain the value it's told to point to.
When it comes to the hole on the stack, it might be possible to optimize
it away as well. The IAR compiler typically doesn't do stack frame
trimming, as we commit to the stack frame relative early in the code
generation phase (which has other advantages). However, even if it
would, I'm not 100% it would be legal to optimize away the location on
the stack.
For example, the volatile register I'm accessing might compare the value
with the address of other variables. If the locations of ch would be
optimized away, then the program might behave differently.
To conclude, the location and the value of a variable are two different
things that are governed by different set of rules. It might be legal to
optimize one but not the other.
-- Anders Lindgren, IAR Systems
--
Disclaimer: Opinions expressed in this posting are strictly my own and
not necessarily those of my employer.
Reply by davidbrown563●October 1, 20102010-10-01
--- In m..., "david collier" wrote: >
> Anders,
>
> Thank you for your illuminating discussion.
>
> I can see that "not doing this" would add to the grief of the compiler
> writer.... but can I take it a little further forward?
>
> There is a "reasonable user gripe" here - if the optimiser decides it
> doesn't need to store ch to memory, and that is a reasonable decision
in
> this case, then you might reasonably expect it to un-think it's
> association of the hole on the stack with ch. At which point ptr=&ch
> would become a problem for it to compile, and it would have to do
> something - probably wind the optimisation level down one and re-process
> the current procedure from the top. I don't know if I call it a
compiler
> bug, but it does manage to create a pointer to a location which does not,
> and will not, contain the value it's told to point to.
> so you ask
> // ------------------------
> test2:
> SUB.W #0x2, SP
> MOV.W SP, &v
> ADD.W #0x2, SP
> RET
> // ------------------------
>
> The big question here: is this code correct?
>
> Well it clearly doesn't accomplish anything useful, which makes it
smell
> a little fishy.
>
> You say yes. I'm not so sure. My feeling is that you've compiled
the
> mov.w on an assumption that the store exists.... then you've keyhole
> optimised out the store, as it is clearly never followed by a read, and
> is thus unneeded.
>
> Maybe the optimiser should say "the setting of a volatile pointer to
> access this location should be considered ( for optimisation purposes )
> to be equivalent to a read"
>
> David
>
C is a language with a standard (actually, several standards...). The standards
are not perfect, but they are not bad, and they form a contract between the
programmer and the compiler writers. IAR do their best to follow these
standards, but their compiler can only generate code for programs that also
follow the standards. The compiler should not be trying to "guess" what the
programmer intended to write - it generates code based on what they /did/
write.
The original poster wrote code that did not do what he thought it would -
that's the programmer's error, not the compiler's.
It's also worth noting that the poster wrote code that was "on the edge" -
it was not as clear or simple as it could be, and at high risk for
misinterpretation about the meaning of the code. In this case it was the poster
that got it wrong, but it could have been the compiler writer.
Code that is written like that is bad code even if it works.
In this case, the issue is that clear code seldom modifies parameters. It is
certainly never good programming to mess around taking addresses of a parameter,
and adding "volatile" to the mix is even worse. If you want to muck around with
a parameter, make a new local variable and use that. The compiler will happily
generate near-optimal code anyway - adding new local variables seldom costs in
code space or time.