geração de código fase final do compilador transforma o código da representação intermediária...

25
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.

Upload: raphael-redondo

Post on 07-Apr-2016

214 views

Category:

Documents


0 download

TRANSCRIPT

Page 1: 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

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.

Page 2: 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

Geração de Código

front-end otimizador decódigo

geradorde código

tabela de símbolos

Page 3: 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

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.

Page 4: 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

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

Page 5: 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

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

Page 6: 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

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

Page 7: 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

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.

Page 8: 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

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

Page 9: 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

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

Page 10: 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

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))

Page 11: 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

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.

Page 12: 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

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

Page 13: 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

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:

Page 14: 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

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.

Page 15: 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

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.

Page 16: 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

Blocos Básicos - exemplo

• begin prod := 0; i := 1; do begin prod := prod + a[i] * b[i]; I := i + 1; end while i <= 20end

Page 17: 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

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)

Page 18: 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

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

Page 19: 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

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

Page 20: 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

Eliminação de subexpressão comum

• a := b + cb := a – dc := b + cd := a – d

• a := b + cb := a – dc := b + cd := b

Page 21: 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

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.

Page 22: 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

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.

Page 23: 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

Troca de comandos

• t1 := b + ct2 := x + y

• t2 := x + yt1 := b + c

Page 24: 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

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

Page 25: 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

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.