Previously, when stack repair code was generated, it always included instructions to save and restore a previously-saved stack position, but this was only actually used for function calls nested within the arguments to other function calls using stack repair code. Now that code is only generated in cases where it is needed, and the stack repair code for other calls is simplified to omit it.
This optimization affects all (non-nested) function calls when not using optimize bit 3, and varargs function calls when not using optimize bit 6.
This could occur due to the new native-code peephole optimizations for stz instructions, which can collapse consecutive identical ones down to one instruction. This is OK most of the time, but not when dealing with volatile variables, so disable it in that case.
The following test case shows the issue (look at the generated code):
#pragma optimize -1
volatile int a;
int main(void) {
a = 0;
a = 0;
}
This could happen in native-code peephole optimization if two stz instructions targeting different global/static locations occurred consecutively.
This was a regression introduced by commit a3170ea7.
The following program demonstrates the problem:
#pragma optimize 1+2+8+64
int i,j=1;
int main (void) {
i = 0;
j = 0;
return j; /* should return 0 */
}
These mainly related to situations where the optimization of multiple natural loops (including those created by continue statements) could interact to generate invalid results. Invalid optimizations could also be performed in certain other cases where there were multiple goto statements targeting a single label and at least one of them formed a loop.
These issues are addressed by appropriately adjusting the control flow and updating various data structures after each loop is processed during loop invariant removal.
This fixes#18 (compca18.c).
This should implement the C standard rules about making macro name tokens ineligible for replacement, except that it does not currently handle cases of nested replacements (such as a cycle of mutually-referential macros).
This fixes#12. There are still a couple other bugs with macro expansion in obscure cases, but I'll consider them separate issues.
The macro was slightly broken in that its 'buf' argument might be evaluated twice. This could be a problem if it was, e.g., a call to an allocation function.
This is needed to ensure correct behavior in cases where the macro is bypassed to access the library function, e.g. by enclosing the function name in parentheses or by taking its address.
These cases should now always work when using an expression of type unsigned as the index. They will work in some cases but not others when using an int as the index: making those cases work consistently would require more extensive changes and/or a speed hit, so I haven't done it for now.
Note that this now uses an "unsigned multiply" operation for all 16-bit index computations. This should actually work even when the index is a negative signed value, because it will wind up producing (the low-order 16 bits of) the right answer. The signed multiply, on the other hand, generally does not produce the low-order 16 bits of the right answer in cases where it overflows.
The following program is an example that was miscompiled (both with and without optimization):
int c[20000] = {3};
int main(void) {
int *p;
unsigned i = 17000;
p = c + 17000u;
return *(p-i); /* should return 3 */
}
This could occur with computations where multiple variables were added to a pointer.
The following program is an example that was miscompiled:
#pragma optimize 1
#pragma memorymodel 1
char c[80000];
int main(void) {
unsigned i = 30000, j = 40000;
c[70000] = 3;
return *(c+i+j); /* should return 3 */
}
This introduces a function to check whether the index portion of a pc_ixa intermediate code operation (used for array indexing) may be negative. This is also used when generating code for the large memory model, which can allow slightly more efficient code to be generated in some cases.
This fixes#45.
This type information is currently used when generating code for the large memory model, but not for the short memory model (which is a bug in itself, causing issue such as #45).
Because the correct type information was not being provided, the code generator could incorrectly use signed index computations when a 16-bit unsigned index value was used in large-memory-model code. The following program is an example that was being miscompiled:
#pragma optimize 1
#pragma memorymodel 1
char c[0xFFFF];
int main(void) {
unsigned i = 0xABCD;
c[0xABCD] = 3;
return c[i]; /* should return 3 */
}
This optimization could apply when indexing into an array whose elements are a power-of-2 size using a 16-bit index value. It is now only used when addressing arrays on the stack (which are necessarily smaller than 64k).
The following program demonstrates the problem:
#pragma optimize 1
#pragma memorymodel 1
long c[40000];
int main(void) {
int i = 30000;
c[30000] = 3;
return c[i]; /* should return 3 */
}
This could already be optimized out by the peephole optimizer, but it's bad enough code that it really shouldn't be generated even when not using that optimization.
This could generate bad code (e.g. invalidly moving stores ahead of loads, as in #44). It would be possible to do this validly in some cases, but it would take more work to do the necessary checks. For now, we'll just block the optimization for bitfield stores.
In combination with the previous commit, this fixes#44.
The code was not accounting for the possibility that the loaded-from location aliases with the destination of an indirect store in the loop, or for the possibility that it may be written by a function called in the loop. Since we don't have sophisticated alias analysis, we now conservatively assume there may be aliasing in all such cases.
This fixes#20 (compca20.c) and #21 (compca21.c).
This is what is required by the C standards.
This partially reverts a change in ORCA/C 2.1.0, which should only have been applied to hexadecimal escape sequences.
For example, the following is now allowed:
typedef void v;
void foo(v) {}
This appears to be permitted under at least C99 and C11 (the C89 wording is less clear), and is accepted by other modern compilers.
This is based on a patch from Kelvin Sherlock, and in turn on code from MPW IIgs ORCA/C, but with modifications to be more standards-compliant.
Bit 1 in #pragma ignore controls a new option to (non-standardly) treat character constants with three or more characters as having type long, so they can contain up to four bytes.
Note that this patch orders the bytes the opposite way from MPW IIgs ORCA/C, but the same way as GCC and Clang.
These are enabled when bit 15 is set in the #pragma debug directive.
Support is still needed to ensure these work properly with pre-compiled headers.
This patch is from Kelvin Sherlock.
Previously, the structure load would be treated as a common subexpression eligible for elimination, but the structure would always be treated as if it had a size of 4 bytes. If it did not, this would generally lead to a crash. (I'm also not sure if dependency analysis was being performed properly for these structures.)
The following program illustrates the problem:
#pragma optimize 17
struct mystruct { char x; } ms;
static void foo(struct mystruct pk) {}
int main(void)
{
struct mystruct *p = &ms;
foo(*p);
foo(*p);
}
This could happen in certain cases where the destination is not considered "simple" (e.g. because it is a local array location that does not fit in the direct page).
The following program demonstrates the problem:
#pragma optimize 1
int main(void) {
long temp1 = 1, temp2 = 2, A[64];
long B[2] = {0};
B[1] = temp1 + temp2;
return B[1]; /* should return 3 */
}
This could occur because a temporary location might be used both in the l-value and r-value computations, but the final assignment code assumed it still had the value from the l-value computation.
The following function demonstrates this problem (*ip is not updated, and *p is trashed):
int badinc(char **p, int *ip)
{
*ip += *(*p)++;
}