T3X/0 Extended Edition - A New T3X Compiler =========================================== T3X is a family of small, portable, procedural, block-structured, recursive, and almost typeless programming languages. The T3X syntax is similar to Pascal, its semantics resembles BCPL's. This Edition includes new commands and operations aliases. T3X/0 is the latest member of the T3X family. Its design is based on the experience made with its predecessors. It is simpler than the full (Release 7) language, but more complete than the minimalistic T3X9 branch. The compiler presented here is a single-stage two-pass compiler that is aimed to be ported quickly to new platforms, typically by just writing a new machine description file. The compiler can run on systems as minimal as CP/M on a Z80 CPU and easily fits in a tiny model DOS executable. It self-compiles in ten minutes on a 4MHz CP/M system (and in the blink of an eye on a modern Unix system). *** Currently Supported Platforms *** Operating System CPU Output format Requires Generic Unix VM Tcode/0 Generic Unix 386 assembly language C compiler FreeBSD 386 assembly language assembler, loader CP/M 2.2 Z80 COM 48K bytes TPA PCDOS 2.0 8086 COM The compiler can operate natively or as a cross-compiler. Almost all combinations are supported: for example, you can cross- compile on CP/M for the TCVM, on the TVCM for Unix, on Unix for DOS, and on DOS for CP/M. Or on CP/M for DOS, etc. The only combinations that are not possible are cross-compilation to Unix on CP/M or DOS, because the source code emitter is too large. NOTE: when compilation is aborted and re-compilation fails, this is usually due to the wrong code generator being linked in place. In this case the following line should bring the code back to a useful state: make clean; make reset; make *** Quick Installation *** If you just want to install T3X/0, edit the T3XDIR, BINDIR, and HOST variables in Makefile and then run "make install". Use HOST=unix, even on FreeBSD, unless you want the static code backend (with does not support T.BREAK, though). If you are not using a 386 processor (or a x86-64 processor with 32-bit compatibility support), you will have to use the bytecode compiler. Just running "make" will build it. *** Bootstrapping *** On a Unix system, just run "make". The T3X/0 archive contains a pre-compiled Tcode/0 executable of the final T3X/0->Tcode/0 compiler as well as a bootstrapping compiler in T3Xr7. So bootstrapping can be accomplished in two ways: (1) by using the pre-compiled binary BIN/TXTRN0.TC to self-compile. $ cc -m32 -o tcvm tcvm.c $ ./tcvm bin/txtrn0.tc txtrn (2) or, by compiling the boostrapping compiler TXTRN0.T with T3Xr7 and then compiling the final compiler with that. $ tx txtrn0.t $ txx txtrn0 txtrn In either case an existing C compiler is needed to compile the Tcode/0 Virtual Machine (TCVM). $ cc -o -m32 tcvm tcvm.c The TCVM is a very basic C program with a length of less than 250 lines. It is a 32-bit program, though, and needs more than 64K bytes of data. You *might* get away with large model on DOS. On 64-bit platforms it must be compiled in 32-bit mode (-m32). There are also pre-compiled binaries for DOS and CP/M in the BIN directory, in case you should want to bootstrap on such a system. See below section for further details. *** Testing *** On a Unix system, just run "make test" and "make triple". There is a simple test suite in PROGRAMS/TEST.T. The compiler should at least pass these tests. To perform the tests, compile the program and run it: $ tcvm txtrn.tc programs/test test $ tcvm test.tc The output of the program should be self-explanatory. Then you can also run the triple test. First re-compile the compiler with itself: $ tcvm txtrn.tc txtrn txtrn1 and then re-compile it again using the compiler generated in the previous step: $ tcvm txtrn1.tc txtrn txtrn2 There should not be any differences between the generated compilers: $ cmp txtrn1.tc txtrn2.tc *** Usage *** The (interpreted) T3X/0 compiler is invoked by using the command line tcvm txtrn.tc program The compiler will then compile the file "program.t" and output a TCVM binary named "program.tc". The compiled program can then itself be run by the TCVM: tcvm program.tc When a second file name is passed to the compiler, it will write the compiled program to that file. tcvm program foo will compile "program.t" to "foo.tc". When the second parameter of the compiler is the string /v (or /V), then it will compile to "program.tc" and in addition echo the name of every function definition while compiling. This can be entertaining on slow systems. When a native code binary for a compiler exists, the compiler can be invoked by just typing "txtrn" instead of "tcvm txtrn.tc". Some compilers generate assembly language output, which needs to be further compiled and linked. The compiler driver script BIN/TX0.SH takes care of this. The details are outlined below. *** Compiling the Compiler *** ------------------------------------------------------------ !!! This process is automated by the BIN/BUILD.SH script !!! ------------------------------------------------------------ First select a platform to compile for. The target files are named TXname (the machine-specific T3X core module) and CGname (the code generator). The target files for the Tcode/0 machine can be found in the root directory of the T3X source code tree and the other targets are in the "targets" directory. Then there are two different emitters, one for direct output of binary programs and one for source-to-source compilation. To cross-compile the compiler for a system other than the Tcode/0 virtual machine (TCVM), follow these steps: 1) Select an emitter: the DOS and CP/M ports need the binary emitter "txemtbin.t" and the Unix ports needs the source code emitter "txemtsrc.t". Link or copy the needed emitter to "txemit.t". E.g.: ln -fs txemtbin.t txemit.t 2) Link the file CGname to "cg.t". Leave "t3x.t" linked to the Tcode machine backend ("txtcvm.t"). E.g.: ln -fs targets/cgcpmz80.t cg.t ln -fs txtcvm.t t3x.t # this should not be necessary 3) Edit the file "cg.t" and change the value of the modpath() function to reflect your installation. Any trailing path seperators must be given (e.g. "lib/" instead of "lib"). Note that a prefix of "" means leave the input file as is. On CP/M only drive letters (A:, etc) may be specified. 4) Compile the compiler. This step will create a TCVM binary "tx-name0" that generates output for the selected platform. E.g.: tcvm txtrn.tc txtrn tx-cpm0 5) Link the file TXname to "t3x.t". E.g.: ln -fs targets/txcpmz80.t t3x.t 6) Compile the compiler again, this time using the compiler created in the previous step. This step will create a binary for the selected platform. E.g.: tcvm tx-cpm0.tc txtrn tx-cpm In the example the final compiler will be named "tx-cpm.com". It will run on CP/M and generate native code for CP/M. 7) Remove the cross-compiler tx-name0.tc and reset "t3x.t" and "cg.t" to their TCVM targets, "txtcvm.t" and "cgtcvm.t". Also reset "txemit.t" to "txemitbin.t". The resulting binary can then be used to compile T3X programs (including the compiler itself) on the selected host platform. All that is needed is the binary itself and the corresponding TXname file (renamed "t3x.t"). It might be necessary to convert the t3x.t file to local text file convention (e.g. on CP/M). All ports that use the source code emitter (like the Unix ports) emit assembly language, which must be further compiled and linked with a system-specific assembler and linker. For the FreeBSD-386 port, the resulting assembly language file can simply be passed to the C compiler controller, cc. E.g.: tcvm tx-fbsd.tc txtrn tx-fbsd will generate a file named "tx-fbsd.s", which can then be compiled with cc: cc -m32 -o tx-fbsd tx-fbsd.s (The -m32 option can/must be omitted on 32-bit machines.) The portable Unix backend works in a similar way, but also needs a runtime library. To finish compilation of the portable Unix version of the compiler, run cc -m32 -o tx-unix tx-unix.s targets/ux386lib.c *** Building other Cross Compilers *** There is a total of 14 compilers that can be built from the T3X/0 code: four host platforms and four target platforms make a total of 16, but two combinations are not possible, because the compiler would be too large to fit in the resulting binary. These compilers exist: Target --> TCVM CP/M DOS Unix* Host ---- TCVM txtrn.tc tx-cpm.tc tx-dos.tc tx-unix.tc CP/M tx-tcvm.com tx-cpm.com tx-dos.com n/a DOS tx-tcvm.com tx-cpm.com tx-dos.com n/a Unix* tx-tcvm tx-cpm tx-dos tx-unix * There is a FreeBSD backend named "fbsd" that can be used in the place of the "unix" backend on FreeBSD-386. It uses a runtime wrapper in assembly language instead of C. Note that this backend does NOT offer a T.BREAK procedure, though. The BUILD.SH script in the "bin" directory can be used to build any of the above compilers by just specifying the host and target platforms as parameters. For instance, $ bin/build.sh cpm dos will generate an executable named "tx-dos.com" that will run on CP/M and generate code for DOS. Note that the DOS compiler for generating DOS output will have the same name, so when you plan to build both, you will have to rename one of them. Also note that when you have both a native compiler and a cross compiler on CP/M, they will need different "t3x.t" files! It is up to you to invent a workable solution. *** Using the Cross Compilers *** The "install" target in the Makefile will build native (cross) compilers for all supported platforms. I.e. the compilers will run on Unix-386 and emit code for the TCVM and for DOS-8086, CP/M-Z80, and Unix-386 / FreeBSD-386. The TX0 script will take care of all necessary steps during compilation. For instance $ tx0 foo will compile foo.t to a Unix-386 executable named "foo", and $ tx0 -t dos foo will compile foo.t to a DOS-8086 executable named "foo.com". *** Using the T3X/0 Compiler on DOS and CP/M *** There are pre-compiled compilers for DOS and CP/M in the BIN directory. To install a T3X/0 compiler on CP/M, copy the file BIN/TX-CPM.COM to TX0.COM on your CP/M disk. Then convert the file CG/TXCPMZ80.T to CP/M text file format and install it as T3X.T on your CP/M disk. The program PROGRAMS/CPMFILE.T can be used to convert the file. $ tcvm txtrn.tc programs/cpmfile cpmfile $ cp targets/txcpmz80.t t3x-cpm.t $ tcvm cpmfile.tc t3x-cpm.t /R $ # copy t3x-cpm.t to your CP/M system as T3X.T To install the compiler on DOS, copy the file BIN/TX-DOS.COM to TX0.COM on your DOS disk and install CG/TXDOS86C.T as T3X.T. Conversion to DOS text file format is optional (it can be done with the program PROGRAMS/DOSFILE.T). If you want to bootstrap the compiler on CP/M, you will also need the file CG/CGCPMZ80.T as CG.T, TXEMTBIN.T as TXEMIT.T, and TXTRN.T. All these files have to be converted to CP/M text file format. On DOS you need CG/CGDOS86C.T as CG.T and TXEMTBIN.T as TXEMIT.T as well as TXTRN.T. Conversion to DOS text format is optional. To compile the compiler on either system, run TX0 TXTRN which will result in a new compiler named TXTRN.COM. On CP/M (@ 4MHz) this will take about 10 minutes. You can use the /V option to entertain yourself while the compiler compiles.