2013-04-24 65 views
5

我与LLVM-Haskell绑定的问题是我得到“重复”名称。我认为解释我的问题的最好方法是用一个小的具体例子(注意这个例子是人为设计的,对于这样一个小例子,它有简单的方法......但它确实指出了我的问题)。Haskell LLVM - 创建重复函数

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 

如果你现在运行这个程序哈斯克尔(你需要一些像进口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绑定是否适合构建编译器的后端。也许有一个合理的解决方案上面 - 我可以找出一种方法来使用它...但似乎更简单,只需手写红外代码...

回答

3

你打电话给newNamedFunction "putchar"里面的CodeGenModule monad两次,这明显具有将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 
+0

这是一个不错的解决方案。 – 2013-04-24 22:46:29

+0

如果您要求库声明“putchar”函数两次,则声明两次。这不是一个错误。这里提出的解决方案是正确的。如果你有更多的功能需要维护,你可以使用getModuleValues获取模块的声明功能。请参阅llvm:example/Vector.hs。但要小心这个错误:https://github.com/bos/llvm/issues/78 – Lemming 2016-08-02 08:10:59