Go

Go: The Assembly Detective Story

Keith Randall fixed a tricky assembler bug affecting indirect tail calls across multiple Go architectures. What started as a seemingly working feature on arm64 and amd64 turned into a cross-platform debugging adventure when other architectures started failing on the dashboard.

Duration: PT4M

https://podlog.io/listen/go-e282e2e6/episode/go-the-assembly-detective-story-becdddc9

Transcript

Hey there, fellow Go developers! Welcome back to another episode of our daily Go podcast. I'm your host, and wow, do I have a fun detective story for you today from the Go repository.

You know those moments when you think you've got something working perfectly, and then reality comes knocking? That's exactly what happened in the Go codebase yesterday, and honestly, it's such a relatable developer experience that I had to share it with you all.

So here's what went down. Keith Randall was working on some assembler code for indirect tail calls - think of these as a way for functions to efficiently hand off control to other functions without the usual overhead. Pretty neat optimization stuff happening under the hood of Go.

Now, Keith did what any reasonable developer would do - he tested it on a couple of architectures first. He tried arm64 and amd64, and boom! Everything worked beautifully. The tests passed, the code looked clean, and I can just imagine that satisfying feeling of pushing working code.

But here's where it gets interesting, and this is such a classic development story. The Go team has this fantastic continuous integration system called the dashboard that tests across all the different architectures that Go supports. And let me tell you, Go supports a lot of them - we're talking ARM, MIPS, PowerPC, RISC-V, s390x, and more.

Well, the dashboard started lighting up red. Turns out, the assembler wasn't handling these indirect tail calls correctly on most of the other architectures. Keith's assumption that if it worked on arm64 and amd64, it would work everywhere else? Not quite right this time.

I love this because it's such a human moment in programming. How many times have we all been there? You test on your machine, maybe one or two environments, everything looks great, and then production - or in this case, the full test suite - tells a different story.

So Keith rolled up his sleeves and dove into the fix. The commit message is beautifully honest about it too - "The assembler isn't handling this correctly for most architectures. Of course, the two I tried first, arm64 and amd64, worked, so I assumed other archs could handle it also. Apparently not."

The fix itself touched six different architecture-specific files. We're looking at changes to ARM, Loong64, MIPS, PowerPC64, RISC-V, and s390x. Each one needed its own tailored approach to handle these indirect tail calls properly. This is the kind of low-level work that makes Go run efficiently across all these different platforms, and it's happening behind the scenes every day.

What I really appreciate about this fix is how it showcases the robustness of Go's development process. The dashboard caught the issue quickly, Keith was able to identify the problem and roll out a comprehensive fix, and multiple reviewers - including Dmitri Shuralyov and Cuong Manh Le - helped ensure the solution was solid.

This is also a great reminder of why comprehensive testing across different environments is so crucial. Those edge cases and platform-specific behaviors can really bite you if you're not careful.

Today's focus for all of us listening: when you're working on something that needs to run across different environments - whether that's different operating systems, browsers, or even just different versions of dependencies - make sure your testing strategy reflects that reality. Don't let the first successful test give you false confidence.

And hey, if you're working on Go itself or any other open source project, remember that these kinds of fixes, even the ones that feel like "oops, my bad" moments, are incredibly valuable contributions. They make the language better for everyone.

That's a wrap for today's episode! Keep coding, keep learning, and remember - even the Go team has those "works on my machine" moments. We're all in this together. Catch you tomorrow with more Go adventures!