LLVM producido por rustc da error sobre el tipo de argumento de main cuando se ejecuta con lli
(1)
Estoy tratando de aprender un poco sobre el IR de LLVM, particularmente qué resultados exactamente rustc. Estoy teniendo problemas para ejecutar incluso un caso muy simple.
Puse lo siguiente en un archivo fuente simple.rs
:
fn main() {
let x = 7u32;
let y = x + 2;
}
y ejecuta rustc --emit llvm-ir simple.rs
para obtener el archivo simple.ll
, que contiene
; 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}
Luego trato de ejecutar esto con el comando
lli-3.9 -load ~/.multirust/toolchains/nightly-x86_64-unknown-linux-gnu/lib/libstd-35ad9950c7e5074b.so simple.ll
pero recibo el mensaje de error
LLVM ERROR: Invalid type for first argument of main() supplied
Puedo hacer una reproducción mínima de esto de la siguiente manera: hago un archivo llamado s2.ll
, que contiene
define i32 @main(i64, i8**) {
ret i32 42
}
y ejecutar lli-3.9 s2.ll
da el mismo mensaje de error. Pero si cambio los contenidos de s2.ll
a
define i32 @main(i32, i8**) {
ret i32 42
}
(es decir, he cambiado el tipo de argc
en main), luego lli-3.9 s2.ll
ejecuta y echo $?
revela que efectivamente regresó 42
.
No creo que deba pasar el i64
explícita: mi lista de argumentos o las cadenas C deben ponerse en la memoria en algún lugar y el puntero y la longitud pasarán a la main
automáticamente, ¿verdad? Por lo tanto, supongo que estoy haciendo algo mal en el camino para invocar a lli
, pero no tengo ni idea de qué.
Rust marca su punto de entrada (la función marcada con #[start]
atributo #[start]
, por defecto la función lang_start
en la biblioteca estándar) como tomar un parámetro argc de tipo isize
. Este es un error porque debería tener el tipo de C int, por lo que debería ser de 32 bits en una plataforma de 64 bits, pero isize
es de 64 bits. Sin embargo, debido a la forma en que funcionan las convenciones de llamadas de 64 bits, esto todavía funciona correctamente. El mismo problema también existe para el tipo de devolución.
Se ha confirmado una solución para esto en 2017-10-01 y debería estar presente en Rust 1.22.
lli
es aparentemente más estricto al verificar el tipo de main
razón por la cual da el error. Pero si usa llc
lugar, debería funcionar correctamente.
Para obtener la firma main
correcta, puede cancelar la main
predeterminada colocando #![no_main]
en la parte superior del módulo, y proporcione su propia marca main
con #[no_mangle]
. Pero tenga en cuenta que esto omitirá la inicialización de la biblioteca estándar.
#![no_main]
#[no_mangle]
pub extern fn main(_argc: i32, _argv: *const *const u8) -> i32 {
0
}
Ver también:
- documentación sobre
lang_items
y deshabilitarmain
-
isize
seguimiento para la función#[start]
, donde algunas personas mencionan queisize
no es correcto.