The LLVM created by rustc gives an error about the type of the main argument when starting with lli

I am trying to learn a little about LLVM IR, especially about what rustc displays. I have a bit of trouble running even a very simple case.

I put the following in the simple.rs source file:

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

and run rustc --emit llvm-ir simple.rs to get a simple.ll file containing

 ; ModuleID = 'simple.cgu-0.rs' source_filename = "simple.cgu-0.rs" target datalayout = "em: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} 

Then I will try to run this with the command

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

but i get an error

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

I can do this with minimal playback as follows: create a file called s2.ll containing

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

and running lli-3.9 s2.ll gives the same error message. But if I change the contents of s2.ll to

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

(i.e., I changed the argc type basically), then lli-3.9 s2.ll starts, and echo $? shows that he really returned 42 .

I don’t think that I would need to pass i64 explicitly - my argument list or C lines should be placed in memory somewhere, and the pointer and length are transferred to main automatically, right? So I suppose I'm doing something wrong in calling lli - but I have no idea what.

+5
source share
1 answer

Rust marks its entry point (the function marked with the #[start] attribute, the default is the lang_start function in the standard library) as accepting an argc parameter of type isize . This is an error because it must be of type C int, therefore it must be 32 bits on a 64-bit platform, but isize is 64 bits. However, due to the way 64-bit calling conventions work, this happens when everything is still working correctly. The same problem exists for the return type.

The fix for this was fixed in 2017-10-01 and should be present in Rust 1.22.

lli apparently stricter in checking the type of main , so it gives an error. But if you use llc instead, it should work correctly.

To get the correct main signature, you can override the default main by putting #![no_main] at the top of the module and providing your main , marked with #[no_mangle] . But note that this will skip initializing the standard library.

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

See also:

+5
source

Source: https://habr.com/ru/post/1271174/


All Articles