2015-11-23 16 views
16

Tôi muốn có thể gọi mã LLVM từ Haskell mà không cần phải thực hiện cuộc gọi đầy đủ chức năng. Ví dụ:Chạy đầu ra LLVM của GHC thông qua liên kết bitcode LLVM đầu tiên

-- Main.hs -- 

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

import GHC.Exts(Word(W#)) 
import GHC.Prim(Word#) 

foreign import ccall llvminc :: Word# -> Word# 

main = do 
    line1 <- getLine 
    let !(W# x1) = read line1 
    let !r1 = llvminc x1 
    print (W# r1) 


-- funcs.ll -- 

define fastcc i64 @llvminc(i64 inreg %x) { 
    %r = add i64 %x, 1 
    ret i64 %r 
} 

tôi có thể biên dịch và liên kết này để tạo ra một chức năng thực thi bằng cách chạy:

ghc -O2 -fllvm Main.hs funcs.ll 

Trên thực tế, thậm chí loại bỏ -fllvm vẫn dẫn đến một chức năng thực thi, ví dụ

ghc -O2 Main.hs funcs.ll 

Dẫn tôi nghi ngờ mạnh mẽ GHC là liên kết những tập tin riêng biệt trong cả hai trường hợp sử dụng C liên kết bình thường.

Thật vậy, khi tôi điều tra sản lượng trung bình sử dụng:

ghc -O2 -fllvm -keep-s-files Main.hs funcs.ll 

tôi thấy sau trong Main.s:

callq suspendThread 
movq %rax, %rbp 
movq %rbx, %rdi 
callq llvminc 
movq %rax, %rbx 
movq %rbp, %rdi 
callq resumeThread 

nào một lần nữa cho thấy rằng GHC chỉ là yêu cầu LLVM để biên dịch các tập tin một cách riêng biệt và sau đó nó chỉ gửi các kết quả đến trình liên kết hệ thống, mà sẽ không inline các cuộc gọi. Thay vào đó, tôi muốn GHC gửi các tệp LLVM ban đầu (cả GHC và người dùng được chỉ định) đến llvm-link, không giống như trình liên kết hệ thống, chỉ cần kết hợp nhiều tệp bitcoin LLVM vào một tệp bitcoin LLVM. Sẽ tốt nhất nếu kết quả này sau đó được biên dịch thành tệp đối tượng mã nguồn gốc và được gửi đến trình liên kết hệ thống, thay vì nhiều tệp đối tượng được gửi đến trình liên kết hệ thống.

Thật vậy, khi tôi đã cố gắng này một cách thủ công, lắp ráp các .ll file có thể đọc được con người để LLVM .bc bitcode, llvm-link ing các bitcode kết quả, sau đó tháo bitcode như vậy:

llvm-as Main.ll 
llvm-as funcs.ll 
llvm-link funcs.bc Main.bc -o combined.bc 
llvm-dis combined.bc 

Tôi tìm thấy sau trong kết quả Mã LLVM

%ln59M = add i64 %ln59L, 1 

trực tiếp sau khi gọi để đọc, không có "cuộc gọi" hoặc trả lại. Chức năng thực tế vẫn còn trong LLVM, nhưng không được nén. Vì vậy, tôi đã cố gắng hướng dẫn GHC liên kết với liên kết LLVM bằng cách thêm -pgml llvm-link vào dòng lệnh, nhưng điều này thất bại một cách ngoạn mục, với llvm-link ném lại nhiều lỗi về các tùy chọn không xác định. Điều này là không đáng ngạc nhiên, vì llvm-link không phải là một liên kết thực sự, nó chỉ kết hợp các tệp LLVM.

Vì vậy, có cách nào để GHC gửi tất cả các tệp LLVM trung gian qua liên kết LLVM để bật tối ưu hóa đa cấp ở cấp LLVM không?

Trả lời