|
1 |
| -# Babygo: a go compiler made from scratch |
| 1 | +# Babygo, a go compiler made from scratch |
| 2 | +Babygo is a small and simple go compiler. (Smallest and simplest in the world, I believe.) |
| 3 | +It is made from scratch and can compile itself. |
2 | 4 |
|
| 5 | +* No dependency to any libraries. Standard libraries and calling of system calls are home made. |
| 6 | +* Lexer, parser and code generator are hand written. |
| 7 | +* Emit assemble code which resutls in a single static binary. |
3 | 8 |
|
4 |
| -# Target machine |
| 9 | +It depends only on `as` as an assembler and `ld` as a linker. |
5 | 10 |
|
6 |
| -x86-64 Linux |
| 11 | +It is composed of only 3 files. |
7 | 12 |
|
8 |
| -# Test |
| 13 | +* main.go - the main compiler |
| 14 | +* runtime.go - runtime and standard library |
| 15 | +* runtime.s - low level of runtime |
9 | 16 |
|
10 |
| -```terminal |
| 17 | +# Design |
| 18 | + |
| 19 | +## Lexer, Parser and AST |
| 20 | +The design and logic of ast, lexer and parser are borrowed (or should I say "stolen") from `go/ast`, `go/scanner` and `go/parser`. |
| 21 | + |
| 22 | +## Code generator |
| 23 | +The design of code generator is borrowed from [chibicc](https://github.com/rui314/chibicc) , a C compiler. |
| 24 | + |
| 25 | +## Remaining parts (Semantic analysis, Type management etc.) |
| 26 | +This is purely my design :) |
| 27 | + |
| 28 | +# Environment |
| 29 | + |
| 30 | +It supports x86-64 Linux only. |
| 31 | + |
| 32 | +If you are not using Linux, you can use [a dedicated docker image](https://hub.docker.com/r/dqneo/ubuntu-build-essential/tags) for this project. |
| 33 | + |
| 34 | +```termiinal |
| 35 | +$ docker pull dqneo/ubuntu-build-essential:go |
11 | 36 | $ ./docker-run
|
12 |
| -# make test |
13 | 37 | ```
|
14 | 38 |
|
15 |
| -# How to do self hosting |
| 39 | +# Usage |
| 40 | + |
| 41 | +## Hello world |
16 | 42 |
|
17 | 43 | ```terminal
|
18 |
| -$ ./docker-run |
| 44 | +# Build babygo |
| 45 | +$ go build -o babygo main.go |
| 46 | +
|
| 47 | +
|
| 48 | +# Build the hello world program by babygo |
| 49 | +$ ./babygo < t/hello.go > /tmp/hello.s |
| 50 | +$ as -o hello.o /tmp/hello.s runtime.s |
| 51 | +$ ld -o hello hello.o |
19 | 52 |
|
20 |
| -# go build -o babygo main.go # 1st generation compiler |
21 |
| -# ./babygo < main.go > /tmp/babygo2.s |
22 |
| -# as -o babygo2.o /tmp/babygo2.s runtime.s |
23 |
| -# ld -o babygo2 babygo2.o # 2nd generation compiler |
24 |
| -# ./babygo2 < main.go > /tmp/babygo3.s |
25 |
| -# diff /tmp/babygo2.s /tmp/babygo3.s # assert babygo2.s and babygo3.s are same. |
| 53 | +# You can confirm it's a single static binary |
| 54 | +$ ldd ./hello |
| 55 | + not a dynamic executable |
| 56 | +
|
| 57 | +# Run hello world |
| 58 | +$ ./hello |
| 59 | +hello world! |
| 60 | +``` |
| 61 | + |
| 62 | +## How to do self hosting |
| 63 | + |
| 64 | +```terminal |
| 65 | +# Build babygo (1st generation) |
| 66 | +$ go build -o babygo main.go |
| 67 | +
|
| 68 | +# Build babygo by babygo (2nd generation) |
| 69 | +$ ./babygo < main.go > /tmp/babygo2.s |
| 70 | +$ as -o babygo2.o /tmp/babygo2.s runtime.s |
| 71 | +$ ld -o babygo2 babygo2.o # 2nd generation compiler |
| 72 | +$ ./babygo2 < main.go > /tmp/babygo3.s |
| 73 | +
|
| 74 | +# Assert babygo2.s and babygo3.s are exactly same |
| 75 | +$ diff /tmp/babygo2.s /tmp/babygo3.s |
| 76 | +``` |
| 77 | + |
| 78 | +## Test |
| 79 | + |
| 80 | +```terminal |
| 81 | +$ make test |
26 | 82 | ```
|
27 | 83 |
|
28 | 84 | # LICENSE
|
|
31 | 87 |
|
32 | 88 | # AUTHOR
|
33 | 89 |
|
34 |
| -@DQNEO |
| 90 | +[@DQNEO](https://twitter.com/DQNEO) |
0 commit comments