且构网

分享程序员开发的那些事...
且构网 - 分享程序员编程开发的那些事

当在Haskell中使用llvm绑定时,模块中找不到'main'函数

更新时间:2023-11-10 18:58:40

问题在于使用 liftA fmap 而不是 = 。当使用类型签名时,它变得更加明显(构建中断)。 _main不是在liftA情况下的CodeGenModule中计算的,所以它不会出现在输出文件中。

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.

修改可能是合理的, writeCodeGenModule 取得 CodeGenModule()而不是 CodeGenModule a 。它使得LLVM JIT用户的生活变得更加复杂,但是可以帮助防止出现这种错误。

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