Haskell 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

Если вы сейчас запустите эту программу на 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 (внешний) путчар объявляется дважды, но второй раз с именем путчар1. У меня есть хорошее представление о том, почему это так, но не очень хорошо для общего подхода. Т.е. я не хочу помещать все внутри одного гигантского CodeGenModule.

Это подводит меня к другой связанной проблеме. Подходит ли привязка LLVM-Haskell для построения серверной части компилятора. Возможно, с разумным решением вышеупомянутого - я могу найти способ использовать это... но кажется, что проще просто написать код ИК...

1 ответ

Решение

Ты звонишь newNamedFunction "putchar" внутри CodeGenModule монада дважды, что, очевидно, имеет побочный эффект от добавления putchar в модуль дважды. Тот факт, что это приводит к двум объявлениям вместо ошибки, вероятно, является ошибкой, пожалуйста, рассмотрите возможность сообщения об этом. Чтобы это исправить, просто сделайте 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
Другие вопросы по тегам