Commit Graph

207 Commits

Author SHA1 Message Date
Stephen Heumann
b363a2c006 Update ORCA/C version number to 2.2.1 final.
Also, update the release notes.
2024-08-21 19:05:15 -05:00
Stephen Heumann
347ad00ff7 Allow the operand of sizeof to be an un-parenthesized compound literal.
This is allowed based on the C standard syntax, but it previously gave a spurious error in ORCA/C, because the parenthesized type name at the beginning of the compound literal was parsed as the complete operand to sizeof.

Here is an example program affected by this:

int main(void) {
        return sizeof (char[]){1,2,3}; // should return 3
}
2024-08-11 20:33:36 -05:00
Stephen Heumann
5f59f152ed Allow function pointer == NULL comparisons under strict type checks.
These were improperly being flagged as an error, because (void*)0 was not being recognized as a null pointer constant in this context.
2024-08-02 20:26:40 -05:00
Stephen Heumann
8278f7865a Support unconvertible preprocessing numbers.
These are tokens that follow the syntax for a preprocessing number, but not for an integer or floating constant after preprocessing. They are now allowed within the preprocessing phases of the compiler. They are not legal after preprocessing, but they may be used as operands of the # and ## preprocessor operators to produce legal tokens.
2024-04-23 21:39:14 -05:00
Stephen Heumann
6b7414384f Fix code generation bug for indirect load/store of 64-bit values.
The issue was that if a 64-bit value was being loaded via one pointer and stored via another, the load and store parts could both be using y for their indexing, but they would clash with each other, potentially leading to loads coming from the wrong place.

Here are some examples that illustrate the problem:

/* example 1 */
int main(void) {
        struct {
                char c[16];
                long long x;
        } s = {.x = 0x1234567890abcdef}, *sp = &s;
        long long ll, *llp = ≪
        *llp = sp->x;
        return ll != s.x; // should return 0
}

/* example 2 */
int main(void) {
        struct {
                char c[16];
                long long x;
        } s = {.x = 0x1234567890abcdef}, *sp = &s;
        long long ll, *llp = ≪
        unsigned i = 0;
        *llp = sp[i].x;
        return ll != s.x; // should return 0
}

/* example 3 */
int main(void) {
        long long x[2] = {0, 0x1234567890abcdef}, *xp = x;
        long long ll, *llp = ≪
        unsigned i = 1;
        *llp = xp[i];
        return ll != x[1]; // should return 0
}
2024-04-10 20:49:17 -05:00
Stephen Heumann
77e0b8fc59 Fix codegen error for some indirect accesses to 64-bit values.
The code was not properly adding in the offset of the 64-bit value from the pointed-to location, so the wrong memory location would be accessed. This affected indirect accesses to non-initial structure members, when used as operands to certain operations.

Here is an example showing the problem:

#include <stdio.h>

long long x = 123456;

struct S {
        long long a;
        long long b;
} s = {0, 123456};

int main(void) {
        struct S *sp = &s;

        if (sp->b != x) {
                puts("error");
        }
}
2024-04-03 21:04:47 -05:00
Stephen Heumann
50636bd28b Fix code generation for qualified struct or union function parameters.
They were not being properly recognized as structs/unions, so they were being passed by address rather than by value as they should be.

Here is an example affected by this:

struct S {int a,b,c,d;};

int f(struct S s) {
    return s.a + s.b + s.c + s.d;
}

int main(void) {
    const struct S s = {1,2,3,4};
    return f(s);
}
2024-04-01 20:37:51 -05:00
Stephen Heumann
83537fd3c7 Disable a peephole optimization that can produce bad code.
The optimization applies to code sequences like:
	dec abs
	lda abs
	beq ...
where the dec and lda were supposed to refer to the same location.

There were two problems with this optimization as written:
-It considered the dec and lda to refer to the same location even if they were actually references to different elements of the same array.
-It did not work in the case where the A register value was needed in subsequent code.

The first of these was already an issue in previous ORCA/C releases, as in the following example:

#pragma optimize -1
int x[2] = {0,0};
int main(void) {
        --x[0];
        if (x[1] != 0)
                return 123;
        return 0; /* should return 0 */
}

I do not believe the second problem was triggered by any code sequences generated in previous releases of ORCA/C, but it can be triggered after commit 4c402fc88, e.g. by the following example:

#pragma optimize -1
int x = 1;
int main(void) {
        int y = 123;
        --x;
        return x == 0; /* should return 1 */
}

Since the circumstances where this peephole optimization was triggered validly are pretty obscure, just disabling it should have a minimal impact on the generated code.
2024-03-17 21:31:18 -05:00
Stephen Heumann
81934109fc Fix issues with type names in the third expression of a for loop.
There were a couple issues here:
*If the type name contained a semicolon (for struct/union member declarations), a spurious error would be reported.
*Tags or enumeration constants declared in the type name should be in scope within the loop, but were not.

These both stemmed from the way the parser handled the third expression, which was to save the tokens from it and re-inject them at the end of the loop. To get the scope issues right, the expression really needs to be evaluated at the point where it occurs, so we now do that. To enable that while still placing the code at the end of the loop, a mechanism to remove and re-insert sections of generated code is introduced.

Here is an example illustrating the issues:

int main(void) {
        int i, j, x;
        for (i = 0; i < 123; i += sizeof(struct {int a;}))
                for (j = 0; j < 123; j += sizeof(enum E {A,B,C}))
                        x = i + j + A;
}
2024-03-13 22:09:25 -05:00
Stephen Heumann
84fdb5c975 Fix handling of empty macro arguments as ## operands.
Previously, there were a couple problems:

*If the parameter that was passed an empty argument appeared directly after the ##, the ## would permanently be removed from the macro record, affecting subsequent uses of the macro even if the argument was not empty.
*If the parameter that was passed an empty argument appeared between two ## operators, both would effectively be skipped, so the tokens to the left of the first ## and to the right of the second would not be combined.

This example illustrates both issues (not expected to compile; just check preprocessor output):

#pragma expand 1
#define x(a,b,c) a##b##c
x(1, ,3)
x(a,b,c)
2024-02-22 21:55:46 -06:00
Stephen Heumann
d1847d40be Set numString properly for numeric tokens generated by ##.
Previously, it was not necessarily set correctly for the newly-generated token. This would result in incorrect behavior if that token was an operand to another ## operator, as in the following example:

#define x(a,b,c) a##b##c
x(1,2,3)
2024-02-22 21:42:05 -06:00
Stephen Heumann
c671bb71a5 Document recent library bug fixes. 2024-02-22 21:20:33 -06:00
Stephen Heumann
a646a03b5e Avoid possible errors when using postfix ++/-- on pointer expressions.
There was code that would attempt to use the cType field of the type record, but this is only valid for scalar types, not pointer types. In the case of a pointer type, the upper two bytes of the pointer would be interpreted as a cType value, and if they happened to have one of the values being tested for, incorrect intermediate code would be generated. The lower two bytes of the pointer would be used as a baseType value; this would most likely result in "compiler error" messages from the code generator, but might cause incorrect code generation with no errors if that value happened to correspond to a real baseType.

Code like the following might cause this error, although it only occurs if pointers have certain values and therefore depends on the memory layout at compile time:

void f(const int **p) {
    (*p)++;
}

This bug was introduced in commit f2a66a524a.
2024-02-09 20:45:14 -06:00
Stephen Heumann
7ca30d7784 Do not give a compile error for division of any integer constant by 0.
Division by zero produces undefined behavior if it is evaluated, but in general we cannot tell whether a given expression will actually be evaluated at run time, so we should not report this as a compile-time error.

We still report an error for division by zero in constant expressions that need to be evaluated at compile time. We also still produce a lint message about division by zero if the appropriate flag is enabled.
2024-02-02 20:03:34 -06:00
Stephen Heumann
c9dc566c10 Update release notes. 2024-02-02 18:31:48 -06:00
Stephen Heumann
4d8eaf93bc Update documentation for ORCA/C 2.2.0 release. 2023-07-20 14:14:07 -05:00
Stephen Heumann
9a56a50f5f Support FPE card auto-detection.
The second parameter of #pragma float is now optional, and if it missing or invalid then the FPE slot is auto-detected by the start-up code. This is done by calling the new ~InitFloat function in the FPE version of SysFloat.
2023-06-26 18:33:54 -05:00
Stephen Heumann
0021fd81bc #pragma float: Generate code in the .root file to set the FPE slot.
This allows valid FPE-using programs to be compiled using only #pragma float, with no changes needed to the code itself.

The slot-setting code is only generated if the slot is 1..7, and even then it can be overridden by calling setfpeslot(), so this should not cause compatibility problems for existing code.
2023-06-17 18:13:31 -05:00
Stephen Heumann
966da239ee Update release notes and tests to reflect recent SysFloat changes. 2023-06-16 20:46:01 -05:00
Stephen Heumann
5b294721f2 Document recent bug fixes in libraries. 2023-06-11 18:57:42 -05:00
Stephen Heumann
e5c69670cd Add documentation and tests for strtod changes. 2023-06-08 20:46:42 -05:00
Stephen Heumann
509f09253f Document recent bug fixes in SysLib and SysFloat. 2023-06-08 19:07:20 -05:00
Stephen Heumann
661c9c440d Add tests, documentation, and headers for lgamma(). 2023-05-21 18:30:15 -05:00
Stephen Heumann
118e326ac9 Miscellaneous small updates to release notes. 2023-04-30 21:36:23 -05:00
Stephen Heumann
0274b0ba83 Document octal formatting bug fix. 2023-04-17 22:00:29 -05:00
Stephen Heumann
3a298ec341 Add documentation and tests for 'a'/'A' printf conversions. 2023-04-16 20:25:15 -05:00
Stephen Heumann
2974c1b4bb Document fprintf bug fix. 2023-04-16 18:58:38 -05:00
Stephen Heumann
9dad2b6186 Update displayed version number to mark this as a development version. 2023-04-16 14:29:02 -05:00
Stephen Heumann
5c96042423 Update ORCA/C version number to 2.2.0 B7.
Also tweak documentation wording in a couple places.
2023-04-06 18:53:34 -05:00
Stephen Heumann
ba57d51500 Add a correction about the debug check box in Prizm. 2023-04-02 22:12:48 -05:00
Stephen Heumann
c678151bde Add tests and documentation for fma(). 2023-04-02 16:31:28 -05:00
Stephen Heumann
a988ef60bc Document bug fix for functions run at exit in large memory model. 2023-03-28 22:11:38 -05:00
Stephen Heumann
be291b2423 Show "Including ..." lines for all headers when using a sym file.
Previously, only the last header from a group of headers represented together would be listed.
2023-03-20 17:22:13 -05:00
Stephen Heumann
ea056f1fbb Avoid listing the first line twice when a pre-include file is used. 2023-03-15 20:43:43 -05:00
Stephen Heumann
3406dbd3ae Prevent a tag declared in an inner scope from shadowing a typedef.
This could occur because when FindSymbol was called to look for symbols in all spaces, it would find a tag in an inner scope before a typedef in an outer scope. The processing order has been changed to look for regular symbols (including typedefs) in any scope, and only look for tags if no regular symbol is found.

Here is an example illustrating the problem:

typedef int T;
int main(void) {
        struct T;
        T x;
}
2023-03-06 21:38:05 -06:00
Stephen Heumann
645b210e7f Prevent tags from shadowing variable names within static initializers.
This occurred due to looking for the symbol in all namespaces rather than only variable space.

Here is an example affected by this:

int X;
int main(void) {
        struct X {int i;};
        static int *i = &X;
}
2023-03-05 22:29:09 -06:00
Stephen Heumann
1f6bc44b48 Fix handling of typedef names immediately after an inner scope where the identifier is redeclared.
If an identifier is used as a typedef in an outer scope but then declared as something else in an inner scope (e.g. a variable name or tag), and that same identifier is the next token after the end of the inner scope, it would not be recognized properly as a typedef name leading to spurious errors.\

Here is an example that triggered this:

typedef char Type;
void f(int Type);
Type t;

Here is another one:

int main(void) {
        typedef int S;
        if (1)
                (struct S {int a;} *)0;
        S x;
}
2023-03-05 21:40:59 -06:00
Stephen Heumann
85890e0b6b Give an error if assembly code tries to use direct page addressing for a local variable that is out of range.
This could previously cause bad code to be produced with no error reported.
2023-03-04 21:06:07 -06:00
Stephen Heumann
bda54c0a79 Document qsort fixes. 2023-02-16 20:38:44 -06:00
Stephen Heumann
a6ef872513 Add debugging option to detect illegal use of null pointers.
This adds debugging code to detect null pointer dereferences, as well as pointer arithmetic on null pointers (which is also undefined behavior, and can lead to later dereferences of the resulting pointers).

Note that ORCA/Pascal can already detect null pointer dereferences as part of its more general range-checking code. This implementation for ORCA/C will report the same error as ORCA/Pascal ("Subrange exceeded"). However, it does not include any of the other forms of range checking that ORCA/Pascal does, and (unlike in ORCA/Pascal) it is controlled by a separate flag from stack overflow checking.
2023-02-12 18:56:02 -06:00
Stephen Heumann
245dd0a3f4 Add lint check for implicit conversions that change a constant's value.
This occurs when the constant value is out of range of the type being assigned to. This is likely indicative of an error, or of code that assumes types have larger ranges than they do in ORCA/C (e.g. 32-bit int).

This intentionally does not report cases where a value is assigned to a signed type but is within the range of the corresponding unsigned type, or vice versa. These may be done intentionally, e.g. setting an unsigned value to "-1" or setting a signed value using a hex constant with the high bit set. Also, only conversions to 8-bit or 16-bit integer types are currently checked.
2023-01-03 18:57:32 -06:00
Stephen Heumann
9f36e99194 Document __useTimeTool and add a declaration for it. 2023-01-02 18:10:41 -06:00
Stephen Heumann
5476118951 Add documentation and headers for timespec_get.
A macro is used to control whether struct timespec is declared, because GNO might want to declare it in other headers, and this would allow it to avoid duplicate declarations. (This will still require changes in the GNO headers. Currently, they declare struct timespec with different field names, although the layout is the same.)
2023-01-01 21:46:19 -06:00
Stephen Heumann
59664df9d9 Document <time.h> bug fixes. 2023-01-01 21:44:02 -06:00
Stephen Heumann
f7a139b4b5 Document use of Time Tool Set by gmtime and strftime.
Also include some tests for strftime %z and %Z conversions (although just producing no output will satisfy them).
2022-12-28 19:57:19 -06:00
Stephen Heumann
7d3f1c8dd7 Add headers, documentation, and tests for tgamma(). 2022-12-24 20:21:31 -06:00
Stephen Heumann
265a16d2f5 Add headers, documentation, and tests for erf() and erfc(). 2022-12-17 22:26:59 -06:00
Stephen Heumann
4bc486eade Do not require unused static functions to be defined.
This mostly implements the rule in C17 6.9 p3, which requires a definition to be provided only if the function is used in an expression. Per that rule, we should also exclude most sizeof or _Alignof operands, but we don't do that yet.
2022-12-12 22:10:36 -06:00
Stephen Heumann
fe62f70d51 Add lint option to check for unused variables. 2022-12-12 21:47:32 -06:00
Stephen Heumann
17936a14ed Rework root file code for CDevs to avoid leaking user IDs.
Formerly, the code would allocate user IDs but never free them. The result was that one user ID was leaked for each time a CDev was opened and closed.

The new root code calls new cleanup code in ORCALib, which detects if the CDev is going away and deallocates its user ID if so.
2022-12-11 22:01:29 -06:00