Haskell LLVM -- 重复创建函数

5
我在使用LLVM-Haskell绑定时遇到了“重复”名称的问题。我认为最好的方法是用一个小的具体例子来解释我的问题(请注意,这个例子是人为的,对于这样一个小的例子有简单的解决方法...然而,它确实指出了我的问题)。
putc :: TFunction (Int32 -> IO Word32)
putc = newNamedFunction ExternalLinkage "putchar"

simple :: TFunction (Int32 -> IO Word32)
simple = do
    internalputc <- putc
    createNamedFunction ExternalLinkage "simple" $ \x -> do
        call internalputc x
        call internalputc x
        ret (0 :: Word32)

easy :: TFunction (Int32 -> IO Word32)
easy = do 
    internalputc <- putc
    internalsimple <- simple
    createNamedFunction ExternalLinkage "easy" $ \x -> do
        call internalsimple x
        y <- add x (42 :: Int32)
        call internalputc y
        ret (0 :: Word32)

main :: IO ()
main = do
    m <- newNamedModule "Main"
    defineModule m easy
    writeBitcodeToFile "SillyLib" m

如果您现在运行这个Haskell程序(你需要一些导入,如Data.Int/Word和LLVM.Core),您将得到以下输出。
; ModuleID = 'SillyLib'

declare i32 @putchar(i32)

declare i32 @putchar1(i32)

define i32 @simple(i32) {
_L1:
  %1 = call i32 @putchar1(i32 %0)
  %2 = call i32 @putchar1(i32 %0)
  ret i32 0
}

define i32 @easy(i32) {
_L1:
  %1 = call i32 @simple(i32 %0)
  %2 = add i32 %0, 42
  %3 = call i32 @putchar(i32 %2)
  ret i32 0
}

问题在于在IR中,(外部) putchar 声明了两次,但第二次使用了 putchar1 的名称。我知道这是为什么,但没有一个好的通用解决方法。也就是说,我不想把所有东西都放在一个巨大的 CodeGenModule 中。
这带我到另一个相关问题。LLVM-Haskell 绑定是否适合构建编译器的后端?也许有了上述问题的合理解决方案,我可以想出一种使用它的方法...但手写 IR 代码似乎更简单。
1个回答

3
您在 CodeGenModule 单元内两次调用 newNamedFunction "putchar",这显然会产生将 putchar 添加到该模块两次的副作用。事实上,这会导致声明两次而不是出现错误,很可能是一个 bug,请考虑报告它。要解决这个问题,只需将 putc 设为 simple 和 easy 的参数即可。具体做法如下(未经测试):
simple :: Function (Int32 -> IO Word32) -> TFunction (Int32 -> IO Word32)
simple putc =
    createNamedFunction ExternalLinkage "simple" $ \x -> do
        call putc x
        call putc x
        ret (0 :: Word32)

easy :: Function (Int32 -> IO Word32) -> Function (Int32 -> IO Word32) 
        -> TFunction (Int32 -> IO Word32)
easy putc simple' =
    createNamedFunction ExternalLinkage "easy" $ \x -> do
        call simple' x
        y <- add x (42 :: Int32)
        call putc y
        ret (0 :: Word32)

main :: IO ()
main = do
    m <- newNamedModule "Main"
    defineModule m $ do
        putc <- newNamedFunction ExternalLinkage "putchar"
        simple' <- simple putc
        easy putc simple'
    writeBitcodeToFile "SillyLib" m

如果您要求库声明函数“putchar”两次,它将被声明两次。这不是一个错误。这里建议的解决方案是正确的方式。如果您有更多要维护的函数,可以使用getModuleValues来获得模块中声明的函数。请参见llvm:example/Vector.hs。但是请注意这个错误:https://github.com/bos/llvm/issues/78 - Lemming

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接