A pergunta central
Como uma operação abstrata da RI vira instruções de uma máquina concreta?
FGA0003 - Compiladores 1 | Semana 10 | Aula teórica
A geração final consome a RI, já verificada e eventualmente otimizada, e produz código para um alvo.
Como uma operação abstrata da RI vira instruções de uma máquina concreta?
O código-alvo deve preservar o comportamento do programa.
Instruções, registradores e memória devem ser usados com critério.
O código precisa respeitar a arquitetura ou máquina virtual de destino.
Qual tarefa não pertence à geração de código final?
A geração de código final pode produzir um artefato que ainda será processado por outras ferramentas.
Usaremos o mesmo TAC em várias decisões do gerador.
Uma tradução possível carrega valores em registradores, executa operações e armazena o resultado.
Para t1 = a + b; x = t1, qual sequência é coerente?
Selecionar instruções, alocar registradores e escalonar instruções.
Mapeia operações da RI para instruções do alvo.
Decide quais valores ficam em registradores ou na memória.
Reordena instruções para reduzir esperas sem alterar dependências.
Define como variáveis, temporários e estruturas são acessados.
A seleção tenta cobrir a representação intermediária com padrões de instruções disponíveis.
x = y + 1
Escolher a sequência correta e barata para o alvo.
Registradores são rápidos, mas escassos. A alocação decide quais valores permanecem neles.
O que indica uma aresta em um grafo de interferência?
Há mais valores vivos que registradores disponíveis.
Mover temporariamente algum valor para a memória.
Gerar instruções extras de LOAD e STORE.
Derramar valores menos usados ou de menor impacto.
A ordem das instruções pode ser modificada para reduzir latências e aproveitar paralelismo.
Qual condição deve ser preservada ao reordenar instruções?
Legível por humanos, mas dependente da arquitetura.
Permite compilação separada e ligação posterior.
Executável em contexto fixo, com baixa portabilidade.
Portável para ambientes com máquina virtual compatível.
Qual formato é projetado para execução por uma máquina virtual em diferentes plataformas?
Bytecode desloca parte da geração final para o ambiente de execução.
Escolher instruções, administrar registradores e organizar o código sem mudar o programa.
Entrada principal do gerador.
Mapeia operações para o alvo.
Decide onde valores ficam.
Reordena respeitando dependências.
Assembly, objeto, executável ou bytecode.
Próximo passo: prototipar a geração de código final no projeto da equipe.