2014-12-12 13 views
23

tôi biến đổi mã C đơn giản nhấtHiểu IR LLVM đơn giản nhất

#include <stdio.h> 

int main() 
{ 
    return 0; 
} 

để LLVM IR của nó, sử dụng

clang -emit-llvm -S hello.c 

Các tạo IR là:

define i32 @main() #0 { 
     %1 = alloca i32, align 4 
     store i32 0, i32* %1 
     ret i32 0 
    } 

Tuy nhiên, tôi làm không hiểu IR này. (LLVM doc giúp nhưng không nhiều cho người mới bắt đầu)

  1. Tại sao chúng tôi có %1 = alloca i32, align 4? Điều gì tương ứng với mã gốc?
  2. Câu hỏi tương tự cho store i32 0, i32* %1
  3. Alloca có nghĩa là phân bổ trên ngăn xếp (thay vì phân bổ động) không?
  4. 'Căn chỉnh 4' có nghĩa là gì?
+0

Căn chỉnh cho biết hoạt động bộ nhớ phải được căn chỉnh thành 4 byte. Tôi không chắc về phần còn lại. – MariusSiuram

Trả lời

19
define i32 @main() #0 

này định nghĩa một hàm gọi là main mà trả về một số nguyên 32 bit. #0 có nghĩa là sử dụng các thuộc tính có tên #0 cho hàm.Ví dụ: có thể có một cái gì đó như attributes #0 = { alwaysinline alignstack=4 } trong IR và các thuộc tính này sẽ được áp dụng cho main.

%1 = alloca i32, align 4 

Điều này phân bổ số nguyên 32 bit trên ngăn xếp. %1 là tên của một con trỏ đến vị trí này trên ngăn xếp. Các align 4 đảm bảo rằng địa chỉ này sẽ là một bội số của 4

store i32 0, i32* %1 

này đặt 32 bit số nguyên được trỏ đến bởi %1 với giá trị 32 bit 0. Nó giống như nói *x = 1 trong C++

ret i32 0 

này trả về từ hàm có giá trị trả về 32 bit là 0

Bài tập là kỳ quặc, vì bạn không có biến cục bộ trong main. LLVM sử dụng BasicBlock để đại diện cho các nhóm hướng dẫn, và một khối cơ bản có một điểm thoát và một danh sách các hướng dẫn. Tôi đoán là trình biên dịch đã quyết định sử dụng return làm lối thoát khỏi khối cơ bản và đã chọn đưa ít nhất một lệnh vào khối. Nhiệm vụ về cơ bản là một no-op.

12

%n là các thanh ghi ảo sẽ được giải quyết cho sổ đăng ký thực tế khi tạo mã cho máy mục tiêu.

i32 để biết thông tin loại. Trong mã ban đầu nó là một int mà trình biên dịch của bạn đã là số nguyên 32 bit.

alloca dùng để phân bổ dung lượng trên ngăn xếp. Trong ví dụ này, nó là i32 (số nguyên 32 bit) để bạn có thể tải trong giá trị 0 cho giá trị trả lại. align 4 cung cấp sự sắp xếp 4 byte phân bổ này, tức là con trỏ ngăn xếp sẽ nằm trên một địa chỉ được liên kết 4 byte.

Nó không phải là đại diện hiệu quả nhất nhưng đó không phải là mục tiêu nếu IR. IR nên được di chuyển đến các kiến ​​trúc khác nhau. Sau đó, xuống phần phụ trợ để tạo mã máy hiệu quả.

LLVM Language Reference Manual

Tại sao allocastore đang có để làm với điều này là main chức năng. Nếu bạn đã gọi chức năng này một cái gì đó khác, IR sẽ chỉ chứa ret như bạn mong đợi. Từ kiểm tra lắp ráp sản xuất cho chính nó dường như có liên quan đến con trỏ cơ sở stack nhưng tôi không hoàn toàn hiểu tại sao nó ở đó. Thời gian để rút ra các tiêu chuẩn C tôi nghĩ.

Cập nhật: Tôi không tìm thấy bất kỳ điều gì trong tiêu chuẩn C nhưng có vẻ như tiếng kêu này thực hiện điều này cho mọi chức năng chính. Tôi không biết cơ sở mã clang đủ tốt để theo dõi nó mặc dù.

Cập nhật: Xem nhận xét với Bill Lynch bên dưới. Những instuctions đang có:

cho khả năng tiềm ẩn return 0 rằng chức năng chính có

+0

Cảm ơn bạn. Vậy tại sao chúng ta cần% 1 ở đây (câu hỏi của tôi # 1 và # 2)? – zell

+0

@zell: Không cần thiết. Nếu bạn đã bật trình tối ưu hóa (với -O3 chẳng hạn), trình tối ưu hóa sẽ bị xóa. –

+0

@Bill. Cảm ơn bạn. Tuy nhiên, ngay cả đối với một IR không hiệu quả, cần có một lý do% 1 được sử dụng. Điều gì là hợp lý mà LLVM IR cần thêm% 1 (Tôi hoàn toàn hiểu rằng tối ưu hóa sẽ loại bỏ nó).? – zell

2

Biến thường được đặt trên ngăn xếp trong các bản dựng không được tối ưu hóa cho các lý do gỡ lỗi. Trong các bản dựng được tối ưu hóa sử dụng thanh ghi thực, giá trị có thể biến mất trước khi hàm thoát.

Nhận xét về tính di động không chính xác, nếu IR này được chuyển qua 'chọn', nó sẽ loại bỏ ngăn xếp ngăn xếp.

+0

Nhưng không có biến nào trong chính để thử và lưu trữ trên ngăn xếp. Có nhìn vào rất nhiều đầu ra khác clang nó luôn luôn có vẻ để lưu trữ này 0 trên stack trong chính. – DrYap

+0

Giá trị được đặt ở đó là giá trị trả lại. –

+0

Cảm ơn Colin. Thông tin tuyệt vời. Thêm '-O3' vào thế hệ ll trong caes của riêng tôi làm cho IR sooo dễ hiểu hơn nhiều :-) –

Các vấn đề liên quan