Design and Evolution of the T3X Backend The T3X compiler was originally bootstrapped using a compiler that was written in K&R (pre-ANSI) C. Tcode, the language interpreted by the Tcode Virtual Machine (TCVM) was originally used only as an intermediate language. An interpreter for it appeared later. Early on (when the language was still called "T") the compiler got a Tcode optimizer, which resulted in much faster VM and native code executables. Tcode eventually became fast enough to be used for self-compilation and ever since this is how T3X compilers were ported to new platforms. The branch using a Tcode optimizer ended with T3X 8.1.7 in 2004. In 2017 I started to experiment with T3X9, a new, more minimalist approach. The T3X9 compiler originally ran on the 386 only and compiled directly from T3X9 to machine code and only later got a Tcode backend. It turned out that computers had become so fast that a native code backend for T3X is barely necessary at all. T3X9 later became the basis for the two-pass, low-memory, multi-backend T3X/0 compiler. Native code executables are (usually) not only faster than VM code, but they also have the advantage that they do not need a VM to execute. And then there may be targets that are too small to accomodate a VM (such as CP/M) or may still run on hardware on which a VM would be too slow to be useful (DOS on 1980's hardware). However, hardware also evolves faster than in the time when T3X was first developed. When first developed it typically ran on 286 and 386-class machines at clock speed of around 16 or 20MHz. Even on much later hardware, like a 400Mhz 586, the same 16-bit code generator would still work. Today the 386 is not supported my many operating systems any more, and support for the 32-bit x86 in general is diminishing, and new architectures like the ARM and maybe at some time the RISC-V will gain traction on notebook and desktop systems. Given the growing lack of support for old hardware, the emergence of new systems, and the speed of even low-performance systems these days, it seems like a good idea to have a simple, non-optimizing code generator that is easily retargetted to new systems. Personally, I do not even need the speed of T3X/0 native code on most half-way modern systems. T3X/0 can generate code for the TCVM, and the TCVM on Unix even supports extensions like the CONSOLE or SYSTEM module. Native executables are good to have, though, and as a welcome side effect, the compiler can generate code for old systems that are too slow/and or lack the necessary optimizing compilers to run a TCVM efficiently. As can be seen in the below table, the gap between interpreted VM code and native code has decreased substantially, because compiler optimize much more aggressively these days, but a bad native code compiler still beats a good VM interpreter. One thing I would like to have in T3X/0 is more static code generators without dependency on the C standard library, like the FreeBSD-386 one, but given the increasing shift of abstraction from the kernel to the runtime library (e.g. signal), I guess that ship has sailed. T3X/0 Native Code and TCVM Bootstrap Times Platform MHz TCVM Native Ratio -------------- ------- ----------- -------- ----- MSDOS 8088 4.77 4h30m00.00s 8m55.00s 31.0 MSDOS 80286 25.00 46m40.00s 1m45.00s 26.7 FreeBSD ARMv7 900.00 5.23s 0.63s 8.3 FreeBSD x86_64 1000.00 0.85s 0.15s 5.7 TCVM on DOS compiled with Turbo C 2.0. TCVM on FreeBSD X86_64 compiled with Clang 13.0 with -O2. TCVM on FreeBSD ARMv7 compiled with Clang