Dispositivo compilador rápido. Parte 1


Swift no es solo un lenguaje de programación. Este es un proyecto que, además del compilador, incluye muchos otros componentes. Y el compilador en sí no es una caja grande y terrible, que con la ayuda de la magia convierte su código en un conjunto de instrucciones que son comprensibles para la máquina. También se puede dividir en componentes. Si está interesado en cuáles, bienvenido a cat.


No soy especialista en compiladores y no tengo experiencia en esta área. Pero me preguntaba cómo funciona, y comencé a estudiar el compilador Swift. Como el artículo resultó ser demasiado extenso, tuve que dividirlo en 4 partes:


  • resumen general de componentes
  • analizando el archivo fuente,
  • Lenguaje intermedio rápido,
  • LLVM IR y generación de código.

Veloz


Swift ha sido un proyecto de código abierto durante más de dos años. Durante este tiempo, se agregaron muchas mejoras de la comunidad. Puede seguirlos en un sitio especial, así como en el foro . Allí puede discutir sugerencias para mejorar el idioma o presentar sus ideas. Pero para hacer esto, primero debe averiguar cómo funciona el proyecto.


Biblioteca estándar Swift





Las partes principales de Swift, por supuesto, son el compilador y la biblioteca de funciones estándar. Se desarrollan en paralelo y son prácticamente inseparables el uno del otro.


El compilador está escrito en C ++, y la parte principal de stdlib está en Swift. Sin embargo, el lenguaje utilizado tiene varias características:


  • La biblioteca estándar a través del módulo Builtin tiene acceso directo a las funciones del compilador. Esto le permite acceder a representaciones de lenguaje de bajo nivel y punteros en bruto.
  • La biblioteca estándar no usa el modificador de acceso privado. En cambio, los nombres de entidades no públicas comienzan con un guión bajo. Lee más aquí .
  • Utiliza la generación de código usando la utilidad Generate Your Boilerplate (GYB) para reducir la repetición en el código de la biblioteca estándar.

La biblioteca estándar generalmente está asociada con contenedores y funciones útiles que simplifican la vida del desarrollador, pero esto es solo una parte. En total, se pueden distinguir los 3 componentes más interesantes:


  • Núcleo Un núcleo con todos sus protocolos, tipos de datos y funciones. Fuentes
  • Tiempo de ejecución Una capa intermedia entre la biblioteca estándar y el compilador. Es responsable de la conversión de tipos, trabaja con la memoria, la reflexión y otras características dinámicas del lenguaje. Escrito en C ++ y Objective-C. Fuentes
  • SDK Overlays. Contenedores sobre Foundation y otros marcos de sistema que hacen que acceder a ellos desde Swift sea más conveniente. Fuentes

Otros subproyectos





Además del compilador y la biblioteca estándar, hay muchos otros subproyectos en el dominio público. Algunos de ellos se enumeran a continuación.


Kit de origen


Marco de soporte IDE : indexación, resaltado de sintaxis, finalización de código, etc.


SourceKit-LSP


Una implementación de LSP para Swift , basada en SourceKit. Puedes leer sobre qué es aquí .


Administrador de paquetes Swift


Gestor de paquetes para proyectos en Swift.


Fundacion


Puerto de la biblioteca de la Fundación , que es uno de los núcleos del sistema operativo de Apple para plataformas de terceros.


libdispatch (mcd)


GCD para plataformas de terceros.


XCTest


XCTest para plataformas de terceros.


LLDB


LLDB con soporte Swift y REPL.


Soporte de juegos


El proyecto incluye dos marcos: PlaygroundSupport y PlaygroundLogger. Proporcionan interacción con Xcode y una hermosa visualización de datos, respectivamente.


llbuild


Construir sistema .


Gyb


Utilidad para la generación de código.


libcxx


Implementación de la biblioteca estándar de C ++.


Compilador Swift





Un compilador en el sentido más amplio es un programa que convierte el código de un idioma a otro. Pero más a menudo, la compilación se refiere a la conversión del código fuente en el código de la máquina (o en otra representación de bajo nivel), que luego puede usarse para crear un archivo ejecutable.


El compilador a menudo se divide en tres partes: frontend, middlend, backend. El primero es responsable de convertir el código fuente en una representación intermedia, lo cual es conveniente para que el compilador trabaje. Middlend realiza la optimización y el backend genera código de máquina a partir de la representación intermedia optimizada.


Sin embargo, en Swift, la optimización se realiza tanto en el frontend como (la mayoría de) en el backend. Por lo tanto, no se muestra el paso intermedio en el diagrama.


LLVM





El compilador Swift usa LLVM como back-end. LLVM es un gran proyecto que incluye muchas tecnologías. Se basa en la representación intermedia (IR). Esta es una representación de código intermedio universal que se puede convertir a código ejecutable en cualquier plataforma compatible con LLVM.



Si aparece una nueva arquitectura, será suficiente agregar en LLVM la generación de código de máquina desde IR para esta plataforma. Después de eso, todos los idiomas para los que hay un compilador con generación IR admitirán esta arquitectura.


Por otro lado, para crear un compilador para un nuevo lenguaje de programación, es suficiente escribir la traducción del código fuente en IR, y LLVM se encargará de las diversas arquitecturas.


Otra ventaja de este sistema es que LLVM puede optimizar la presentación intermedia, y el front-end puede no participar en la optimización. Esto simplifica enormemente el desarrollo del compilador.


IR tiene tres tipos de pantalla:


  • Un árbol de objetos en la memoria. Cada objeto corresponde a una determinada entidad en el código fuente: función, operador, línea, puntero, etc. Este árbol es creado por el frontend en la etapa de generación de IR.
  • Vista de texto IR se puede inferir como código fuente de bajo nivel. Se puede guardar en un archivo y ejecutar con el intérprete.
  • El formato de bit serializado "bitcode" (no debe confundirse con el bytecode, que se usa, por ejemplo, en Java). Puede usarse como resultado final del backend y transferirse al enlazador para su optimización a nivel de enlace. La conversión al código de máquina en este caso será realizada por el vinculador.

Linker es un programa que genera un archivo ejecutable. Su descripción está más allá del alcance del artículo.


El código fuente de la versión LLVM utilizada en Swift se puede encontrar aquí , y la documentación en el sitio web oficial.


Como puede ver, Apple publicó muchos proyectos interesantes sobre acceso abierto. En la siguiente parte , hablaré sobre analizar el archivo fuente y generar el AST.

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


All Articles