From: Ullrich von Bassewitz (uz_at_musoftware.de)
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 instructions. Regards Uz -- Ullrich von Bassewitz uz_at_musoftware.de ---------------------------------------------------------------------- To unsubscribe from the list send mail to majordomo_at_musoftware.de with the string "unsubscribe cc65" in the body(!) of the mail.
This archive was generated by hypermail 2.1.3 : 2001-12-14 22:05:44 CET