Tuesday 6 May 2014

Building Go - First Steps

As I have mentioned in my previous posts, my goal is to add a new architecture (PowerPC) to the Go toolchain. If successful, you will be able to both compile and install the toolchain on a PowerPC machine. Also, you will be able to cross-compile PowerPC (ppc64) binaries using x86/arm machines. This is due in part to the multi-platform capabilities inherited from Plan 9.

Logically, each of the four fundamental tools in the toolchain (Assembler, Linker, C Compiler, Go Compiler) has some mixture of platform-neutral and platform-specific code. This is evident given the fact that there are platform-neutral directories (ld, cc, gc) as well as platform-specific ones (e.g. 5a, 5l, 5c, 5g). It is clear that that I need to create ppc64 equivalents (e.g. 9a, 9l, 9c, 9g).

At a very superficial level, ppc64 shares some similarities with arm. They are both considered RISC architectures. There are still some very large differences including the endianness and number of registers, but the arm code seems like a better place to start than with x86/amd64, which are much different. I copied the 5x directories to 9x as a starting point to get something compiling.

Running an initial build of the toolchain (using the "src/all.bash" script) falls flat on its face.
$ ./all.bash
# Building C bootstrap tool.
cmd/dist
go tool dist: unknown architecture: ppc64
This is not entirely unexpected. I did not declare the ppc64 architecture anywhere in the code and I have not mapped it to the chosen number '9.' The question is where to put the declaration and mapping. A good place to start is with the "cmd/dist" entry shown in the build log from the "all.bash" script.

The toolchain uses a special C program called 'dist' instead of make to compile the tools, which was quite unexpected. The build log doesn't show the command-line parameters and the dist command doesn't have any debugging symbols making it rather difficult to figure out what goes wrong. Let's fix that by making these changes to the 'make.bash' file:
make.bash:
${CC:-gcc} $mflag -g -O0 -Wall -Werror -o cmd/dist/dist -Icmd/dist "$DEFGOROOT" cmd/dist/*.c
...echo ./cmd/dist/dist bootstrap $buildall $GO_DISTFLAGS -v

./cmd/dist/dist bootstrap $buildall $GO_DISTFLAGS -v # builds go_bootstrap

After some careful debugging I discovered that the declarations should go in the cmd/dist/build.c and cmd/dist/unix.c files:
build.c:
// The known architecture letters.
static char *gochars = "56689";
// The known architectures.
static char *okgoarch[] = {
// same order as gochars
"arm",
"amd64",
"amd64p32",
"386",
"ppc64",
};
dist.c:
else if(contains(u.machine, "arm"))
gohostarch = "arm";
else if(contains(u.machine, "ppc64"))
gohostarch = "ppc64";


Now when I run the all.bash script it gets alot further along but ultimately fails due to missing dependencies. I will go over the problem and my solution in the next post.

No comments:

Post a Comment