nanogo

command module
v0.1.4 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Jan 4, 2022 License: MIT Imports: 9 Imported by: 0

README

NanoGo

NanoGo is a Go (golang) compiler for homebrew / hobby CPUs.

Status

Note: this is a work in progress! Currently the following should work:

  • built in print() and println()
  • word-sized operations (int and uint)
  • string literals and iterating over strings
  • memory mapped I/O using unsafe
  • extern funcs with assembly snippets (useful if you have I/O instructions)

Also, only rj32 and A32 are supported, but if you would like assistance adding your CPU, open an issue.

What is it?

This compiler will take a Go package, read in all the packages it depends on in the usual way Go programs work, and compile all the code down into assembler in a style that is compatible with customasm.

As of this writing, customasm does not support linking, so a single large assembly file is produced. A "CPU Def" file can be included which configures the assembly language, as well as the memory layout with #banks.

Why Go?

C is great, but the language is not the easiest to parse, and while there's many great projects like LCC, they are not the easiest to work on and modify for a homebrew CPU.

Go is a very simple language, and is very fast to learn, yet powerful enough to be very productive.

As well, Go has a parser and type checker right in the the standard library. Further, there's an excellent SSA library that does most of the work of the frontend of a compiler. So all that's really required is a simple backend, which is what NanoGo is.

Installing

Install Go for your system, then there are releases with prebuilt binaries and the runtime library source, plus some example programs.

Or you can install with go's installer:

go install github.com/rj45/nanogo@latest

You will also want to install customasm.

You may also want to install emurj if you want to be able to run programs in an rj32 emulator.

You may need to set up a NANOGOROOT if you get errors about not being able to find the standard library code. Set it to the folder containing the src folder.

Running

You can run NanoGo to produce assembly like so:

nanogo -o output.asm asm testdata/seive/seive.go

If you have customasm installed, then you can get a binary or hex file (depending on the architecture) like so:

nanogo -o output.hex build testdata/seive/seive.go

If you have emurj installed, you can build and run the program like so:

nanogo run testdata/seive/seive.go

If you'd like to inspect, say, what phases the compiler goes through and all the transformations it does, say, on the main.main() function of the above code, you can produce an ssa.html using a modified version of the code Go uses for its compiler:

nanogo -dump main__main asm testdata/seive/seive.go

And then you can open ssa.html in your browser.

ssa.html

There is also a way to generate various .dot graphs of the flow of values through the program using this:

nanogo -dump main__main asm testdata/seive/seive.go

You can look at the control flow graph at the time of register allocation:

control flow graph

Or an exploded view of the flow of values through the program (at register allocation):

value flow graph

A .dot viewer like xdot is recommended because it will highlight which line goes where and allow you to zoom in.

Limitations

Keep in mind that it took a team of people many years to build the Go compiler and make it as good as it is. There is a lot of work to do to come close to that.

So, while all of Go is parsed, currently many parts of Go are simply not implemented and will result in obscure errors if you try to use them. In the future, a consistent way to track where errors come from and better documentation for them may make this easier.

Defer is ignored, though it could be implemented in the future. There's no allocation yet, nor any freeing of memory. Recovering from panics will not be implemented. Runtime type reflection is not yet implemented. Maps are not yet implemented. Interfaces are similarly not there, nor slices. Global arrays do work however.

ints, uints, bytes, runes and pointers are 16-bits for rj32. But non-standard sizes can violate some assumptions in the standard library, so anything relying on those assumptions will have bugs.

Almost none of the standard library is supported. You can try it and see if it will work, but some fundamental assumptions are violated, as well as many features relied on are missing. This compiler is meant to help you write your own standard library, kernel, OS and other software for your own homebrew CPU, so you could see the lack of a standard library as a feature.

Design

NanoGo uses the golang.org/x/tools/go/ssa package to build and parse Go into SSA form.

This IR is then converted into a different IR which is easier to work with and transform.

After transformation there is a SSA based tree register allocator which uses the properties of SSA to allocate registers in linear time.

After a final transformation pass, then finally assembly code is generated and output.

Retargeting / Porting to Your CPU

Some effort was put in to make this easy. See the retargeting documentation.

Contributing

Contributions are welcome!

Please open an issue if you intend to submit a PR if you want to make sure the contribution would be welcome beforehand. This is optional, but recommended if you're going to spend more than a few hours on it.

For PRs, please at least describe the purpose of the PR, and a brief explanation of what changes you made and why. Why is quite important, and will serve as documentation for others.

Contributions of your own architecture are welcome, but please ensure you have a working customasm cpudef and a publicly accessible emulator with install instructions. Other documentation on how your architecture works is also quite useful for those maintaining it as features are added.

Please be kind to one another and put effort into determining a kind way to share criticism.

Forking, commercial use and permission

If you want to fork this project or use it commercially you do not need my permission nor do you need to inform me. But if you feel like letting me know, I would appreciate it, and you can do so via opening an issue.

If you do fork this project, all I ask is that the LICENSE file be kept intact and that your own copyright line be added to it. It's also polite to change the name if the fork should be made public.

License

Copyright (c) 2021 rj45 (github.com/rj45)

Licensed under the MIT License (MIT), see LICENSE.

Some parts Copyrighted by the Go Authors, under a BSD like license, see Go's LICENSE.

Some parts Copyrighted by the TinyGo Authors, under a BSD like license, see TinyGo's LICENSE.

Documentation

The Go Gopher

There is no documentation for this package.

Directories

Path Synopsis
a32
asm
Package goenv returns environment variables that are used in various parts of the compiler.
Package goenv returns environment variables that are used in various parts of the compiler.
ir
op
reg
ir2
Package ir2 contains an Intermediate Representation (IR) in Static Single Assignment (SSA) form.
Package ir2 contains an Intermediate Representation (IR) in Static Single Assignment (SSA) form.
typ
experimental simplified type system Defintions: - A `byte` is the smallest addressable unit in the CPU, this does not need to be 8 bits, though it usually is.
experimental simplified type system Defintions: - A `byte` is the smallest addressable unit in the CPU, this does not need to be 8 bits, though it usually is.
src

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL