Can't output from .hs to .hc with GHC in Haskell
Asked Answered
B

1

5

I was intrigued when I heard that GHC can output a file to C .

The Glasgow Haskell Compiler (GHC) compiles to native code on a number of different architectures—as well as to ANSI C—using C-- as an intermediate language.

So I installed the Haskell Platform and created a simple .hs file.

main = putStrLn "Hello, World!"

And according to the manual.

-C Stop after generating C (.hc file)

Now I run the command.

ghc -C test.hs

But it doesn't create a .hc file, nor does it stop mid-compilation.

$ ls
test.exe  test.hi  test.hs  test.o
Bartley answered 13/8, 2013 at 11:0 Comment(4)
Have you tried passing -fvia-C in addition to -C? IIRC GHC doesn't use the C backend by default (it can directly generate assemblies for various machine, including llvm).Twelvemo
I got a warning saying that "The -fvia-C flag does nothing; it will be removed in a future GHC release". Augustss, why would I be disappointed?Bartley
It looks entirely unlike C code a human would write. It's basically unreadable. It's also not as efficient as you'd hope. The only way it gets efficient is by mangling the assembly code generated by the C compiler.Vinitavinn
Afaik, GHC has booted the C backend completely, including scrapping C generation from the compiler. If you want to, you can look at the C-- (--ddump-cmm) or the assembly (-ddump-asm) but I'm afraid that's as close as you get. GHC generates really weird code, but you can learn to make sense of "GHC-style" imperative code.Wind
C
8

If you want to understand how Haskell programs execute at a low level, it is probably best to study Core instead (-ddump-simpl). After that point the code becomes really hard to read even for experts. The main reason is that GHC's stack and heap management gets hard-coded. As a result, low-level generated Haskell code is basically a giant mess of tiny procedures, doing complex pointer arithmetic before finishing with indirect jumps to unknown locations. The worst kind of spaghetti code.

To provide something of an actual answer - you could generate C by going over the LLVM backend:

ghc -ddump-llvm -ddump-to-file hello_world.hs
opt -O2 hello_world.dump-llvm | llc -O2 -march c -o hello_world.c

But the result will just illustrate the point. Even a trivial fib function will take about 80 lines of code.

In case you are really interested in the gory details, I would recommend reading through this blog post by Edward Z. Yang. He basically walks through the whole compilation pipeline involved in translating a simple piece of Haskell code.

Crosby answered 13/8, 2013 at 18:7 Comment(4)
Awesome, got it in C++. Transforms to this apparently :D pastebin.com/r4Dy0ZD5Bartley
Note that the C++ code you pasted is actually a generator for the final machine code (using LLVM as a library). But trying to run it is futile in any case, trust me...Crosby
is this still expected to work with ghc 7.10? opt gives an error on my .dump-llvm file "expected top-level entity"Tolmach
This is probably about the extra "==..." markers and dates that the dump adds. You will have to remove them to make it valid LLVM code. Alternatively, do ghc ... -fllvm -keep-tmp-files -v and use the file name ending in .ll file from the verbose output.Crosby

© 2022 - 2024 — McMap. All rights reserved.