Làm thế nào để biên dịch clang để llvm IR


150

Tôi muốn clang biên dịch C/C++mã của tôi thành mã LLVMbyte thay vì thực thi nhị phân. Làm thế nào tôi có thể đạt được điều đó? Và nếu tôi nhận được LLVMmã byte, làm thế nào tôi có thể biên dịch nó thành tệp thực thi nhị phân.

Về cơ bản tôi muốn thêm một số mã của riêng tôi vào LLVMmã byte trước khi biên dịch thành tệp thực thi nhị phân.


Tôi đoán nó được gọi là mã bit LLVM
PreeJackie

Câu trả lời:


204

Cho một số tệp C / C ++ foo.c:

> clang -S -emit-llvm foo.c

Sản xuất foo.llmột tệp LLVM IR.

Các -emit-llvmtùy chọn cũng có thể được thông qua để trình biên dịch front-end trực tiếp, và không phải là lái xe bằng phương pháp -cc1:

> clang -cc1 foo.c -emit-llvm

Sản xuất foo.llvới IR. -cc1thêm một số tùy chọn thú vị như -ast-print. Kiểm tra -cc1 --helpđể biết thêm chi tiết.


Để biên dịch LLVM IR hơn nữa để lắp ráp, hãy sử dụng llccông cụ:

> llc foo.ll

Sản xuất foo.svới lắp ráp (mặc định cho kiến ​​trúc máy bạn chạy nó trên). llclà một trong những công cụ LLVM - đây là tài liệu của nó .


7
-S làm gì ở đây?
meawoppl

13
@meawoppl: -S như trong gcc nói rằng phát ra tập hợp văn bản chứ không phải tập hợp nhị phân
Eli Bendersky

À. Tôi đã có một thời gian khó khăn để tìm thấy bất cứ điều gì trong các tài liệu về nó. Có an toàn không khi cho rằng nhiều cờ trong cấu trúc cờ gcc gương gương?
meawoppl

@EliBendersky Bạn có biết cách biên dịch nhiều tệp .c và .h thành một IR có thể đọc được của con người để tôi có thể chạy IR bằng cách sử dụng 'lli theIrFile' không? Cảm ơn
bộ nhớ cache

1
@cache: biên dịch từng tệp thành tệp IR của riêng mình và sau đó sử dụng trình liên kết LLVM để kết hợp
Eli Bendersky

20

Sử dụng

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

9
Tôi khuyên bạn nên giữ nguyên ý nghĩa mở rộng. IOW, .onên tham khảo các tệp đối tượng nhị phân, .sđể tập hợp các tệp và một cái gì đó khác (theo quy ước .ll) cho các tệp IRVM. Nếu không, nó dễ bị nhầm lẫn. Clang / LLVM hiện không có trình liên kết riêng cho các đối tượng nhị phân (mặc dù một trong số đó đang hoạt động). Trình liên kết LLVM llvm-ldchỉ tham gia một số tệp IR thành một
Eli Bendersky

1
@EliBendersky: bạn chính xác khi có liên quan đến tiện ích mở rộng tệp - và giao diện clang thực sự làm đúng nếu .bcđược sử dụng; Ngoài ra, hãy nhớ rằng llvm-ldcó thể đóng vai trò là tiền đề cho chuỗi công cụ hệ thống, tức là câu trả lời trước đây của tôi sử dụng llvm-ld -nativesẽ hoạt động như mong đợi ....
Christoph

1
@rickfoosusa: hoạt động với tôi - foo.bclà tệp bitcode LLVM
Christoph

1
Làm việc cho tôi : clang -emit-llvm -o test.bc -c test.c && file test.bc: test.bc: LLVM IR bitcode.
ntc2

18

Nếu bạn có nhiều tệp nguồn, có lẽ bạn thực sự muốn sử dụng tối ưu hóa thời gian liên kết để xuất một tệp bitcode cho toàn bộ chương trình. Các câu trả lời khác được đưa ra sẽ khiến bạn kết thúc với một tệp bitcode cho mọi tệp nguồn.

Thay vào đó, bạn muốn biên dịch với tối ưu hóa thời gian liên kết

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

và cho bước liên kết cuối cùng, thêm đối số -Wl, -plugin-opt = cũng-emit-llvm

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

Điều này cung cấp cho bạn cả chương trình được biên dịch và mã bit tương ứng với nó (chương trình.bc). Sau đó, bạn có thể sửa đổi chương trình.bc theo bất kỳ cách nào bạn muốn và biên dịch lại chương trình đã sửa đổi bất cứ lúc nào bằng cách thực hiện

clang program.bc -o program

mặc dù lưu ý rằng bạn cần bao gồm bất kỳ cờ liên kết cần thiết nào (cho các thư viện bên ngoài, v.v.) ở bước này một lần nữa.

Lưu ý rằng bạn cần phải sử dụng trình liên kết vàng để làm việc này. Nếu bạn muốn buộc clang sử dụng một trình liên kết cụ thể, hãy tạo một liên kết tượng trưng đến trình liên kết đó có tên "ld" trong một thư mục đặc biệt có tên "fakebin" ở đâu đó trên máy tính của bạn và thêm tùy chọn

-B/home/jeremy/fakebin

đến bất kỳ bước liên kết ở trên.


13

Nếu bạn có nhiều tệp và bạn không muốn phải nhập từng tệp, tôi khuyên bạn nên làm theo các bước đơn giản sau (Tôi đang sử dụng clang-3.8nhưng bạn có thể sử dụng bất kỳ phiên bản nào khác):

  1. tạo tất cả .llcác tập tin

    clang-3.8 -S -emit-llvm *.c
  2. liên kết chúng thành một

    llvm-link-3.8 -S -v -o single.ll *.ll
  3. (Tùy chọn) Tối ưu hóa mã của bạn (có thể một số phân tích bí danh)

    opt-3.8 -S -O3 -aa -basicaaa -tbaa -licm single.ll -o optimised.ll
  4. Tạo lắp ráp (tạo một optimised.stệp)

    llc-3.8 optimised.ll
  5. Tạo thực thi (có tên a.out)

    clang-3.8 optimised.s

Giải pháp của bạn khá độc đáo: bạn đã sử dụng "-S" thay vì chỉ để nó làm đầu ra nhị phân. Có sự khác biệt nào giữa việc có "-S" và không có "-S" không?
Peter Teoh

@PeterTeoh Tôi sử dụng -Stùy chọn (ở bước 2), tôi chỉ định rằng tôi muốn tạo đầu ra trong LLVM IR. Về cơ bản, đặt tất cả các tệp * .ll vào một tệp duy nhất. Tôi làm điều này để kiểm tra xem các tối ưu hóa có thực sự thay đổi mã hay không, single.lloptimised.llbây giờ trông sẽ khác (mã khôn ngoan) và bạn cũng có thể hiển thị báo cáo để xem liệu có sự khác biệt nào không.
Kiko Fernandez

-basicaaalà một cờ sai, -basicaaphải được sử dụng thay thế.
anton_rh

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.