Commit Graph

329 Commits

Author SHA1 Message Date
Stephen Heumann
f2d15b8fc7 Fix optimizer bug where casts with unused results could sometimes cause stack corruption.
This problem could lead to crashes in code like the following (derived from a csmith-generated test case):

#pragma optimize 1
static int main(void) {
    long i = 2;
    (long)(i > 1);
}
2018-03-26 19:57:18 -05:00
Stephen Heumann
7f94876fa8 Fix mis-optimization of "expression && non-zero constant" operations with 32-bit type.
The previous code may have been intended to convert this to a "!=0" test, which would have been valid if correctly implemented, but with the current code generator that actually yields worse code than the original version, so for now I just removed the optimization for this case.

This problem could lead to crashes in code like the following (derived from a csmith-generated test case):

#pragma optimize 1
int main(int argc, char *argv[]){
    long l_57 = argc;

    return (4 ^ l_57) && 6;
}
2018-03-26 18:30:45 -05:00
Stephen Heumann
db98f7842d Fix mis-evaluation of certain equality comparisons with intermediate code optimization.
This affected comparisons of the form "logical operation or comparison == constant other than 0 or 1". These should always evaluate to 0 (false), but could mis-evaluate to true due to the bad optimization.

The following program gives an example showing the problem:

#pragma optimize 1
int main(void) {
        int i = 0, j = 42;
        return (i || j) == 123;
}
2018-03-26 18:20:36 -05:00
Stephen Heumann
7266b1d613 Properly support use of const structs and unions in assignments and as function arguments.
Here's an example that shows the issues (derived from a csmith-generated test case):

struct S {
   unsigned f;
};

void f1(struct S p) {
    printf("%u\n", p.f);
}

int main(void) {
    const struct S l = {123};
    struct S s;

    f1(l);

    s = l;
    printf("%u\n", s.f);
}
2018-03-25 20:56:15 -05:00
Stephen Heumann
4746d9ff60 Allow initialization of local vars with const-qualified struct or union type.
Here's an example that shows the problem (derived from a csmith-generated test case):

void f(void)
{
    const struct S {int i;} s = {1};
}
2018-03-25 18:22:37 -05:00
Stephen Heumann
9b08d4337a Prevent errors in loop invariant removal from trying to remove only the left subexpression of a comma operator.
Such subexpressions are not of the right form to work with the existing code, because they do not generate a value for use in the enclosing expression. For now, the code has been changed to simply not remove the subexpression in these cases. Alternative code could be written to make it work, but that might be more trouble than it's worth.

Here's an example that shows the problem (derived from a csmith-generated test case):

#pragma optimize 32+1 /* also had a problem with just 32 */
int main(void) {
    int x, y=10; /* also had problems if x was global */
    do {
        x=42, y-=1;
    } while (y);
    return x+y;
}
2018-03-25 18:22:37 -05:00
Stephen Heumann
237af41e90 Fix issue where a label with the same name as a typedef name was parsed as the beginning of a declaration.
This would lead to errors in programs like the following:

int main(void) {
        typedef int x;
x: ;
}

Even before support for mixed statements and declarations was introduced, this error could happen if the labeled statement was the first statement after the declarations in a block (as in the above example). Adding that support also allowed this error to happen with later statements in a block. The C4.2.4.1.CC test case was affected by this.
2018-03-25 18:22:37 -05:00
Stephen Heumann
d6502c0719 Implement C99 scope rules for selection and iteration statements.
Under these rules, if, switch, for, while, and do statements each have their own block scopes separate from the enclosing scope, and their substatements also have their own block scopes.

This patch always applies the C99 scope rules, but a flag can be changed to disable them or make them conditional on a configuration setting.
2018-03-25 18:22:37 -05:00
Stephen Heumann
14adcd6a80 Allow mixed declarations and statements (C99). 2018-03-25 18:22:37 -05:00
MikeW50
24bf693985
Merge pull request #56 from ksherlock/printf_scanf
Add printf/scanf format checking [WIP]
2018-03-25 15:06:58 -06:00
MikeW50
e6c6d2d516
Merge pull request #52 from ksherlock/debugger-documentation
Debugger documentation
2018-03-25 15:06:39 -06:00
Kelvin Sherlock
b9e6e4dd27 merge in updates from the ORCA Debugger disk. 2018-03-25 00:33:31 -04:00
ksherlock
7ef2ee2fcc Update Debugger.md
add updates after orca debugger was published.
2018-03-24 23:42:49 -04:00
ksherlock
e69b437dc7 Update Debugger.md
name strings are stored in pascal format, not c format.
2018-03-24 23:42:49 -04:00
ksherlock
a4e825198f Update Debugger.md
table format fixes
2018-03-24 23:42:49 -04:00
ksherlock
e620357dc6 Create Debugger.md
from ORCA/Debugger appendix A, including mistakes.
2018-03-24 23:42:49 -04:00
Kelvin Sherlock
6c1ccc5c0d Squashed commit of the following:
commit 4265329097538640e9e21202f1b141bcd42a44f3
Author: Kelvin Sherlock <ksherlock@gmail.com>
Date:   Fri Mar 23 21:45:32 2018 -0400

    indent to match standard indent.

commit 783518fbeb01d2df43ef2083d3341004c05e4e2e
Author: Kelvin Sherlock <ksherlock@gmail.com>
Date:   Fri Mar 23 20:21:15 2018 -0400

    clean up the typenames

commit 29b627ecf5ca9b8a143761f85a1807a6ca35ddd9
Author: Kelvin Sherlock <ksherlock@gmail.com>
Date:   Fri Mar 23 20:18:04 2018 -0400

    enable feature_hh, warn about %n with non-int modifier.

commit fc4ac8129e3772c4eda36658e344ec475938369c
Author: Kelvin Sherlock <ksherlock@gmail.com>
Date:   Fri Mar 23 15:13:47 2018 -0400

    warn thar %lc, %ls, etc are unsupported.

commit 7e6b433ba0552f7e52f0f034d398e9195c764326
Author: Kelvin Sherlock <ksherlock@gmail.com>
Date:   Fri Mar 23 13:36:25 2018 -0400

    warn about hh/ll modifier (if not supported)

commit 1943c9979d0013f9f38045ec04a962fbf0269f31
Author: Kelvin Sherlock <ksherlock@gmail.com>
Date:   Fri Mar 23 11:42:41 2018 -0400

    use error facilities for format errors.

commit 7811168f56dca1387055574ba8d32638da2fad96
Author: Kelvin Sherlock <ksherlock@gmail.com>
Date:   Thu Mar 22 15:34:21 2018 -0400

    add feature flags to disable c99 enhancements until orca lib is updated.

commit c2149cc5953155cfc3c3b4d0483cd25fb946b055
Author: Kelvin Sherlock <ksherlock@gmail.com>
Date:   Thu Mar 22 08:59:10 2018 -0400

    Add printf/scanf format checking [WIP]

    This parses out the xprintf / xscanf format string and compares it with the function arguments.

    enabled via #pragma lint 16.
2018-03-23 21:51:27 -04:00
Stephen Heumann
5685009791 Update release notes to cover recent changes. 2018-03-17 22:54:53 -05:00
Stephen Heumann
324c979f3b Correctly handle tentative struct/union and array definitions that are not completed.
In the case of structs or unions, an error is now produced. This addresses one of the problems mentioned in issue #53.

In the case of arrays, tentative definitions like "int i[];" are now permitted at file scope. If not completed by a subsequent definition, this winds up producing an array with one element, initialized to 0. See the discussion and example in C99/C11 section 6.9.2 (or C90 section 6.7.2 and example in TC1).
2018-03-06 22:53:52 -06:00
Stephen Heumann
c55acd1150 Give an error if the element type of an array type is an incomplete or function type. 2018-03-06 22:46:23 -06:00
Stephen Heumann
96f04b168e Do not enter forward-declared struct parameters in the global symbol table.
Memory for them is still allocated from the global pool, to ensure they remain available for as long as the function prototype that references them.

This addresses one of the problems mentioned in issue #53.
2018-03-06 19:46:51 -06:00
Stephen Heumann
78db036a85
Merge pull request #55 from ksherlock/debugger_struct_2
more nested struct type tweaks
2018-03-06 15:52:02 -06:00
Kelvin Sherlock
ae55b80f2f Previous embedded struct debugger fix didn't account for pointers to structs (ExpandPointerType).
This always pre-increments symLength then compensate by subtracting 12 in GetTypeDisp.
2018-03-05 23:15:14 -05:00
Stephen Heumann
cbdb773101 Add snprintf() and vsnprintf() prototypes in <stdio.h>. 2018-03-05 19:01:42 -06:00
Stephen Heumann
ef30698ac8 Update <ctype.h> header to include isblank(), as both a macro and function.
In order to work right, this needs either GNO's ORCALib (which already included isblank()) or a copy of ORCA's ORCALib with the corresponding patch applied.
2018-03-05 18:59:25 -06:00
Stephen Heumann
28fa8b1853 Merge branch 'stack-repair-opt' 2018-03-04 16:09:08 -06:00
Stephen Heumann
0884c019d2 Generate correct debugger symbol tables for nested struct types.
Previously, when a struct type first appeared in a symbol table nested within another struct type, subsequent references to that type would use the wrong offset and be corrupted. This occurred because the symbol table length had not yet been updated to reflect the size of the entry for the outer structure at the time the inner one was processed.

Fixes #54.
2018-02-28 23:31:10 -06:00
Stephen Heumann
83df2fd9e1 Revert definition of FILE structure in <stdio.h> to match the implementation in ORCALib.
It had been changed to reflect changes in the ORCALib code that added a second putback buffer element, but those changes were problematic and have been reverted for now. (It's also not clear if ORCALib binaries with the larger putback buffer were ever distributed--at the least, they aren't on Opus ][ or in any of the ORCA/C 2.2.0 beta releases.)
2018-02-28 22:57:41 -06:00
Stephen Heumann
5b26b8cc5b Expand all tabs in assembly files to spaces.
This allows the code to be displayed properly on GitHub and in modern text editors, which typically do not support the irregularly-spaced tab stops used for ORCA/M code. It also avoids any possibility of problems building the code if the SysTabs file is missing or has been customized with non-standard tab stops.
2018-02-10 21:55:24 -06:00
Stephen Heumann
bd110d7e21
Merge pull request #51 from ksherlock/debugger_forward_struct_decl
Fix debugger symbol tables with forward declared structs
2018-02-10 21:17:03 -06:00
Kelvin Sherlock
c11218359f forward-declared structs have no field list and generate an invalid debugger symbol table. Generate a valid struct entry by re-using the default error struct ({ field: int }) 2018-02-09 22:14:36 -05:00
Stephen Heumann
bdd60d9d08 When using varargs stack repair, only disable native-code peephole opt in functions containing varargs calls.
There is no need to reduce the optimization in other functions, which will not contain any varargs stack repair code.
2018-01-13 21:37:28 -06:00
Stephen Heumann
4a7644e0b5 Don't allocate stack space for varargs stack repair unless it's needed.
If there are no varargs calls (and nothing else that saves stack positions), then space doesn't need to be allocated for the saved stack position. This can also lead to more efficient prolog/epilog code for small functions.
2018-01-13 20:02:43 -06:00
Stephen Heumann
f24f37aa9f Generate more efficient stack repair code (2).
Previously, the stack repair code always generated code to save and restore a register, but this can be omitted except in cases where a 32-bit value or pointer is returned.
2018-01-12 22:32:12 -06:00
Stephen Heumann
b697094c58 Generate more efficient stack repair code (1).
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.
2018-01-12 22:28:47 -06:00
Stephen Heumann
44714767e5 Don't optimize out certain volatile stores.
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;
}
2018-01-07 21:50:32 -06:00
Stephen Heumann
38345e4ca2 Update ORCA/C version number to 2.2.0 B2. 2017-12-13 23:05:20 -06:00
Stephen Heumann
13434dd520 Update release notes. 2017-12-13 22:20:59 -06:00
Stephen Heumann
5312843b93 Don't invalidly eliminate certain stores of 0 to global/static variables.
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 */
}
2017-12-13 20:03:48 -06:00
Stephen Heumann
4e7a7e67e7 Fix problems with loop invariant removal optimization.
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).
2017-12-12 13:50:17 -06:00
Stephen Heumann
89f4257742
Merge pull request #46 from ksherlock/profile_flag_exit
generate function exit cop with profiling / #pragma debug 4.
2017-12-07 20:31:45 -06:00
Stephen Heumann
5152790b00 Don't inappropriately re-expand a macro's name when it appears within the macro.
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.
2017-12-05 23:28:57 -06:00
Kelvin Sherlock
dbfa542fba generate function exit cop with profiling / pragma debug 4. Expected by prizm. 2017-12-05 21:31:36 -05:00
Stephen Heumann
bfb929f4a7 Remove the setbuf macro in favor of just calling the library function.
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.
2017-11-12 23:57:28 -06:00
Stephen Heumann
dedd50c81e Include prototypes for standard library functions that are also defined as macros.
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.
2017-11-12 23:27:15 -06:00
Stephen Heumann
10c9e70f85 Update release notes. 2017-11-12 21:43:39 -06:00
Stephen Heumann
14cb6c6b8f Merge commit '3c09d1c4ff3ae3afc9afe0f44d58c5502ea953ed' 2017-11-12 20:08:26 -06:00
Stephen Heumann
ba09d5ee6d Fix issues with addressing/pointer arithmetic using unsigned indexes that generate a displacement of 32K to 64K.
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 */
}
2017-11-12 17:21:05 -06:00
Stephen Heumann
df42ce257f Fix issue where certain address computations could be improperly restricted to a 32K or 64K range (even when using the large memory model).
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 */
}
2017-11-12 12:29:06 -06:00
Stephen Heumann
103af4c4a4 Generate more efficient code for some indexing operations affected by the previous commit. 2017-11-11 21:55:22 -06:00