2012-02-05 12 views
104

Chcę clang do kompilacji mojego kodu C/C++ do LLVM kodu bajtowego zamiast pliku binarnego. Jak mogę to osiągnąć? A jeśli otrzymam kod bajtowy LLVM, w jaki sposób mogę go zabrać do dalszej kompilacji do pliku binarnego.Jak zrobić clang kompilacji do llvm IR

Zasadniczo chcę dodać trochę mojego kodu do kodu bajtowego LLVM przed kompilacją do pliku wykonywalnego binarnego.

Odpowiedz

143

względu niektóre C/C++ plik foo.c:

> clang -S -emit-llvm foo.c 

Wytwarza foo.ll który jest plikiem LLVM IR.

Opcja -emit-llvm może być również przekazana do przedniego końca kompilatora, a nie za pomocą sterownika -cc1:

> clang -cc1 foo.c -emit-llvm 

Wytwarza foo.ll z IR. -cc1 dodaje kilka fajnych opcji, takich jak -ast-print. Aby uzyskać więcej informacji, sprawdź numer -cc1 --help.


Aby skompilować LLVM IR dodatkowo do montażu, należy użyć narzędzia llc:

> llc foo.ll 

Produkuje foo.s z montażem (zwłoce do architektury maszynowego go uruchomić na). llc jest jednym z narzędzi LLVM - here is its documentation.

+3

Co robi -S tutaj? – meawoppl

+8

@meawoppl: -S jak w gcc mówi, że emituje zespół tekstowy zamiast zmontowanego pliku binarnego –

+0

Ahha. Miałem trudności ze znalezieniem czegokolwiek w dokumentach na ten temat. Można bezpiecznie założyć, że wiele flag w strukturze flagi gcc lustra clang? – meawoppl

16

Zastosowanie

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

. Zalecane jest zachowanie nienaruszonych znaczeń rozszerzeń. IOW, '.o' powinien odnosić się do plików obiektów binarnych,' .s' do plików zespołu i czegoś innego (przez konwencję '.ll') do plików LLVM IR. W przeciwnym razie łatwo się pogubić. Clang/LLVM nie mają teraz własnego łącznika dla obiektów binarnych (choć jeden jest w pracach). Łącznik LLVM 'llvm-ld' po prostu dołącza kilka plików IR do jednego –

+1

@EliBendersky: masz rację, jeśli chodzi o rozszerzenia plików - a front interfejsu clang właściwie robi to, co należy, jeśli użyto' .bc'; należy także pamiętać, że 'llvm-ld' może działać jako frontend dla systemu toolchain, tj. moja poprzednia odpowiedź używająca' llvm-ld -native' powinna działać zgodnie z oczekiwaniami ... – Christoph

+0

Nie działa. foo.bc jest plikiem obiektowym. – rickfoosusa

17

Jeśli masz wiele plików źródłowych, prawdopodobnie rzeczywiście chcesz użyć linku-time-optymalizacji wyjście jednego pliku bitcode dla całego programu. Inne podane odpowiedzi spowodują, że skończy się plik bitcodu dla każdego pliku źródłowego.

Zamiast chcesz skompilować z link-czasowej optymalizacji

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

i na końcowym etapie linkowania, dodać argument -Wl, -plugin-opt = również emitują-llvm

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

To daje zarówno skompilowany program i odpowiadający mu bitcode (program.bc). Następnie można modyfikować program.bc w dowolny sposób, i rekompilacji zmodyfikowanego programu w dowolnym momencie, wykonując

clang program.bc -o program 

chociaż należy pamiętać, że trzeba uwzględnić niezbędne flagi łącznikiem (dla zewnętrznych bibliotek, etc) na ten krok ponownie.

Pamiętaj, że musisz użyć złotego linkera, aby to zadziałało.Jeśli chcesz, aby wymusić szczęk do korzystania z konkretnego łącznika, należy utworzyć dowiązania do tego łącznika nazwie „LD” w specjalnym katalogu o nazwie „fakebin” gdzieś na komputerze, a także dodać opcję

-B/home/jeremy/fakebin 

do wszelkich krokach łączących powyżej.

+1

To było bardzo pomocne, dziękuję! – baibo

5

Jeśli masz wiele plików i nie chcesz mieć wpisywać każdy plik, polecam, aby przestrzegać tych prostych kroków (używam clang-3.8 ale można użyć dowolnej innej wersji):

  1. wygenerować wszystkie .ll plików

    clang-3.8 -S -emit-llvm *.c 
    
  2. połączyć je w jeden

    llvm-link-3.8 -S -v -o single.ll *.ll 
    
  3. (opcjonalnie) Optymalizacja kodu (być może niektóre analizy alias)

    opt-3.8 -S -O3 -aa -basicaaa -tbaa -licm single.ll -o optimised.ll 
    
  4. Generowanie montaż (generuje plik optimised.s)

    llc-3.8 optimised.ll 
    
  5. Tworzenie wykonywalny (nazwane a.out)

    clang-3.8 optimised.s 
    
+0

Twoje rozwiązanie jest dość wyjątkowe: użyłeś "-S" zamiast pozostawić go jako wyjście binarne. Czy jest jakaś różnica między posiadaniem "-S" i brakiem "-S"? –

+0

@PeterTeoh Korzystam z opcji '-S' (w kroku 2), określam, że chciałbym utworzyć wyjście w LLVM IR. Zasadniczo, umieść wszystkie pliki * .ll w jednym. Robię to, aby sprawdzić, czy optymalizacje naprawdę zmieniają kod, tzn. 'Single.ll' i' optimimised.ll' powinny teraz wyglądać inaczej (w sensie kodu), a także możesz wyświetlić raport, aby zobaczyć, czy jest jakakolwiek różnica . –

Powiązane problemy