Cara membuat kompilasi dentang ke llvm IR

150

Saya ingin dentang untuk mengkompilasi C/C++kode saya untuk LLVMbytecode daripada biner dieksekusi. Bagaimana saya bisa mencapainya? Dan jika saya mendapatkan LLVMbytecode, bagaimana saya bisa membawanya ke kompilasi lebih lanjut ke biner yang dapat dieksekusi.

Pada dasarnya saya ingin menambahkan beberapa kode saya sendiri ke LLVMbytecode sebelum dikompilasi ke binary executable.

pythonic
sumber
Saya kira itu disebut sebagai LLVM bitcode
PreeJackie

Jawaban:

204

Diberikan beberapa file C / C ++ foo.c:

> clang -S -emit-llvm foo.c

Menghasilkan foo.llfile IR LLVM.

The -emit-llvmpilihan juga dapat dikirimkan ke compiler front-end langsung, dan tidak pengemudi dengan cara -cc1:

> clang -cc1 foo.c -emit-llvm

Diproduksi foo.lldengan IR. -cc1menambahkan beberapa opsi keren seperti -ast-print. Lihat -cc1 --helpdetail lebih lanjut.


Untuk mengkompilasi LLVM IR lebih lanjut ke perakitan, gunakan llcalat ini:

> llc foo.ll

Diproduksi foo.sdengan perakitan (default ke arsitektur mesin tempat Anda menjalankannya). llcadalah salah satu alat LLVM - di sini adalah dokumentasinya .

Eli Bendersky
sumber
7
Apa yang dilakukan -S di sini?
meawoppl
13
@meawoppl: -S seperti di gcc mengatakan memancarkan perakitan tekstual daripada biner yang dirakit
Eli Bendersky
Ahha. Saya mengalami kesulitan menemukan apa pun dalam dokumen tentang hal itu. Aman untuk berasumsi bahwa banyak bendera dalam struktur flag clang mirror gcc?
meawoppl
@EliBendersky Apakah Anda tahu cara mengkompilasi beberapa file .c dan .h menjadi satu IR yang dapat dibaca manusia sehingga saya dapat menjalankan IR menggunakan 'lli theIrFile'? Terima kasih
cache
1
@cache: kompilasi masing-masing ke dalam file IR sendiri dan kemudian gunakan linker LLVM untuk menggabungkan
Eli Bendersky
20

Menggunakan

clang -emit-llvm -o foo.bc -c foo.c
clang -o foo foo.bc
Christoph
sumber
9
Saya akan merekomendasikan untuk menjaga makna ekstensi tetap utuh. TKI, .oharus merujuk ke file objek biner, .ske file rakitan, dan sesuatu yang lain (berdasarkan konvensi .ll) ke file IR LLVM. Kalau tidak mudah bingung. Dentang / LLVM sekarang tidak memiliki tautan sendiri untuk objek biner (meskipun satu masih dalam pengerjaan). Linker LLVM llvm-ldhanya menggabungkan beberapa file IR menjadi satu
Eli Bendersky
1
@EliBendersky: Anda benar di mana ekstensi file yang bersangkutan - dan frontend dentang sebenarnya melakukan hal yang benar jika .bcdigunakan; juga, ingatlah bahwa llvm-lddapat bertindak sebagai antarmuka untuk toolchain sistem, yaitu jawaban saya sebelumnya menggunakan llvm-ld -nativeharus bekerja seperti yang diharapkan ....
Christoph
1
@rickfoosusa: berfungsi untuk saya - foo.bcadalah file bitcode LLVM
Christoph
1
Bekerja untuk saya: clang -emit-llvm -o test.bc -c test.c && file test.bc: test.bc: LLVM IR bitcode.
ntc2
18

Jika Anda memiliki banyak file sumber, Anda mungkin sebenarnya ingin menggunakan optimasi waktu-tautan untuk menghasilkan satu file bitcode untuk seluruh program. Jawaban lain yang diberikan akan menyebabkan Anda berakhir dengan file bitcode untuk setiap file sumber.

Sebagai gantinya, Anda ingin mengompilasi dengan optimasi tautan-waktu

clang -flto -c program1.c -o program1.o
clang -flto -c program2.c -o program2.o

dan untuk langkah penghubung terakhir, tambahkan argumen -Wl, -plugin-opt = also-emit-llvm

clang -flto -Wl,-plugin-opt=also-emit-llvm program1.o program2.o -o program

Ini akan memberikan Anda berdua program dikompilasi dan bitcode sesuai dengan itu (program.bc). Anda kemudian dapat memodifikasi program.bc dengan cara apa pun yang Anda suka, dan mengkompilasi ulang program yang dimodifikasi kapan saja dengan melakukan

clang program.bc -o program

meskipun perlu diketahui bahwa Anda perlu menyertakan flag linker yang diperlukan (untuk perpustakaan eksternal, dll) pada langkah ini lagi.

Perhatikan bahwa Anda harus menggunakan penghubung emas agar ini berfungsi. Jika Anda ingin memaksa dentang menggunakan tautan tertentu, buat symlink ke tautan yang bernama "ld" di direktori khusus yang disebut "fakebin" di suatu tempat di komputer Anda, dan tambahkan opsi

-B/home/jeremy/fakebin

untuk setiap langkah yang menghubungkan di atas.

Jeremy Salwen
sumber
13

Jika Anda memiliki banyak file dan Anda tidak ingin harus mengetik setiap file, saya sarankan Anda mengikuti langkah-langkah sederhana ini (saya menggunakan clang-3.8tetapi Anda dapat menggunakan versi lain):

  1. buat semua .llfile

    clang-3.8 -S -emit-llvm *.c
  2. menghubungkannya menjadi satu

    llvm-link-3.8 -S -v -o single.ll *.ll
  3. (Opsional) Optimalkan kode Anda (mungkin beberapa analisis alias)

    opt-3.8 -S -O3 -aa -basicaaa -tbaa -licm single.ll -o optimised.ll
  4. Hasilkan perakitan (menghasilkan optimised.sfile)

    llc-3.8 optimised.ll
  5. Buat yang dapat dieksekusi (bernama a.out)

    clang-3.8 optimised.s
Kiko Fernandez
sumber
Solusi Anda cukup unik: Anda menggunakan "-S" bukan hanya meninggalkannya sebagai keluaran biner. Apakah ada perbedaan antara memiliki "-S" dan tidak memiliki "-S"?
Peter Teoh
@PeterTeoh Saya menggunakan -Sopsi (pada langkah 2), saya menentukan bahwa saya ingin menghasilkan output dalam LLVM IR. Pada dasarnya, letakkan semua file * .ll menjadi satu. Saya melakukan ini untuk memeriksa apakah optimisasi benar-benar mengubah kode, yaitu single.lldan optimised.llsekarang harus terlihat berbeda (berdasarkan kode) dan Anda juga dapat menunjukkan laporan untuk melihat apakah ada perbedaan sama sekali.
Kiko Fernandez
-basicaaaadalah bendera yang salah, -basicaaharus digunakan sebagai gantinya.
anton_rh