Llvm IR'ye clang derlemesi nasıl yapılır


154

Clang'ın C/C++kodumu LLVMikili çalıştırılabilir dosya yerine bayt koduna derlemesini istiyorum . Bunu nasıl başarabilirim? Ve LLVMbayt kodunu alırsam, onu ikili çalıştırılabilir dosyada daha fazla derlemek için nasıl kullanabilirim?

Temel olarak LLVM, ikili yürütülebilir dosyaya derlemeden önce bayt koduna kendi kodumun bir kısmını eklemek istiyorum .


Sanırım buna LLVM bit kodu deniyor
PreeJackie

Yanıtlar:


208

Bazı C / C ++ dosyası verildiğinde foo.c:

> clang -S -emit-llvm foo.c

foo.llLLVM IR dosyası olan üretir .

-emit-llvmSeçeneği de yardımıyla sürücü doğrudan derleyici ön ucuna geçti ve değil edilebilir -cc1:

> clang -cc1 foo.c -emit-llvm

Üretir foo.llIR. -cc1gibi bazı harika seçenekler ekler -ast-print. -cc1 --helpDaha fazla ayrıntı için göz atın .


LLVM IR'yi derlemeye daha fazla derlemek için şu llcaracı kullanın :

> llc foo.ll

Üretir foo.smontaj (makine mimarisi bunu çalıştırmak varsaymak) ile. llcLLVM araçlarından biridir - işte dokümantasyonu .


7
-S burada ne yapar?
meawoppl

14
@meawoppl: -Gcc'deki gibi, birleştirilmiş ikili program yerine metinsel birleştirme yayıyor diyor
Eli Bendersky

Ahha. Belgelerde bununla ilgili bir şey bulmakta zorlanıyordum. Clang mirror gcc bayrak yapısındaki birçok bayrağın olduğunu varsaymak güvenlidir?
meawoppl

@EliBendersky IR'yi 'lli theIrFile' kullanarak çalıştırabilmem için birden fazla .c ve .h dosyasını tek bir insan tarafından okunabilir IR'de nasıl derleyeceğinizi biliyor musunuz? Teşekkürler
önbellek

1
@cache: her birini kendi IR dosyasında derleyin ve birleştirmek için LLVM bağlayıcısını kullanın
Eli Bendersky

21

Kullanım

clang -emit-llvm -o foo.bc -c foo.c
clang -o foo foo.bc

9
Uzantı anlamlarını olduğu gibi tutmanızı tavsiye ederim. IOW, .oikili nesne dosyalarına, .sderleme dosyalarına ve başka bir şeye (geleneksel olarak .ll) LLVM IR dosyalarına başvurmalıdır. Aksi takdirde kafanın karışması kolaydır. Clang / LLVM artık ikili nesneler için kendi bağlayıcısına sahip değil (bir tanesi çalışmalarda olsa da). LLVM bağlayıcı llvm-ldbirkaç IR dosyasını tek bir dosyada birleştiriyor
Eli Bendersky

1
@EliBendersky: Dosya uzantıları söz konusu olduğunda haklısınız - ve clang ön ucu .bc, kullanılırsa aslında doğru olanı yapar ; ayrıca, llvm-ldbunun sistem araç zinciri için ön uç işlevi görebileceğini unutmayın , yani önceki cevabım llvm-ld -nativebeklendiği gibi çalışmalıdır ....
Christoph

1
@rickfoosusa: benim için çalışıyor - foo.bcbir LLVM bit kodu dosyasıdır
Christoph

1
Benim için çalışır: clang -emit-llvm -o test.bc -c test.c && file test.bc: test.bc: LLVM IR bitcode.
ntc2

18

Birden fazla kaynak dosyanız varsa, muhtemelen tüm program için bir bit kodu dosyası çıkarmak için bağlantı zamanı optimizasyonunu kullanmak istersiniz. Verilen diğer cevaplar, her kaynak dosya için bir bit kodu dosyası elde etmenize neden olacaktır.

Bunun yerine, bağlantı zamanı optimizasyonu ile derlemek istiyorsunuz

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

ve son bağlama adımı için -Wl, -plugin-opt = also-emit-llvm argümanını ekleyin

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

Bu size hem derlenmiş bir program hem de ona karşılık gelen bit kodu verir (program.bc). Daha sonra program.bc'yi istediğiniz şekilde değiştirebilir ve değiştirilen programı istediğiniz zaman yeniden derleyebilirsiniz.

clang program.bc -o program

her ne kadar gerekli bağlayıcı bayraklarını (harici kitaplıklar vb. için) bu adımda tekrar eklemeniz gerektiğini unutmayın.

Bunun çalışması için altın bağlayıcı kullanmanız gerektiğini unutmayın. Clang'ı belirli bir bağlayıcıyı kullanmaya zorlamak istiyorsanız, bilgisayarınızda bir yerde "fakebin" adlı özel bir dizinde "ld" adlı bağlayıcıya sembolik bağlantı oluşturun ve seçeneği ekleyin

-B/home/jeremy/fakebin

yukarıdaki herhangi bir bağlantı adımına.



13

Birden fazla dosyanız varsa ve her bir dosyayı yazmak zorunda kalmak istemiyorsanız, şu basit adımları izlemenizi tavsiye ederim (kullanıyorum clang-3.8ancak başka bir sürümü de kullanabilirsiniz):

  1. tüm .lldosyaları oluştur

    clang-3.8 -S -emit-llvm *.c
    
  2. onları tek bir tanesine bağlayın

    llvm-link-3.8 -S -v -o single.ll *.ll
    
  3. (İsteğe bağlı) Kodunuzu optimize edin (belki bazı takma ad analizleri)

    opt-3.8 -S -O3 -aa -basicaaa -tbaa -licm single.ll -o optimised.ll
    
  4. Derleme oluştur (bir optimised.sdosya oluşturur )

    llc-3.8 optimised.ll
    
  5. Yürütülebilir dosya oluştur (adlandırılmış a.out)

    clang-3.8 optimised.s
    

Çözümünüz oldukça benzersiz: İkili çıktı olarak bırakmak yerine "-S" kullandınız. "-S" olmasıyla "-S" olmaması arasında bir fark var mı?
Peter Teoh

@PeterTeoh -SSeçeneği kullanıyorum (2. adımda), çıktıyı LLVM IR'de üretmek istediğimi belirtiyorum. Temel olarak, tüm * .ll dosyalarını tek bir dosyaya koyun. Bunu, optimizasyonların kodu gerçekten değiştirip değiştirmediğini kontrol etmek için yapıyorum, yani single.llve optimised.llşimdi farklı görünmesi gerekiyor (kod açısından) ve ayrıca herhangi bir fark olup olmadığını görmek için raporu da gösterebilirsiniz.
Kiko Fernandez

-basicaaayanlış bir bayraktır, -basicaabunun yerine kullanılmalıdır.
anton_rh
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.