{"id":23812555,"url":"https://github.com/rj45/nanogo","last_synced_at":"2025-09-06T21:30:47.036Z","repository":{"id":57641515,"uuid":"435265184","full_name":"rj45/nanogo","owner":"rj45","description":"NanoGo a Go (golang) Subset for Homebrew / Hobby CPUs","archived":false,"fork":false,"pushed_at":"2024-01-08T18:01:13.000Z","size":1326,"stargazers_count":6,"open_issues_count":2,"forks_count":2,"subscribers_count":3,"default_branch":"main","last_synced_at":"2025-04-07T10:36:21.122Z","etag":null,"topics":["assembly","compiler","cpu","go","golang","hobby-compiler","hobby-language","hobby-project","homebrew-computer","processor-design"],"latest_commit_sha":null,"homepage":"","language":"Go","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"other","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/rj45.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2021-12-05T19:57:51.000Z","updated_at":"2024-08-07T08:26:50.000Z","dependencies_parsed_at":"2024-06-20T10:18:04.247Z","dependency_job_id":"79ce928b-4c9a-4dba-b916-06bf63b08826","html_url":"https://github.com/rj45/nanogo","commit_stats":null,"previous_names":[],"tags_count":4,"template":false,"template_full_name":null,"purl":"pkg:github/rj45/nanogo","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/rj45%2Fnanogo","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/rj45%2Fnanogo/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/rj45%2Fnanogo/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/rj45%2Fnanogo/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/rj45","download_url":"https://codeload.github.com/rj45/nanogo/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/rj45%2Fnanogo/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":273965095,"owners_count":25199200,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","status":"online","status_checked_at":"2025-09-06T02:00:13.247Z","response_time":2576,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["assembly","compiler","cpu","go","golang","hobby-compiler","hobby-language","hobby-project","homebrew-computer","processor-design"],"created_at":"2025-01-02T02:30:34.940Z","updated_at":"2025-09-06T21:30:46.727Z","avatar_url":"https://github.com/rj45.png","language":"Go","funding_links":[],"categories":[],"sub_categories":[],"readme":"# NanoGo\n\n`NanoGo` is a Go (golang) compiler for homebrew / hobby CPUs.\n\n## Status\n\nCurrently a major refactor (well more like rewrite) is in progress to switch to a new and improved IR. Along with it the tranforms in xform are also getting a revamp. The new code is in ___2 packages but the old code is still there and should still work.\n\nThis is a work in progress! Currently the following should work:\n\n- built in `print()` and `println()`\n- word-sized operations (`int` and `uint`)\n- string literals and iterating over strings\n- memory mapped I/O using `unsafe`\n- extern funcs with assembly snippets (useful if you have I/O instructions)\n\nAlso, only [rj32](https://github.com/rj45/rj32) and [A32](https://github.com/Artentus/a32emu) are supported, but if you would like assistance adding your CPU, open an issue. The key things needed to support a new CPU are a fully working emulator (that works on mac, linux and windows, arm and x86), and an assembler (customasm is preferred).\n\n## What is it?\n\nThis 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 assembly in a style that is compatible with [customasm](https://github.com/hlorenzi/customasm).\n\nAs 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 `#bank`s.\n\n## Why Go?\n\nC is great, but the language is not the easiest to parse, and while there's many great projects like [LCC](https://github.com/drh/lcc), they are not the easiest to work on and modify for a homebrew CPU.\n\nGo is a very simple language, and is very fast to learn, yet powerful enough to be very productive.\n\nAs well, Go has a parser and type checker right in the the standard library. Further, there's an excellent [SSA library](https://golang.org/x/tools/go/ssa) 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.\n\n## Installing\n\nInstall [Go](https://golang.org/) for your system, then there are [releases](https://github.com/rj45/nanogo/releases) with prebuilt binaries and the runtime library source, plus some example programs.\n\nOr you can install with go's installer:\n\n```sh\ngo install github.com/rj45/nanogo@latest\n```\n\nYou will also want to install [customasm](https://github.com/hlorenzi/customasm).\n\nYou may also want to install [emurj](https://github.com/rj45/rj32/emurj) if you want to be able to run programs in an `rj32` emulator.\n\nYou 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.\n\n## Running\n\nYou can run NanoGo to produce assembly like so:\n\n```sh\nnanogo -o output.asm asm testdata/seive/seive.go\n```\n\nIf you have [customasm](https://github.com/hlorenzi/customasm) installed, then you can get a binary or hex file (depending on the architecture) like so:\n\n```sh\nnanogo -o output.hex build testdata/seive/seive.go\n```\n\nIf you have [emurj](https://github.com/rj45/rj32/emurj) installed, you can build and run the program like so:\n\n```sh\nnanogo run testdata/seive/seive.go\n```\n\nIf 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:\n\n```sh\nnanogo -dump main__main asm testdata/seive/seive.go\n```\n\nAnd then you can open `ssa.html` in your browser.\n\n![ssa.html](./docs/img/ssa_html.png)\n\nThere is also a way to generate various `.dot` graphs of the flow of values through the program using this:\n\n```sh\nnanogo -dump main__main asm testdata/seive/seive.go\n```\n\nYou can look at the control flow graph at the time of register allocation:\n\n![control flow graph](docs/img/control_flow.png)\n\nOr an exploded view of the flow of values through the program (at register allocation):\n\n![value flow graph](docs/img/value_flow.png)\n\nA `.dot` viewer like `xdot` is recommended because it will highlight which line goes where and allow you to zoom in.\n\n## Limitations\n\nKeep 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.\n\nSo, 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.\n\nDefer 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.\n\n`int`s, `uint`s, `byte`s, `rune`s 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.\n\nAlmost 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.\n\n## Design\n\nNanoGo uses the [golang.org/x/tools/go/ssa](https://golang.org/x/tools/go/ssa) package to build and parse Go into [SSA form](https://en.wikipedia.org/wiki/Static_single_assignment_form).\n\nThis IR is then [converted](./parser) into a different [IR](./ir) which is [easier to work with](https://www.hpl.hp.com/techreports/Compaq-DEC/WRL-2000-2.html) and [transform](./xform).\n\nAfter transformation there is a [SSA based tree register allocator](./regalloc) which uses the properties of SSA to [allocate registers in linear time](https://compilers.cs.uni-saarland.de/projects/ssara/).\n\nAfter a final transformation pass, then finally [assembly code is generated](./codegen) and output.\n\n## Retargeting / Porting to Your CPU\n\nSome effort was put in to make this easy. See [the retargeting documentation](docs/retargeting.md).\n\n## Contributing\n\nContributions are welcome! If you spot a bug or an error, and have some time, submit a PR. Otherwise an issue is awesome. Typo fixes or docs are even welcome!\n\nContributions of your own architecture are welcome! See [the retargeting documentation](docs/retargeting.md).\n\nPlease be kind to one another and put effort into determining a kind way to share criticism.\n\n## Forking, commercial use and permission\n\nIf 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.\n\nIf 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.\n\n## License\n\nCopyright (c) 2021-2023 Ryan \"rj45\" Sanche ([github.com/rj45](https://github.com/rj45))\n\nLicensed under the MIT License (MIT), see [LICENSE](./LICENSE).\n\nSome parts Copyrighted by the Go Authors, under a BSD like license, see [Go's LICENSE](https://github.com/golang/go/blob/666fc173c02ff3004ac9ef867aa4eec7e243dde3/LICENSE). Files with this license are marked in the header.\n\nSome parts Copyrighted by the TinyGo Authors, under a BSD like license, see [TinyGo's LICENSE](./LICENSE.tinygo). Files with this license are marked in the header.\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Frj45%2Fnanogo","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Frj45%2Fnanogo","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Frj45%2Fnanogo/lists"}