Rust: Propuesta optimiza la llamada de funciones

Fuentes: 2024-04-17 • 5505 words • 61 minutes • #dark-arts • #assembly • #rust The Rust Calling Convention We Deserve

Este artículo explora una propuesta para mejorar la convención de llamada en Rust, especialmente en arquitecturas x86, y cómo esto impacta la eficiencia del código generado. La convención de llamada define cómo se pasan los argumentos a las funciones y cómo se devuelven los valores, y la actual convención utilizada por Rust (que se basa en la convención de llamada 'C' de LLVM) a menudo resulta en código subóptimo, especialmente para funciones simples. Por ejemplo, una función que extrae un elemento de un array puede terminar pasando el array completo por puntero en lugar de por valor, lo que implica una sobrecarga innecesaria.

La propuesta central es introducir una nueva bandera de compilación, -Zcallconv=fast, que permitiría a Rust generar código más eficiente al pasar argumentos por valor directamente en registros en lugar de por puntero. Esto implicaría una reingeniería de la forma en que LLVM genera el código, incluyendo la determinación del número máximo de valores que pueden pasarse por registro, la decisión de cómo devolver valores (por registro o por referencia), y la optimización de la asignación de argumentos a los registros disponibles. Se plantea que, para mantener la compatibilidad, la convención de llamada 'legacy' (la actual) se mantendría como predeterminada y se usaría para funciones con punteros a funciones y bloques extern "Rust" {}, donde la compatibilidad es crucial.

La implementación de esta nueva convención requeriría modificar LLVM, lo que implica definir explícitamente qué argumentos van en qué registros y generar un 'prolago' y 'epilago' de función que decodifiquen los argumentos desde los registros. Se reconoce que esta solución no es universal (por ejemplo, no sería aplicable a WASM o en builds de depuración), y que la optimización de la asignación de argumentos a registros es un problema complejo (similar al problema de la mochila). El artículo detalla los pasos necesarios para implementar esta mejora, incluyendo la generación de firmas LLVM IR, la creación de un 'shim' para funciones con punteros y la implementación de heurísticas para la asignación de argumentos a registros, con el objetivo final de generar código más rápido y eficiente en Rust.