2015-11-25 25 views
5

Sto provando a effettuare una chiamata a un prim di importazione straniera scritto in LLVM, utilizzando le idee da questo post ma continuo a ricevere segfaults. Ecco cosa ho attualmente.foreign import prim call a LLVM

In Haskell

{-# LANGUAGE GHCForeignImportPrim #-} 
{-# LANGUAGE MagicHash, UnboxedTuples #-} 
{-# LANGUAGE ForeignFunctionInterface, UnliftedFFITypes #-} 

import GHC.Prim 

foreign import prim "primllvm" primllvm :: Word# -> Word# -> (# Word#, Word# #) 

E nel .ll file di

define cc10 void @primllvm(i64* %baseReg, i64* %sp, i64* %hp, i64* %buffer, i64 %length, i64 %r3, i64 %r4, i64 %r5, i64 %r6, i64* %spLim, float %f1, float %f2, float %f3, float %f4, double %d1, double %d2) 
{ 
    %fp = bitcast i64* %sp to void(i64*, i64*, i64*, i64*, i64, i64, i64, i64, i64, i64*, float, float, float, float, double, double)* 
    tail call cc10 void %fp(i64* %baseReg, i64* %sp, i64* %hp, i64* %buffer, i64 %length, i64 %r3, i64 %r4, i64 %r5, i64 %r6, i64* %spLim, float %f1, float %f2, float %f3, float %f4, double %d1, double %d2) noreturn; 
    ret void 
} 

In teoria credo che questo dovrebbe semplicemente tornare è argomenti come una tupla, ma come ho detto, solo segfaults. Qualsiasi aiuto per ottenere questo lavoro apprezzato.

risposta

2

ho trovato due problemi con il tuo codice:

  1. Anche se la firma dice si passa in due Word# argomenti sul lato Haskell, sul lato LLC avete i64* %buffer e i64 %length (tipo di nota di %buffer è un tipo di puntatore!).

  2. C'è un ulteriore livello di riferimento indiretto nello sp: sp punti nello stack e la parte superiore dello stack è il puntatore di continuazione. Il tuo codice sembra provare a interpretare il puntatore dello stack come il puntatore della funzione stesso.

Non so LLVM, ho appena ricostruito insieme, cercando in post del blog si è collegato, sapendo GHC, e giocare; così alla fine ho dovuto ricorrere a guardare clang s' uscita, quindi ci potrebbe essere un modo più efficiente per gestire 2 #, ma in ogni caso qui è una versione che funziona e implementa lo scambio di due numeri a 64 bit:

define cc10 void @primllvm(i64* %baseReg, i64* %sp, i64* %hp, 
          i64 %x, i64 %y, i64 %r3, i64 %r4, i64 %r5, i64 %r6, 
          i64* %spLim, 
          float %f1, float %f2, float %f3, float %f4, 
          double %d1, double %d2) 
{ 
    %1 = getelementptr inbounds i64* %sp, i64 0 
    %2 = load i64* %1, align 8 
    %cont = inttoptr i64 %2 to void (i64*, i64*, i64*, 
            i64, i64, i64, i64, i64, i64, 
            i64*, 
            float, float, float, float, 
            double, double)* 

    tail call cc10 void %cont(i64* %baseReg, i64* %sp, i64* %hp, 
          i64 %y, i64 %x, i64 %r3, i64 %r4, i64 %r5, i64 %r6, 
          i64* %spLim, 
          float %f1, float %f2, float %f3, float %f4, 
          double %d1, double %d2) noreturn 
    ret void 
} 

codice Haskell per il test:

{-# LANGUAGE GHCForeignImportPrim #-} 
{-# LANGUAGE MagicHash, UnboxedTuples, BangPatterns #-} 
{-# LANGUAGE ForeignFunctionInterface, UnliftedFFITypes #-} 

import GHC.Prim 
import GHC.Word 

foreign import prim "primllvm" primllvm :: Word# -> Word# -> (# Word#, Word# #) 

main :: IO() 
main = do 
    let !(W# w1) = 12 
     !(W# w2) = 34 
     !(# w1', w2' #) = primllvm w1 w2 
     x = W# w1' 
     y = W# w2' 
    print (x, y) 

costruzione:

llc -filetype=obj -o Define.o Define.ll 
ghc --make Use.hs Define.o