<div dir="ltr"><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex">   * Upstream changes into Cabal to make your new compiler a first-class<br>     citizen. This is what GHCJS did.</blockquote><div><br></div><div>Just a word of caution, please don't do this. It leads to non-negligible maintainence burden on your and on the cabal side. Rather try as hard as you can to make your compiler behave like a ghc wrt to cabal. Or add generic support for more powerful compilers to cabal. Adding special handling for one additional compiler will just result in bitrot, odd quirks that only happen with that one compiler, and just a maintenance nightmare for everyone involved.</div><div><br></div><div>We will be ripping out GHCJS custom logic from cabal. And I've also advised the Asterius author not to go down that route.</div><div><br></div><div>My suggesting--if I may--is to try and build a c-like toolchain around your compiler. That has some notion of compiler, archiver, linker, and those could you empty shell wrappers, or no-ops, depending on your target.</div><div><br></div><div>Cheers,</div><div> Moritz</div></div><br><div class="gmail_quote"><div dir="ltr" class="gmail_attr">On Tue, Mar 30, 2021 at 11:08 AM Ben Gamari <<a href="mailto:ben@well-typed.com">ben@well-typed.com</a>> wrote:<br></div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex">Clinton Mead <<a href="mailto:clintonmead@gmail.com" target="_blank">clintonmead@gmail.com</a>> writes:<br>
<br>
> Thanks again for the detailed reply Ben.<br>
><br>
> I guess the other dream of mine is to give GHC a .NET backend. For my<br>
> problem it would be the ideal solution, but it looks like other attempts in<br>
> this regard (e.g. Eta, GHCJS etc) seem to have difficulty keeping up with<br>
> updates to GHC. So I'm sure it's not trivial.<br>
><br>
> It would be quite lovely though if I could generate .NET + Java + even<br>
> Python bytecode from GHC.<br>
><br>
> Whilst not solving my immediate problem, perhaps my efforts are best spent<br>
> in giving GHC a plugin architecture for backends (or if one already<br>
> exists?) trying to make a .NET backend.<br>
><br>
This is an interesting (albeit ambitious, for the reasons others have<br>
mentioned) idea. In particular, I think the CLR has a slightly advantage<br>
over the JVM as a Haskell target in that it has native tail-call<br>
support [1]. This avoids a fair amount of complexity (and performance<br>
overhead) that Eta had to employ to work around this lack in the JVM.<br>
<br>
I suspect that writing an STG -> CLR IR wouldn't itself be difficult.<br>
The hard part is dealing with the primops, RTS, and core libraries.<br>
<br>
[1] <a href="https://docs.microsoft.com/en-us/previous-versions/windows/silverlight/dotnet-windows-silverlight/56c08k0k(v=vs.95)?redirectedfrom=MSDN" rel="noreferrer" target="_blank">https://docs.microsoft.com/en-us/previous-versions/windows/silverlight/dotnet-windows-silverlight/56c08k0k(v=vs.95)?redirectedfrom=MSDN</a><br>
<br>
> I believe "Csaba Hruska" is working in this space with GRIN, yes?<br>
<br>
Csaba is indeed using GHC's front-end and Core pipeline to feed his own<br>
compilation pipeline. However, I believe his approach is currently quite<br>
decoupled from GHC. This may or may not complicate the ability to<br>
integrate with the rest of the ecosystem (e.g. Cabal; Csaba, perhaps you could<br>
comment here?)<br>
<br>
<br>
><br>
> I read SPJs paper on Implementing Lazy Functional Languages on Stock<br>
> Hardware: The Spineless Tagless G-machine<br>
> <<a href="https://www.microsoft.com/en-us/research/publication/implementing-lazy-functional-languages-on-stock-hardware-the-spineless-tagless-g-machine/" rel="noreferrer" target="_blank">https://www.microsoft.com/en-us/research/publication/implementing-lazy-functional-languages-on-stock-hardware-the-spineless-tagless-g-machine/</a>><br>
> which<br>
> implemented STG in C and whilst it wasn't trivial, it didn't seem<br>
> stupendously complex (even I managed to roughly follow it). I thought to<br>
> myself also, implementing this in .NET would be even easier because I can<br>
> hand off garbage collection to the .NET runtime so there's one less thing<br>
> to worry about. I also, initially, don't care _too_ much about performance.<br>
><br>
Indeed, STG itself is reasonably straightforward. Implementing tagged<br>
unions in the CLR doesn't even look that hard (F# does it, afterall).<br>
However, there are plenty of tricky bits:<br>
<br>
 * You still need to implement a fair amount of RTS support for a full<br>
   implementation (e.g. light-weight threads and STM)<br>
<br>
 * You need to shim-out or reimplement the event manager in `base`<br>
<br>
 * What do you do about the many `foreign import`s used by, e.g.,<br>
   `text`?<br>
<br>
 * How do you deal with `foreign import`s elsewhere?<br>
<br>
> Of course, there's probably a whole bunch of nuance. One actually needs to,<br>
> for example, represent all the complexities of GADTs into object orientated<br>
> classes, maybe converting sum types to inheritance hierarchies with Visitor<br>
> Patterns. And also you'd actually have to make sure to do one's best to<br>
> ensure exposed Haskell functions look like something sensible.<br>
><br>
> So I guess, given I have a bit of an interest here, what would be the best<br>
> approach if I wanted to help GHC develop more backends and into an<br>
> architecture where people can add backends without forking GHC? Where could<br>
> I start helping that effort? Should I contact "Csaba Hruska" and get<br>
> involved in GRIN? Or is there something that I can start working on in GHC<br>
> proper?<br>
><br>
At the moment we rather lack a good model for how new backends should<br>
work. There are quite a few axes to consider here:<br>
<br>
 * How do core libraries (e.g. `text`) work? Various choices are:<br>
<br>
   * Disregard the core libraries (along with most of Hackage) and just<br>
     take the Haskell language<br>
<br>
   * Reimplement many of the core libraries in the target language (e.g.<br>
     as done by GHCJS)<br>
<br>
 * How does the compiler interact with the Haskell build toolchain (e.g.<br>
   Cabal)? Choices are:<br>
<br>
   * Disregard the Haskell build toolchain. My (possibly incorrect)<br>
     understanding is this is what GRIN does.<br>
<br>
   * Implement something that looks enough like GHC to fool Cabal.<br>
<br>
   * Upstream changes into Cabal to make your new compiler a first-class<br>
     citizen. This is what GHCJS did.<br>
<br>
 * How does the backend interact with GHC? Choices:<br>
<br>
   * The GRIN model: Run the GHC pipeline and serialise the resulting IR<br>
     (in the case of GRIN, STG) to a file to be slurped up by another process<br>
<br>
   * The Clash/GHCJS model: Implement the new compiler as an executable<br>
     linking against the GHC API. <br>
<br>
   * The frontend plugin model: For many years now GHC has had support<br>
     for "front-end plugins". This mechanism allows a plugin to<br>
     fundamentally redefine what the GHC executable does (e.g.<br>
     essentially adding a new "mode" to GHC, a la --interactive or<br>
     --make). It's not impossible that one could use this to implement a<br>
     new backend.<br>
<br>
   * A hypothetical "backend plugin" mechanism: Currently GHC has no<br>
     means of introducing plugins after the Core pipeline. Perhaps this<br>
     should change? This would need a fair amount of design as aspects<br>
     of the backend currently tend to leak into GHC's frontend. John<br>
     Ericson has been keen on cleaning this up.<br>
<br>
Anyways, lots to think about.<br>
<br>
> Considering that I've been playing around with Haskell since 2002, and I'd<br>
> like to actually get paid to write it at some point in my career, and I<br>
> have an interest in this area, perhaps this is a good place to start, and<br>
> actually helping to develop a pluggable backend architecture for GHC may be<br>
> more useful for more people over the long term than trying to hack up an<br>
> existing GHC to support 32 bit Windows XP, a battle I suspect will have to<br>
> be refought every time a new GHC version is released given the current<br>
> structure of GHC.<br>
><br>
Yes, 32-bit Windows support sounds like something of a futile exercise.<br>
If the problem were *merely* GHC, then perhaps it would be possible.<br>
However, the entirety of the open-source compiler community struggles<br>
with Windows. For instance, binutils struggles to support even 64-bit<br>
Windows without regressions (e.g. see<br>
<a href="https://gitlab.haskell.org/ghc/ghc/-/issues/16780#note_342715" rel="noreferrer" target="_blank">https://gitlab.haskell.org/ghc/ghc/-/issues/16780#note_342715</a>).<br>
<br>
Cheers,<br>
<br>
- Ben<br>
<br>
_______________________________________________<br>
ghc-devs mailing list<br>
<a href="mailto:ghc-devs@haskell.org" target="_blank">ghc-devs@haskell.org</a><br>
<a href="http://mail.haskell.org/cgi-bin/mailman/listinfo/ghc-devs" rel="noreferrer" target="_blank">http://mail.haskell.org/cgi-bin/mailman/listinfo/ghc-devs</a><br>
</blockquote></div>