Commit Graph

599 Commits

Author SHA1 Message Date
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
Stephen Heumann
58771ec71c Do not do macro expansion after each ## operator is evaluated.
It should only be done after all the ## operators in the macro have been evaluated, potentially merging together several tokens via successive ## operators.

Here is an example illustrating the problem:

#define merge(a,b,c) a##b##c
#define foobar
#define foobarbaz a
int merge(foo,bar,baz) = 42;
int main(void) {
        return a;
}
2022-05-24 22:38:56 -05:00
Stephen Heumann
deca73d233 Properly expand macros that have the same name as a keyword or typedef.
If such macros were used within other macros, they would generally not be expanded, due to the order in which operations were evaluated during preprocessing.

This is actually an issue that was fixed by the changes from ORCA/C 2.1.0 to 2.1.1 B3, but then broken again by commit d0b4b75970.

Here is an example with the name of a keyword:

#define X long int
#define long
X x;
int main(void) {
        return sizeof(x); /* should be sizeof(int) */
}

Here is an example with the name of a typedef:

typedef short T;
#define T long
#define X T
X x;
int main(void) {
        return sizeof(x); /* should be sizeof(long) */
}
2022-05-24 22:22:37 -05:00
Stephen Heumann
daff1754b2 Make volatile loads from IO/softswitches access exactly the byte(s) specified.
Previously, one-byte loads were typically done by reading a 16-bit value and then masking off the upper 8 bits. This is a problem when accessing softswitches or slot IO locations, because reading the subsequent byte may have some undesired effect. Now, ORCA/C will do an 8-bit read for such cases, if the volatile qualifier is used.

There were also a couple optimizations that could occasionally result in not all the bytes of a larger value actually being read. These are now disabled for volatile loads that may access softswitches or IO.

These changes should make ORCA/C more suitable for writing low-level software like device drivers.
2022-05-23 21:10:29 -05:00
Stephen Heumann
21f266c5df Require use of digraphs in macro redefinitions to match the original.
This is part of the general requirement that macro redefinitions be "identical" as defined in the standard.

This affects code like:

#define x [
#define x <:
2022-04-05 19:47:22 -05:00
Stephen Heumann
a1d57c4db3 Allow ORCA/C-specific keywords to be disabled via a new pragma.
This allows those tokens (asm, comp, extended, pascal, and segment) to be used as identifiers, consistent with the C standards.

A new pragma (#pragma extensions) is introduced to control this. It might also be used for other things in the future.
2022-03-26 18:45:47 -05:00
Stephen Heumann
b2edeb4ad1 Properly stringize tokens that start with a trigraph.
This did not work correctly before, because such tokens were recorded as starting with the third character of the trigraph.

Here is an example affected by this:

#define mkstr(a) # a
#include <stdio.h>
int main(void) {
        puts(mkstr(??!));
        puts(mkstr(??!??!));
        puts(mkstr('??<'));
        puts(mkstr(+??!));
        puts(mkstr(+??'));
}
2022-03-25 18:10:13 -05:00
Stephen Heumann
f531f38463 Use suffixes on numeric constants in #pragma expand output.
A suffix will now be printed on any integer constant with a type other than int, or any floating constant with a type other than double. This ensures that all constants have the correct types, and also serves as documentation of the types.
2022-03-01 19:46:14 -06:00
Stephen Heumann
182cf66754 Properly stringize tokens with line continuations or non-initial trigraphs.
Previously, continuations or trigraphs would be included in the string as-is, which should not be the case because they are (conceptually) processed in earlier compilation phases. Initial trigraphs still do not get stringized properly, because the token starting position is not recorded correctly for them.

This fixes code like the following:

#define mkstr(a) # a
#include <stdio.h>
int main(void) {
        puts(mkstr(a\
bc));
        puts(mkstr(qr\
));
        puts(mkstr(\
xy));
        puts(mkstr(12??/
34));
        puts(mkstr('??<'));
}
2022-03-01 19:01:11 -06:00
Stephen Heumann
fec7b57ec2 Generate a string representation of tokens merged with ##.
This is necessary for correct behavior if such tokens are subsequently stringized with #. Previously, only the first half of the token would be produced.

Here is an example demonstrating the issue:

#define mkstr(a) # a
#define in_between(a) mkstr(a)
#define joinstr(a,b) in_between(a ## b)
#include <stdio.h>
int main(void) {
        puts(joinstr(123,456));
        puts(joinstr(abc,def));
        puts(joinstr(dou,ble));
        puts(joinstr(+,=));
        puts(joinstr(:,>));
}
2022-02-22 18:48:34 -06:00
Stephen Heumann
6cfe8cc886 Remove an unused string representation of macro tokens.
The string representation of macro tokens is needed for some preprocessor operations, but we get this in other ways (e.g. based on tokenStart/tokenEnd).
2022-02-21 18:39:39 -06:00
Stephen Heumann
8f27b8abdb Print any ## tokens in #pragma expand output.
Note that ## will not currently be recognized as a token in some contexts, leading to it not being printed.
2022-02-20 20:53:37 -06:00
Stephen Heumann
bf7a6fa5db Use separate functions for merging tokens with ## and merging adjacent strings.
These are conceptually separate operations occurring in different phases of the translation process. This change means that ## can no longer merge string constants: such operations will give an error about an illegal token. Cases like this are technically undefined behavior, so the old behavior could have been permitted, but it is clearer and more consistent with other compilers to treat this as an error.
2022-02-20 20:16:08 -06:00
Stephen Heumann
26e1bfc253 Allow generation of digraphs via ## token merging. 2022-02-20 18:57:03 -06:00
Stephen Heumann
2b062a8392 Make ## token merging on character constants give an error.
This ultimately should be supported, but that will be more work. For now, we just set the string representation to '?', which will usually give an error when merged. (Previously, whatever was at memory location 0 would be treated as the string representation of the token. Frequently this would just be an empty string, leading to no error but incorrect results.)
2022-02-20 16:19:00 -06:00
Stephen Heumann
da978932bf Save string representation of macros defined on command line.
This is necessary for correct operation of the # and ## preprocessor operators on the tokens from such macros.

Integers with a sign character still have the non-standard property of being treated as a single token, so they cannot be used with ##, but in most cases such uses will now give an error.
2022-02-20 15:35:49 -06:00
Stephen Heumann
2a9ec8fc43 Explicitly terminate PCH generation if there is an initialized variable.
Initialized variables have always been one of the things that stops PCH generation, but previously this was only detected when trying to write out the symbol records at the point of a later #include. On a subsequent compile using the sym file, nothing would recognize that PCH generation had stopped for this reason, so the PCH code would recognize the later #include as a potential opportunity to extend the sym file, and therefore would delete it to force regeneration next time. This led to the sym file being deleted and regenerated on alternate compiles, so its full benefit was not realized.

There is code in Header.pas to abort PCH generation if an initialized symbol is found. That is probably superfluous after this change, but it has been left in place for now.
2022-02-19 14:22:25 -06:00
Stephen Heumann
aabbadb34b Terminate header generation if #warning is encountered.
This is necessary to ensure that the warning message is printed on subsequent compiles.
2022-02-19 14:06:15 -06:00
Stephen Heumann
a73dce103b Terminate PCH generation if an #append is encountered.
If the appended file was another C file and that file contained an #include, this would create an invalid record in the sym file. It would record memory from the buffer holding the original file to the buffer holding the appended file. In general, these are not contiguous, so superfluous data from other parts of memory would be included in the sym file. This record would normally just be treated as invalid on subsequent compiles, but it could theoretically be very large (depending on the memory layout) and might contain sensitive data from other parts of memory.
2022-02-19 14:05:07 -06:00
Stephen Heumann
1e98a63bf4 Avoid generating duplicate "Including ..." messages.
This could happen if a header was saved in the sym file, but the sym file data was not actually used because the source code in the main file did not match what was saved.
2022-02-16 21:31:49 -06:00
Stephen Heumann
f2d6625300 Save #pragma path directives in sym files.
They were not being saved, which would result in ORCA/C not searching the proper paths when looking for an include file after the sym file had ended. Here is an example showing the problem:

#pragma path "include"
#include <stdio.h>
int k = 50;
#include "n.h" /* will not find include:n.h */
2022-02-15 21:27:35 -06:00
Stephen Heumann
30fcc7227f Tweak comments in Scanner.asm.
There are no code changes.
2022-02-15 20:51:16 -06:00
Stephen Heumann
3893db1346 Make sure #pragma expand is properly applied in all cases.
There were various places where the flag for macro expansions was saved, set to false, and then later restored. If #pragma expand was used within those areas, it would not be properly applied. Here is an example showing that problem:

void f(void
#pragma expand 1
) {}

This could also affect some uses of #pragma expand within precompiled headers, e.g.:

#pragma expand 1
#include "a.h"
#undef foobar
#include "b.h"
...

Also, add a note saying that code in precompiled headers will not be expanded. (This has always been the case, but was not clearly documented.)
2022-02-15 20:50:02 -06:00
Stephen Heumann
8c0d65616c Remove an unnecessary variable. 2022-02-13 21:36:03 -06:00
Stephen Heumann
c96cf4f1dd Do not save predefined and command-line macros in the sym file.
Previously, these might or might not be saved (based on the contents of uninitialized memory), but in many cases they were. This was unnecessary, since these macros are automatically defined when the scanner is initialized. Reading them from the sym file could result in duplicate copies of them in the macro list. This is usually harmless, but might result in #undefs of macros from the command line not working properly.
2022-02-13 20:17:33 -06:00
Stephen Heumann
b493dcb1da Add lint check to require whitespace after names of object-like macros.
This is a requirement added in C99, so it is added as part of the C99 syntax checks.

This affects definitions like:

#define foo;
2022-02-13 19:44:56 -06:00
Stephen Heumann
c169c2bf92 Fully prohibit redefinition of predefined macros.
Code like the following was previously being allowed:

#define __STDC__ /* no tokens */
2022-02-13 18:10:45 -06:00
Stephen Heumann
5d7c002819 Fix bug causing some #undefs to be ignored when using a sym file.
This would occur if the macro had already been saved in the sym file and the #undef occurred before a subsequent #include that was also recorded in the sym file. The solution is simply to terminate sym file generation if an #undef of an already-saved macro is encountered.

Here is an example showing the problem:

test.c:
#include "test1.h"
#undef x
#include "test2.h"

int main(void) {
#ifdef x
        return x;
#else
        return y;
#endif
}

test1.h:
#define x 27

test2.h:
#define y 6
2022-02-13 16:33:43 -06:00
Stephen Heumann
b231782442 Add option to use a custom pre-include file.
This is a file that will be included before the source file is processed. If specified, it is used instead of the default .h file.
2022-02-12 21:36:39 -06:00
Stephen Heumann
913a333f9f Record the cc= string in the symbol file and require it to match.
Macros and include paths from the cc= parameters may be included in the symbol file, so incorrect behavior could result if the symbol file was used for a later compilation with different cc= parameters.
2022-02-12 19:45:04 -06:00
Stephen Heumann
06e17cd8f5 Give an error if file names or command-line parameters are too long.
The source file name, keep name, NAMES= string, and cc= string are all restricted to 255 characters, but these limits were not previously enforced, and exceeding them could lead to strange behavior.
2022-02-12 15:42:15 -06:00
Stephen Heumann
bd811559d6 Fix issues with keep names in sym files.
There were a couple issues that could occur with #pragma keep and sym files:

*If a source file used #pragma keep but it was overridden by KEEP= on the command line or {KeepName} in the shell, then the overriding keep name would be saved to the sym file. It would therefore be applied to subsequent compilations even if it was no longer specified in the command line or shell variable.

*If a source file used #pragma keep, that keep name would be recorded in the sym file. On subsequent compilations, it would always be used, overriding any keep name specified by the command line or shell, contrary to the usual rule that the name on the command line takes priority.

With this patch, the keep name recorded in the sym file (if any) should always be the one specified by #pragma keep, but it can be overridden as usual.
2022-02-06 21:49:08 -06:00
Stephen Heumann
9cdf199c3a Clarify that sym files still need to be deleted when adding defaults.h.
The old wording made it sound like it applied only to .sym files generated by an old version of ORCA/C, but that is not the case.
2022-02-06 19:06:51 -06:00
Stephen Heumann
5f03dee66a Allow negated long long constants in cc= defines.
These are still treated as one token, like other negated numbers specified in cc=(-d...).
2022-02-06 15:33:42 -06:00
Stephen Heumann
efb363a04d Update a comment. 2022-02-06 15:08:04 -06:00
Stephen Heumann
7d4f923470 Improve error handling for cc= options on command line. 2022-02-06 14:24:22 -06:00
Stephen Heumann
785a6997de Record source file changes within a function as part of debug info.
This affects functions whose body spans multiple files due to includes, or is treated as doing so due to #line directives. ORCA/C will now generate a COP 6 instruction to record each source file change, allowing debuggers to properly track the flow of execution across files.
2022-02-05 18:32:11 -06:00
Stephen Heumann
5ac79ff36c Stop capitalizing file names in debug information.
This does not seem to be necessary for any of the debuggers (at least in their latest versions), and it obviously causes problems with case-sensitive filesystems.
2022-02-04 22:15:02 -06:00
Stephen Heumann
7322428e1d Add an option to print file names in error messages.
This can help identify if an error is in the main source file or an include file.
2022-02-04 22:10:50 -06:00
Stephen Heumann
4cb2106ee4 Change the name of the current source file on an #include or #append.
This causes __FILE__ to give the name of an include file if used within it, which seems to be what the standards intend (and what other compilers do). It also affects the file name recorded in debugging information for functions declared in an include file.

(Note that occ will generate a #line directive before an #append, essentially to work around the problem this patch fixes. After the patch, such a #line directive is effectively ignored. This should be OK, although it may result in a difference in whether a full or partial pathname is used for __FILE__ and in debug info.)
2022-02-03 22:22:33 -06:00
Stephen Heumann
dce9d36edd Comment out unused error messages and update docs about errors. 2022-02-01 22:16:57 -06:00
Stephen Heumann
e36503508a Allow more forms of address expressions in static initializers.
There were several forms that should be permitted but were not, such as &"str"[1], &*"str", &*a (where a is an array), and &*f (where f is a function).

This fixes #15 and also certain other cases illustrated in the following example:

char a[10];
int main(void);
static char *s1 = &"string"[1];
static char *s2 = &*"string";
static char *s3 = &*a;
static int (*f2)(void)=&*main;
2022-01-29 21:59:25 -06:00
Stephen Heumann
e8d90a1b69 Do not generate extra zero bytes after certain string constants.
These extra bytes are unnecessary after the changes in commit 5871820e0c to make string constants explicitly include their null terminators.

The extra bytes would be generated for code like the following:

int main(void) {
        static char *s1 = "abc", *s2 = "def", *s3 = "ghi";
}
2022-01-29 18:27:03 -06:00
Stephen Heumann
02fbf97a1e Work around the SANE comp conversion bug in another place.
This affects casts to comp evaluated at compile time, e.g.:

static comp c = (comp)-53019223785472.0;
2022-01-22 18:22:37 -06:00
Stephen Heumann
5357e65859 Fix indentation of a few lines. 2022-01-22 18:21:11 -06:00
Stephen Heumann
f4b0993007 Specify correct location for the default .h file. 2022-01-17 18:27:39 -06:00
Stephen Heumann
242bef1f6e Correct a comment. 2022-01-17 18:27:10 -06:00