Clásicamente, un compilador tiene tres partes: análisis léxico, análisis y generación de código. El análisis léxico divide el texto del programa en palabras clave, nombres y valores del idioma. El análisis muestra cómo se combinan los tokens que provienen del análisis léxico en declaraciones sintácticamente correctas para el lenguaje. La generación de código toma las estructuras de datos producidas por el analizador y las traduce en código de máquina o alguna otra representación. Hoy en día, el análisis léxico y el análisis pueden combinarse en un solo paso.
Claramente, la persona que escribe el generador de código debe comprender el código de la máquina de destino a un nivel muy profundo, incluidos los conjuntos de instrucciones, las canalizaciones del procesador y el comportamiento de la memoria caché. De lo contrario, los programas producidos por el compilador serían lentos e ineficientes. Es muy posible que puedan leer y escribir código de máquina representado por números octales o hexadecimales, pero generalmente escribirán funciones para generar el código de máquina, refiriéndose internamente a tablas de instrucciones de máquina. Teóricamente, la gente que escribe el lexer y el analizador podría no saber nada sobre la generación del código de máquina. De hecho, algunos compiladores modernos le permiten conectar sus propias rutinas de generación de código que pueden emitir código de máquina para algunas CPU de las que los escritores lexer y parser nunca han oído hablar.
Sin embargo, en la práctica, los escritores de compiladores en cada paso saben mucho sobre las diferentes arquitecturas de procesador, y eso les ayuda a diseñar las estructuras de datos que necesitará el paso de generación de código.