Commit Graph

745 Commits

Author SHA1 Message Date
Stephen Heumann
6d07043783 Do not treat uses of enum types from outer scopes as redeclarations.
This affects code like the following:

enum E {a,b,c};
int main(void) {
        enum E e;
        struct E {int x;}; /* or: enum E {x,y,z}; */
}

The line "enum E e;" should refer to the enum type declared in the outer scope, but not redeclare it in the inner scope. Therefore, a subsequent struct, union, or enum declaration using the same tag in the same scope is acceptable.
2022-07-18 21:34:29 -05:00
Stephen Heumann
fd54fd70d0 Remove some unnecessary/duplicate code.
This mainly comments out statements that zero out data that was already set to zero by a preceding Calloc call.
2022-07-18 21:19:44 -05:00
Stephen Heumann
60efb4d882 Generate better code for indexed jumps.
They now use a jmp (addr,X) instruction, rather than a more complicated code sequence using rts. This is an improvement that was suggested in an old Genie message from Todd Whitesel.
2022-07-18 21:18:26 -05:00
Stephen Heumann
c36bf9bf0a Ignore storage class when creating enum tag symbols.
This avoids strangeness where an enum tag declared within a typedef declaration would act like a typedef. For example, the following would compile without error:

typedef enum E {a,b,c} T;
E e;
2022-07-18 18:37:26 -05:00
Stephen Heumann
2cbcdc736c Allow the same identifier to be used as a typedef and an enum tag.
This should be allowed (because they are in separate name spaces), but was not.

This affected code like the following:

typedef int T;
enum T {a,b,c};
2022-07-18 18:33:54 -05:00
Stephen Heumann
bdf8ed4f29 Simplify some code. 2022-07-17 18:15:29 -05:00
Stephen Heumann
6bfd491f2a Update release notes. 2022-07-14 18:40:59 -05:00
Stephen Heumann
6934c8890d Detect several cases of inappropriate operand types being used with ++ or --. 2022-07-12 18:35:52 -05:00
Stephen Heumann
63d33b47bf Generate valid code for "dereferencing" pointers to void.
This covers code like the following, which is very dubious but does not seem to be clearly prohibited by the standards:

int main(void) {
        void *vp;
        *vp;
}

Previously, this would do an indirect load of a four-byte value at the location, but then treat it as void. This could lead to the four-byte value being left on the stack, eventually causing a crash. Now we just evaluate the pointer expression (in case it has side effects), but effectively cast it to void without dereferencing it.
2022-07-12 18:34:58 -05:00
Stephen Heumann
417fd1ad9c Generate better code for && and ||. 2022-07-11 21:16:18 -05:00
Stephen Heumann
312a3a09b9 Generate better code for long long >= comparisons. 2022-07-11 19:20:55 -05:00
Stephen Heumann
687a5eaa45 Generate better code for pc_not on boolean operands. 2022-07-11 18:54:39 -05:00
Stephen Heumann
b5b76b624c Use pei rather than load+push in a few places. 2022-07-11 18:42:14 -05:00
Stephen Heumann
607211d38e Rearrange some labels to facilitate branch-shortening optimization. 2022-07-11 18:39:00 -05:00
Stephen Heumann
23b870908e Recognize pc_not as a boolean operation for purposes of optimizations.
This generates better code for certain things, like the following assignment:

_Bool b = !x;
2022-07-11 18:36:10 -05:00
Stephen Heumann
753c9b9f20 Adjust the way FE_DFL_ENV is defined.
This avoids any possible issue with code possibly expecting __FE_DFL_ENV to be in the data bank when using the large memory model, although I don't think that happened in practice.
2022-07-11 18:30:37 -05:00
Stephen Heumann
c3567c81a4 Correct comments. 2022-07-11 18:23:36 -05:00
Stephen Heumann
9b31e7f72a Improve code generation for comparisons.
This converts comparisons like x > N (with constant N) to instead be evaluated as x >= N+1, since >= comparisons generate better code. This is possible as long as N is not the maximum value in the type, but in that case the comparison is always false. There are also a few other tweaks to the generated code in some cases.
2022-07-10 22:27:38 -05:00
Stephen Heumann
7b0dda5a5e Fix a flawed optimization.
The optimization could turn an unsigned comparison "x <= 0xFFFF" into "x < 0".

Here is an example affected by this:

int main(void) {
        unsigned i = 1;
        return (i <= 0xffff);
}
2022-07-10 22:25:55 -05:00
Stephen Heumann
76e4b1f038 Optimize away some tax/tay instructions used only to set flags. 2022-07-10 17:35:56 -05:00
Stephen Heumann
bf40e861aa Fix indentation. 2022-07-10 13:12:10 -05:00
Stephen Heumann
2dff68e6ae Eliminate an unnecessary instruction in quad-to-word conversion.
The TAY instruction would set the flags, but that is unnecessary because pc_cnv is a "NeedsCondition" operation (and some other conversions also do not reliably set the flags).

The code is also changed to preserve the Y register, possibly facilitating register optimizations.
2022-07-09 21:48:56 -05:00
Stephen Heumann
4470626ade Optimize division/remainder by various constants.
This generally covers powers of two and certain other values. (Details differ for signed/unsigned div/rem.)
2022-07-09 15:05:47 -05:00
Stephen Heumann
054719aab2 Fix bug in code generation for the product of two constants.
This was a problem introduced in commit 393b7304a0. It could cause a compiler error for unoptimized array indexing code, e.g.:

int a[100];
int main(void) {
        return a[5];
}
2022-07-09 15:01:25 -05:00
Stephen Heumann
00e7fe7125 Increase some size limits.
The new value of maxLocalLabel is aligned with the C99+ requirement to support "511 identifiers with block scope declared in one block".

The value of maxLabel is now the maximum it can be while keeping the size of the labelTab array under 32 KiB. (I'm not entirely sure the address calculations in the code generated by ORCA/Pascal would work correctly beyond that.)
2022-07-08 21:30:14 -05:00
Stephen Heumann
f0d827eade Generate more efficient code for certain subtractions.
This affects 16-bit subtractions where where only the left operand is "complex" (i.e. most things other than constants and simple loads). They were using an unnecessarily complicated code path suitable for the case where both operands are complex.
2022-07-07 18:38:41 -05:00
Stephen Heumann
7898c619c8 Fix several cases where a condition might not be evaluated correctly.
These could occur because the code for certain operations was assumed to set the z flag based on the result value, but did not actually do so. The affected operations were shifts, loads or stores of bit-fields, and ? : expressions.

Here is an example showing the problem with a shift:

#pragma optimize 1
int main(void) {
        int i = 1, j = 0;
        return (i >> j) ? 1 : 0;
}

Here is an example showing the problem with a bit-field load:

struct {
        signed int i : 16;
} s = {1};
int main(void) {
        return (s.i) ? 1 : 0;
}

Here is an example showing the problem with a bit-field store:

#pragma optimize 1
struct {
        signed int i : 16;
} s;
int main(void) {
        return (s.i = 1) ? 1 : 0;
}

Here is an example showing the problem with a ? : expression:

#pragma optimize 1
int main(void) {
        int a = 5;
        return (a ? (a<<a) : 0) ? 0 : 1;
}
2022-07-07 18:26:37 -05:00
Stephen Heumann
393b7304a0 Optimize 16-bit multiplication by various constants.
This optimizes most multiplications by a power of 2 or the sum of two powers of 2, converting them to equivalent operations using shifts which should be faster than the general-purpose multiplication routine.
2022-07-06 22:24:54 -05:00
Stephen Heumann
497e5c036b Use new 16-bit unsigned multiply routine that complies with C standards.
This changes unsigned 16-bit multiplies to use the new ~CUMul2 routine in ORCALib, rather than ~UMul2 in SysLib. They differ in that ~CUMul2 gives the low-order 16 bits of the true result in case of overflow. The C standards require this behavior for arithmetic on unsigned types.
2022-07-06 22:22:02 -05:00
Stephen Heumann
11a3195c49 Use properly result type for statically evaluated ternary operators.
Also, update the tests to include statically-evaluated cases.
2022-07-04 22:30:25 -05:00
Stephen Heumann
f5d5b88002 Correct result strings in a couple tests. 2022-07-04 22:29:15 -05:00
Stephen Heumann
f6fedea288 Update release notes and header to reflect recent stdio fixes. 2022-07-04 22:28:45 -05:00
Stephen Heumann
06bf0c5f46 Remove macro definition of rewind() which does not clear the IO error indicator.
Now rewind() will always be called as a function. In combination with an update to the rewind() function in ORCALib, this will ensure that the error indicator is always cleared, as required by the C standards.
2022-06-24 18:32:08 -05:00
Stephen Heumann
c987f240c6 Optimize out ? : operations with constant conditions.
The condition expression may become a constant due to optimizations, and optimizing out the ? : operation may also enable further optimizations.
2022-06-24 18:23:29 -05:00
Stephen Heumann
102d6873a3 Fix type checking and result type computation for ? : operator.
This was non-standard in various ways, mainly in regard to pointer types. It has been rewritten to closely follow the specification in the C standards.

Several helper functions dealing with types have been introduced. They are currently only used for ? :, but they might also be useful for other purposes.

New tests are also introduced to check the behavior for the ? : operator.

This fixes #35 (including the initializer-specific case).
2022-06-23 22:05:34 -05:00
Stephen Heumann
15dc3a46c4 Allow casts between long long and pointer types.
This applies to casts in executable code. Some casts in initializers still don't work.
2022-06-20 21:55:54 -05:00
Stephen Heumann
5e20e02d06 Add a function to make a pointer type.
This allows us to refactor out code that was doing this in several places.
2022-06-19 17:55:08 -05:00
Stephen Heumann
e5501dc902 Update test for maximum length of string constants. 2022-06-18 22:03:22 -05:00
Stephen Heumann
58849607a1 Use cgPointerSize for size of pointers in various places.
This makes no practical difference when targeting the GS, but it better documents what the relevant size is.
2022-06-18 19:30:20 -05:00
Stephen Heumann
a3104853fc Treat string constant base types as having unknown number of elements.
I am not aware of any effect from this, but the change makes their element count consistent with the size of 0 (indicating an incomplete type).
2022-06-18 19:18:29 -05:00
Stephen Heumann
802ba3b0ba Make unary & always yield a pointer type, not an array.
This affects expressions like &*a (where a is an array) or &*"string". In most contexts, these undergo array-to-pointer conversion anyway, but as an operand of sizeof they do not. This leads to sizeof either giving the wrong value (the size of the array rather than of a pointer) or reporting an error when the array size is not recorded as part of the type (which is currently the case for string constants).

In combination with an earlier patch, this fixes #8.
2022-06-18 18:53:29 -05:00
Stephen Heumann
91b63f94d3 Note an error in the manual. 2022-06-17 18:45:59 -05:00
Stephen Heumann
67ffeac7d4 Use the proper type for expressions like &"string".
These should have a pointer-to-array type, but they were treated like pointers to the first element.
2022-06-17 18:45:11 -05:00
Stephen Heumann
5e08ef01a9 Use quotes around "C" locale in release notes.
This is consistent with the usage in the C standards.
2022-06-15 21:54:11 -05:00
Stephen Heumann
8406921147 Parse command-line macros more consistently with macros in code.
This makes a macro defined on the command line like -Dfoo=-1 consist of two tokens, the same as it would if defined in code. (Previously, it was just one token.)

This also somewhat expands the set of macros accepted on the command line. A prefix of +, -, *, &, ~, or ! (the one-character unary operators) can now be used ahead of any identifier, number, or string. Empty macro definitions like -Dfoo= are also permitted.
2022-06-15 21:52:35 -05:00
Stephen Heumann
161bb952e3 Dynamically allocate string space, and make it larger.
This increases the limit on total bytes of strings in a function, and also frees up space in the blank segment.
2022-06-08 22:09:30 -05:00
Stephen Heumann
3c2b492618 Add support for compound literals within functions.
The basic approach is to generate a single expression tree containing the code for the initialization plus the reference to the compound literal (or its address). The various subexpressions are joined together with pc_bno pcodes, similar to the code generated for the comma operator. The initializer expressions are placed in a balanced binary tree, so that it is not excessively deep.

Note: Common subexpression elimination has poor performance for very large trees. This is not specific to compound literals, but compound literals for relatively large arrays can run into this issue. It will eventually complete and generate a correct program, but it may be quite slow. To avoid this, turn off CSE.
2022-06-08 21:34:12 -05:00
Stephen Heumann
a85846cc80 Fix codegen bug with pc_bno in some cases with a 64-bit right operand.
The desired location for the quad result was not saved, so it could be overwritten when generating code for the left operand. This could result in incorrect code that might trash the stack.

Here is an example affected by this:

#pragma optimize 1
int main(void) {
        long long a, b=2;
        char c = (a=1,b);
}
2022-06-08 20:49:32 -05:00
Stephen Heumann
0e8b485f8f Improve debug printing of pcodes.
Some pcode instruction names were missing.
2022-06-08 20:49:16 -05:00
Stephen Heumann
0b6d150198 Move Short function out of the blank segment.
This makes a bit more room in the blank segment, which is necessary when codegen debugging is enabled.
2022-05-26 19:15:03 -05:00