Centro de Estudos, Desenvolvimento e Inovação em Software | Universidade de Brasília

Geração de código intermediário

FGA0003 - Compiladores 1 | Semana 8 | Aula teórica

Prof. Sergio Antônio Andrade de Freitas
Compiladores 1 - Engenharia de Software · 2025/2
símbolo CEDIS logo UnB
símbolo CEDISCEDIS
2/29

Objetivos de aprendizagem

  • Definir o papel da representação intermediária no compilador.
  • Comparar AST, DAG, TAC, bytecode e SSA.
  • Transformar expressões simples em código de três endereços.
  • Relacionar ações semânticas do Bison à geração de RI.
  • Diagnosticar oportunidades de otimização em código intermediário.
símbolo CEDISCEDIS
3/29

Roteiro da aula

  1. 01Revisão do pipeline de compilação
  2. 02Conceito e benefícios da RI
  3. 03Famílias de representações intermediárias
  4. 04Exemplo guiado de AST para TAC
  5. 05SSA, bytecode e otimizações
  6. 06Síntese para a prática com Flex e Bison
símbolo CEDISCEDIS
4/29

Revisão do pipeline construído

Até aqui, o compilador já reconhece tokens, estrutura sintática e parte das regras semânticas.

  • Flex transforma caracteres em tokens.
  • Bison valida a gramática e constrói estruturas internas.
  • A análise semântica anota tipos, escopos e declarações.
  • A próxima questão é representar o programa para gerar código.
Pipeline do compilador com destaque na representação intermediária
A RI aparece após a validação semântica e antes da otimização.
seção

Da análise para a síntese

A representação intermediária marca a transição entre entender o programa e produzir uma forma executável.

símbolo CEDISCEDIS
6/29

Por que usar uma representação intermediária?

Modularidade

Separa front-end e back-end, reduzindo acoplamento.

Portabilidade

Facilita adaptar o compilador a novas arquiteturas-alvo.

Otimização

Permite aplicar transformações antes do código final.

Testabilidade

Torna visível uma etapa intermediária do compilador.

símbolo CEDISCEDIS
7/29
atividade

Atividade 1: papel da RI

Qual é a principal função da representação intermediária em um compilador?

  1. Substituir completamente as análises léxica e sintática.
  2. Fornecer uma representação interna que conecte o front-end ao back-end.
  3. Executar diretamente o programa antes da análise semântica.
  4. Armazenar apenas os erros encontrados pelo compilador.
QR Code para acesso à atividade
símbolo CEDISCEDIS
8/29
Mapa de famílias de representações intermediárias
Cada formato privilegia uma finalidade de análise, tradução ou otimização.

Famílias de representações intermediárias

A RI não é um único formato. Ela pode preservar estrutura, linearizar operações ou preparar execução em máquina virtual.

  • Alto nível: AST e DAG.
  • Linear: notação pós-fixada e TAC.
  • Máquina virtual: P-Code e bytecode.
  • Otimização: SSA e fluxo de dados.
símbolo CEDISCEDIS
9/29

Representações gráficas: AST e DAG

AST

  • Preserva hierarquia abstrata do programa.
  • Remove tokens auxiliares da gramática concreta.
  • É adequada para análise semântica e travessias.

DAG

  • Compartilha subexpressões equivalentes.
  • Reduz recomputações em expressões repetidas.
  • Expõe oportunidades de otimização local.
símbolo CEDISCEDIS
10/29

Quando um DAG economiza trabalho?

Na expressão x = (a + b) * (a + b), a subexpressão a + b aparece duas vezes.

  • A AST representa as duas ocorrências separadamente.
  • O DAG compartilha um único nó para a subexpressão comum.
  • Essa estrutura antecipa a eliminação de subexpressões comuns.
Comparação entre AST e DAG para uma expressão com subexpressão comum
Compartilhar nós evita representar a mesma computação duas vezes.
símbolo CEDISCEDIS
11/29
atividade

Atividade 2: AST e DAG

Qual característica diferencia um DAG de uma AST no contexto de otimização?

  1. O DAG pode compartilhar um mesmo nó entre ocorrências equivalentes de uma subexpressão.
  2. O DAG mantém obrigatoriamente todos os parênteses e separadores do código-fonte.
  3. A AST não representa operadores ou operandos.
  4. A AST sempre contém menos nós que o DAG.
QR Code para acesso à atividade
seção

Linearizar para gerar código

Para emitir código, é útil transformar estruturas hierárquicas em uma sequência explícita de instruções.

símbolo CEDISCEDIS
13/29

Representações lineares

Notação pós-fixada

Operadores aparecem depois dos operandos: a b +.

TAC

Instruções simples com no máximo três endereços.

Quádruplas

Registram operador, argumento 1, argumento 2 e resultado.

Triplas

Referenciam resultados por posição da instrução.

símbolo CEDISCEDIS
14/29
Transformação de AST em código de três endereços
A estrutura da AST determina a ordem de emissão do TAC.

Exemplo guiado: de expressão para TAC

A expressão x = a * b + c exige respeitar precedência, criar temporária e emitir instruções em ordem.

  • Primeiro, calcula-se a * b.
  • O resultado intermediário é guardado em t1.
  • Depois, soma-se t1 com c e armazena-se em x.
símbolo CEDISCEDIS
15/29

TAC como contrato de teste

Entrada

x = a * b + c;

  • O parser reconhece a expressão.
  • A AST preserva a precedência.
  • A semântica valida identificadores e tipos.

Saída intermediária

t1 = a * b x = t1 + c

  • A ordem de avaliação fica explícita.
  • Temporárias tornam resultados visíveis.
  • Testes podem comparar a RI esperada.
símbolo CEDISCEDIS
16/29
atividade

Atividade 3: geração de TAC

Qual TAC representa corretamente x = a * b + c?

  1. t1 = b + c; x = a * t1
  2. t1 = a * b; x = t1 + c
  3. t1 = a + b; x = t1 * c
  4. x = a; x = b; x = c
QR Code para acesso à atividade
símbolo CEDISCEDIS
17/29

Quádruplas, triplas e triplas indiretas

Quádruplas

Cada instrução possui operador, dois argumentos e resultado.

  • Exemplo: (*, a, b, t1)
  • Fácil de reordenar e otimizar.

Triplas

O resultado é identificado pela posição da instrução.

  • Exemplo: (*, a, b)
  • Reduz campos, mas exige cuidado ao mover instruções.
símbolo CEDISCEDIS
18/29

Máquinas virtuais: P-Code e bytecode

P-Code

Representação de máquina de pilha comum em compiladores educacionais.

Bytecode

Formato portável executado por uma máquina virtual, como JVM ou CLR.

Interpretação

A VM executa instruções intermediárias diretamente.

JIT

A VM compila trechos frequentes para código nativo em tempo de execução.

símbolo CEDISCEDIS
19/29

SSA: cada definição recebe uma versão

Em Static Single Assignment, cada variável recebe valor apenas uma vez. Novas atribuições geram novas versões.

  • x1, x2 e x3 representam versões distintas.
  • Funções φ combinam valores em junções de controle.
  • SSA facilita análises de fluxo de dados e otimizações.
Fluxo de controle com função phi em SSA
A função φ seleciona a versão que chega ao ponto de junção.
símbolo CEDISCEDIS
20/29
atividade

Atividade 4: SSA

Por que SSA utiliza diferentes versões de uma variável?

  1. Para assegurar que cada versão seja definida uma única vez.
  2. Para permitir que uma variável tenha vários tipos simultaneamente.
  3. Para eliminar a necessidade de fluxo de controle.
  4. Para substituir todas as variáveis por constantes.
QR Code para acesso à atividade
símbolo CEDISCEDIS
21/29

Geração de RI com Flex e Bison

1

1. Reconhecer

Flex retorna tokens para o parser gerado pelo Bison.

2

2. Construir

Ações semânticas criam nós da AST durante reduções.

3

3. Validar

A análise semântica anota tipos e identifica escopos.

4

4. Emitir

Uma travessia da AST gera temporárias e instruções TAC.

símbolo CEDISCEDIS
22/29

Cabeçalho institucional nos exemplos de código

Todo código didático gerado para a disciplina deve identificar a origem e o propósito.

  • FGA0003 - Compiladores 1
  • Curso de Engenharia de Software
  • Universidade de Brasília (UnB)
  • Exemplo didático: geração de código intermediário
símbolo CEDISCEDIS
23/29

Modelo mínimo de emissão de TAC

Funções auxiliares

  • novaTemp() cria temporárias.
  • emitir(op, arg1, arg2, res) registra instruções.
  • gerarTAC(no) percorre a AST.

Cuidados

  • Gerar código dos filhos antes do pai.
  • Preservar precedência já representada na AST.
  • Testar expressões pequenas antes de comandos complexos.
símbolo CEDISCEDIS
24/29

Otimizações em código intermediário

Constant folding

Calcula expressões constantes em tempo de compilação.

Constant propagation

Substitui usos por valores constantes conhecidos.

Dead code elimination

Remove instruções que não afetam o resultado observável.

CSE

Reutiliza o resultado de subexpressões comuns.

símbolo CEDISCEDIS
25/29
atividade

Atividade 5: otimização sobre RI

Considere t1 = a + b; t2 = a + b; x = t1 * t2. Qual otimização é diretamente aplicável?

  1. Eliminação de subexpressões comuns.
  2. Movimentação de código invariante de laço.
  3. Eliminação de código inalcançável.
  4. Desenrolamento de laço.
QR Code para acesso à atividade
símbolo CEDISCEDIS
26/29

Da aula teórica para a prática

AST e análise semântica

O compilador valida a estrutura e os significados básicos do programa.

Representação intermediária

A AST anotada é transformada em uma forma linear e testável.

Protótipo de TAC

As equipes implementam emissão de instruções e validam casos simples.

Otimização e código final

A RI passa a alimentar transformações e geração de saída executável.

símbolo CEDISCEDIS
27/29
Uma boa representação intermediária torna explícito o que precisa ser preservado e o que pode ser transformado.
Síntese da aula
símbolo CEDISCEDIS
28/29

Referências

  1. Aho, A. V., Lam, M. S., Sethi, R., & Ullman, J. D. (2006). Compilers: Principles, Techniques, and Tools (2nd ed.). Pearson.
  2. Appel, A. W. (2002). Modern Compiler Implementation in Java (2nd ed.). Cambridge University Press.
  3. Cooper, K. D., & Torczon, L. (2012). Engineering a Compiler (2nd ed.). Morgan Kaufmann.
  4. Cytron, R., Ferrante, J., Rosen, B. K., Wegman, M. N., & Zadeck, F. K. (1991). Efficiently computing static single assignment form and the control dependence graph. ACM TOPLAS, 13(4), 451-490.
  5. Wirth, N. (2005). Compiler Construction. ETH Zurich.
símbolo CEDISCEDIS
29/29

Encerramento

Da AST anotada ao TAC, o compilador passa a ter uma forma verificável, transformável e preparada para a geração de código final.

→ avançar · ← voltar · deslize (touch) · n notas · f tela cheia · p imprimir