public inbox for gcc@gcc.gnu.org
 help / color / mirror / Atom feed
* register variable is clobbered by passing parameter to a function
@ 2004-03-15 10:54 Wolfgang Kuehn
  2004-03-15 22:51 ` Richard Henderson
  2004-03-16 10:20 ` Dave Korn
  0 siblings, 2 replies; 11+ messages in thread
From: Wolfgang Kuehn @ 2004-03-15 10:54 UTC (permalink / raw)
  To: gcc

target-mcu: AVR
gcc-version: 3.3.1  (latest WINAVR-distribution)

When I declare an often used variable as register, the variable is modified
after calling a function.
Example-code:

register  char often_used_variable asm ("r16");
char foo;
void function1 (char p1, char p2, char p3, char p4, char p5) {   };

int main (void)
{
often_used_variable = 5;
function1 (6,7,8,9,10);
foo = often_used_variable;
}

is compiled to (opt. level=s):

int main (void)
{
.
.
often_used_variable = 5;
ldi r16, 0x05 ; 5       <-- 
function1 (6,7,8,9,10);
ldi r16, 0x0A ; 10   <--- here it happens
ldi r18, 0x09 ; 9
ldi r20, 0x08 ; 8
ldi r22, 0x07 ; 7
ldi r24, 0x06 ; 6
rcall .-24 ; 0x4a

foo = often_used_variable;
sts 0x0060, r16

} // main
.
and foo is now 10 instead of 5.

but without any warning.
If I use the register r18, I get a compiler-warning: call clobbered register
... (and the code is inoperative too).
I could not found anything about this behaviour in the gcc-online-docs.
It only happens with parameters passed to a function, that the register
variable is wasted.
If I use r14 and I have 6 parameters, the result is the same! (r14 is
wasted).
In a bigger application I use an often used variable in such a matter. It
saves a lot of space and runtime. And it works. But once a day it wouldn't
work and I debugged. It was when I added a function with some more
parameters. I know, that the register-keyword is not obligatory for the
compiler, but then he shall give me at least a warning.
Now I am not shure, how safe is my code, are there more side effects?

if I make in my example-code the variable local, the same happens.

K&R says, the compiler can ignore the keyword. But in this case he doesn't
ignores it, he uses the register but then he uses it for himself (for the
parameter passing).
If it is a local var, too.

When I debugged my application, I noticed, that in case of register decl.,
the compiler doesn't use the r16, in case of standard decl. he used the r16.
So I think, it is a bug, that only in the parameter passing he "forgot" to
use another register for passing.

Bug or feature?
Each comment is welcome.

Best regards
Wolfgang

^ permalink raw reply	[flat|nested] 11+ messages in thread

* Re: register variable is clobbered by passing parameter to a function
  2004-03-15 10:54 register variable is clobbered by passing parameter to a function Wolfgang Kuehn
@ 2004-03-15 22:51 ` Richard Henderson
  2004-03-16 11:50   ` Wolfgang Kuehn
  2004-03-16 10:20 ` Dave Korn
  1 sibling, 1 reply; 11+ messages in thread
From: Richard Henderson @ 2004-03-15 22:51 UTC (permalink / raw)
  To: Wolfgang Kuehn; +Cc: gcc

On Mon, Mar 15, 2004 at 11:54:46AM +0100, Wolfgang Kuehn wrote:
> Bug or feature?

Feature.  If you use hard register variables, you MUST know what
you're doing.  This code is doing something stupid, and got what
it deserved.


r~

^ permalink raw reply	[flat|nested] 11+ messages in thread

* RE: register variable is clobbered by passing parameter to a function
  2004-03-15 10:54 register variable is clobbered by passing parameter to a function Wolfgang Kuehn
  2004-03-15 22:51 ` Richard Henderson
@ 2004-03-16 10:20 ` Dave Korn
  1 sibling, 0 replies; 11+ messages in thread
From: Dave Korn @ 2004-03-16 10:20 UTC (permalink / raw)
  To: gcc

 

> -----Original Message-----
> From: gcc-owner On Behalf Of Wolfgang Kuehn
> Sent: 15 March 2004 10:55

> When I declare an often used variable as register, the 
> variable is modified after calling a function.
> Example-code:
> 
> register  char often_used_variable asm ("r16"); char foo;
> void function1 (char p1, char p2, char p3, char p4, char p5) {   };

> I could not found anything about this behaviour in the 
> gcc-online-docs.

  It's right there in the bit about asm ("register"):

Docs
 -> Extensions to the C Language Family
   -> Variables in Specified Registers
     -> Specifying Registers for Local Variables

[
http://gcc.gnu.org/onlinedocs/gcc-3.3.3/gcc/Local-Reg-Vars.html#Local%20Reg%
20Vars ]

" Defining such a register variable does not reserve the register; it
remains available for other uses in places "

" This option does not guarantee that GCC will generate code that has this
variable in the register you specify at all times. You may not code an
explicit reference to this register in an asm statement and assume it will
always refer to this variable. "

> K&R says, the compiler can ignore the keyword. 

That's the register keyword itself; do not confuse it with the asm register
attribute, which is an entirely separate (gcc-specific) feature.


    cheers, 
      DaveK
-- 
Can't think of a witty .sigline today....

^ permalink raw reply	[flat|nested] 11+ messages in thread

* Re: register variable is clobbered by passing parameter to a function
  2004-03-15 22:51 ` Richard Henderson
@ 2004-03-16 11:50   ` Wolfgang Kuehn
  2004-03-16 12:30     ` Michael Matz
  0 siblings, 1 reply; 11+ messages in thread
From: Wolfgang Kuehn @ 2004-03-16 11:50 UTC (permalink / raw)
  To: Richard Henderson; +Cc: gcc

I know, what I do. This code snippet is the extract to see without any
overhead what happens with the compiled result.
In my original application the changing of the global variable to register
saves about 20% of program memory and I need this extra space for further
functionality.
And the code does what it shall (in register-version too). GCC compiles
exactly what it shall.
But only in the case of passing parameters to a function he "forget" that
the register is occupied by the variable.
For passing parameters he starts with r24 and goes down straight to the
lower registers (up to r8).
If there are still more parameters for passing, then he uses the stack.
Thats all ok, but:
if I use a local register variable, there is no warning, not even I use a
clobbered register (r18 and higher).
if I use a global register variable, there is a warning in case of clobbered
register, what is ok.
But no warning in case of non-clobbered registers.
The register keyword is not obligatory for the compiler, he can use a
register for the variable or not. But when he uses it,
then he shall not use it for other things (like passing) , or at least save
it. Or at least give a warning.
So I can not be shure, what result is compiled, is it reliable or not.
This behaviour says in conclusion, that you never has to use the register
keyword, because the compiler makes what he want. The harvard architecture
of the AVR-processor with his amount of registers is predestinated to make
use of registers.
So I believe, it is a bug.
The gcc-docu says:
a.. Global register variables reserve registers throughout the program. This
may be useful in programs such as programming language interpreters which
have a couple of global variables that are accessed very often.
a..  Choose a register which is normally saved and restored by function
calls on your machine, so that library routines will not clobber it.
a.. Call-saved registers (r2-r17, r28-r29): Calling C subroutines leaves
them unchanged.

I discussed these problems before in the avr-gcc-forum and they were not
shure is it a compiler bug or a document bug. They advised me to get the
help of the mailing list: "There the real gcc gurus can probably answer your
question".

best regards
wolfgang


^ permalink raw reply	[flat|nested] 11+ messages in thread

* Re: register variable is clobbered by passing parameter to a function
  2004-03-16 11:50   ` Wolfgang Kuehn
@ 2004-03-16 12:30     ` Michael Matz
  2004-03-16 12:39       ` Michael Matz
  2004-03-16 12:43       ` Dave Korn
  0 siblings, 2 replies; 11+ messages in thread
From: Michael Matz @ 2004-03-16 12:30 UTC (permalink / raw)
  To: Wolfgang Kuehn; +Cc: Richard Henderson, gcc

Hi,

On Tue, 16 Mar 2004, Wolfgang Kuehn wrote:

> I know, what I do.

You believe you know what you do, but ...

> The register keyword is not obligatory for the compiler, he can use a

... this, and ...

> This behaviour says in conclusion, that you never has to use the register
> keyword, because the compiler makes what he want.

... this indicates that in fact you don't.  You confuse the "register" 
keyword (which is an official ISO C keyword, but merely a hint to the 
compiler where to place the variable, ignored mostly by GCC) with register 
variables (those with an added 'asm ("d0")') which is an GCC extension.

> a.. Global register variables reserve registers throughout the program. This
> may be useful in programs such as programming language interpreters which
> have a couple of global variables that are accessed very often.

This says nothing about local register variables, like you used.

In essence local register variables don't contain the value you think they 
do.  They really represent the register itself at the point of the 
reference, i.e. depend on how the compiler choose to layout the code 
surrounding that reference.  In particular they don't prevent other values 
from being placed into the same register (in difference to global register 
vars).


Ciao,
Michael.

^ permalink raw reply	[flat|nested] 11+ messages in thread

* Re: register variable is clobbered by passing parameter to a function
  2004-03-16 12:30     ` Michael Matz
@ 2004-03-16 12:39       ` Michael Matz
  2004-03-16 12:43       ` Dave Korn
  1 sibling, 0 replies; 11+ messages in thread
From: Michael Matz @ 2004-03-16 12:39 UTC (permalink / raw)
  To: Wolfgang Kuehn; +Cc: Richard Henderson, gcc

Hi,

On Tue, 16 Mar 2004, Michael Matz wrote:

> > may be useful in programs such as programming language interpreters which
> > have a couple of global variables that are accessed very often.
> 
> This says nothing about local register variables, like you used.

Excuse me, I confused you with another one ;-)  Your problem is that r16 
is used to pass arguments.  The use of that register as gobal register var 
doesn't prevent this, so it will be changed over function calls.


Ciao,
Michael.

^ permalink raw reply	[flat|nested] 11+ messages in thread

* RE: register variable is clobbered by passing parameter to a function
  2004-03-16 12:30     ` Michael Matz
  2004-03-16 12:39       ` Michael Matz
@ 2004-03-16 12:43       ` Dave Korn
  2004-03-16 13:00         ` Ian Lance Taylor
  1 sibling, 1 reply; 11+ messages in thread
From: Dave Korn @ 2004-03-16 12:43 UTC (permalink / raw)
  To: gcc


> -----Original Message-----
> From: gcc-owner On Behalf Of Michael Matz
> Sent: 16 March 2004 12:30

> > a.. Global register variables reserve registers throughout the 
> > program. This may be useful in programs such as programming 
> language 
> > interpreters which have a couple of global variables that 
> are accessed very often.
> 
> This says nothing about local register variables, like you used.

  Actually, taking a closer look at his sample code, the variable is defined
at file scope.  So if that's an accurate extract of what he's been
compiling, it should have been a global register variable.

---quote---
Example-code:

register  char often_used_variable asm ("r16"); char foo;
void function1 (char p1, char p2, char p3, char p4, char p5) {   };

int main (void)
{
often_used_variable = 5;
function1 (6,7,8,9,10);
foo = often_used_variable;
}
---quote---

  So there may be a genuine bug here.

  Wolfgang, your best bet is probably to just add -fixed-r16 to your
compile-time flags.  And don't call any library functions that were compiled
without it.


    cheers, 
      DaveK
-- 
Can't think of a witty .sigline today....

^ permalink raw reply	[flat|nested] 11+ messages in thread

* Re: register variable is clobbered by passing parameter to a function
  2004-03-16 12:43       ` Dave Korn
@ 2004-03-16 13:00         ` Ian Lance Taylor
  2004-03-16 13:21           ` Dave Korn
  0 siblings, 1 reply; 11+ messages in thread
From: Ian Lance Taylor @ 2004-03-16 13:00 UTC (permalink / raw)
  To: gcc

"Dave Korn" <dk@artimi.com> writes:

>   Wolfgang, your best bet is probably to just add -fixed-r16 to your
> compile-time flags.  And don't call any library functions that were compiled
> without it.

This is AVR, and he is trying to use r16.  According to
function_arg_regno_p() in avr.c, that register can be used to pass
parameters to functions.  gcc can't handle declaring a register used
for parameter passing as fixed.

Trying to do that is an implicit ABI change anyhow.  Maybe gcc should
warn about this, but it doesn't.

Ian

^ permalink raw reply	[flat|nested] 11+ messages in thread

* RE: register variable is clobbered by passing parameter to a function
  2004-03-16 13:00         ` Ian Lance Taylor
@ 2004-03-16 13:21           ` Dave Korn
  0 siblings, 0 replies; 11+ messages in thread
From: Dave Korn @ 2004-03-16 13:21 UTC (permalink / raw)
  To: gcc


> -----Original Message-----
> From: gcc-owner On Behalf Of Ian Lance Taylor

> "Dave Korn" <dk@artimi.com> writes:
> 
> >   Wolfgang, your best bet is probably to just add 
> -fixed-r16 to your 
> > compile-time flags.  And don't call any library functions that were 
> > compiled without it.
> 
> This is AVR, and he is trying to use r16.  According to
> function_arg_regno_p() in avr.c, that register can be used to 
> pass parameters to functions.  gcc can't handle declaring a 
> register used for parameter passing as fixed.

  Ah.  Then my advice should have been "Change r16 to some safer register."
Hopefully that should then suffice to make his global-register-var work
correctly and there isn't actually a bug in gcc.

> Trying to do that is an implicit ABI change anyhow.  Maybe 
> gcc should warn about this, but it doesn't.
> 
> Ian

  Fair enough.  It would be simple enough for the code that implements
-fixed-rXX to clear the corresponding entries from the CALL_USED_REGISTERS
and REG_ALLOC_ORDER arrays at the same time as it sets the entry in
FIXED_REGISTERS; but I guess there's no general way to allow for what
backends might do with registers in prolog/epilog or varargs codegeneration.

  As to the implicit ABI change, well, we're a long way into the realms of
"don't do this unless you know exactly what you're doing" anyway.  Issuing a
warning seems tricky, without having some knowledge of what goes on inside
functions in the backend.  The best bet might be to add a bit more
documentation to the register-vars pages, indicating that registers chosen
should not be call-used or fixed-for-other-purposes-by-the-abi.


    cheers, 
      DaveK
-- 
Can't think of a witty .sigline today....

^ permalink raw reply	[flat|nested] 11+ messages in thread

* Re: register variable is clobbered by passing parameter to a function
  2004-03-16 14:18 Wolfgang Kuehn
@ 2004-03-16 14:47 ` Ian Lance Taylor
  0 siblings, 0 replies; 11+ messages in thread
From: Ian Lance Taylor @ 2004-03-16 14:47 UTC (permalink / raw)
  To: Wolfgang Kuehn; +Cc: gcc

"Wolfgang Kuehn" <wolfgang.kuehn@kristensen.de> writes:

> Last question: what means ABI ?

It means Application Binary Interface.  In this case it refers to the
calling convention, which is a binary interface between functions.
You can only safely call between functions which are all compiled with
the same ABI.

Ian

^ permalink raw reply	[flat|nested] 11+ messages in thread

* Re: register variable is clobbered by passing parameter to a function
@ 2004-03-16 14:18 Wolfgang Kuehn
  2004-03-16 14:47 ` Ian Lance Taylor
  0 siblings, 1 reply; 11+ messages in thread
From: Wolfgang Kuehn @ 2004-03-16 14:18 UTC (permalink / raw)
  To: gcc

> > Wolfgang, your best bet is probably to just add -fixed-r16 to your
> >compile-time flags.  And don't call any library functions that were
compiled
> >without it.

-ffixed-r16 has no effect at passing.

>> This is AVR, and he is trying to use r16.  According to
>> function_arg_regno_p() in avr.c, that register can be used to
> >pass parameters to functions.  gcc can't handle declaring a
>> register used for parameter passing as fixed.

>Ah.  Then my advice should have been "Change r16 to some safer register."
>Hopefully that should then suffice to make his global-register-var work
>correctly and there isn't actually a bug in gcc.

  Some safer register are r4,r5 and r6. And there is no effect by passing
parameters. But the register r16 (and all other above this) are more
efficient, because you can load only these immediately (ldi r16,0x10) ,
set/reset bits (sbr r17,1) and other very effective instructions.
Its a pity not to exhaust the complete power of this little processor.

In moment the best workaround for my application is not to pass more than
four (char) parameters to a function, so I am free to use the powerful
r16-register.

>The best bet might be to add a bit more
>documentation to the register-vars pages, indicating that registers chosen
>should not be call-used or fixed-for-other-purposes-by-the-abi.

Thats very welcome.

Last question: what means ABI ?

best regards
wolfgang

^ permalink raw reply	[flat|nested] 11+ messages in thread

end of thread, other threads:[~2004-03-16 14:47 UTC | newest]

Thread overview: 11+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2004-03-15 10:54 register variable is clobbered by passing parameter to a function Wolfgang Kuehn
2004-03-15 22:51 ` Richard Henderson
2004-03-16 11:50   ` Wolfgang Kuehn
2004-03-16 12:30     ` Michael Matz
2004-03-16 12:39       ` Michael Matz
2004-03-16 12:43       ` Dave Korn
2004-03-16 13:00         ` Ian Lance Taylor
2004-03-16 13:21           ` Dave Korn
2004-03-16 10:20 ` Dave Korn
2004-03-16 14:18 Wolfgang Kuehn
2004-03-16 14:47 ` Ian Lance Taylor

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