2013-04-24 12 views
5

Problem, który mam z powiązaniami LLVM-Haskell, polega na tym, że otrzymuję "zduplikowane" nazwy. Myślę, że najlepszym sposobem na wyjaśnienie mojego problemu jest mały konkretny przykład (zauważ, że przykład jest wymyślny, a na tak mały przykład są proste sposoby na jego obejście ... jednak wskazuje to na mój problem).Haskell LLVM - Powielone funkcje utworzone

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 

Jeśli teraz uruchomić ten program Haskell (będziesz potrzebować import jak Data.Int/Word i LLVM.Core), można uzyskać następujące dane wyjściowe.

; 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 
} 

Problem polega na tym, że w IR, (zewnętrzna) putchar jest zadeklarowana dwukrotnie, ale po raz drugi z nazwą putchar1. Mam dobre wyczucie tego, dlaczego tak jest, ale nie ma to sensu dla dobrego, ogólnego sposobu obejścia tego. To znaczy. Nie chcę wrzucać wszystkiego do jednego gigantycznego CodeGenModule.

To doprowadza mnie do kolejnego pokrewnego problemu. Czy powiązanie LLVM-Haskell jest odpowiednie do budowania zaplecza kompilatora. Być może rozsądnym rozwiązaniem powyższego - mogę znaleźć sposób na jego użycie ... ale wydaje się prostsze po prostu ręczne napisanie kodu IR ...

Odpowiedz

3

Dzwonisz pod numer newNamedFunction "putchar" w monadę CodeGenModule , co oczywiście ma efekt uboczny dodania do modułu dwukrotnie: putchar. Fakt, że powoduje to dwa oświadczenia zamiast błędu, jest prawdopodobnie błędem, proszę rozważyć zgłoszenie go. Aby to naprawić, po prostu ustaw parametr putc jako parametr simple i easy. Będzie to wyglądało mniej więcej w następujący sposób (nie testowane):

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

To dobre rozwiązanie. –

+0

Jeśli poprosisz bibliotekę o dwukrotne zadeklarowanie funkcji "putchar", zostanie ona zadeklarowana dwukrotnie. To nie jest błąd. Proponowane tutaj rozwiązanie jest właściwe. Jeśli masz więcej funkcji do utrzymania, możesz użyć getModuleValues, aby uzyskać deklarowane funkcje modułu. Zobacz llvm: example/Vector.hs. Ale uważaj na ten błąd: https://github.com/bos/llvm/issues/78 – Lemming