I’m having trouble understanding how Haskell (GHC) compiles programs, and how those programs are run.
- GHC is the canonical example of a nontrivial program written in Haskell. However, parts of GHC seem not to be written in Haskell, namely the runtime environment (in C/C–). Why is that? Performance reasons? (I am aware of this site and its friends, but cannot make much sense of them.)
- Speaking of the runtime environment: Why does a compiled language need one? Shouldn’t the compiled program be machine code and nothing else? From what I understand, a runtime environment is somewhat similar to a virtual machine or a bytecode interpreter, that deals with some form of meta code and does the actual calculations based on that. So: what does the GHC runtime do exactly, and why is it necessary in the first place?
- Concerning the FFI: How are C calls handled? Initially, I thought using the FFI generates a single executable where Haskell and C are compiled together. However, I read multiple times that GHC programs kind of do a call out of the program to the C function. This is especially relevant to understand the problem the FFI has with parallel programming. So: how are FFI functions different from normal Haskell functions?
To compile and execute a programming language on stock hardware you need a number of things:
C, Java, and GHC Haskell are examples of such systems. In the case of GHC, the entire architecture is described here. The pieces are also described individually, and in detail.
The runtime services (aka “the GHC runtime”) are described over several papers: