Show HN: Go Plan9 Memo

(pehringer.info)

181 points | by pehringer 6 hours ago ago

57 comments

  • joeegan2202 4 hours ago

    A couple points on Go assembly:

    1. On amd64 those ints are actually 64bit. If you used int32 then they would be be word aligned in the parameter list. However, there is a gotcha with that. The return values will always start at a dword aligned offset on 64bit system.

    2. NOSPLIT is defined in "textflag.h" which Go's compiler automatically provides. However, NOSPLIT is, from everything I've read, only respected on runtime.XX functions, so it's not doing anything there, and it's also not necessary. NOSPLIT tells the compiler not to insert code to check if the stack needs to split because it's going to overflow, which is technically unnecessary if the function doesn't need any stack space. It's basically only there on the function that checks for stack splits, to prevent that code from being injected into itself.

    • pehringer 4 hours ago

      Thank you for the explanation! That makes a lot more sense :)

  • mxey 4 hours ago

    > After doing some preliminary research I discovered that Go uses its own internal assembly language called Plan9.

    Is the language actually called that?

    • rsc 40 minutes ago

      No. It's just Go assembly. (It happens to be a Plan 9-derived syntax, but we call it Go assembly.) See https://go.dev/doc/asm.

    • nzach 4 hours ago

      This is a fair question. Initially I just assumed this was true. Because someone who did research on this topic would not get something like this wrong. And besides that, if you know a little about the project this name could make some sense.

      But the more I look into it, the more I think this is just a LLM hallucination.

      The doc about the 'assembly' format doesn't give a proper name. It just calls 'go assembler'.

      And I think the source of this hallucination was this first paragraph:

      > The assembler is based on the input style of the Plan 9 assemblers, which is documented in detail elsewhere. If you plan to write assembly language, you should read that document although much of it is Plan 9-specific. The current document provides a summary of the syntax and the differences with what is explained in that document, and describes the peculiarities that apply when writing assembly code to interact with Go.

    • mseepgood 3 hours ago

      No, it doesn't have a name. Plan 9 is an operating system, and this style of assembly language syntax originates from the assembler used on this operating system. Its like saying "The GNU Compiler Collection uses its own internal assembly language called Unix."

  • saclark11 5 hours ago

    > Overall, pretty weird stuff. I am not sure why the Go team went down this route. Maybe it simplifies the compiler by having this bespoke assembly format?

    Rob Pike spoke on the design of Go's assembler at a talk in 2016 [1][2]. I think it basically came down to the observation that most assembly language is roughly the same, so why not build a common assembly language that "lets you talk to the machine at the lowest level and yet not have to learn a new syntax." It also enables them to automatically generate a working assembler given an instruction manual PDF for a new architecture as input.

    [1]: https://www.youtube.com/watch?v=KINIAgRpkDA [2]: https://go.dev/talks/2016/asm.slide#1

    • alphazard 5 hours ago

      And it worked. Go established cross-compilation as table-stakes for new programming languages, at a time when very few were doing it well, if at all.

      • cloudfudge 4 hours ago

        Yes, this is a great leap forward in my opinion. I had to do a project at a previous job where I wrote an agent that ran on x86, MIPS and ARM, and doing it in Go was a no-brainer. The other teams who had a bunch of C code that was a nightmare to cross-compile were so jealous they eventually moved a lot of things to Go.

        I've been doing this for 35 years and cross compiling anything nontrivial was always a toolchain nightmare. Discovering a world where all I had to do was set GOARCH=mips64 (and possibly GOOS=darwin if I wanted mac binaries) before invoking the compiler is so magical I was extremely skeptical when I first read about it.

        • somat 26 minutes ago

          A fair enough assessment, it be that way, however I will note that a large reason that C exists in the first place was to have a machine independent language to write programs in.

        • bombela 2 hours ago

          As long as you don't have C libraries to cross compile / link against of course ;)

          • akira2501 16 minutes ago

            sqlite is the only thing that makes me sad I have CGO_ENABLED=0.

      • p_l 4 hours ago

        Go essentially copied the design from Plan9 compilers, which it was originally based on. It's one of the many things it inherited from Plan9 environment.

        • kjksf 4 hours ago

          It's more "reused" because Plan9 compilers were designed / co-implemented by Pike / Thomson, 2 out of 3 original designers of Go.

          For those interested, here's Thomson's paper about Plan9 C compilers: https://9p.io/sys/doc/compiler.html and https://doc.cat-v.org/bell_labs/new_c_compilers/

          • derefr 3 hours ago

            I would love to see a deep dive on what features / architectural paradigms the Golang runtime shares with Plan9. Has anything like that been written?

            One that always sticks out to me personally is the use in Go of the term "dial" instead of "connect" for network connection establishment. This is, AFAICT, another Pike+Thompson-ism, as it can be seen previously in the form of the Plan9 dial(3) syscall — https://9fans.github.io/plan9port/man/man3/dial.html .

            ---

            A tangent: I have wondered before whether Pike and Thompson drafted the design for the language that would become Golang long before working at Google, initially to replace C specifically in the context of being the lingua-franca for systems programming on Plan 9. And that, therefore — at least in the designer's minds — Golang would have always had Plan9 as its secret "flagship target" that it should have a 1:1 zero-impedance abstraction mapping onto. Even if they never bothered to actually make a Plan9 Golang runtime.

            You could test this hypothesis by implementing an actual Golang runtime for Plan9†, and then comparing it to the Golang runtimes for other OSes — if Plan9 were the "intended home" for Golang programs, then you'd expect the Golang runtime to be very "thin" on Plan9.

            (To put that another way: imagine the Golang runtime as something like WINE — a virtualization layer that implements things that could be syscalls / OS library code, in the form of client-side runtime shim code. A "WINE implementation for Windows" would be an extremely thin shim, as every shim call would just point to a 1:1-API-matched piece of OS-provided code. My hypothesis here is that "Golang for Plan9" is the same kind of thing as "WINE for Windows.")

            † I was saying this as a thought experiment, not thinking there would actually be a Plan9 implementation of the Golang runtime... but there is! (https://go.dev/wiki/Plan9) So someone can actually check this :)

            • mbivert 3 hours ago

              > I would love to see a deep dive on what features / architectural paradigms the Golang runtime shares with Plan9. Has anything like that been written?

              If it has, then it's most likely available on https://cat-v.org/. Even if it hasn't, cat-v.org is a great starting point.

              Besides, close to your line of thought, and assuming you didn't knew about this already, Pike & al previously worked on Limbo[0], a "predecessor" of Go, used to wrote Inferno[1], a Plan9-like OS, which could be hosted on arbitrary OSes via a bespoke virtual machine called "Dis".

              So there were indeed a few previous "drafts" for Go. I'd doubt that Go has been designed "for" Plan9 though.

              [0]: https://en.wikipedia.org/wiki/Limbo_(programming_language)

              [1]: https://en.wikipedia.org/wiki/Inferno_(operating_system)

              • exitb 2 hours ago

                There’s also libthread[1] which implements concurrency model similar to goroutines (at least earlier, as they appear to be no longer just cooperatively scheduled?). That manual also mentions Alef and Newsqueak as influential predecessors.

                [1] http://man.9front.org/2/thread

            • gavindean90 2 hours ago

              It sort of was and Rob blogged about it. It is based really on Newsqueak and plan9 C which is very different from Unix C

            • pram an hour ago

              I'd guess dial is probably a Bell Labs-ism

  • umvi 4 hours ago

    > Basically, I wanted a set of functions that would allow me to perform simd operations on slices.

    How is this actually used though? I searched the whole article, and no where are any operations being performed on slices.

    Edit: I found what I was looking for in the linked docs: https://pkg.go.dev/github.com/pehringer/simd#pkg-index

    So basically if you have 2 slices you want to add together, instead of a for loop you could do it in parallel with simd using:

        simd.AddInt32(slice1, slice2, result)
  • sedatk an hour ago

    > 4 represents “NOSPLIT” which we need for some reason

    For those who are curious: "In the general case, the frame size [the parameter after NOSPLIT] is followed by an argument size, separated by a minus sign. (It's not a subtraction, just idiosyncratic syntax.) The frame size $24-8 states that the function has a 24-byte frame and is called with 8 bytes of argument, which live on the caller's frame. If NOSPLIT is not specified for the TEXT, the argument size must be provided. For assembly functions with Go prototypes, go vet will check that the argument size is correct."

    Source: https://go.dev/doc/asm

  • lexh 5 hours ago

    A bit over my head, but I enjoyed the way the writing brings us along for the ride.

    This can’t be the first pass someone has made at something like this, right? There must be literal dozens of SIMD thirsty Gophers around. Would a more common pattern be to use CGO?

  • pixelesque 3 hours ago

    Very minor nit, doesn't change anything about the article otherwise, but the SIMD acronym stands for *Single* Instruction, Multiple Data conventionally.

  • spiffistan 4 hours ago

    There was a controversy when Go came out about the naming due to another language also being called Go, and the top voted alternative name was Plan9, and as an homage they may have used that internally instead.

    • stonogo 4 hours ago

      The top voted alternative was "Issue 9" which served as a reference to Plan 9 and happened to be the actual issue number in the Go project on Google Code opened by the guy who's programming language (named "Go!") was already out there.

  • pehringer 5 hours ago

    If you want to see some Plan9 in the std library check out the math package!

    https://github.com/golang/go/tree/master/src/math

  • tempfile 5 hours ago

    Is Plan9 in this context related at all to Bell Labs's Plan9? Seems too similar to be coincidence.

    • 201984 5 hours ago

      From https://go.dev/doc/asm:

      > The assembler is based on the input style of the Plan 9 assemblers, which is documented in detail elsewhere. If you plan to write assembly language, you should read that document although much of it is Plan 9-specific.

      That first sentence links to https://9p.io/sys/doc/asm.html. So yes, definitely not a coincidence.

    • pjmlp 5 hours ago

      Go is the evolution of Limbo from Inferno, which was designed based on the failure of Alef on Plan 9, combined with a minor set of Oberon-2 influences.

    • kibwen 5 hours ago

      Go itself is from the same people who worked on Plan9 (which is why I find the choice of name in the OP particularly confusing).

    • saclark11 5 hours ago

      Yes. Two of Go's creators, Rob Pike and Ken Thompson, were also authors of Plan 9 at Bell Labs.

    • wrs 5 hours ago

      Yes, some of the same people created Go.

  • pphysch 5 hours ago

    This is neat. Why do you think this is not already part of the standard library?

    • twoodfin 4 hours ago

      I think the more interesting architecture / priorities question is why the Go compiler can't yet(?) auto-vectorize?

    • pehringer 5 hours ago

      I think the Go std lib is focused on portability over raw performance

  • nzach 5 hours ago

    > I am not sure why the Go team went down this route. Maybe it simplifies the compiler by having this bespoke assembly format?

    This was to allow for easy cross-compilation.

    You should probably clarify that you are talking about 'golang plan9 assembly format', and not about the plan9 OS. This confused me a lot. (https://en.wikipedia.org/wiki/Plan_9_from_Bell_Labs)

    I didn't know you could easily hand write 'golang assembly' for your functions. This seems really useful in some cases.

    But I do wonder, why the std lib doesn't offer this ?

    EDIT: I found the anwser: https://github.com/golang/go/issues/53171

    Here is a good explanation provided by Ian Lance Taylor:

    > This proposal is focused on code generation rather than language, and the details of how it changes the language are difficult to understand. Go is intended to be a simple language that it is easy to understand. Introducing complex semantics for performance reasons is not a direction that the language is going to take.

  • rob74 5 hours ago

    In case it's not obvious, the "Plan 9" in the Go Assembler's name comes from https://en.wikipedia.org/wiki/Plan_9_from_Bell_Labs, and the reason for that is of course that two of the "Go founders" (Rob Pike and Ken Thompson) are Bell Labs alumni. Some more background on the Go assembler: https://go.dev/doc/asm

    • p_l 4 hours ago

      The reason for that is not just being alumni, but also that Go implementation started on top of Plan 9's compiler infrastructure that was later rewritten in pure Go

    • colechristensen 5 hours ago

      The same people used the same name for two computer related projects.

      That's certainly an ... interesting choice.

      • lloeki 5 hours ago

        It is, essentially, the same project. Plan9 is the umbrella term for the whole operating system.

        https://plan9.io/sys/doc/comp.html

        IIRC before Go was self compiling, it was compiled using 9c, and its architecture inherits from 9c.

        EDIT: some nearby threads got the details better!

        • floren 4 hours ago

          > IIRC before Go was self compiling, it was compiled using 9c, and its architecture inherits from 9c.

          Back in those days I actually found that, with a few small tweaks, I could compile the Plan 9 operating system using Go's C suite. We didn't pursue it further but this was one of the options we looked into for cross-compiling Plan 9 from other operating systems.

          • stonogo 4 hours ago

            Since to Go C suite was ported Plan 9 compilers, I'm not sure why this would be a surprise. Since I'm obviously missing something would you share your thoughts on what challenges you expected?

            • floren 3 hours ago

              It wasn't any surprise, nor did I intend to imply it was surprising, just relaying an anecdote. There were a few differences that required small tweaks to the source, but we got the Plan 9 kernel compiled with the Go C compilers in a day.

        • colechristensen 4 hours ago

          Interesting trivia about the connection to plan9 the operating system.

          >Go uses its own internal assembly language called Plan9.

          Plan9 is the name of the OS. You wouldn't name a programming language "Linux", even if Linus created it and it was super related or not at all related.

          • seryoiupfurds 4 hours ago

            It's not "plan9 assembly language" as in "the assembly language named plan9". Read it as "the otherwise unnamed custom assembly language used in the plan9 operating system".

            The article simply misspoke by saying that the assembly language is "called plan9".

            • debugnik 2 hours ago

              No way, the article consistently refers to the assembler syntax as "Plan9" throughout the text and title and they talk about "x86 Plan9" and "arm Plan9".

              Considering there is no introduction at all to this beyond "I discovered it's called Plan9", I'm assuming the author really thinks this is a language widely named "Plan9".

              • KerrAvon 2 hours ago

                They seem to be badly mistaken

      • colechristensen 11 minutes ago

        EDIT: it seems the author is just mistaken, the Go assembler is just referred to by everyone else as "Go Assembler" and nothing to do with plan9, other than the various connections to its origin.

      • lagniappe 5 hours ago

        Definitely don't look into Nix then