clang es el front-end del compilador, que se utiliza para el preprocesamiento, el análisis léxico y el análisis de sintaxis. Puede convertir el resultado en un árbol de sintaxis abstracto AST, y luego pasarlo al back-end del compilador LLVM para finalmente generar un ejecutable. programa.
El proceso de compilación de código se puede dividir en preprocesamiento, análisis léxico, análisis de sintaxis, análisis semántico, código objeto, vinculación y generación de programas ejecutables.Este artículo usa el comando clang para completar la compilación de una pieza de código C++ en la plataforma MacOS.
Cree un nuevo archivo main.cpp y escriba código C++.
#include <iostream>
#define STR "Hello world"
int main(int argc, const char * argv[]) {
std::string a = STR;
std::cout << a << std::endl;
return 0;
}
Primero usamos el comando clang para ver el proceso de compilación de este segmento de código. Dado que el código es C ++, necesitamos usar clang ++
clang++ -ccc-print-phases main.cpp
La información de salida del terminal
+- 0: input, "main.cpp", c++
+- 1: preprocessor, {
0}, c++-cpp-output
+- 2: compiler, {
1}, ir
+- 3: backend, {
2}, assembler
+- 4: assembler, {
3}, object
+- 5: linker, {
4}, image
6: bind-arch, "x86_64", {
5}, image
La entrada se refiere al archivo de código fuente de entrada, el preprocesador está preprocesando, el compilador es la parte frontal del compilador y el compilador realiza análisis léxico, análisis de sintaxis y análisis semántico. Luego, el backend genera un ensamblaje y genera archivos de objetos. Linker es un enlace para generar una imagen. Finalmente, bind-arch procesa la información de la arquitectura y genera archivos de imagen relacionados con la arquitectura.
1. Ver el proceso de preprocesamiento del preprocesador
clang++ -E main.cpp -o main.i
El archivo main.i generado es muy largo, deslice hacia abajo para ver la parte del código fuente
int main(int argc, const char * argv[]) {
std::string a = "Hello world";
std::cout << a << std::endl;
return 0;
}
Se puede ver que en la etapa de preprocesamiento, la definición de la macro se expande y la parte del código aún no se ha procesado.
2. Ver análisis léxico
clang++ -fmodules -E -Xclang -dump-tokens main.cpp
El resultado del análisis léxico generado es muy largo, aquí hay solo una breve sección
identifier 'std' [StartOfLine] [LeadingSpace] Loc=<main.cpp:14:5>
coloncolon '::' Loc=<main.cpp:14:8>
identifier 'cout' Loc=<main.cpp:14:10>
lessless '<<' [LeadingSpace] Loc=<main.cpp:14:15>
identifier 'a' [LeadingSpace] Loc=<main.cpp:14:18>
lessless '<<' [LeadingSpace] Loc=<main.cpp:14:20>
identifier 'std' [LeadingSpace] Loc=<main.cpp:14:23>
coloncolon '::' Loc=<main.cpp:14:26>
identifier 'endl' Loc=<main.cpp:14:28>
semi ';' Loc=<main.cpp:14:32>
return 'return' [StartOfLine] [LeadingSpace] Loc=<main.cpp:15:5>
numeric_constant '0' [LeadingSpace] Loc=<main.cpp:15:12>
semi ';' Loc=<main.cpp:15:13>
r_brace '}' [StartOfLine] Loc=<main.cpp:16:1>
eof '' Loc=<main.cpp:16:2>
El análisis léxico consiste en analizar el código fuente y generar tokens uno por uno. A partir de los resultados, se reconocen std, ::, cout, a y otros símbolos. El lado izquierdo es el tipo de token, como identificador identificador, punto y coma, eof es el final del archivo. El número de línea y el número de columna de cada símbolo en el código fuente se registran a la derecha.
3. Análisis de sintaxis
clang++ -fmodules -fsyntax-only -Xclang -ast-dump main.cpp
4. Análisis semántico
clang++ -S -emit-llvm main.cpp
El directorio actual generará el archivo de análisis de sintaxis main.ll
5. Archivo de montaje
clang++ -S main.cpp
El directorio actual generará el archivo de ensamblaje de main.s
6. Generar archivos de destino
clang++ -c main.s
El directorio actual generará el archivo de objeto main.o, que está en forma binaria.
7. Generar archivos ejecutables
clang++ main.cpp -o main
El archivo principal se genera en el directorio actual. Ejecute ./main en la línea de comando para ejecutar el programa y mostrar Hello world