Haskell LLVM中的Segfault - 通用代码生成

时间:2014-06-21 22:10:12

标签: haskell llvm

我正在尝试跟随LLVM bindings教程here,然后遇到段错误。以下代码的工作原理 ,因为它会将模块标题打印到output.ll,但它也会在某处发生段错误。

module Main where

import Control.Monad.Error
import LLVM.General.Module
import LLVM.General.Context
import qualified LLVM.General.AST as AST

--Create and write out an empty LLVM module
main :: IO ()
main = writeModule (AST.defaultModule { AST.moduleName = "myModule" })

outputFile :: File
outputFile = File "output.ll"

writeModule :: AST.Module -> IO ()
writeModule mod = withContext $ (\context ->
                    liftError $ withModuleFromAST context mod (\m ->
                      liftError $ writeLLVMAssemblyToFile outputFile m))

--perform the action, or fail on an error
liftError :: ErrorT String IO a -> IO a
liftError = runErrorT >=> either fail return

我怀疑这与链接教程中的以下提示有关:

  

记住不要传递或尝试使用括号外的资源非常重要,因为这会导致未定义的行为和/或段错误。

我认为在这种情况下,“括号”是由withContext函数实现的,这似乎应该处理所有内容。

如果我将writeModule的定义更改为

writeModule mod = do assembly <- (withContext $ (\context ->
                       liftError $ withModuleFromAST context mod moduleLLVMAssembly))
                    putStrLn assembly

也就是说,不是写入文件而是打印出LLVM程序集的字符串表示,而不是抛出段错误。

有没有人有这些绑定的经验?我也有兴趣知道我引用警告的失败案例。也就是说,如何“忘记”不使用括号外的资源?所有似乎需要Context的函数都需要一个。这种资源范围问题究竟不是Haskell擅长处理的问题吗?

版本信息:

  • llvm-general-3.4.3.0
  • LLVM version 3.4
  • Default target: x86_64-apple-darwin13.2.0

1 个答案:

答案 0 :(得分:3)

如果您共享LLVM和cabal环境会有所帮助,LLVM因为与其自身向后兼容而臭名昭着,因此使用最新版本的绑定可能存在问题。

幕后writeLLVMAssemblyToFile正在使用C ++调用来执行文件IO操作,并推测它在最终确定文件资源时持有对LLVM模块的引用。

尝试使用moduleString将模块渲染为String,然后仅提升到IO monad以从Haskell调用writeFile,而不是通过C ++进行写入。

import LLVM.General.Context
import LLVM.General.Module as Mod
import qualified LLVM.General.AST as AST

import Control.Monad.Error

main :: IO ()
main = do
  writeModule (AST.defaultModule { AST.moduleName = "myModule" })
  return ()

writeModule :: AST.Module -> IO (Either String ())
writeModule ast =
  withContext $ \ctx ->
    runErrorT $ withModuleFromAST ctx ast $ \m -> do
      asm <- moduleString m
      liftIO $ writeFile "output.ll" asm

根据我的经验,绑定仍然可能相当脆弱,如果问题仍然存在,您应该在issue tracker上询问。

编辑:这是随后修复的旧版本的解决方法。请参阅:https://github.com/bscarlet/llvm-general/issues/109