COMPILADORES 08 Prof. Marcos GERAÇÃO DE CÓDIGO Compilação GERAÇÃO DE CÓDIGO A fase final de compilação é a geração de códigos. Recebe como entrada uma representação do programa-fonte (depois das análises: Lexica, Sintática e Semântica) e produz um programa-alvo equivalente. GERAÇÃO DE CÓDIGO São impostas muitas exigências a um gerador de código, pois o cócigo de saída tem que ser correto e de alta qualidade, possibilitando a melhor utilização dos recursos da máquina possível. GERAÇÃO DE CÓDIGO Responsável por produzir o código-alvo (final); Criação de estruturas que fará a alocação de memória para cada variável usada no programa; Criação das instruções intermediárias e elas são otimizadas e traduzidas numa seqüência de instruções de máquina (0´s e 1´s). GERAÇÃO DE CÓDIGO Utilização de estruturas básicas (templates) para a geração de código; Tratamento das estruturas If-then ou if-thenelse; Tratamento das estruturas de Loops (while, do-while, for). GERAÇÃO DE CÓDIGO Etapas Código de três endereços (inttermediário); Otimização: Geração final do código máquina. GERAÇÃO DE CÓDIGO Etapas Vantagens em se fazer em passos: Possibilita a otimização e melhoria do código intermediário fornecendo um código mais eficiente. Simplifica a implementação do compilador, com resoluções gradativas; Melhora a possibilidade de portabilidade:. GERAÇÃO DE CÓDIGO Código de Três Endereços Cada instrução referencia, no máximo, três variáveis (endereços de memória) Usa memória como auxílio básico; Uso extensivo de nomes temporários; Exemplos de instruções: A := B op C A := op B A := B goto L If A op log_B goto L GERAÇÃO DE CÓDIGO Código de Três Endereços A, B, C: identificadores, constantes ou temporários op: qualquer operador Op log: operador lófico de comparação Pode-se usar também ponteiro (*) ou endereço (&) GERAÇÃO DE CÓDIGO Código de Três Endereços Exemplo Valor := Valinicial + Taxa * 60 _t1 := int to real(60) _t2 := id3 * _t1 id1 _t3 := id2 + _t2 Id2 id1 = _t3 id3 Valor Valor Inicial Taxa GERAÇÃO DE CÓDIGO Notação Após a criação da árvore sintática, as expressões assumem formas que facilitam a criação de código. Estas expressões são: INFIXA, PRÉ-FIXA PÓS-FIXA. As GERAÇÃO DE CÓDIGO Notação Infixa Operador está entre os operandos: (A + B) Pré-Fixa Operador precede os operandos: ( + AB) Pós-Fixa Operador após os operandos: (AB +) GERAÇÃO DE CÓDIGO Notação INFIXA (a+b)*c a+b*c a*(b+c) PRÉ-FIXA ab+c* abc*+ abc+* PÓS-FIXA *+abc +a*bc *a+bc GERAÇÃO DE CÓDIGO Notação As formas pré-fixa e pós-fixa são conhecidas como notação polonesa e notação polonesa reversa. A notação pós-fixa tem mostrado ser a mais eficiente para construção de algoritmos. GERAÇÃO DE CÓDIGO Código de Três Endereços Para a realização da conversão infixa em pós-fixa, deve-se considerar a precedência das operações. Devemos lembrar que as operações de precedência mais alta devem ser convertidas primeiro. Em seguida, a parte convertida é encarada como um único operando. GERAÇÃO DE CÓDIGO Notação Suponha a expressão A + B * C. Colocando-se os parênteses para reforçar a precedência, ficaremos com A + (B * C). GERAÇÃO DE CÓDIGO Notação Então, deve-se converter à parte da multiplicação, obtendo-se A + (BC *). Agora imagine que D seja igual a BC*; ficaríamos assim A + D, o que resultaria AD+. Finalmente, realizando a devida substituição, ficamos com a forma final pósfica igual a ABC*+.