Haskell LLVM - 创建的重复功能

Jon*_*her 5 dsl haskell code-generation dsl-tools llvm

我对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
Run Code Online (Sandbox Code Playgroud)

如果您现在运行此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
}
Run Code Online (Sandbox Code Playgroud)

问题是在IR中,(外部)putchar被声明两次,但第二次使用名称putchar1.我很清楚为什么会这样,但对于一个很好的通用方法来说,这并不是很好的意义.即我不想把一切都放在一个巨大的CodeGenModule里面.

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

Mik*_*kov 3

您在 monadnewNamedFunction "putchar"内部调用两次,这显然会产生两次添加到模块CodeGenModule的副作用。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
Run Code Online (Sandbox Code Playgroud)