14 ms·
Tiny-C Compiler (2001)
- activismand 4y ago[dead]
- stevekemp 4y agoThat's a cute project, thanks for sharing. I hacked in support for ">", ">=", and "<=" to match the "<" support, but I just noticed that ints are truncated, so the maximum value stored in a variable is 127.
- feeley 4y agoAuthor here. Just for context tinyc.c was created in 2000 (I found the file in my archives and the last modification date is January 12, 2001). I was not aware at the time of Fabrice Bellard's work which after all won the IOCCC in 2001, so the confusion with TCC was not intentional. My tinyc.c was meant to teach the basics of compilers in a relatively accessible way, from parsing to AST to code generation to bytecode interpreter. And yes it is the subset of C that is tiny, not a tiny compiler for the full C language.
- bullen 4y agoI wish I had time to make a list what would be required to bootstrap this. Either by adding complexity (more features to the compiler) or dropping complexity (fewer C features in the implementation). Did you ever look at that? Edit: functions, enum, struct, arrays and maybe make all variables/functions a-z? Edit2: https://joyofsource.com/projects/bootstrappable-tcc.html https://joyofsource.com/projects/bootstrappable-tcc.html Edit3: https://news.ycombinator.com/item?id=35135384 https://news.ycombinator.com/item?id=35135384
- feeley 4y agoHaven't looked at what it would take to support C89 (or other) fully. Certainly it is possible to extend the compiler in small increments to implement more stuff: all the operators, local variables, arrays, pointers, functions, etc. The hardest part I would say is implementing types (starting with the C syntax for types!) and also handling the memory allocation for them. Nothing too complex when you know what you are doing. My personal interest is with higher-level languages and I have worked on various Scheme systems over the last 30 years. If you like small language implementations then take a look at Ribbit which is feature-full with a tiny VM. Also check out sectorlisp (not my work) which is a fascinating tour de force.
- stevefan1999 4y agoWould you think rewriting this to generate a minimal set of instructions could be benefitial to the compiler bootstrapping?
- feeley 4y agoI'm not sure what you mean by "minimal set of instructions". What is more important for bootstrapping is to restrict the programming style used to write the compiler. So if that was the goal I would implement pointers and maybe arrays, and not implement other types such as structs (which can be useful but add complexity to the compiler, i.e. it is no longer the case that a value fits in a machine word). Functions and function call would obviously be useful to add. But that's about it. What I'd love to do someday is to write a compiler for a fairly complete C subset in POSIX shell. The goal would be to use only a POSIX shell and this compiler to compile TCC, and then use TCC to bootstrap gcc, all from source. This would be a great tool for reproducible builds from source. If someone here finds this interesting and would like to help out, please reach out to me.
- sitkack 4y agoI want to thank you for this pedagogical tool, I have used a couple times to learn a new language by porting this exercise. How did you use this in your teaching? It seems like it could the basis for a longer term project that students could take in many directions.
- feeley 4y agotinyc.c was designed to illustrate three things at once in a second year course on concepts of programming languages. The course had 4 parts: imperative programming (using C), functional programming (using Scheme), and logic programming (using Prolog), and programming language implementation. For the imperative programming part it was important to show enough of the C language for the following operating systems course, so we needed to show C manual memory management and pointers in a rather detailed way. So tinyc.c was principally an example of programming with pointers, including pointer arithmetic such as *pc++. It was indirectly an example of compiler and interpreter, subjects we also covered in the course. I have also used parts of the compiler in a third year compiler course but not as the basis of a project. I have always asked (forced?) my students to use Scheme to implement their compiler projects... a much friendlier language than C for compiler writing.
- bakul 4y agoThis doesn't have types, functions, arrays or much error checking. It has one char identifiers. I don't think we should read into this any more than a tiny example or experiment by the author.
- Koshkin 4y agoSigh. I wish people would teach compilers using Oberon as an example. One can write a small yet complete compiler for (what turns out to be not-so-tiny) a language.
- peacefulhat 4y agoBest to pick languages anybody has heard of.
- fernly 4y agoUm, excuse me, but there existed a Tiny-C in 1979. Whatever you are talking about creating in 2000 is in no way an original idea. References: Dr. Dobb's Journal #32 (Feb 1979) page 41, review of Tiny-C User Manual by Ted Shapin [0] Dr. Dobb's Journal #35 (May 1979) page 37, "Tiny-C Interpreter on C-Dos" by Ray Duncan[1] Tiny-C Associates incorporated in Holmdel, NJ, March 1978 [2] "Tiny C" trademark application filed 1979, cancelled 1987 [3] There was also a "Small C", see DDJ #45 (May 1980), "A Small C Compiler for the 8080s" by Ron Cain[4]. Cain references buying a copy of "the Tiny-C interpreter from Tiny-C Associates" and finding it too slow, so he bootstraps his own C compiler, writing it in C, compiles it on a UNIX system, then using it to compile itself to get the 8080 machine code. See also DDJ #69 (July 1982) p. 66, "Small C for the 9900" by Matthew Halfant[5], porting Cain's compiler to another platform. [0] https://archive.org/details/dr_dobbs_journal_vol_04_201803/page/n95/mode/2up https://archive.org/details/dr_dobbs_journal_vol_04_201803/p... [1] https://archive.org/details/dr_dobbs_journal_vol_04_201803/page/n231/mode/2up https://archive.org/details/dr_dobbs_journal_vol_04_201803/p... [2] https://www.bizapedia.com/nj/tiny-c-associates.html https://www.bizapedia.com/nj/tiny-c-associates.html [3] https://alter.com/trademarks/tiny-c-73219160 https://alter.com/trademarks/tiny-c-73219160 [4]https://archive.org/details/dr_dobbs_journal_vol_05_201803/page/n189/mode/2up https://archive.org/details/dr_dobbs_journal_vol_05_201803/p... [5] https://archive.org/details/dr_dobbs_journal_vol_07_201803/page/n325/mode/2up https://archive.org/details/dr_dobbs_journal_vol_07_201803/p...
- feeley 4y agoTo be clear, I'm not claiming to be the first to have used the name Tiny-C, just that the confusion with TCC is not intentional. Your links to DDJ are great an bring back memories of the good old days when there was much to learn from reading DDJ and Byte magazine!
- bluedino 4y agoHow long would it take to write a toy C compiler?
- kadirmalak 4y agoI liked it. I like those kind of short useful examples but it's an interpreter. That makes a huge difference. So, the title is misleading.
- m1r 4y agoneat
- biancachandon 4y ago[dead]
- americanfailure 4y ago[dead]
- wolfcubwolfcub 4y ago[dead]
- velvetcanyon 4y ago[dead]
- sweetwhimsy 4y ago[dead]
- flyingoffmyfeet 4y ago[dead]
- miss_mystique 4y ago[dead]
- daypursuits22 4y ago[dead]
- justonemorepage 4y ago[dead]
- spicysugar3 4y ago[dead]
- sinthewild2 4y ago[dead]
- justgoogleit 4y ago[dead]
- netgusto 4y agoIt’s worth noting that this is a compiler for the Tiny-C language, and not as one might think a tiny compiler for the C language.
- unwind 4y agoIt's probably better to call it an interpreter, since it will also run the program and print the values of all non-zero variables afterward. Calling it a compiler is (to me) really stretching things, I can't see any code to emit any other form of the code, it's all aimed at evaluating (executing) it. Edit: oops, I didn't read the code closely enough, it does emit code but only internally, that code is what gets executed. Thanks for the corrections!
- northernskys30 4y agoIt compiles to a sort of byte code that is executed by a stack based virtual machine.
- userbinator 4y agoIt is a compiler rather than a direct evaluator, since it generates bytecode for a stack VM --- and also includes the interpreter for that (look at the bottom).
- masklinn 4y agoThat’s more or less every interpreter. CPython compiles to bytecode before interpreting that, yet nobody would call it a compiler.
- Mike_12345 4y agoThat is definitely a compiler and anyone with a CS degree would call it that if they were discussing its functionality, because that's technically what it is. (Referring specifically to the part which compiles Python to bytecode) Your SQL database also has a compiler. SQL is compiled to an execution plan. Compile doesn't only mean "create a machine code executable file".
- ttvecthrowaway 4y agoNot to be confused with https://bellard.org/tcc/ https://bellard.org/tcc/, which is a tiny compiler for the C language.
- squarefoot 4y agoIt is sad that tcc is unmaintained as it would be really useful in small embedded systems. I just tried it on Debian and compilation fails without #undefining CONFIG_TCC_MALLOC_HOOKS in lib/bcheck.c. After compilation it passes tests, but they warn that it could be unreliable.
- jart 4y agoTry chibicc. It's x86_64 native and so much more readable as a codebase than TCC.
- dantrell 4y agoWhile Fabrice Bellard is no longer working on TCC [0] and an official release tarball hasn't been packaged since version 0.9.27 (5 years ago) the project is by no means unmaintained. For details, check their current working repository [1] and mailing list [2]. [0]: https://bellard.org/tcc/ https://bellard.org/tcc/ [1]: https://repo.or.cz/tinycc.git https://repo.or.cz/tinycc.git [2]: https://lists.nongnu.org/archive/html/tinycc-devel/ https://lists.nongnu.org/archive/html/tinycc-devel/
- siliconunit 4y agoI'm quite confused, not the same project at all? To me tiny c compiler always meant the bellard page. Super useful stuff for micro hacky projects.
- WoodenChair 4y agoThis is an interpreter for a super restricted subset of C and it looks well written from a pedagogical standpoint (keeps thing pretty simple, fairly easy to read). But it's slightly awk to strip-down a language (what features do you keep, what do you lose?). I think it's more fun to build an interpreter for an actual tiny language. In my next book I have interpreters for Brainfuck [0], an obfuscated kind of joke of a language, and Tiny BASIC[1] a real tiny language that was used on early personal computers. These are pretty common first projects for folks interested in doing an interpreter. Here's why real languages are better than stripped down languages: Anyone with programming knowledge can implement a Brainfuck interpreter in a few hours and run any Brainfuck program. Anyone with a tiny bit of CS knowledge can implement a Tiny BASIC interpreter in just a day and then you can run any real Tiny BASIC program from the late 70s. It's cool to run real programs people actually used. With this stripped down C, there are no pre-made real programs... 0:https://en.wikipedia.org/wiki/Brainfuck https://en.wikipedia.org/wiki/Brainfuck 1:https://en.wikipedia.org/wiki/Tiny_BASIC https://en.wikipedia.org/wiki/Tiny_BASIC
- doodlesdev 4y agoAnother language that's more modern and currently useful but which is very tiny to write an interpreter for is Lua [0][1]. Currently the official Lua interpreter has around 30k LOC which I find pretty amusing for a language used so widely in games and for scripting purposes [2]. Of course it's still at least an order of magnitude larger than a small Tiny BASIC interpreter but the fact it's a current language used in so many places makes it even more interesting to make your for-fun implementation. Also related to small language implementations I find notable PicoC [3] which is a C interpreter written in around 3k LOC of C. Past discussion about it here 13 years ago [4]. [0]: https://www.lua.org/about.html https://www.lua.org/about.html [1]: https://www.lua.org/spe.html https://www.lua.org/spe.html [2]: https://en.wikipedia.org/wiki/Lua_(programming_language) https://en.wikipedia.org/wiki/Lua_(programming_language) [3]: https://gitlab.com/zsaleeba/picoc https://gitlab.com/zsaleeba/picoc [4]: https://news.ycombinator.com/item?id=1658890 https://news.ycombinator.com/item?id=1658890
- benj111 4y agoWhile I appreciate your point. 1. You use the example of a tiny basic of a 'real language' and I don't see how tiny basic is a 'real language', but tiny C is a stripped down language. 2. You can build on this to make a full c implementation. A minimal c implementation that can potentially bootstrap a full c environment is more useful than a brainfuck interpreter.
- northernskys30 4y agoI did my CS degree at umontreal and this was an assignment in a second year class. This was a pretty interesting introduction to compilers, and even if this is a toy subset of C, this was challenging, at least for me. We would get 0 if there were any memory leak, so we were pretty paranoid about it. The second assignment was writing a Scheme interpreter.
- ndiddy 4y agoThat's kind of surprising they cared so much about memory use, a lot of one-shot C programs such as compilers don't bother freeing memory and let the OS clean up after them once they exit.
- ComputerGuru 4y agoI was about to comment and say the same thing, but as a graded learning exercise there is certainly value in that approach.
- userbinator 4y agoIt's unfortunately not self-compiling, but has a structure which is very reminiscent of C4 --- another tiny C-subset compiler + stack-based VM which is self-compiling: https://news.ycombinator.com/item?id=8558822 https://news.ycombinator.com/item?id=8558822 The 26 predefined integer variables make this look like a variant of minimal BASIC, except with structured control flow instead of only GOTO.
- bullen 4y agoAha, this is interesting!
- zabzonk 4y agonot sure i understand how enums work here. but interesting.
- bitwize 4y agoOh, Marc Feeley. Wonder if we'll see a Tiny-C target for Gambit?
- feeley 4y agoThat's not on my TODO! But Gambit does have support for TCC. For example you can use TCC to compile a file to a dynamically loadable object file (aka shared library). The compilation is faster than gcc and the code size is typically smaller too: $ cat hello.scm (display "hello!\n") $ gsc hello.scm $ gsi hello.o1 hello! $ ls -l hello.o1 # this is generated by gcc -rwxrwxr-x 1 feeley feeley 18152 Mar 13 17:16 hello.o1 $ rm hello.o1 $ gsc -cc "tcc -shared" hello.scm $ gsi hello.o1 hello! $ ls -l hello.o1 # this is generated by tcc -rwxrwxr-x 1 feeley feeley 4432 Mar 13 17:17 hello.o1
- jokoon 4y agofirst assignment would be to add the multiply and divide operators... I admit I have trouble understanding how the VM run() function works... anybody can give some insight?
- mav88 4y agoThe function runs through the program by incrementing the program counter (*pc++) and dispatching what instruction it sees. It's a stack-based VM so individual instructions are pushed onto and popped from the stack depending on the operation. Is there anything specific you don't grok? Happy to help.
- mati365 4y agoRecently I'm working on toy C compiler and x86 Assembler in TypeScript[1] and I can confirm that the amount of work that have to be done to compile and print simple Hello World is astronomically huge (as the satisfaction) [1] https://github.com/Mati365/ts-c-compiler https://github.com/Mati365/ts-c-compiler
- Narishma 4y agoThis isn't a C compiler though. It's a compiler for a language called Tiny-C.
- deleted 4y ago[deleted]
- deleted 4y ago[deleted]