2017-08-24 16 views
5

Tôi đang cố gắng tìm hiểu một chút về LLVM IR, đặc biệt là những gì chính xác kết quả đầu ra rustc. Tôi đang gặp một chút rắc rối khi chạy ngay cả một trường hợp rất đơn giản.LLVM được tạo ra bởi rustc cho lỗi về kiểu đối số của chính khi chạy với lli

tôi đặt sau đây trong một tập tin nguồn simple.rs:

fn main() { 
    let x = 7u32; 
    let y = x + 2; 
} 

và chạy rustc --emit llvm-ir simple.rs để tải tệp simple.ll, chứa

; ModuleID = 'simple.cgu-0.rs' 
source_filename = "simple.cgu-0.rs" 
target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128" 
target triple = "x86_64-unknown-linux-gnu" 

; Function Attrs: uwtable 
define internal void @_ZN6simple4main17h8ac50d7470339b75E() unnamed_addr #0 { 
start: 
    br label %bb1 

bb1:            ; preds = %start 
    ret void 
} 

define i64 @main(i64, i8**) unnamed_addr { 
top: 
    %2 = call i64 @_ZN3std2rt10lang_start17ha09816a4e25587eaE(void()* @_ZN6simple4main17h8ac50d7470339b75E, i64 %0, i8** %1) 
    ret i64 %2 
} 

declare i64 @_ZN3std2rt10lang_start17ha09816a4e25587eaE(void()*, i64, i8**) unnamed_addr 

attributes #0 = { uwtable } 

!llvm.module.flags = !{!0} 

!0 = !{i32 1, !"PIE Level", i32 2} 

sau đó tôi cố gắng chạy này với lệnh

lli-3.9 -load ~/.multirust/toolchains/nightly-x86_64-unknown-linux-gnu/lib/libstd-35ad9950c7e5074b.so simple.ll 

nhưng tôi nhận được thông báo lỗi e

LLVM ERROR: Invalid type for first argument of main() supplied 

tôi có thể làm cho một bản tái tạo tối thiểu về điều này như sau: tôi thực hiện một tập tin gọi là s2.ll, chứa

define i32 @main(i64, i8**) { 
    ret i32 42 
} 

và chạy lli-3.9 s2.ll đưa ra thông điệp lỗi tương tự. Nhưng nếu tôi thay đổi nội dung của s2.ll để

define i32 @main(i32, i8**) { 
    ret i32 42 
} 

(ví dụ: Tôi đã thay đổi loại argc trong chính) sau đó lli-3.9 s2.ll chạy, và echo $? tiết lộ rằng nó đã thực sự trở 42.

Tôi không nghĩ mình cần phải vượt qua một cách rõ ràng - danh sách đối số hoặc chuỗi C của tôi nên được đặt vào bộ nhớ ở đâu đó và con trỏ và độ dài được tự động chuyển đến main, phải không? Vì vậy, tôi giả định rằng tôi đang làm một cái gì đó sai trái trong cách gọi lli - nhưng tôi không có ý tưởng gì.

Trả lời

5

Rust đánh dấu điểm vào của nó (hàm được đánh dấu bằng #[start] thuộc tính, theo mặc định hàm lang_start trong thư viện chuẩn) như tham số argc loại isize. This is a bug vì nó phải có loại C int, do đó, nó phải là 32 bit trên nền tảng 64 bit, nhưng isize là 64 bit. Tuy nhiên, do cách thức các quy ước gọi điện 64 bit hoạt động, điều này xảy ra vẫn hoạt động chính xác. Vấn đề tương tự cũng tồn tại đối với loại trả về.

A fix vì điều này đã được cam kết vào ngày 2017-10-01 và phải có mặt trong Rust 1.22.

lli rõ ràng là nghiêm ngặt hơn về việc kiểm tra loại main đó là lý do khiến lỗi này xảy ra. Nhưng nếu bạn sử dụng llc thay vào đó, nó sẽ hoạt động chính xác.

Để có được đúng main chữ ký, bạn có thể hủy mặc định main bằng cách đặt #![no_main] ở phía trên cùng của mô-đun, và cung cấp riêng main của bạn được đánh dấu bằng #[no_mangle]. Nhưng lưu ý rằng điều này sẽ bỏ qua việc khởi tạo thư viện chuẩn.

#![no_main] 

#[no_mangle] 
pub extern fn main(_argc: i32, _argv: *const *const u8) -> i32 { 
    0 
} 

Xem thêm:

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