O que é um compilador?

Mulher trabalhando em casa em computador

Autores

Josh Schneider

Staff Writer

IBM Think

Ian Smalley

Staff Editor

IBM Think

O que é um compilador?

Um compilador é um tipo de programa de computador que converte código de uma linguagem de programação (a linguagem-fonte) em outra linguagem de programação (a linguagem-alvo).

Compiladores são usados para transformar código-fonte de alto nível em código-alvo de baixo nível (como linguagem assembly, código-objeto ou código de máquina), preservando a funcionalidade do programa.

Ferramentas crítica para a programação de computadores moderna e prática, os compiladores permitem que os programadores trabalhem em código de alto nível legível por humanos e, em seguida, convertam o código-fonte em código de destino executável. Compiladores também ajudam desenvolvedores de software a criar programas executáveis eficientes com segurança, estabilidade e portabilidade aprimoradas. Isso porque os compiladores auxiliam na identificação e resolução de erros, criando aplicações executáveis portáteis.

Embora todos os compiladores convertam código de alto nível em código executável de baixo nível, diferentes tipos de compiladores são usados para diferentes linguagens de programação e aplicações. Por exemplo, um compilador cruzado é usado para produzir código para um tipo diferente de CPU ou sistema operacional daquele no qual está em execução.

Quando o compilador ideal não está disponível ou ainda não foi desenvolvido, um compilador bootstrap temporário é usado para compilar um compilador mais permanente, melhor otimizado para compilar qualquer linguagem de programação específica.

Uma breve lista de outros softwares relacionados inclui:

  • Descompiladores: funcionam como compiladores reversos e convertem código de baixo nível em linguagens de alto nível.
  • Compiladores de fonte para fonte (ou transpilers): convertem código de alto nível em outras linguagens de alto nível.
  • Reescritores de linguagem: convertem expressões formais de código em diferentes formas sem alterar a linguagem.
  • Compiladores-compiladores: usados para criar compiladores genéricos e reutilizáveis ou componentes de compiladores que podem ser incorporados em finalidades mais específicas de projeto.

As mais recentes notícias de tecnologia, corroboradas por insights de especialistas.

Mantenha-se atualizado sobre as tendências mais importantes (e intrigantes) do setor em IA, automação, dados e muito mais com o boletim informativo Think. Consulte a Declaração de privacidade da IBM.

Agradecemos sua inscrição!

Sua assinatura será entregue em inglês. Você pode encontrar um link para cancelar a assinatura em todos os boletins informativos. Você pode gerenciar suas inscrições ou cancelar a inscrição aqui. Consulte nossa Declaração de privacidade da IBM para obter mais informações.

Como os compiladores funcionam

Na prática, usar um compilador pode ser tão simples quanto inserir um comando em uma linha de comando em qualquer sistema Linux (ou equivalente), especificando o arquivo executável do compilador e os arquivos-fonte a serem compilados. Esse comando instrui o sistema a processar o código-fonte, compilando-o em código de máquina de destino e resultando nos arquivos-objeto necessários para produzir um programa executável.

Compiladores de código aberto, como o GNU Compiler Collection (GCC) — uma robusta coleção de compiladores C comumente usada para compilar código C em programas C — ou o Clang estão disponíveis em repositórios como GitHub. Outros compiladores podem ser instalados sem custo ou adquiridos de uma ampla variedade de distribuidores. Eles também podem ser incorporados em ambientes de desenvolvimento integrados (IDEs) populares, que agrupam várias utilidades para desenvolvimento de software, incluindo editores de texto, documentação de API e ferramentas de depuração.     

Independentemente do compilador específico empregado, o processo de compilação de código envolve a passagem do código-fonte por vários níveis de análise, otimização e, em última instância, geração de código. O código-fonte passa sequencialmente pelas diferentes camadas de análise e é avaliado em cada etapa do processo.

Se o compilador reconhecer quaisquer problemas no código-fonte original, ele poderá retornar uma mensagem de erro, solicitando que os desenvolvedores corrijam os erros identificados antes de prosseguir com a compilação do restante do código. Em geral, os compiladores seguem as seguintes etapas:

  1. Análise léxica: a primeira etapa da compilação passa o código-fonte pelo analisador léxico (lexer) do compilador, um programa que transforma caracteres em unidades de linguagem significativas, como palavras-chave, identificadores e operadores. Essas unidades são conhecidas coletivamente como tokens. Essa etapa essencialmente prepara o código-fonte para a próxima etapa, convertendo elementos significativos e importantes do código em tokens com os quais o compilador pode trabalhar.
  2. Análise sintática: a segunda etapa do processo de compilação envia os tokens do lexer para o parser do compilador. Um parser é um programa que verifica erros de sintaxe e garante que o código-fonte siga corretamente as regras da linguagem-fonte. Se o parser não detectar erros durante a análise, ele gera uma representação abstrata da estrutura geral do código chamada Árvore de sintaxe abstrata (AST).
  3. Análise semântica: após verificar a sintaxe do código, um compilador realiza uma análise semântica no código analisado para deduzir a função pretendida do código-fonte. Nessa etapa, o compilador verifica erros lógicos, como variáveis não declaradas ou uso incorreto de operadores.
  4. Otimização: a otimização é uma etapa opcional comum em muitos compiladores para melhorar o desempenho geral do código compilado. A otimização pode identificar e remover código desnecessário, resultando em programas mais rápidos, eficientes e estáveis, além de encurtar o processo final de depuração.
  5. Geração de código: na etapa final do processo, o compilador converte a AST em código legível pela máquina. A saída final da geração de código é um código em linguagem assembly que pode então ser convertido em código binário e executado pelo sistema do computador.
AI Academy

Preparando-se para a IA com a nuvem híbrida

Liderada pelos principais líderes da IBM, o currículo dessa experiência foi desenvolvido para ajudar líderes empresariais a terem o conhecimento necessário para priorizar os investimentos em IA capazes de estimular o crescimento.

Estrutura do compilador de três estágios

Alguns compiladores podem não aderir estritamente à estrutura anterior. No entanto, embora alguns compiladores possam conter mais ou menos etapas, todas as fases da compilação podem ser atribuídas a um de três estágios: front-end, middle-end e back-end.

Essa estrutura de três estágios permite que os compiladores adotem uma abordagem modular. Ela possibilita combinar múltiplos front-ends para diferentes linguagens com back-ends para diferentes CPUs, compartilhando as capacidades de otimização de vários middle-ends aplicáveis.

Os três estágios de um compilador envolvem a seguinte distribuição:

  1. Front-end: o front-end de um compilador inclui aspectos de análise léxica, análise sintática e análise semântica. Esse estágio verifica a sintaxe e a semântica de acordo com as regras da linguagem-fonte e pode identificar e localizar erros no código-fonte. Pressupondo que não sejam encontrados erros, o front-end do compilador converte o código-fonte em uma representação intermediária (IR) — uma conversão temporária de nível mais baixo do código-fonte — para o middle-end.
  2. Middle-end: o estágio de middle-end de um compilador executa várias otimizações de código na IR, independentemente da arquitetura de CPU que esteja sendo alvo do processo geral de compilação. Ao aplicar otimizações no código-fonte de forma independente do código de máquina de destino, o compilador pode aplicar otimizações generalizadas que melhoram o desempenho do código em múltiplas versões. Essas melhorias podem ser feitas independentemente da linguagem ou da arquitetura de hardware suportada.
  3. Back-end: o estágio de back-end usa a saída do estágio de middle-end e pode executar outras otimizações e conversões específicas de CPU. Nesse estágio final do processo de compilação, o compilador gera código assembly dependente do alvo, incluindo alocação de registradores e escalonamento de instruções. O estágio de back-end geralmente resulta em código de máquina especializado para sistemas operacionais e hardware de destino.

Benefícios de usar um compilador

Embora compiladores não sejam explicitamente necessários para produzir código utilizável, a grande variedade e complexidade tanto das linguagens de programação quanto dos ambientes de máquina tornam os compiladores uma necessidade prática para criar software executável. Estes são os quatro principais benefícios de usar compiladores de software.

Facilitar a programação em linguagens de alto nível

Linguagens de programação de alto nível usam sintaxe e palavras-chave mais próximas das linguagens faladas, o que as torna muito mais fáceis de usar para desenvolvedores. Compiladores convertem esse código legível por humanos no código de máquina mais complexo necessário para executar aplicações de software otimizadas.

Alguns exemplos de linguagens de alto nível incluem:

  • Python (usada para desenvolvimento web, ciência de dados e outros)
  • Java (usada para desenvolvimento Android, aplicações corporativas e outros)
  • C++ (usada para desenvolvimento de jogos, sistemas operacionais e outros)
  • JavaScript (usada para desenvolvimento web dinâmico e interativo)
  • PHP (usada para script do lado do servidor no desenvolvimento web)
  • C# (usada para aplicações Windows, desenvolvimento de jogos com o motor Unity)
Reduzir repetição

Compiladores ajudam a melhorar a eficiência convertendo código de alto nível em código de máquina executável. A saída do compilador é armazenada com a extensão de arquivo .exe, que é executada diretamente por um computador. Devido ao compilador, escrever um programa executável se torna uma tarefa realizada uma única vez.

Depois de concluído, o código compilado pode ser executado quantas vezes for necessário. Esse processo ajuda os programas a rodarem, em geral, mais rápido e com mais eficiência, já que certas aplicações ou partes de aplicações podem ser executadas separadamente das tarefas de software em tempo de execução.

Melhorar portabilidade

Nem todos os sistemas conseguem executar todos os tipos de código de programação. Compiladores são usados para converter os tipos de código que desenvolvedores preferem usar nos tipos de código de que os sistemas precisam para operar. Dessa forma, compiladores melhoram a portabilidade dos programas ao converter software para uma ampla variedade de linguagens compatíveis, que podem ser facilmente armazenadas, transferidas e executadas em diversos sistemas operacionais e arquiteturas de hardware.

Promover otimização geral

Durante o processo de compilação, compiladores podem identificar e corrigir erros e falhas de software, resultando em programas mais estáveis e melhor otimizados. Compiladores também podem ajudar a melhorar a segurança do software, prevenindo erros relacionados a memória, como estouro de buffer, e gerando avisos se potenciais problemas de memória forem detectados.

Compiladores versus interpretadores

Embora compiladores sejam usados para converter código-fonte em código de máquina executável, interpretadores são outro tipo de programa que pode fornecer funcionalidade semelhante, mas por um mecanismo diferente.

Em vez de converter o código-fonte, interpretadores executam diretamente o código-fonte ou usam um código intermediário conhecido como bytecode, uma representação de baixo nível e independente de plataforma do código-fonte. O bytecode serve como intermediário entre o código-fonte legível por humanos e o código de máquina, sendo projetado para execução por uma máquina virtual (VM) em vez de diretamente no hardware de um computador.

Teoricamente, qualquer linguagem de programação pode ser executada com um compilador ou um interpretador. No entanto, linguagens de programação individuais tendem a ser mais adequadas para compilação ou para interpretação.

Na prática, a distinção entre linguagens de compilador e linguagens de interpretador às vezes pode se confundir — assim como a distinção entre compiladores e interpretadores em si — já que ambos os tipos de programas podem apresentar funcionalidades sobrepostas. Embora algumas linguagens sejam mais comumente compiladas e outras mais comumente interpretadas, é possível escrever um compilador para uma linguagem comumente interpretada e vice-versa.

As linguagens de alto nível geralmente são criadas com um tipo de conversão em mente — compilação ou interpretação —, mas essas são mais sugestões do que limitações rígidas. Por exemplo, BASIC é frequentemente chamada de linguagem interpretada e C de linguagem compilada, mas existem compiladores para BASIC assim como há interpretadores para C.

A principal diferença entre interpretadores e compiladores está no tempo e na otimização. Ambos os tipos de programas tentam converter código-fonte em código de destino que seja primeiro funcional e depois otimizado.

Dependendo do ambiente operacional, o código compilado ou interpretado pode ser mais adequado para rodar de forma eficiente, considerando as capacidades de hardware, memória e armazenamento. Dependendo das restrições de um programa específico, aplicação e hardware, compilação, interpretação ou uma combinação de ambos pode fornecer os melhores resultados.

Assim, a interpretação não pode substituir inteiramente a compilação, mas pode mover as funções de compilação para o segundo plano por meio de um processo de conversão gradual. Compiladores empregam uma estratégia de conversão antecipada (AOT), que converte o código-fonte em código de destino inteiramente antes de criar um arquivo executável.

Interpretadores, por outro lado, executam o código diretamente conforme uma aplicação o exige ou usam bytecode como intermediário para gerar código-fonte executável por máquina virtual. Dessa forma, interpretadores podem oferecer alguns ganhos de velocidade ou flexibilidade, mas em algum momento um conjunto de instruções de máquina executadas diretamente deve ser fornecido ao final do stack de execução.

Em alguns casos, quando a eficiência leve é prioridade, interpretadores especiais podem ser preferíveis a compiladores por sua capacidade de realizar conversão just-in-time (JIT). O JIT é uma estratégia que compila partes do código-fonte em código de destino em um buffer de memória para execução imediata. A interpretação JIT compila código sob demanda, combinando a eficiência da compilação única de um compilador tradicional com a flexibilidade de executar código repetidamente — muitas vezes mais rápido do que interpretadores padrão de bytecode.

No entanto, à medida que as tendências modernas em direção à compilação JIT aumentam, junto com a interpretação de bytecode dependente da situação, muitos compiladores estão sendo projetados para oferecer recursos tanto de compilação quanto de interpretação. Essa sobreposição torna ainda mais tênue a linha entre essas duas categorias.

Soluções relacionadas
IBM Cloud Infrastructure Center 

O IBM Cloud Infrastructure Center é uma plataforma de software compatível com o OpenStack para gerenciamento da infraestrutura de nuvens privadas em sistemas IBM zSystems e no IBM LinuxONE.

Explore o Cloud Infrastructure Center
Soluções de infraestrutura de TI

Conheça servidores, armazenamento e software projetados para sua estratégia corporativa de nuvem híbrida e IA.

Saiba mais sobre as soluções de infraestrutura de TI
Soluções de infraestrutura em nuvem

Encontre a solução ideal de infraestrutura em nuvem para as necessidades do seu negócio e expanda os recursos conforme a demanda.

Soluções em nuvem
Dê o próximo passo

Transforme sua infraestrutura empresarial com as soluções da IBM prontas para IA e nuvem híbrida. Descubra servidores, armazenamento e software projetados para proteger, expandir e modernizar seus negócios ou acesse insights de especialistas para aprimorar sua estratégia de IA generativa.

Saiba mais sobre as soluções de infraestrutura de TI Baixe o e-book