2. Sumário
Geração de código
-Geração de código intermediário
*Vantagens e Desvantagens
-Otimização
*Tipos
-Geração de código objeto(Final)
-Geração de código objeto–Convenção com a Linguagem C
-Referências.
2
3. Geração de código
A geração de código é uma das tarefas mais complexas
do compilador.
-Depende da linguagem-fonte, da máquina-alvo e seu
ambiente de execução e sistema operacional.
É conveniente dividi-la em etapas menores.
-Geração de código intermediário, otimização e geração
de código objeto.
3
5. Geração de código intermediário
Até o momento, utilizamos a árvore sintática e a tabela
de símbolos. Entretanto, ela não corresponde em nada
com o código-objeto.
Pode ser interessante gerar um código mais próximo do
objeto antes de fazer a tradução final:
Código intermediário
5
6. Geração de código intermediário
Esta fase utiliza a representação interna produzida
pelo analisador sintático e gera como saída uma
sequência de código.
Esse código pode, eventualmente, ser o código objeto
final mas, na maioria das vezes, se constitui em um
código intermediário, pois a tradução do código fonte
para objeto em mais de um passo apresenta algumas
vantagens.
6
7. Vantagens
Possibilita a otimização de código intermediário, de
modo a se obter o código objeto oficial mais eficiente;
Resolve, gradualmente, as dificuldades de passagem de
código objeto(alto nível para baixo nível), já que o
código fonte pode ser visto como um texto condensado
que explore em inúmeras instruções elementares de
baixo nível;
Simplifica a implementação do compilador.
7
8. Desvantagens
O compilador precisa fazer um passo a mais, dessa
forma, a tradução do código fonte para o objeto
leva a uma compilação mais lenta.
O intermediário não especifica detalhes da
maquina alvo.
8
9. Exemplo de Código Intermediário
while I < 100 do I := J + I ;
Para o comando while apresentado anteriormente, o gerador de código
intermediário, recebendo a árvore de derivação mostrada na figura, poderia produzir
a seguinte sequência de instruções.
9
10. While I < 100 do I := J+I;
L0 If I < 100 goto L
Goto L2
L1 Temp := J+I
I:=Temp
Goto L0
L2 ...
A linguagem intermediária do exemplo acima é
chamada "código de três endereços", pois cada
instrução tem no máximo três operandos.
10
11. Código de três endereços
Instrução mais básica: x = y op z
Exemplo:
2*a+(b-3) -> t1 = 2 * a
t2 = b - 3
t3 = t1 + t2
11
13. Otimização
Processo que visa melhorar a qualidade do código gerado
pelo compilador.
A Otimização de código é a estratégia de examinar o código
intermediário, produzido durante a fase de geração de
código com objetivo de produzir, através de algumas
técnicas, um código que execute com bastante eficiência
Qualidade de código pode ser medida por vários ângulos
Velocidade
Tamanho do código
Memória utilizada para temporários
13
15. Otimização
Apesar do termo otimização, não há garantia que o código
obtido durante o processo seja o melhor possível.
A otimização de código faz com que o compilador gaste
muito tempo de compilação, e deve ser implementada se o
uso do compilador realmente necessite de um código
objeto eficiente.
Entre as melhorias, podemos ter a escolha de modos de
endereçamento para melhorar o desempenho, a
substituição de instruções lentas por outras mais rápidas e
a eliminação de operações redundantes ou desnecessárias.
15
21. Geração de código objeto
Os principais requisitos impostos a geradores de código
objeto são os seguintes:
-O código gerado deve ser correto e de alta qualidade.
-O código deve fazer uso efetivo dos recursos da máquina.
-O código gerado deve executar eficientemente.
-O problema de gerar código ótimo é insolúvel
(indecidível) como tantos outros.
Na prática, devemos contentar-nos com técnicas
heurísticas que geram bom código (não necessariamente
ótimo).
21
22. Geração de código objeto
O gerador de código recebe como entrada uma
representação intermediária do programa fonte e o mapeia
em um linguagem objeto.
Se a linguagem objeto for código de máquina de alguma
arquitetura, devem-se selecionar os registradores ou
localizações de memória para cada das variáveis usadas
pelo programa.
Depois, os códigos intermediários são traduzidos em
sequencias de instruções e máquina que realizam a mesma
tarefa.
Um aspecto crítico da geração de código está relacionado à
cuidadosa atribuição dos registradores às variáveis do
programa.
22
23. Geração de código objeto –
Convenção com a Linguagem C
Por exemplo, uma sequência de código possível para a
expressão dada poderia ser (em uma linguagem de
montagem hipotética):
MOV R0, index ;; valor de index -> R0
MUL R0, 2 ;; dobra valor em R0
MOV R1, &a ;; endereço de a -> R1
ADD R1, R0 ;; adiciona R0 a R1
MOV *R1, 6 ;;constante 6 -> endereço em R1
23
24. Geração de código objeto –
Convenção com a Linguagem C
Nesse código, usamos uma convenção de C para os
modos de endereçamento, assim, &a é o endereço de a
(ou seja, o endereço inicial da matriz) e *R1 significa o
endereçamento indireto de registro (ou seja, a última
instrução armazena o valor 6 no endereço contido em
R1).
Nesse código, também assumimos que a máquina
efetua endereçamento de bytes e que inteiros ocupam
dois bytes de memória (daí o uso de 2 como fator de
multiplicação na segunda instrução).
24
26. REFERÊNCIAS
AHO, Alfredo V et al. COMPILADORES:
PRINCÍPIOS, TÉCNICAS E FERRAMENTAS. 2ª Ed,
São Paulo: 2008.
Disponível em:
http://www.ybadoo.com.br/ead/cmp/09/CMP_slides.
pdf. Acesso em 30 de Nov 2012.
26