EmbeddedRelated.com
Forums

Bug in IAR for MSP430

Started by ratishpunnoose September 23, 2010
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.

--
Paul Curtis, Rowley Associates Ltd http://www.rowley.co.uk
SolderCore arriving Winter 2010! http://www.soldercore.com


Beginning Microcontrollers with the MSP430

> 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

--- 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.

> 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
--- 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.
>
>

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

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

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...

Best, Dan.

BTW, Redd, good to see your old sig back!