[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[Tinycc-devel] TinyCC on Windows & some suggestions
From: |
Robert Schlicht |
Subject: |
[Tinycc-devel] TinyCC on Windows & some suggestions |
Date: |
Sun, 10 Mar 2024 17:59:56 +0100 |
At our university we offer a course where we program simple spatial simulations
in various programming languages, one of them being C, for illustrating
close-to-the-machine programming concepts. We here need a C implementation that
is small (since it’s accessed over a network), works out of the box on Windows
computers (since our students are beginners) and runs fast (so compiler errors
are available instantaneously). We do not need advanced developer tools, and
code running three times slower is acceptable because that is still faster than
scripting languages.
TCC is obviously a good option here, and for our course starting in April of
this year, I put together a package https://rschlicht.eu/tc-ide.zip that
includes a minimalist IDE running TCC and a very basic form of a C standard
library, all contained in a standalone executable tc-ide.exe. The library is
just headers that directly access the Windows API (no runtime needed) and
should satisfy the requirements of a conforming freestanding implementation,
while also including common memory, file, math and the printf family of
functions. (If anyone finds this useful, I’ll gladly contribute it to the TCC
project.)
The executable is compiled by itself, although this currently requires a few
hacks and workarounds to get it working as desired. I list these here as
suggestions for improving TCC:
(1) For using TCC as a library, it would be nice if it did a more thorough
cleanup:
– In a few places exit() is called in case of failure, but terminating the
program is not very user-friendly; cleanly propagating failure or even some
longjmp hacks might provide a better solution. [tc-ide does the latter, while
patching function calls to keep track of memory and open files.]
– Another problem I encountered is that TCC does not always properly restore
the state of the global variables; compiling the following code fragment the
first time produces an error message (as it should), but the second time it
causes an exception (which I assume is a bug):
void nothing(void) {for ( ; ; ) break;} void garbage(void) {switch
[The workaround in tc-ide is ugly but straightforward: Make a copy of the
memory block containing all global variables, and restore this block after TCC
returns.]
(2) I really appreciate that TCC can directly link to functions in Windows DLLs
with no auxiliary .lib file and that it even supports directives like #pragma
comment(lib,"kernel32"). The current implementation of the DLL lookup with a
huge number of lseek & read calls (via read_mem() in tccpe.c) may be
inefficient on some file systems. [tc-ide avoids this issue by creating file
mappings in memory and redirecting lseek and read to those memory buffers,
which it has to deal with anyway to access the embedded headers.]
(3) The C23 preprocessor directive #embed would be of help for embedding
headers and other files as byte arrays in the program. [tc-ide currently does
this by providing a non-standard feature with a custom notation like #include
"stdlib.h#".]
(4) TCC uses fixed buffer sizes for file paths in certain places. For example,
libtcc.c has 260(=MAX_PATH) in config_tccdir_w32() and _fullpath(), 1000 in
tcc_add_systemdir() and 1024 in tcc_add_library_internal(), while tccelf.c has
1024 in getcwd(). Windows has been supporting long file paths for quite a while
now, so it might be better to allocate those buffers dynamically:
https://learn.microsoft.com/en-us/windows/win32/fileio/maximum-file-path-limitation
(5) Some rarely used C library functions could perhaps be replaced to make the
code less dependent on such features. Examples are the single use of alloca()
in libtcc.c to set up a buffer and the use of scanf() in tccpp.c to convert the
TCC version string into a number. [tc-ide here provides stubs.]
(6) It would be useful to allow the user to set the entry point symbol (either
the one called by the OS or the one called by the startup code), like other
compilers do. [tc-ide provides its own version of _start(), which simply calls
main().]
(7) Additional observations:
– In tcc_new() (tcclib.c), checking the return value of tcc_mallocz is probably
redundant.
– In tcc_close() (tcclib.c), I do not understand why the test is ">0" instead
of ">=0". Typically 0 is stdin, but maybe the code should not rely on that.
– The protection of InitializeCriticalSection() in tcc.h is not thread-safe and
can lead to a race condition.
– In Windows, the semicolon ';' can appear in file names and is therefore
perhaps not an ideal PATHSEP path separator character (despite that fact that
it is still used in that function in the Path environment variable); a double
null-terminated string could be a better choice.
Let me conclude with a question on the licenses. As I understand it, TCC is
licensed under LGPL, although there is also a more permissive RELICENSING
statement, but I assume this is irrelevant due to the various contributions by
authors not listed there. Is that so, or am I missing something?
Robert
- [Tinycc-devel] TinyCC on Windows & some suggestions,
Robert Schlicht <=