Go -> C++ transpiler idea: Miracle child or horrible abomination?

1,391 views
Skip to first unread message

Brad

unread,
Mar 24, 2017, 11:32:20 PM3/24/17
to golang-nuts
Interested in any feedback about the idea of making a Go -> C++ transpiler.  Here's the rationale:

* Go as a language has lots of awesome things that make it highly productive.  Lots of Gophers would love to use Go for more projects but some common issues include:
* Trying to convince your team or management to adopt Go over a "more traditional" language can be a tough sell: Your PHB is likely to tell you it's not worth the risk, because the next developer he hires may not like Go and he'll be screwed, whereas he knows he can find someone who will write C++ or Java.
* And there is also the issue of the environments in which Go will run.  On embedded platforms (e.g. Parallax Propeller, Arduino) you can write C++, but you're not going to get a Go compiler for it.
* There's also the fact in a scenario where Go co-exists with C or C++, Go has to have the main function and has to build the executable. Unless you build a shared library, you can't just start implementing parts of your project in Go and gradually phase things over.

It's also worth noting that some of these scenarios just will never support all the features of the Go language, and so full support will not happen.  You probably won't get goroutines on an Arduino, for example. But, that doesn't mean it wouldn't be useful to be able to write Go code in these cases that doesn't use that feature and is otherwise 100% correct Go.

So, what if the following existed:

* Tool that converts Go to C++:
* Comments and formatting are preserved - the resulting C++ is readable.  You can tell your boss "there's no loss here - if this doesn't work, we'll throw away the Go code and keep working on the C++", even though you know you will burn in hell for doing that ;)
* Language constructs which have an obvious simple mapping are just directly converted (byte -> uint8_t, structs are structs, etc.)
* Things that can be done with C++ code but are just ugly (e.g. defer, implemented with goto) would be done like that - the transpiler would just emit that code.
* Features that are syntactic sugar around runtime implementations are emits as calls to a stripped down version of the runtime that just does the bare minimum to support what's needed: e.g. maps and slices are implemented with a C++ template - the template is the same one that is just dropped in the output as "map.h" and the transpiler emits code that uses it.
* Heap allocations are mapped to a GC lib implemented in C++ - same as maps above, just more complicated.  Same with channels.
* Reflection could be done by emitting a bunch of type info and making all that work, but probably wouldn't get around to doing this in a first version.
* "go" gets mapped to pthread_create(), cognew() or whatever.
* As much as possible this things are kept as some sort of simple template of the corresponding C++ code to output, so you can easily adjust how allocations or "go" or whatever are emitted for a particular environment.
* The standard library would probably need to be forked, the things that are heavily intertwined with the Go runtime ("runtime", "reflection", etc.) would probably just not be available initially, and the ones that can be patched and transpiled would be, and then some would probably just need a separate implementation in C++ (e.g. "sync").  There would be an obvious way to do this and it would be a normal thing in this scenario to say: "let's drop in an implementation of fmt that supports only the barebones formatting for use on embedded systems", etc.
* Features/packages that are not supported would result in a transpiler error.  I.e. some things "you just can't do" with this tool and that's okay.

Assuming this actually worked, it might considerably lower the bar for adopting Go, and allow it to be used to develop in environments where we're not likely to see a port of the compiler any time soon.  (Or where it's literally impossible because there are things in the language that the platform just can't do.)

I could potentially devote some time to building this out, but I wanted to see if anyone had feedback on the concept.  I realize it's not a simple project, but with the above setup it could be implemented incrementally.

Raffaele Sena

unread,
Mar 25, 2017, 12:27:59 AM3/25/17
to Brad, golang-nuts

If you use --lang=c it will actually generate c++ code.

It's not perfect but it does the bulk of the conversion. Unfortunately working with only the ast has it's limits (and I wrote this before the ssa stuff was available)

-- Raffaele
--
You received this message because you are subscribed to the Google Groups "golang-nuts" group.
To unsubscribe from this group and stop receiving emails from it, send an email to golang-nuts...@googlegroups.com.
For more options, visit https://groups.google.com/d/optout.

andrewc...@gmail.com

unread,
Mar 25, 2017, 6:50:12 AM3/25/17
to golang-nuts
Its a bad idea for many reasons.

- The actual implementation is harder than convincing someone to just use the official Go compiler.
- Some features don't map cleanly to C++
- C++ programmers won't like it, and neither will go programmers.
- Nobody will fund the maintenance of this compiler and it will quickly be abandoned.

Konstantin Khomoutov

unread,
Mar 25, 2017, 7:08:55 AM3/25/17
to andrewc...@gmail.com, golang-nuts
On Sat, 25 Mar 2017 03:49:55 -0700 (PDT)
andrewc...@gmail.com wrote:

> Its a bad idea for many reasons.
>
> - The actual implementation is harder than convincing someone to just
> use the official Go compiler.
> - Some features don't map cleanly to C++
> - C++ programmers won't like it, and neither will go programmers.
> - Nobody will fund the maintenance of this compiler and it will
> quickly be abandoned.

There's also the problem of the conversion being one-way: if a C++
programmer spots an error in the generated code, it has to be traced
back to the Go source, be fixed there and the C++ code re-generated.
(And the another problem is that like with many "transpilers", a tiny
change in the source might trigger swaths of changes in the generated
content. And this also hints at that only the "reference" code base
could be sensibly version-controlled.).

So this approach is OK for cases like Facebook having been transpiling
their PHP to C++ (because no one is supposed to hack on the generated
code base -- just compile it and run), but much less so for having
programmers hacking "on both sides" of the codebase.

Brad

unread,
Mar 25, 2017, 6:49:41 PM3/25/17
to golang-nuts, andrewc...@gmail.com
My thought was that the translation would be one-way - you would avoid hacking on the C++ part unless you were completely abandoning the Go part.

I see the point on the disparity between what it would take to migrate a project to Go vs the effort to build such a project.  Although part of my motivation here is the potential for running a subset of the Go language in an environment where it otherwise won't be supported.

That said, the more I look through the Go lang spec it becomes apparent that, yes, some really important features don't map to C++ well at all (or could require significantly different implementations in different environments).  Garbage collection (or an alternative like reference counting), inline functions/closures, channels, etc.  It gets pretty crazy pretty quick.  And leaving those out would dramatically cut down the amount Go code that would convert correctly, thus largely defeating the purpose.

Dave Cheney

unread,
Mar 25, 2017, 8:07:18 PM3/25/17
to golang-nuts
I think it's a fine idea. For a decade C++ was actually compiled to C, via cfront. It well past time that Go returns the favour.

This would also help flush out a lot of unspoken assumptions about what a Go program requires from the underlying operating system.

Lee Nipper

unread,
Mar 25, 2017, 8:16:56 PM3/25/17
to golang-nuts
> it might considerably lower the bar for adopting Go

I think Go as a language and the tooling make the bar quite low already. With a small time investment it becomes a very productive language for most developers.

Choosing a project which makes sense to completely write in Go, and sharing that experience with team peers is one means to promote adoption and awareness of its strengths.

mura

unread,
Mar 25, 2017, 10:17:49 PM3/25/17
to golang-nuts
A ANSI-C (probably with GNU extension if helpful)  transpiler/backend would be much more useful than a C++ one.
C is far more widespread and easier to integrate. C *and* C++ projects can both integrate C source. But C projects cannot integrate C++ source.

The users who want to build the gc compiler from source could use the C output to bootstrap it, instead of installing Go 1.4.x or another binary release. It's more likely that a system happens to have a C compiler installed.

Brad

unread,
Mar 27, 2017, 9:19:05 PM3/27/17
to golang-nuts
Thanks for all feedback here.  It sounds like while there are some significant caveats this could work and would have value.  I think the big question is what are all these integration points that are provided by the Go runtime that are not available in a C/C++ environment and how big of a task is it to implement them (even if the implementations are initially much more naive than what Go has).

I also think the case for going with C as opposed to C++ is pretty strong, I'll definitely look at that (architecturally it could be set up so that either could be plugged in but the odds of ever getting around to implementing the second language choice seem fairly low).

I will try to find time to rough out some initial stuff on this and will post an update if I get something that looks promising.

Andrew Chambers

unread,
Mar 27, 2017, 9:42:27 PM3/27/17
to Brad, golang-nuts
I suggest looking at the prior art of gopherjs and Elliot stonehams haxe based transpiler.

--
You received this message because you are subscribed to a topic in the Google Groups "golang-nuts" group.
To unsubscribe from this topic, visit https://groups.google.com/d/topic/golang-nuts/eUnAY0-Reew/unsubscribe.
To unsubscribe from this group and all its topics, send an email to golang-nuts+unsubscribe@googlegroups.com.

Brad

unread,
Mar 27, 2017, 10:17:33 PM3/27/17
to golang-nuts, bradg...@gmail.com
Thanks, yes I'm casually familiar with both projects but will dig deeper.  It's true that some big parts of what I'm describing have already been done, targeting other languages.
To unsubscribe from this group and all its topics, send an email to golang-nuts...@googlegroups.com.

Ruby Spring

unread,
Mar 28, 2017, 10:28:29 AM3/28/17
to golang-nuts
Probably a weird and orthogonal suggestion : transpile go-->rust and eliminate the gc overhead without dealing with the horrible syntax, if that is even feasible..

Andy Balholm

unread,
Mar 28, 2017, 2:00:47 PM3/28/17
to Ruby Spring, golang-nuts
If global ownership inference, with enough flexibility to replace a garbage collector, were practical, I suppose the Rust compiler would have it already. But if you want to prove the Rust developers wrong, go ahead and do it in a transpiler.

Andy

mura

unread,
Mar 30, 2017, 11:06:24 PM3/30/17
to golang-nuts
Just thought about maybe this could be used to generate the C header and source files for C binding.

Currently we have to write a hybrid language called cgo for FFI. It's not always the best approach.
I'd like to have a C header that can be included to implement a 'driver' for the Go runtime and using the driver as a bridge to the system shared libraries.

And then the complicated stuff for Go <-> C could probably be removed from the runtime and delegate to the C driver.


On Saturday, March 25, 2017 at 11:32:20 AM UTC+8, Brad wrote:

Brad

unread,
Mar 31, 2017, 12:16:27 AM3/31/17
to golang-nuts
I see what you're saying.

One unfortunate thing about this approach is that it doesn't help in cases where the Go runtime isn't supported/ported.

I'm thinking of embedded environments as an example - to implement garbage collection probably requires a very careful approach and something custom for the specific platform in question.

For this example of garbage collection (and each facet needs it's own consideration - reflection, scheduling, etc.), on more "normal" platforms it could work to either a) use Go's garbage collector, or b) use one of various standalone garbage collection libraries, e.g. http://tinygc.sourceforge.net/  Whereas in the embedded environment you may want a completely different implementation.

My thought on how this would end up going would be to translate code like this:

example.go:

type SimpleStruct struct {
 A
int
}

func doSomething
() {

 ss
:= &SimpleStruct{}

 
// something happens here to force heap allocation above, instead of stack

}



gets translated into something like:

example.c:

typedef {
 
int A;
} SimpleStruct;

void doSomething() {

 
SimpleStruct *ss = ZERO(HEAP_ALLOCATE(SimpleStruct));

}


The idea being that HEAP_ALLOCATE is a macro and can has a definition somewhere that is environment-specific and swappable.

I'm not familiar enough with the guts of the Go runtime to know what it would take to implement that macro by calling into the Go RT.

Basile Starynkevitch

unread,
Mar 31, 2017, 8:14:12 AM3/31/17
to golang-nuts


On Saturday, March 25, 2017 at 4:32:20 AM UTC+1, Brad wrote:
Interested in any feedback about the idea of making a Go -> C++ transpiler. [....]

A very important point it to get a precise multi-threaded garbage collector in C++. This is painfully difficult, and if you succeed (perhaps by using Boehm's conservative Garbage Collector or Ravenbrook's Memory Pool System) you'll probably get a GC much less efficient that what Go has.

(I have designed and coded GCC MELT and I speak of experience: even debugging a single-threaded GC friendly to C++ is painful).

Another point is the major difference between C++ containers and Go ones.

IMHO, it is not very realistic.

You might however code (after several years of hard work) some Go -> C compiler based above Boehm's GC. Similar stuff has been done for Scheme in Bigloo. But the result will be slower than Go.

Read the GC handbook to understand why.

If you do things like this, you need to budget nearly ten years of work. Are you sure it is worth the trouble?

Cheers.

Basile Starynkevitch (France).

leandro...@gmail.com

unread,
Apr 4, 2017, 12:48:25 AM4/4/17
to golang-nuts
Brad,


On Friday, March 24, 2017 at 8:32:20 PM UTC-7, Brad wrote:
Interested in any feedback about the idea of making a Go -> C++ transpiler.  Here's the rationale:
(...)
Assuming this actually worked, it might considerably lower the bar for adopting Go, and allow it to be used to develop in environments where we're not likely to see a port of the compiler any time soon.  (Or where it's literally impossible because there are things in the language that the platform just can't do.)

I've tried doing this in the past, but life got in the way.  However, someone pointed me out to this thread and I decided to bootstrap the project over the weekend.  The code generated by the compiler is still not compilable, but the transformations are already looking good.  Contributions are (very) welcome!

The repository is at https://github.com/lpereira/gomoku -- and the project is released under the same license as Go itself.  (Also, this is my first "serious" Go project, so feedback is also appreciated.)

Cheers,
    Leandro
Reply all
Reply to author
Forward
0 new messages