Aquí hay un archivo C simple con una definición de enumeración y una main
función:
enum days {MON, TUE, WED, THU};
int main() {
enum days d;
d = WED;
return 0;
}
Se transmite al siguiente LLVM IR:
define dso_local i32 @main() #0 {
%1 = alloca i32, align 4
%2 = alloca i32, align 4
store i32 0, i32* %1, align 4
store i32 2, i32* %2, align 4
ret i32 0
}
%2
evidentemente es la d
variable, a la que se le asignan 2. ¿A qué %1
corresponde si se devuelve cero directamente?
c
llvm
llvm-codegen
macleginn
fuente
fuente
clang-9 -S -emit-llvm simple.c
main
( godbolt.org/z/kEtS-s ). El enlace muestra cómo se asigna el ensamblado a la fuentemain
, la misteriosa variable adicional desaparece. Curiosamente, también desaparece si omite lareturn
declaración por completo (que es legalmain
en C y equivalente areturn 0;
).main
loint main(int argc, char **argv)
que vesargc
y loargv
copias en la pila, pero la misteriosa variable cero sigue ahí además de ellas.Respuestas:
Este
%1
registro fue generado por clang para manejar múltiples declaraciones de retorno en una función . Imagine que tiene una función para calcular el factorial de un entero. En lugar de escribirlo asíProbablemente harías esto
¿Por qué? Porque Clang insertará esa
result
variable que contiene el valor de retorno para usted. Hurra. Ese es el propósito exacto de eso%1
. Mire el ir para una versión ligeramente modificada de su código.Código modificado,
IR
Ahora lo ves
%1
haciéndose útil, ¿eh? Como los otros han señalado, para las funciones con una sola declaración de retorno, esta variable probablemente será eliminada por uno de los pasos de optimización de llvm.fuente
¿Por qué importa esto? ¿Cuál es el problema real?
Creo que la respuesta más profunda que está buscando podría ser: la arquitectura de LLVM se basa en interfaces bastante simples y muchos pases. Las interfaces tienen que generar el código correcto, pero no tiene que ser un buen código. Pueden hacer lo más simple que funciona.
En este caso, Clang genera un par de instrucciones que resultan no ser utilizadas para nada. Eso generalmente no es un problema, porque alguna parte de LLVM eliminará las instrucciones superfluas. Clang confía en que eso suceda. Clang no necesita evitar emitir código muerto; su implementación puede centrarse en la corrección, simplicidad, comprobabilidad, etc.
fuente
Porque Clang se hace con análisis de sintaxis, pero LLVM ni siquiera ha comenzado con la optimización.
El front-end de Clang ha generado IR (representación intermedia) y no código de máquina. Esas variables son SSA (Asignaciones estáticas individuales); aún no están vinculados a registros y, en realidad, después de la optimización, nunca lo serán porque son redundantes.
Ese código es una representación algo literal de la fuente. Es lo que golpea a LLVM para su optimización. Básicamente, LLVM comienza con eso y se optimiza a partir de ahí. De hecho, para la versión 10 y x86_64, llc -O2 eventualmente generará:
fuente