¿Por qué hay tan pocos compiladores de C?

72

C es uno de los lenguajes más utilizados en el mundo. Representa una gran proporción del código existente y continúa utilizándose para una gran cantidad de código nuevo. Es amado por sus usuarios, es tan ampliamente portado que poder ejecutar C es para muchos la definición informal de una plataforma , y sus fanáticos lo elogian por ser un lenguaje "pequeño" con un conjunto relativamente limpio de características.

Entonces, ¿dónde están todos los compiladores?

En el escritorio, hay (de manera realista) dos : GCC y Clang. Pensando en ello durante unos segundos, probablemente recordará que Intel también existe. Hay un puñado de otros, demasiado oscuros para que la persona promedio los nombre y casi universalmente no se molestan en admitir una versión de idioma reciente (o, a menudo, incluso un subconjunto de idiomas bien definido, solo "un subconjunto"). La mitad de los miembros de esta lista son notas al pie históricas; la mayoría del resto son muy especializados y aún no implementan el lenguaje completo. Muy pocos parecen ser de código abierto.

Scheme y Forth, otros idiomas pequeños que sus admiradores adoran por él, probablemente tengan más compiladores que usuarios reales. Incluso algo como SML tiene más implementaciones "serias" para elegir que C. Mientras que el anuncio de un nuevo compilador C (inacabado) que apunta a la verificación en realidad ve algunas respuestas bastante negativas, y las implementaciones veteranas luchan por conseguir suficientes contribuyentes para ponerse al día C99.

¿Por qué? ¿Es tan difícil implementar C? No es C ++. ¿Los usuarios simplemente tienen una idea muy sesgada sobre en qué grupo de complejidad se encuentra (es decir, que en realidad está más cerca de C ++ que de Scheme)?


fuente
61
MSVC todavía cuenta, como compilador de C89 al menos. Probablemente más popular que Intel incluso.
Rufflewind
22
Wikipedia enumera bastantes compiladores de C. Se vuelven muy comunes cuando te encuentras en el reino incrustado.
113
¿Cuántos compiladores necesitas para compilar tu código C?
Bryan Chen
76
La pregunta se basa en una premisa falsa. Analog Devices, armcc, el compilador C de Bruce, el compilador cruzado Bare-C, el compilador Borland, el compilador clang, el compilador Cosmic C, el compilador CodeWarrior, el compilador dokto, el compilador Ericsson, y ni siquiera estoy fuera del primeras cinco letras del alfabeto todavía. Hay una cantidad increíblemente grande de compiladores de C. La pregunta es "¿por qué hay tan pocos compiladores de C, si no contamos estas docenas como compiladores de C reales?" Ha definido la gran mayoría de los compiladores de C como no interesantes, por lo que no hay muchos de ellos.
Eric Lippert
19
Las preguntas de "por qué" son malas para este sitio en el mejor de los casos y "¿por qué no?" las preguntas son peores. Si fuera a verte en una fiesta y preguntarte "entonces, ¿por qué no corres en veleros?" Creo que con razón lo consideraría una pregunta extraña. No necesita dar una justificación para NO participar en un pasatiempo técnicamente difícil, físicamente riesgoso y muy costoso. Escribir cualquier pieza de software no trivial es costoso, difícil y arriesgado y, por lo tanto, requiere una gran motivación. Una mejor pregunta sería "¿por qué hay tantos compiladores de C?" Es sorprendente que haya más de uno.
Eric Lippert

Respuestas:

153

Hoy en día, necesita un compilador de C real para ser un compilador de optimización , especialmente porque C ya no es un lenguaje cercano al hardware, porque los procesadores actuales son increíblemente complejos ( fuera de orden , canalizados , superescalares , con cachés complejos y TLB , por lo tanto, necesita programación de instrucciones , etc ...). Los procesadores x86 actuales no son como los procesadores i386 del siglo anterior, incluso si ambos pueden ejecutar el mismo código de máquina. Vea que el C no es un lenguaje de bajo nivel (Su computadora no es un PDP-11 rápido) escrito por David Chisnall.

Pocas personas están utilizando compiladores de C ingenuos no optimizadores como tinycc o nwcc , ya que producen código que es varias veces más lento de lo que pueden proporcionar los compiladores de optimización.

Codificar un compilador de optimización es difícil. Observe que tanto GCC como Clang están optimizando alguna representación de código "neutral en el lenguaje fuente" (Gimple para GCC, LLVM para Clang). ¡La complejidad de un buen compilador de C no está en la fase de análisis!

En particular, hacer un compilador de C ++ no es mucho más difícil que hacer un compilador de C: analizar C ++ y transformarlo en alguna representación de código interno es complejo (porque la especificación de C ++ es compleja), pero se entiende bien, pero las partes de optimización son aún más complejo (dentro de GCC: las optimizaciones intermedias, el lenguaje de origen y el procesador de destino neutral, forman la mayoría del compilador, con el resto equilibrado entre los front-end para varios idiomas y los back-end para varios procesadores). Por lo tanto, la mayoría de los compiladores de C optimizadores también pueden compilar algunos otros lenguajes, como C ++, Fortran, D, ... Las partes específicas de C ++ de GCC son aproximadamente el 20% del compilador ...

Además, C (o C ++) se usa tanto que las personas esperan que su código sea compilable incluso cuando no sigue exactamente los estándares oficiales, que no definen con suficiente precisión la semántica del lenguaje (por lo que cada compilador puede tener su propia interpretación de eso). Mire también el compilador comprobado CompCert C y el analizador estático Frama-C , que se preocupa por una semántica más formal de C.

Y las optimizaciones son un fenómeno de cola larga : implementar algunas optimizaciones simples es fácil, ¡pero no harán que un compilador sea competitivo! Debe implementar muchas optimizaciones diferentes, y organizarlas y combinarlas inteligentemente, para obtener un compilador del mundo real que sea competitivo. En otras palabras, un compilador de optimización del mundo real tiene que ser una pieza compleja de software. Por cierto, tanto GCC como Clang / LLVM tienen varios generadores de código C / C ++ especializados internos. Y ambos son enormes bestias (varios millones de líneas de código fuente, con una tasa de crecimiento de varios por ciento cada año) con una gran comunidad de desarrolladores (unos pocos cientos de personas, que trabajan principalmente a tiempo completo, o al menos a medio tiempo).

Tenga en cuenta que no hay ningún compilador C multiproceso (que yo sepa), incluso si algunas partes de un compilador podrían ejecutarse en paralelo (por ejemplo, optimización intraprocesal, asignación de registros, programación de instrucciones ...). Y la construcción paralela con make -jno siempre es suficiente (especialmente con LTO ).

Además, es difícil obtener fondos para codificar un compilador de C desde cero, y ese esfuerzo debe durar varios años. Finalmente, la mayoría de los compiladores de C o C ++ son software libre hoy en día (ya no hay un mercado para nuevos compiladores propietarios vendidos por startups) o al menos son productos monopólicos (como Microsoft Visual C ++ ), y es casi obligatorio ser un software gratuito para los compiladores ( porque necesitan contribuciones de muchas organizaciones diferentes).

Me encantaría obtener fondos para trabajar en un compilador de C desde cero como software libre, ¡pero no soy tan ingenuo como para creer que hoy es posible!

Basile Starynkevitch
fuente
14
(there is no more a market for proprietary compilersDile eso al equipo de Visual Studio ...
Mason Wheeler
18
Microsoft tiene el monopolio. Quise decir que las pequeñas empresas que desarrollan nuevos compiladores de C no venderán muchos de ellos. ¿Puedes nombrar un competidor propietario reciente para MSVC?
Basile Starynkevitch
12
Hay muchos compiladores patentados en el mundo de HPC. PGCC, NAG e ICC son los más utilizados.
Davidmh
37
@MasonWheeler: VS se regala gratis hoy en día (como en la cerveza). Las versiones no gratuitas agregan herramientas, pero el compilador de C en VS2013 es el mismo en todas las versiones. Simplemente no hay mercado, ni siquiera para ellos.
MSalters
3
Pero tanto GCC como LLVM están operando en representaciones mucho más bajas, y también optimizan el código C ++ y C (y Ada y Fortran, para GCC). Por el contrario, diría que C ++ requiere más optimización (especialmente al compilar código usando su STL) que C!
Basile Starynkevitch
70

Me gustaría cuestionar su suposición subyacente de que solo hay un pequeño número de implementaciones de C.

Ni siquiera sé C, no uso C, no soy miembro de la comunidad C y, sin embargo, incluso sé mucho más que los pocos compiladores que mencionaste.

En primer lugar, está el compilador que probablemente eclipsa por completo a GCC y Clang en el escritorio: Microsoft Visual C. A pesar de las incursiones que OSX y Linux han estado haciendo en el escritorio, y la cuota de mercado que iOS y Android han "robado" lejos de los antiguos usuarios tradicionales de escritorio, Windows sigue siendo el sistema operativo de escritorio dominante, y la mayoría de los programas de escritorio de Windows C probablemente se compilan con herramientas de Microsoft.

Tradicionalmente, cada vendedor de SO y cada vendedor de chips tenían sus propios compiladores. Microsoft, como proveedor de SO, tiene Microsoft Visual C. IBM, como proveedor de SO y proveedor de chips, tiene XLC (que es el compilador predeterminado del sistema para AIX, y el compilador con el que se compilan tanto AIX como i / OS) . Intel tiene su propio compilador. Sun / Oracle tiene su propio compilador en Sun Studio.

Luego, están los proveedores de compiladores de alto rendimiento como PathScale y The Portland Group, cuyos compiladores (y bibliotecas OpenMP) se utilizan para la numeración.

Digital Mars también sigue en el negocio. Creo que Walter Bright tiene la distinción única de ser la única persona en el planeta que logró crear un compilador de C ++ con calidad de producción (principalmente) solo.

Por último, pero no menos importante, tenemos todos los compiladores patentados para microcontroladores integrados. IIRC, se venden más microcontroladores cada año que las CPU de escritorio, móviles, servidores, estaciones de trabajo y mainframe que se han vendido en toda la historia de la informática combinada. Entonces, definitivamente no son productos especializados.

Se hace una mención honorífica a TruffleC , un intérprete de C (!) Que se ejecuta en la JVM (!) Escrito usando el marco de intérprete Truffle AST que es solo un 7% más lento que GCC y Clang (lo que sea más rápido en cualquier punto de referencia particular) en todo el Computer Languages ​​Benchmark Game, y más rápido que ambos en microbenchmarks. Usando TruffleC, el equipo de Truffle pudo obtener su versión de JRuby + Truffle para ejecutar extensiones de Ruby C más rápido que la implementación real de C Ruby.

Entonces, estas son 6 implementaciones además de las que enumeraste, que puedo nombrar en la parte superior de mi cabeza, sin siquiera saber nada sobre C.

Jörg W Mittag
fuente
1
Fuera de Microsoft Visual C, la mayoría de los compiladores de C que menciona rara vez se usan.
Basile Starynkevitch
66
MSVC es el gran compilador de C ++, pero para C es difícil de usar y está permanentemente atascado en C89; Los compiladores de microcontroladores suelen ser específicos del objetivo, atascados en C89 y extravagantes; TruffleC todavía no parece estar disponible (pero es interesante, gracias). Sin embargo, Pathscale y Digital Mars se parecen más al tipo de contraejemplos que estaba buscando.
Leushenko
8
@ Mario, mi significado no es que C89 esté roto, pero C89 no es la forma actualizada del lenguaje; y eso significa que existen menos compiladores actualizados .
Leushenko
66
@Leushenko MSVC no está permanentemente atascado en C89. Ha habido algunas discusiones y se deben agregar más funciones C99. Para empezar, la mayor parte de la biblioteca C99 es compatible a partir de MSVC 2015 y algunas características del lenguaje también (principalmente las cosas necesarias para C ++ 11).
Morwenn
55
@Morwenn: la política de Microsoft parece ser que C99 no resuelve ningún problema que C ++ aún no haya resuelto, y que si está haciendo la programación del sistema, debería usar el subconjunto tipo C de C ++ (cualquier cosa que no requiera el tiempo de ejecución o donde no puede controlar dónde va a colocar las cosas el compilador: importante si necesita asegurarse de que el código o los datos no se eliminen de los estados donde la paginación está desactivada). Las únicas características de C99 serán las que se requieren en especificaciones posteriores de C ++, y aquellas que no son fáciles de implementar.
Mike Dimmick
8

¿Cuántos compiladores necesitas?

Si tienen diferentes conjuntos de características, crea un problema de portabilidad. Si se comercializan, elige el "predeterminado" (GCC, Clang o VS). Si le importa el último rendimiento del 5%, tiene un punto de referencia.

Si está haciendo un trabajo de lenguaje de programación de forma recreativa o con fines de investigación, es probable que sea en un lenguaje más moderno. De ahí la proliferación de compiladores de juguetes para Scheme y ML. Aunque OCaml parece estar obteniendo cierta tracción para usos no académicos y no de juguete.

Tenga en cuenta que esto varía mucho según el idioma. Java tiene esencialmente la cadena de herramientas Sun / Oracle y la GNU. Python tiene varios compiladores, ninguno de los cuales es realmente respetado en comparación con el intérprete estándar. Rust and Go tiene exactamente una implementación cada uno. C # tiene Microsoft y Mono.

pjc50
fuente
1
Es obvio que hay razones más interesantes para desarrollar un compilador de ML ... Simplemente pensé que la comunidad C, siendo probablemente tres órdenes de magnitud más grande, equilibraría ese efecto. Pero puede que tengas razón, 1000 * 0todavía está 0.
Leushenko
La creación de un nuevo compilador a menudo se vincula con la fragmentación de la comunidad (ya sea causada o causando). Por ejemplo, el mantenedor egcs vs gcc se dividió. Además, la compatibilidad de la fuente C tiende a ser inferior al 100%.
pjc50
@ pjc50: La forma en que la norma está escrita de manera efectiva subdivide C en un número de dialectos disjuntas basándose en cosas como el tipo básico de int, y requerirá diferentes compiladores de interpretar el mismo código fuente de maneras muy diferentes.
supercat
55
Creo que Go tiene dos implementaciones (la 6g/ 8g/ ... toolchain y gccgo). También solía haber una implementación comercial patentada muy interesante llamada erGo, que era a) una implementación nativa de Go de Windows en un momento en que ni gccgo ni el compilador original de Go funcionaban muy bien en Windows, b) una compañía que apostaba por Go, mucho tiempo incluso antes de que se convirtiera en 1.0, yc) la primera implementación de Go escrita en Go (gccgo y 6g / 8g están escritos en C). Sin embargo, tanto el proyecto como la compañía desaparecieron, incluso antes de que salieran de la beta cerrada.
Jörg W Mittag
6

C / C ++ es único entre los lenguajes compilados, ya que tiene 3 implementaciones principales de una especificación común.

Siguiendo la regla de descartar cualquier cosa que no se use mucho, cualquier otro lenguaje compilado tiene 0 a 1.

Y creo que javascript es la única razón por la que necesita especificar 'compilado'.

soru
fuente
2
La etiqueta "C" se aplica a varios idiomas diferentes; algunos definen el código uint16_t a=48000u; unsigned uint32_t b=(a*a)/2;como la asignación al bvalor 8192. Algunos lo definen como la asignación de 1152000000. La mayoría lo considera hoy en día como Comportamiento indefinido y es probable que almacene 3299483648, pero no promete nada al respecto.
supercat
1
@supercat: Ah, un buen extraño con desbordamientos y reglas de promoción de enteros. Depende del uso 2o 2uaparentemente.
Zan Lynx
1
@ZanLynx: No creo que haya casos en los que 2 versus 2u sean legítimamente importantes; El único caso que sé dónde podría importar involucra Comportamiento Indefinido con 2 y 2u.
supercat
3
@supercat: ¿cómo obtendrías un comportamiento indefinido /2u? El desbordamiento sin signo está definido (como módulo 2 ^ N para N definido por la implementación) pero la división ni siquiera puede desbordarse.
MSalters
2
El comportamiento indefinido provendría de la multiplicación de valores que serían promovidos a firmados int, pero cuyo producto no encajaría en ese tipo. La conversión de ese resultado a unsigned int probablemente cambiaría la interpretación del valor resultante, pero no negaría el Comportamiento Indefinido del cálculo anterior.
supercat
5

Entonces, ¿cuál es su idioma de destino?

Los compiladores SML a menudo apuntan a C o algo así como LLVM (o como se ve en su enlace, JVM o JavaScript).

Si está compilando C, no es porque vaya a la JVM. Vas a algo peor que C. Mucho peor. Y luego puedes duplicar ese infierno menor muchas veces para todas tus plataformas de destino.

Y claro, C no es C ++, pero diría que está más cerca de C ++ que Scheme. Tiene su propio subconjunto de maldad de comportamiento indefinido (estoy mirando el tamaño de los tipos incorporados). Y si arruinas esas minucias (o lo haces "correctamente" pero inesperadamente) entonces tienes décadas de código existente en sistemas vitales que te dirá cuán terrible eres. Si arruinas un compilador SML, simplemente no funcionará, y alguien podría notarlo. Algún día.

Telastyn
fuente
SML / NJ y PolyML están compilando en código máquina ...
Basile Starynkevitch
2
¿Cómo es el tamaño int "Comportamiento indefinido"? ¿Y por qué sería UB una carga para los vendedores de compiladores de todos modos? La única carga real para los escritores de compiladores es que los anchos int están definidos en la implementación, no no especificados, por lo que debe documentar lo que hizo.
MSalters
@MSalters En realidad, los escritores de compiladores para una plataforma establecida tienen la carga de igualar lo que otros hicieron antes que ellos. A veces esto está documentado y estandarizado, a veces no. Es fácil encontrar el tamaño de un int, pero es más difícil encontrar qué se hace con los valores de registro y dónde se almacenan los argumentos al llamar a una función (que puede cambiar según los tipos de argumento y el tipo de retorno de la función), las reglas de diseño de estructura, etc.
Random832
@MSalters La mayoría de las personas esperan inttener 32 o 64 bits, pero puede ser tan pequeño como 16 bits. No es difícil en absoluto producir un número fuera del rango [−32767, +32767]y el intdesbordamiento es UB. También hay char/ shortser promovido int ao unsigned int dependiendo de si intpuede representar cada valor del tipo original, lo que puede desencadenar aún más una conversión de inta unsigned intsi los operandos tenían diferentes tipos y se convirtieron de manera diferente, además de potencialmente otra conversión cuando asigna el resultado a una variable .
Doval
@MSalters Hay suficiente margen de maniobra en el tamaño de los tipos estándar y suficientes conversiones implícitas que apostaría a que para casi cualquier programa C no trivial hay una variedad de tamaños enteros legales que harán que haga lo incorrecto o que no se definan comportamiento.
Doval