3

I'm trying to use Haskell's LLVM bindings to create a very simple 'hello world' standalone app. The idea is, when I run my Haskell application, it will spit out some bytecode that can in turn be run and will output "hello world!"

-- hellofunc prints out "hello world"
hellofunc :: CodeGenModule (Function (IO ()))


_main :: (Function (IO ())) -> CodeGenModule (Function (IO ()))
_main func = createNamedFunction ExternalLinkage "main" $ do
        call func
        ret ()

main = writeCodeGenModule "hello.bc" (liftA _main hellofunc)

When I run this, I see the following error:

'main' function not found in module.

I'm explicitly creating the main function using createNamedFunction. What am I missing?

Vlad the Impala
  • 15,572
  • 16
  • 81
  • 124
  • You can try to `llvm-dis hello.bc` to see what's wrong with `@main`. – arrowd Feb 24 '12 at 09:17
  • It gets written as _fun2. I'm trying to understand if I'm using `createNamedFunction` incorrectly or there is a bug in that function. – Vlad the Impala Feb 24 '12 at 17:12
  • Btw. identifiers starting with an underscore like "_main" mark unused identifiers. GHC will not warn if they are not used. Thus, better only mark functions as unused if they are actually unused. See also: https://ghc.haskell.org/trac/ghc/ticket/4959 – Lemming Aug 02 '16 at 08:32

1 Answers1

3

The problem lies in the use of liftA or fmap rather than =<<. It becomes more obvious (a build break) when type signatures are used. _main is not evaluated in CodeGenModule in the liftA case, and so it doesn't appear in the output file.

It may be reasonable to modify writeCodeGenModule to take CodeGenModule () instead of CodeGenModule a. It makes life just a bit more complicated for users of the LLVM JIT but would help prevent errors such as this one.

import Control.Applicative
import LLVM.Core
import LLVM.ExecutionEngine
import LLVM.Util.File

--
-- hellofunc prints out "hello world"
hellofunc :: CodeGenModule (Function (IO ()))
hellofunc = createNamedFunction ExternalLinkage "hello" $ do
  ret ()

_main :: (Function (IO ())) -> CodeGenModule (Function (IO ()))
_main func = createNamedFunction ExternalLinkage "main" $ do
  call func
  ret ()

generateModuleBind :: CodeGenModule (Function (IO ()))
generateModuleBind = _main =<< hellofunc

-- Couldn't match expected type `Function (IO ())'
--             with actual type `CodeGenModule (Function (IO ()))'
--
-- this is the desired type:
-- generateModuleLiftA :: CodeGenModule (Function (IO ()))
--
-- but this is the actual type:
generateModuleLiftA :: CodeGenModule (CodeGenModule (Function (IO ())))
generateModuleLiftA = liftA _main hellofunc

main :: IO ()
main = writeCodeGenModule "hello.bc" generateModuleBind
Nathan Howell
  • 4,627
  • 1
  • 22
  • 30
  • 2
    Argh, thank you. The tl;dr for others looking for the answer: I used `CodeGenModule` as an Applicative instead of a Monad. I replaced `liftA` with an infix `=<<` and now everything works fine. – Vlad the Impala Feb 26 '12 at 06:23