Una Intermediate Language (IL), también conocida como código intermedio o bytecode, es una representación de código que se encuentra entre el código fuente de alto nivel (como C#, Java o Python) y el código máquina específico de una arquitectura. Su propósito principal es desacoplar el proceso de compilación en fases distintas: una que traduce el código fuente a IL y otra que traduce la IL a código máquina nativo o la interpreta. Esto permite aplicar optimizaciones independientes de la plataforma y facilita la portabilidad, ya que la misma IL puede ser ejecutada en diferentes arquitecturas mediante una máquina virtual (VM) o un compilador Just-In-Time (JIT).
La implementación de IL es fundamental en muchos ecosistemas de software modernos. Ejemplos prominentes incluyen el Common Intermediate Language (CIL) de .NET, que es el bytecode al que se compilan lenguajes como C#, F# y VB.NET antes de ser ejecutados por el Common Language Runtime (CLR). Otro ejemplo clave es el Java bytecode, que es el formato de IL al que se compilan los programas Java y que es interpretado o compilado JIT por la Java Virtual Machine (JVM). WebAssembly (Wasm) es una IL binaria de bajo nivel diseñada para ser un objetivo de compilación portátil para lenguajes de alto nivel, permitiendo su ejecución de alto rendimiento en navegadores web y entornos de servidor.
Para un arquitecto de sistemas, la elección y el entendimiento de una IL son cruciales por varias razones estratégicas. Primero, la IL facilita la interoperabilidad entre lenguajes, permitiendo que componentes escritos en diferentes lenguajes se integren si todos compilan a la misma IL (como en .NET o JVM). Segundo, la IL es clave para la portabilidad, ya que una aplicación puede ejecutarse en múltiples sistemas operativos y arquitecturas sin recompilación específica para cada uno, reduciendo la complejidad de despliegue. Tercero, las optimizaciones pueden aplicarse a nivel de IL, lo que puede mejorar el rendimiento de la aplicación independientemente del lenguaje fuente original. Sin embargo, el uso de una IL introduce una capa de abstracción que puede añadir una sobrecarga de rendimiento (aunque a menudo mitigada por compiladores JIT avanzados) y puede complicar la depuración en ciertos escenarios. Un arquitecto debe sopesar estos trade-offs al diseñar plataformas o seleccionar tecnologías, considerando el equilibrio entre rendimiento, portabilidad, interoperabilidad y complejidad del ecosistema.