Re: [cc65] Register variables

Date view Thread view Subject view

From: Ullrich von Bassewitz (
Date: 1999-07-19 08:35:10

> Couldn't you forbid the & operator for register variables?

Unfortunately, the standard does not allow that. Forbidding the & operator for
register variables would be the last resort.

> Or save the
> register calls on the stack before the function call and pass the address
> of the stack location?  Note that for the latter, you must handle nested
> function calls properly, e.g. f(g(&x)) must store x on stack before
> calling g and restore it after calling x.  And I think the standard would
> allow you to do f(g(&x),x) in the same way: even if g() modifies x, it is
> implementation-defined whether f() gets the modified x as its second
> parameter.

The evaluation order of parameters in a function call is undefined, so the
latter wouldn't be a problem. Putting the variable into main store temporarily
is no solution either, since it will break the following code:

 	static char* p;

	void f1 (char* s)
	    p = s;

	void f2 (char c)
	    *p = c;

	void f (void)
	    register char c;
	    f1 (&c);
	    f2 (c);
To be really sure, a register variable that has its address taken must not go
into a register (gcc is doing it this way). Unfortunately, the cc65 parser is
too stupid to do things like that (when it sees the address operator, the code
to put the variable into zero page storage has already been generated, and
there is no way back).

If no one has a better idea, my solution will probably be to disable register
variables by default. Register variables must be enabled explicitly (-Or or
something similar) and if you do that, taking the address of a register
variable will cause a warning. There will be another switch (or a #pragma) to
disable this warning, in case you're really sure, your code is right (there
are places in the C library where this is the case). Another option will allow
the compiler to save the old register variable contents onto the call stack
(at $100). The space on the call stack is limited, but saving the variables
onto the call stack is much faster.

> Remember that you will have to store register variables on stack every
> time you call a function that has register variables or that calls a
> function that has register variables.  I guess it's easiest to always
> store the register variables before every function call.  Some life-time
> analysis could be useful: if a variable is only used in the beginning of
> a function, you can discard it when doing a function call at the end of
> the function.

The old values of register variables are of course saved in a function that
uses register variables. The current parser is very simple, so there is no
chance to do a life time analysis, the parser does generate assembler code
directly instead of producing an AST.

> How does it work then?  What kind of a parser is it?  Hand-written
> top-down or what?

It's a hand written recursive descent parser that generates assembler code
directly (remember: cc65 is a descendant of Small-C). The optimizer runs
through the assembler code and searches for specific patterns that are
generated by the code generator. It does also remove unnecessary load



Ullrich von Bassewitz                        
To unsubscribe from the list send mail to with
the string "unsubscribe cc65" in the body(!) of the mail.

Date view Thread view Subject view

This archive was generated by hypermail 2.1.3 : 2001-12-14 22:05:44 CET