Go compiler made from scratch, which can compile itself. It's going to be the smallest and simplest go compiler in the world.

Babygo, a go compiler made from scratch

Test

Babygo is a small and simple go compiler. (Smallest and simplest in the world, I believe.) It is made from scratch and can compile itself.

  • No dependency to any libraries. Standard libraries and calling of system calls are home made.
  • Lexer, parser and code generator are hand written.
  • Emit assemble code which resutls in a single static binary.

It depends only on as as an assembler and ld as a linker.

It is composed of only a fiew files.

  • main.go - the main compiler
  • runtime.s - low level of runtime
  • src/ - internal packages
  • lib/ - libraries

Design

Lexer, Parser and AST

The design and logic of ast, lexer and parser are borrowed (or should I say "stolen") from go/ast, go/scanner and go/parser.

Code generator

The design of code generator is borrowed from chibicc , a C compiler.

Remaining parts (Semantic analysis, Type management etc.)

This is purely my design :)

Environment

It supports x86-64 Linux only.

If you are not using Linux, you can use a dedicated docker image for this project.

$ docker pull dqneo/ubuntu-build-essential:go
$ ./docker-run

Usage

Hello world

# Build babygo
$ go build -o babygo *.go

# Compile the hello world program by babygo
$ ./babygo t/hello.go > /tmp/hello.s

# Assemble and link
$ as -o hello.o /tmp/hello.s runtime.s
$ ld -e _rt0_amd64_linux -o hello hello.o

# Run hello world
$ ./hello
hello world!

How to do self hosting

# Build babygo (1st generation)
$ go build -o babygo *.go

# Build babygo by babygo (2nd generation)
$ ./babygo *.go > /tmp/babygo2.s
$ as -o babygo2.o /tmp/babygo2.s runtime.s
$ ld -e _rt0_amd64_linux  -o babygo2 babygo2.o # 2nd generation compiler

# Assert babygo2.s and babygo3.s are exactly same
$ ./babygo2 *.go > /tmp/babygo3.s
$ diff /tmp/babygo2.s /tmp/babygo3.s

Test

$ make test

Reference

License

MIT

Author

@DQNEO

Owner
DQNEO
Software Engineer at @mercari
DQNEO
Comments
  • LuaJIT instruction set backend?

    LuaJIT instruction set backend?

    LuaJIT [1] is one of the fastest tracing compilers [2], which due to its size and modest runtime requirements is capable to work in tightly resource restricted environments.

    For its speed and efficiency, LuaJIT is popular in many fields e.g. openresty based service frontends (Kong, Apisix), game engines, apps scripting (neovim), scientific computing, and naturally also in the edge computing.

    It's JITed CTypes manipulation primitives and FFI works on native speed, which is used in many libraries, including two stable kernel syscall wrappers: ljsyscall [3] for Unix-likes and win32 TINN [4] for Win32.

    Its current architecture/OS support matrix is [5], with some non-finished architecture ports [6] from external contributors.

    IMHO, a go compiler backend targeting the LuaJIT instruction set [7][8] (and FFI lib), would make many valuable go developments reusable in non-traditional for the go ecosystem fields like e.g. embedded scenarios, still under very acceptable performance. How hard looks such backend?

    [1] https://repo.or.cz/luajit-2.0.git/blob_plain/HEAD:/doc/luajit.html [2] https://luajit.me/ [3] https://github.com/justincormack/ljsyscall/ [4] https://github.com/Wiladams/TINN. [5] https://repo.or.cz/luajit-2.0.git/blob_plain/HEAD:/doc/install.html [6] https://github.com/LuaJIT/LuaJIT/issues?q=is%3Aissue+is%3Aopen+label%3A%22new+port%22 [7] https://sourcegraph.com/github.com/LuaJIT/[email protected]/-/blob/src/lj_bc.h [8] http://wiki.luajit.org/Bytecode-2.0

  • build babygo error

    build babygo error

    i clone the project, compile it locally use go build -o babygo main.go, and the compiler output: image

    local machine go env:

    GO111MODULE=""
    GOARCH="amd64"
    GOBIN=""
    GOCACHE="/Users/dingwenjiang/Library/Caches/go-build"
    GOENV="/Users/dingwenjiang/Library/Application Support/go/env"
    GOEXE=""
    GOFLAGS=""
    GOHOSTARCH="amd64"
    GOHOSTOS="darwin"
    GOINSECURE=""
    GONOPROXY="*.byted.org,*.everphoto.cn,git.smartisan.com"
    GONOSUMDB="*.byted.org,*.everphoto.cn,git.smartisan.com"
    GOOS="darwin"
    GOPATH="/Users/dingwenjiang/go"
    GOPRIVATE="*.byted.org,*.everphoto.cn,git.smartisan.com"
    GOPROXY="https://goproxy.byted.org,https://goproxy.cn,direct"
    GOROOT="/usr/local/go"
    GOSUMDB="sum.golang.google.cn"
    GOTMPDIR=""
    GOTOOLDIR="/usr/local/go/pkg/tool/darwin_amd64"
    GCCGO="gccgo"
    AR="ar"
    CC="clang"
    CXX="clang++"
    CGO_ENABLED="1"
    GOMOD=""
    CGO_CFLAGS="-g -O2"
    CGO_CPPFLAGS=""
    CGO_CXXFLAGS="-g -O2"
    CGO_FFLAGS="-g -O2"
    CGO_LDFLAGS="-g -O2"
    PKG_CONFIG="pkg-config"
    GOGCCFLAGS="-fPIC -m64 -pthread -fno-caret-diagnostics -Qunused-arguments -fmessage-length=0 -fdebug-prefix-map=/var/folders/b1/c9m_f9ds2d15433dvj3b24n00000gp/T/go-build018035766=/tmp/go-build -gno-record-gcc-switches -fno-common"
    
  • Pass arguments in packed layout

    Pass arguments in packed layout

    	var a uint8 = 'a'
    	var b uint8 = 'b'
    	var c uint8 = 'c'
    	d := receiveBytes(a, b, c)
    
    	0x001d 00029 (sample.go:14)	MOVB	$97, "".a+23(SP)
    	0x0022 00034 (sample.go:15)	MOVB	$98, "".b+22(SP)
    	0x0027 00039 (sample.go:16)	MOVB	$99, "".c+21(SP)
    	0x002c 00044 (sample.go:17)	MOVBLZX	"".a+23(SP), AX
    	0x0031 00049 (sample.go:17)	MOVB	AL, (SP)
    	0x0034 00052 (sample.go:17)	MOVBLZX	"".b+22(SP), AX
    	0x0039 00057 (sample.go:17)	MOVB	AL, 1(SP)
    	0x003d 00061 (sample.go:17)	MOVB	$99, 2(SP)
    	0x0042 00066 (sample.go:17)	PCDATA	$1, $0
    	0x0042 00066 (sample.go:17)	CALL	"".receiveBytes(SB)
    	0x0047 00071 (sample.go:17)	MOVBLZX	8(SP), AX
    	0x004c 00076 (sample.go:17)	MOVB	AL, "".d+20(SP)
    
    
  • reflect.TypeOf(x).String()

    reflect.TypeOf(x).String()

    package main
    
    import "reflect"
    import "fmt"
    
    type MyType struct {
    	id int
    }
    
    func main() {
    	fmt.Printf("%s\n", reflect.TypeOf(&MyType{}).String())
    }
    
    *main.MyType
    
  • Hello World panics

    Hello World panics

    $ ./babygo example/hello.go
    panic: main.QualifiedIdent("os.Stdout Not found in ExportedQualifiedIdents")
    
    goroutine 1 [running]:
    main.lookupForeignIdent(...)
    	/Users/prologic/babygo/main.go:3818
    main.getTypeOfExpr({0x10ab900?, 0xc0000ac108})
    	/Users/prologic/babygo/main.go:2841 +0x1139
    main.emitFuncall({0x10ab900?, 0xc0000ac138?}, {0xc000097070?, 0x1, 0x1}, 0x0?)
    	/Users/prologic/babygo/main.go:914 +0x325
    main.emitCallExpr(0xc000098ba0, 0x10c41fa?)
    	/Users/prologic/babygo/main.go:1043 +0xee
    main.emitExpr({0x10ab200?, 0xc000098ba0?}, 0x1077dba?)
    	/Users/prologic/babygo/main.go:1437 +0x259
    main.emitExprStmt(...)
    	/Users/prologic/babygo/main.go:1808
    main.emitStmt({0x10ab3c0?, 0xc000097120?})
    	/Users/prologic/babygo/main.go:2406 +0x23d
    main.emitFuncDecl({0xc0000a2350, 0x4}, 0xc0000d2000)
    	/Users/prologic/babygo/main.go:2474 +0x3a5
    main.generateCode(0xc0000c2240)
    	/Users/prologic/babygo/main.go:2661 +0x629
    main.buildPackage(0xc0000c2240, 0xc0000d1db0)
    	/Users/prologic/babygo/main.go:4407 +0x2f7
    main.main()
    	/Users/prologic/babygo/main.go:4487 +0x79a
    
ReCT-Go-Compiler - A compiler for the ReCT programming language written in Golang

ReCT-Go-Compiler A compiler for the ReCT programming language written in Golang

Nov 30, 2022
Gentee - script programming language for automation. It uses VM and compiler written in Go (Golang).

Gentee script programming language Gentee is a free open source script programming language. The Gentee programming language is designed to create scr

Dec 15, 2022
GopherLua: VM and compiler for Lua in Go

GopherLua: VM and compiler for Lua in Go. GopherLua is a Lua5.1 VM and compiler written in Go. GopherLua has a same goal with Lua: Be a scripting lang

Dec 31, 2022
Monkey programming language project from 'Writing An Interpreter In Go'and 'Writing A Compiler In Go' Books
Monkey programming language project from 'Writing An Interpreter In Go'and 'Writing A Compiler In Go' Books

Monkey Monkey programming language ?? project from "Writing An Interpreter In Go

Dec 16, 2021
A multi-pass compiler written in Go comprised of scanner, recursive-descent parser, generation of AST, intermediate representation (ILOC), and code generation (Armv8).

GoLite Project - Go Huskies! This is a project conducted and led in the course MPCS 51300 Compilers at the University of Chicago. In a group of two, w

Jan 10, 2022
This is a Virtual Operating System made by using GOLANG and FYNE.
This is a Virtual Operating System made by using GOLANG and FYNE.

Virtual-Operating-System This is a Virtual Operating System made by using GOLANG and FYNE. Hello! All In this project I have made a virtual Operating

Nov 1, 2021
OperatingSys-GO - A Virtual Operating System made by using GOLANG and FYNE

Operating-System This is a Virtual Operating System made by using GOLANG and FYN

Jan 2, 2022
A simple virtual machine - compiler & interpreter - written in golang

go.vm Installation Build without Go Modules (Go before 1.11) Build with Go Modules (Go 1.11 or higher) Usage Opcodes Notes The compiler The interprete

Dec 17, 2022
Compiler for a small language into x86-64 Assembly

Compiler This project is a small compiler, that compiles my own little language into X86-64 Assembly. It then uses yasm and ld to assemble and link in

Dec 13, 2022
Cc - Toy C compiler for golang

Grammars program = funcDecl* decl = declspec declarator ("{" compou

May 2, 2022
Bfc - A compiler for brainfuck by someone who has no idea how compilers work

bfc bfc is a bad (probably) Brainfuck compiler. It compiles only to x64 assembly

Feb 5, 2022
Floppa programming language inspired by the brainf*ck programming language. Created just for fun and you can convert your brainf*ck code to floppa code.

Floppa Programming Language Created just for fun. But if you want to contribute, why not? Floppa p.l. inspired by the brainf*ck programming language.

Oct 20, 2022
TinyGo drivers for sensors and other devices that use I2C, SPI, GPIO, ADC, and UART interfaces.

TinyGo Drivers This package provides a collection of hardware drivers for devices such as sensors and displays that can be used together with TinyGo.

Jan 8, 2023
❄️ Elsa is a minimal, fast and secure runtime for JavaScript and TypeScript written in Go

Elsa Elsa is a minimal, fast and secure runtime for JavaScript and TypeScript written in Go, leveraging the power from QuickJS. Features URL based imp

Jan 7, 2023
Interactive Go interpreter and debugger with REPL, Eval, generics and Lisp-like macros

gomacro - interactive Go interpreter and debugger with generics and macros gomacro is an almost complete Go interpreter, implemented in pure Go. It of

Dec 30, 2022
The Humboldt Web Framework and Toolkit. Using this as an interpeter and server, build webistes in an MVC pattern using Lua.

Humboldt Web Framework Humboldt is a framework written in Go using Lua files to build web applications. What is this framework for? People who want to

Jan 21, 2022
Process manager for Procfile-based applications and tmux
Process manager for Procfile-based applications and tmux

Overmind Overmind is a process manager for Procfile-based applications and tmux. With Overmind, you can easily run several processes from your Procfil

Jan 4, 2023
An experimental port of TinyRb to Google go, both as a means of learning go and exploring alternate approaches to implementing Ruby. Work is currently focused on the GoLightly VM.

tinyrb¶ ↑ A tiny subset of Ruby with a Lua'esc VM. Everything in TinyRb should run in the big Ruby. (except bugs and things that don't comply to the p

Sep 22, 2022
A shell parser, formatter, and interpreter with bash support; includes shfmt

sh A shell parser, formatter, and interpreter. Supports POSIX Shell, Bash, and mksh. Requires Go 1.14 or later. Quick start To parse shell scripts, in

Jan 8, 2023