geração de código fase final do compilador transforma o código da representação intermediária...
TRANSCRIPT
Geração de Código
• Fase final do compilador• Transforma o código da representação
intermediária no código final• Independente de otimizações• Código deve estar correto e ser de alta
qualidade, fazendo uso eficiente dos recursos da máquina-destino.
Geração de Código
front-end otimizador decódigo
geradorde código
tabela de símbolos
Geração de código
• geração de código ótimo é um problema indecidível.
• Usa-se hurísticas para gerar código bom, mas não ótimo.
• Qualidade do gerador de código afeta significativamente a performance de um programa.
Geração de código – aspectos relevantes
• entrada para o gerador de código – sem erros, na notação intermediária
• Programas gerados: código objeto relocável/não relocável, assembler, C.
• Gerenciamento de memória• Seleção de instruções – uniformidade de
instruções, completude, velocidade, tamanho
Seleção de instruções - exemplo
• para este tipo de instrução:x := y + z
• usar este template:MOV y, R0ADD z, R0MOV R0,x
Seleção de instruções – exemplo (cont.)
• compilar:a := b + cd := a + e
• MOV b, R0ADD c, R0MOV R0,aMOV a,R0ADD e,R0MOV R0,d
Geração de código – aspectos relevantes (cont.)
• Alocação de registradores – problema NP-completo.
• Escolha da ordem de avaliação – problema NP-completo
• Técnicas de geração de código.
Conjunto de instruções da máquina-destino
• n registradores R0, R1, …, Rn-1• instruções do tipo
op source, destinationpor exemplo MOV, ADD, SUB
• modos de endereçamento: absoluto, registrador, indexado, indeireto por registrador, indireto indexado
Modos de endereçamentoModo Forma Endereço Custo
absoluto M M 1
registrador R R 0
indexado c(R) c + contents(R) 1
registrador indexado
*R contents(R) 0
indireto indexado
*c(R) contents(c + contents(R))
1
literal #c c 1
Modos de endereçamento - exemplos
• MOV R0, M• MOV 4(R0),M
contents(4 + contents(R0))• MOV *4(R0),M
contents(contents(4 + contents(R0)))• MOV #1,R0• SUB 4(R0), *12(R1)
contents(contents(12 + contents(R1))) – contents(contents(4 + R0))
Custo de instruções
• 1 + custo do modo de endereçamento do operando de origem + custo do modo de endereçamento do operando de destino
• Comprimento da instrução.
Custo de instruções - exemplo
• a := b + c• MOV b,R0
ADD c,R0MOV R0,a
• MOV b,aADD c,a
• se R0, R1 e R2 contém o endereço de a, b e c:MOV *R1, *R0ADD *R2, *R0
Gerenciamento do ambiente de tempo de execução
/* código de c */action1
call paction2
halt
/* código de p */action3
return
return address
arr
i
j
return address
buf
n
Registro de ativação de c (64 bytes)
Registro de ativação de p (88 bytes)
0:
8:
56:
60:
0:
4:
84:
Grafo de Fluxo
• um grafo representando comandos de três endereços é chamado de grafo de fluxo (flow graph) é usado para entender algorítmos de geração de código, mesmo que não seja efetivamente construido.
• Nós representam computações, e arestas representam o fluxo de controle.
Blocos Básicos
• Sequência de comandos consecutivos em que o fluxo de controle entra no início e sai no final, sem possibilidade de desvio exceto no final.
• x := y + zdefine x e usa (ou referencia) y e z
• um nome em um bloco básico está vivo em um determinado ponto, se ele é usado depois daquele ponto do programa, possivelmente em outro bloco básico.
Blocos Básicos - exemplo
• begin prod := 0; i := 1; do begin prod := prod + a[i] * b[i]; I := i + 1; end while i <= 20end
Blocos Básicos - exemplo• (1) prod := 0
(2) i := 1(3) t1 := 4 * i(4) t2 := a [t1](5) t3 := 4 * i(6) t4 := b [t3](7) t5 := t2 * t4(8) t6 := prod + t5(9) prod := t6(10) t7 := i + 1(11) i := t7(12) if i <= 20 goto (3)
Transformações em blocos básicos
• transformações têm que preservar a semântica do bloco básico: os blocos antes e depois da transformação tem que ser equivalentes, i.e. computar o mesmo conjunto de expressões para os nomes vivos na saída do bloco.
• Transformações locais x transformações globais
Transformações locais
• transformações que preservam a estrutura:– eliminação de subexpressão comum– eliminação de código morto– renomeação de variáveis temporárias– troca de dois comandos adjacentes independentes
• transformações algébricas– x := x + 0– x := x * 1– de x := y ** 2 para x := y * y
Eliminação de subexpressão comum
• a := b + cb := a – dc := b + cd := a – d
• a := b + cb := a – dc := b + cd := b
Eliminação de código morto
• suponha que a variável x está morta no ponto em que ocorre a atribuição x := y + z Este comando pode ser removido sem mudar o resultado do bloco básico.
Renomeação de variáveis
• se temos o comandot := b + conde t é uma variável temporária, podemos substitui-lo poru := b + conde u é uma nova variável temporária, e substituir todas as referências a t por referências a u.
Troca de comandos
• t1 := b + ct2 := x + y
• t2 := x + yt1 := b + c
Grafo de Fluxo
t1 := 4 * it2 := a [t1]t3 := 4 * it4 := b [t3]t5 := t2 * t4t6 := prod + t5prod := t6t7 := i + 1i := t7if i <= 20 goto B2
prod := 0i := 1 B1
B2
Informações sobre próximo uso
• Coleta informações para cada variável em um bloco básico:– se ela está viva ao final do bloco– onde ela é usada (onde é seu próximo uso) dentro do
bloco.• Permite reuso de variáveis temporárias, e
facilita geração de código.