• Nenhum resultado encontrado

Compiladores-13

N/A
N/A
Protected

Academic year: 2021

Share "Compiladores-13"

Copied!
44
0
0

Texto

(1)

Geração de Código

Intermediário

“Nação se levantará contra nação e reino contra reino. Haverá terremotos em vários lugares e também

fomes. Essas coisas são o início das dores [...]. O irmão trairá seu próprio irmão, entregando-o à morte, e o mesmo fará o pai a seu filho.”

(2)

Etapas da Compilação

Análise Léxica Análise Sintática Analise Semântica Geração de Código Intermediário Geração de Código Final Front-End (Análise) Back-End (Síntese)

(3)

Sumário da Aula

 Introdução

 Código de Três Endereços  Traduzindo Expressões

(4)
(5)

Geração de Código

Intermediário

O objetivo dessa etapa é gerar um código

intermediário equivalente ao código fonte dado

como entrada para o compilador

 Entrada: árvore sintática anotada  Saída: código intermediário

(6)

Código Intermediário

 O nome “intermediário” indica:

Que ele não é tão abstrato quanto o código fonte, nem tão dependente de máquina quanto o código alvo final

 Que ele é gerado em uma etapa intermediária da compilação (antes do código-alvo)

Um código intermediário deve ser simples e

independente de máquina

(7)

Objetivo

É simples para:

 Ser fácil de traduzir para código de máquina

É independente de máquina para:

Deixar apenas o back-end dependente de máquina

 Permitir gerar código para várias máquinas diferentes (a partir de uma mesma linguagem fonte)

(8)

Código Intermediário

 Existem diversos tipos

 A escolha depende da linguagem fonte e, até

mesmo, da(s) linguagem(ns) alvo

 Um desenvolvedor pode criar um novo tipo de

(9)

Código Intermediário

O livro afirma que a árvore sintática (já vista)

pode ser entendida como um tipo de código intermediário

(10)

Código Intermediário

 Veremos aqui um tipo mais interessante de

código intermediário – o código de três

endereços

 Mais fácil de traduzir para código final, como códigos assembly de x86 ou de MIPS, por exemplo

(11)
(12)

Código de Três Endereços

 Programas representados como uma simples

lista de instruções

 Muitas instruções são similares aos comandos de linguagens imperativas

 Porém são tão simples que lembram as instruções de vários códigos assembly (e.g., MIPS)

 As instruções usam, no máximo, três operandos

(13)

Tipos de Endereços

 Um “endereço” pode ser:

Um nome – representando uma variável, função, etc.

Uma constante – valor literal de um número, uma string, um caractere, etc.

Um temporário – variável auxiliar criada pelo compilador (t1, t2, etc.)

(14)

Tipos de Instruções

 Instruções de atribuição da forma

Onde op é um operador binário aritmético,

binário ou lógico

 Exemplo:

x = y op z

(15)

Tipos de Instruções

 Instruções de atribuição da forma

Onde op é um operador unário, como: negação

lógica, menos, conversão de tipo

 Exemplos:

x = op y

t1 = (int) temp; t1 = - temp;

(16)

Tipos de Instruções

 Instruções de cópia

 Numa fase posterior, de otimização, essa

instrução pode ser removida

(17)

Tipos de Instruções

 Desvio incondicional

Desvia para o rótulo L : faz com que a próxima

instrução a ser executada seja a que tem o rótulo L  Exemplo: goto L label2: aux = t + 1; ... goto label2

(18)

Tipos de Instruções

 Desvios condicionais

Desviam para o rótulo L dependendo do valor

booleano de x

if x goto L

(19)

Tipos de Instruções

 Desvios condicionais com operadores

relacionais (<, >, ==, !=, ...)

Desvia para L se o resultado da operação

relacional for verdadeiro

 Exemplo:

if x relop y goto L

label2:

aux = t + 1;

(20)

Tipos de Instruções

 Chamada de procedimento

Chama o procedimento Proc

(21)

Tipos de Instruções

 Preparação de parâmetros

 Definem os valores que serão passados em

uma chamada de procedimento

O exemplo dado representa: Proc(x1, x2, ...) param x1

param x2 ...

(22)

Tipos de Instruções

 Retorno de valor

 Usada dentro de um procedimento para retornar

o valor y

(23)

Tipos de Instruções

 Atribuições de endereços e ponteiros

 Acessam, respectivamente:

 O endereço de memória da variável y

 O valor que está no endereço que y guarda  O valor que está no endereço que x guarda

x = &y x = *y *x = y

(24)
(25)

Traduzindo Expressões

 Uma expressão com várias operações...

 ...é decomposta em expressões menores, com

uma operação cada

myVar = aux + temp * 3

t1 = 3

t2 = temp * t1 t3 = aux + t2 myVar = t3

(26)

Traduzindo Expressões

 A árvore sintática, na verdade, já guarda as

expressões decompostas da forma desejada

 O resultado de cada sub-expressão pode ser

armazenado em alguma variável

 Pode ser necessário criar uma variável temporária (criar função nextTempVar())

(27)

Traduzindo Expressões

 A regra geral para traduzir um nó que

representa uma operação binária:

1. Gerar o código das duas sub-expressões

2. Pegar os nomes das variáveis que guardam o resultado de cada sub-expressão

3. Criar uma instrução para executar a operação sobre essas duas variáveis

(28)

Exemplo

(29)

Curto-Circuito

Em expressões lógicas com operadores &&

(and) e || (or), é possível abreviar a avaliação, em alguns casos

 Lembrando que:

 Basta uma expressão ser falsa para o && delas dar falso

 Basta uma expressão ser verdadeira para o || delas dar verdadeiro

(30)

Curto-Circuito

 Em uma condição (expr1 && expr2)

 Se expr1 for falsa, nem precisa avaliar expr2

 Em uma condição (expr1 || expr2)

(31)

Curto-Circuito

 Avaliação de expressões lógicas com

curto-circuito é quando a avaliação dos seus

operandos é interrompida nos casos em que já é possível antecipar o valor dela

 Usada em muitas linguagens

 C/C++  Java  Python

(32)
(33)

Traduzindo Instruções

 Veremos como fazer a tradução de alguns

comandos mais representativos

 Atribuição  If-Else

 While

 Referências

(34)

Atribuição

 Primeiro, deve-se gerar código para a expressão

do lado direito

 Retorna o nome da variável que guardará o resultado da expressão

 Por fim, basta fazer uma instrução de cópia d a

variável retornada para a variável do lado esquerdo da atribuição

(35)

If-Else

 Criar dois labels (rótulos) únicos*

LElse: para o comando do else

LDepois: para a próxima instrução, após o if-else

* - crie um procedimento nextLabel() para retornar strings únicas

(36)

If-Else

 A primeira coisa a fazer é gerar o código da

expressão de teste

 Retorna o nome de uma variável

 Depois, deve-se gerar um comando de desvio

condicional ifFalse-goto aplicado à variável e ao label LElse

(37)

If-Else

 Depois, deve-se gerar o código do comando

dentro do if

 Lembrando que ele só vai ser atingido quando a expressão for verdadeira

Depois, gerar um desvio incondicional goto para

o label LDepois

(38)

If-Else

A seguir, deve-se escrever o label LElse

 Marca o início do código do else

Gerar o código do comando dentro do elseE, por fim, escrever o label LResto

(39)

If-Else

<código que avalia a expressão de teste aqui>

TN = <resultado da expressão>

ifFalse TN goto labelElse <código do bloco do “if”> goto labelResto

labeElse:

<código do bloco do “else”> labelResto:

(40)

If-Else

<código que avalia a expressão de teste aqui>

TN = <resultado da expressão>

ifFalse TN goto labelElse <código do bloco do “if”>

goto labelResto labeElse:

<código do bloco do “else”>

(41)

While

 Criar dois labels únicos

LInicio: para o início do while

LResto: para o próximo comando, após o while

 Naturalmente, deve-se começar escrevendo o

(42)

While

 Depois, gerar o código da expressão de teste

 E receber o nome da variável que guarda o resultado da expressão...

Depois, gerar um desvio condicional

ifFalse-goto aplicado à variável e ao label LResto

 Quando a expressão não for verdade, passa para o primeiro comando após o while

(43)

While

 Em seguida, deve-se gerar o código do

comando interno do while

 Depois, gerar uma instrução de desvio

incondicional goto para o label LInicio

 Para avaliar a expressão novamente e decidir se entra no laço novamente ou termina

(44)

Traduzindo Instruções

 Mostrei UMA possível maneira de gerar código

para cada um desses comandos

 A maneira vista é relativamente fácil de

implementar, mas gera código ineficiente

 A fase de otimização (que não veremos), poderia compensar isso...

 Usem esses exemplos como base para

Referências

Documentos relacionados

A diferença é que o certificado NF-e pode ser emitido em nome de um funcionário, ficando apenas para emissão de Nota Fiscal, sem acesso aos demais dados da empresa. Já o e-CNPJ

Como profissional de marketing digital, você precisa da permissão de um consumidor, cliente ou visitante do site para enviar a eles qualquer forma de comunicação que

E) CRIE NO SEU CADERNO UM TÍTULO PARA ESSA HISTÓRIA EM QUADRINHOS.. 3- QUE TAL JUNTAR AS SÍLABAS ABAIXO PARA FORMAR O NOME DE CINCO SUGESTÕES DE PRESENTE PARA O DIA

&#34;Ó bela menina, irei lhe responder, Não é eu que sou cruel,.. Vocês me fazem ser

Você precisa de foco no que faz para chegar longe, precisa ser bom em algo, tão bom que o seu cliente sempre lembrará de você quando precisar daquele frete... Você deve estar

Esteja atento quando estiver na estrada: é comum encontrar caminhões com a logomarca da empresa rodando por este Brasil, isto pode significar um caminhão de transportadora com

J.THYMM, Lda., desenvolve a sua atividade de produção de Leite na Herdade Vale de Cardeiros situada na Freguesia de Seda, concelho de Alter do Chão e Distrito de Portalegre (Fig..

•  Compilador lê todo o código-fonte e converte-o para linguagem de máquina (código-objeto);.. Compiladores