【问题标题】:Haskell LLVM -- Duplicate Functions CreatedHaskell LLVM——创建了重复的函数
【发布时间】:2013-04-17 09:34:52
【问题描述】:

我在使用 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。我很清楚为什么会这样,但对于解决这个问题的一般方法来说不是一个很好的感觉。 IE。我不想把所有东西都放在一个巨大的 CodeGenModule 中。

这让我想到了另一个相关的问题。 LLVM-Haskell 绑定是否适合构建编译器的后端。也许对上述问题有一个合理的解决方案——我可以想出一种使用它的方法……但手写 IR 代码似乎更简单……

【问题讨论】:

    标签: haskell code-generation llvm dsl dsl-tools


    【解决方案1】:

    您在 CodeGenModule monad 中调用了 newNamedFunction "putchar" 两次,这显然具有将 putchar 添加到模块两次的副作用。这导致两个声明而不是错误的事实可能是一个错误,请考虑报告它。要解决此问题,只需将putc 设为simpleeasy 的参数。这看起来大致如下(未经测试):

    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。但要小心这个错误:github.com/bos/llvm/issues/78
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-12-28
    • 2019-01-25
    • 2017-01-11
    • 1970-01-01
    • 2021-12-04
    相关资源
    最近更新 更多