ref: 9b65a9cadd670f9cdd7ac4d8e203240fbfcd80cf
dir: /README/
Introduction ============ This is the suckless C compiler, a very stupid non-retargetable compiler for the Z80. It is intended to be very simple and suitable for running on small machines (like MSX for example), and leaves almost all optimizations to the programmer. After a lot of years seeing compilers for the Z80 I noticed that it is very hard for a C compiler to generate good programs for 8 Bit processors like the Z80, with an expensive indirect addressing mode, so the best solution is not to try to make the compiler optimizing, but instead use C as a macro macro assembler. In order to reach this target, we need a compiler that does exactly the things the programmer wants to do. For example, if a variable is a register it MUST be a register and should fail in any other case. If a variable is automatic operations should be attempted to be realized with the stack directly (for example use ADD A,(IX+4) instead of allocating the variable into a register add and store it again in memory). If you declare an automatic variable you are either doing it wrong or you need it for recursion (static variables are you friends). This is the reason why I began to develop this compiler, and I hope it will be useful for you. Derivations from standard C =========================== This compiler is near to being fully compatible with the C99 standard, but there are some differences: - Type qualifiers are accepted but ignored. ----------------------------------------- Type qualifers make the type system ugly, and their uselessness add unnecessary complexity to the compiler (and increased compilation time): - const: The definition of const is not clear in the standard. If a const value is modified the behaviour is implementation defined. It seems it was defined in order to be able to allocate variables in ROM rather than error detection. This implememtation will not warn about these modifications and the compiler will treat them like normal variables (the standard specifies that a diagnosic message must be printed). - volatile: The definition of volatile is not concrete, because it is defined as 'remove all optimizations applied to the variable', which of course depends on the kind of optimizations applied to the variable. This qualifier was added to the standard to be able to deal with longjmp (local variables that are not volatile have undefined state) and for memory mapped registers or variables whose values are modified asynchronously. This can be achieved with special pragma values though. In the first case, this is non-portable code by definition (depending on the register mapped), so it is better to deal with it using another solution (compiler extensions or direct assembler). In the second case, it generates a lot of problems with modern processors and multithreading, where not holding the value in a register is good enough (an explicit memory barrier is needed). - restrict: This qualifer can only be applied to pointers to mark that the pointed object has no other alias. This qualifer was introduced to be able to fix some performance problems in numerical algorithms, where FORTRAN could achieve a better performance (and in fact even with this specifier FORTRAN has a better performance in this field). Ignoring it doesn't make the code non-standard and in almost all applications the performance will be the same. - Function type names ------------------- C99 allows you to define type names of function types and write something like: int f(int (int)); Accepting function types in typenames (or abstract declarators) makes the grammar ambiguous because it is impossible to differentiate between: (int (f)) -> function returning int with one parameter of type f (int (f)) -> integer variable f Function type names are stupid, because they are used as an alias of the function pointer types, but it is stupid that something like sizeof(int (int)) is not allowed (because here it should be understood as the size of a function), but is f(int (int)) is allowed because it is understood as a parameter of function pointer type. This complexity is not needed at all as function pointers fix all these problems without this complexity (and they are the more usual way of writing such code).