compiladores - aula01

28
Introdução à Compilação - Aula 01 - Noiza Waltrick Trindade [[email protected]] Compiladores

Upload: lalah-sz

Post on 30-Jun-2015

305 views

Category:

Documents


3 download

TRANSCRIPT

Page 1: Compiladores - aula01

Introdução à Compilação

- Aula 01 -

Noiza Waltrick Trindade

[[email protected]]

Compiladores

Page 2: Compiladores - aula01

Pág. 2

O que é um Compilador?

“Um compilador é um programa que lê um programa

escrito em uma linguagem (linguagem fonte) e a

traduz em um programa equivalente em outra

linguagem (linguagem alvo).”

Aho, Sethi, Ullman.

Page 3: Compiladores - aula01

Pág. 3

O que é um Compilador?

Nesse processo de tradução, há duas tarefas

básicas a serem executadas por um compilador,

conhecida como modelo análise-síntese:

– Análise, em que o texto de entrada (na linguagem fonte) é

examinado, verificado e compreendido

• Análise léxica, sintática e semântica

– Síntese, ou geração de código, em que o texto de saída

(na linguagem objeto) é gerado, de forma a corresponder

ao texto de entrada

Page 4: Compiladores - aula01

Pág. 4

É possível representar completamente a sintaxe de

uma LP através de uma gramática sensível ao

contexto.

Mas como não existem algoritmos práticos para

tratar essas gramáticas, a preferência recai em usar

gramáticas livres de contexto.

Deixa-se para a análise semântica a verificação de

todos os aspectos da linguagens que não se

consegue exprimir de forma simples usando

gramáticas livres de contexto.

Page 5: Compiladores - aula01

Pág. 5

A implementação de reconhecedores de linguagens

regulares (autômatos finitos) é mais simples e mais

eficiente do que a implementação de reconhecedores de

linguagens livres de contexto (autômatos de pilha).

Nesse caso, é possível usar expressões regulares para

descrever a estrutura de componentes básicos das LP, tais

como identificadores, palavras reservadas, literais numéricos,

operadores e delimitadores, etc.

Essa parte da tarefa de análise (análise léxica) é

implementada separadamente, pela simulação de autômatos

finitos.

Page 6: Compiladores - aula01

Pág. 6

Compiladores – Separando em partes

Um dos modelos possíveis para a construção de compiladores faz a separação total entre o front-end, encarregado da fase de análise, e o back-end, encarregado da geração de código, de forma que◦ O front-end e back-end se comunicam

apenas através da representação intermediária

◦ O front-end depende exclusivamente da linguagem fonte;

◦ O back-end depende exclusivamente da linguagem objeto.

Verificador de Tipos

Parser

Desugarer

Sintaxe Core

CoreToSTG

Sintaxe STG

Gerador de IL

Código MSIL

(Texto)

ILDASM

Gerador GHC

Código Assembly

/ Código C

Assembler / Compilador C

Código Nativo

CorePrinter

ArquivoCore

PhxSTGCompiler

JIT

Código Nativo

Arquivo Haskell '

Otimizações

Haskell.

NE

T

GH

C N

ativo

Assembly MSIL

Front-end

Back-end

Page 7: Compiladores - aula01

Pág. 7

Compiladores – Separando em partes

Um dos modelos possíveis para a construção de

compiladores faz a separação total entre o front-

end, encarregado da fase de análise, e o back-end,

encarregado da geração de código, de forma que

– O front-end e o back-end se comunicam apenas através

da representação intermediária

Page 8: Compiladores - aula01

Pág. 8

Compiladores – Separando em partes

– O front-end depende exclusivamente da linguagem fonte;

• Consiste das fases que dependem primariamente da linguagem

fonte e são praticamente independentes da máquina alvo.

Normalmente, inclui a análise léxica, análise sintática, análise

semântica, a geração do código intermediário, além do

gerenciamento da tabela de símbolos e o tratador de erros. Às vezes

até o otimizador de código é colocado no front end.

– O back-end depende exclusivamente da linguagem destino.

• Consiste das fases que dependem da máquina alvo e geralmente

não dependem, em nada, do programa-fonte. As fases que contêm

estas propriedades são o otimizador de código e o gerador de

código, além do gerenciador da tabela de símbolos e o tratador de

erros.

Page 9: Compiladores - aula01

Pág. 9

Compiladores – Separando em partes

Simplifica a implementação de novos

compiladores

◦ Front-end específico para cada

linguagem

◦ Back-end específico para a arquitetura

alvo

Page 10: Compiladores - aula01

Pág. 10

Compiladores - Fases

Analisador

léxico

Analisador

sintático

Analisador

semântico

Gerador de

código

intermediário

Otimizador

de código

Gerador de

código

código fonte

código alvo

Tratador de

erros

Gerador tabela

de símbolos

Page 11: Compiladores - aula01

Pág. 11

Fases

Conjunto de alterações feitas no código as quais

são responsáveis por uma atividade específica do

processo de compilação

– Análise Léxica (scanner)

– Análise Sintática (parser)

– Análise Semântica

– Otimização

– Geração de código

Page 12: Compiladores - aula01

Pág. 12

Análise Léxica

Também chamada de scanner

Agrupa caracteres em símbolos (ou tokens)

Entrada: fluxo de caracteres

Saída: fluxo de símbolos

Símbolos são:

– Palavras reservadas, identificadores de variáveis e

procedimentos, operadores, pontuação,...

Uso de expressões regulares no reconhecimento

Lex/Flex são ferramentas que geram scanners.

Page 13: Compiladores - aula01

Pág. 13

Análise Léxica

Dado os caracteres da instrução

montante := saldo + taxa_de_juros * 30;

São identificados os seguintes tokens:

Identificador montant

Símbolo de atribuição :=

Identificador saldo

Símbolo de adição +

Identificador taxa_de_juros

Símbolo de multiplicação *

Número 30

Page 14: Compiladores - aula01

Pág. 14

Análise Sintática

Também chamada de parser

Agrupa símbolos em unidades sintáticas

– Ex.: os 3 símbolos A+B podem ser agrupados em uma estrutura

chamada de expressão.

Expressões depois podem ser agrupados para formar

comandos ou outras unidades.

Saída: representação da árvore de parse do programa

Gramática livre de contexto é usada para definir a estrutura

do programa reconhecida por um parser

Yacc/Bison são ferramentas para gerar parsers

Page 15: Compiladores - aula01

Pág. 15

Análise Sintática

Comando

Expressão

Identificador

Expressão

Expressão

Expressão

Expressão

:=

+

*

Identificador

Identificador

montante

saldo

taxa_de_juros

Número

60

Árvore gerada para: montante := saldo + taxa_de_juros * 60

Page 16: Compiladores - aula01

Pág. 16

Análise Semântica

Verifica se estruturas sintáticas, embora corretas

sintaticamente, têm significado admissível na linguagem.

Por exemplo, não é possível representar em uma gramática

livre de contexto uma regra como “todo identificador deve

ser declarado antes de ser usado“

Um importante componente é checagem de tipos.

Utiliza informações coletadas anteriormente e armazenadas

na tabela de símbolos

Considerando “A + B”, quais os possíveis problemas

semânticos?

Saída: árvore de parse anotada

Page 17: Compiladores - aula01

Pág. 17

Análise Semântica

montante +

*

saldo

taxa_de_juros

*

60

montante +

*

saldo

taxa_de_juros

*

inttoreal

Conversão de inteiro para real inserida pela análise semântica

Page 18: Compiladores - aula01

Pág. 18

Gerador de Código Intermediário

Usa as estruturas produzidas pelo analisador

sintático e verificadas pelo analisador semântico

para criar uma seqüência de instruções simples

(código intermediário)

Está entre a linguagem de alto nível e a linguagem

de baixo nível

Page 19: Compiladores - aula01

Pág. 19

Gerador de Código Intermediário

Considere que temos um único registrador

acumulador.

Considere o comando de atribuição

x := a + b * c

pode ser traduzido em:

t1:=b*c

t2:=a+t1

x:=t2

Pode-se fazer um gerador de código relativamente

simples usando regras como:

Page 20: Compiladores - aula01

Pág. 20

Gerador de Código Intermediário

Toda operação aritmética (binária) gera 3 instruções. Para b*c

1. Carga do primeiro operando no acumuladorload b

2. Executa a operação correspondente com o segundo operando, deixando o resultado no acumuladormult c

3. Armazena o resultado em uma nova variável temporáriastore t1

Um comando de atribuição gera sempre duas instruções. Para x:= t2

1. Carrega o valor da expressão no acumuladorload t2

2. Armazena o resultado na variávelstore x

Page 21: Compiladores - aula01

Pág. 21

Gerador de Código Intermediário

Para o comando de atribuiçãox := a + b * c;

é gerado o código intermediário:1. Load b { t1 := b * c }2. Mult c3. Store t14. Load a { t2 := a + t1 }5. Add t16. Store t27. Load t28. Store x { x := t2 }

Page 22: Compiladores - aula01

Pág. 22

Otimizador de Código

Independente da máquina

Melhora o código intermediário de modo que o

programa objeto seja menor (ocupe menos espaço

de memória) e/ou mais rápido (tenha tempo de

execução menor)

A saída do otimizador de código é um novo código

intermediário

Page 23: Compiladores - aula01

Pág. 23

Otimizador de Código

1. Load b

2. Mult c

3. Add a

4. Store x

Page 24: Compiladores - aula01

Pág. 24

Otimizador de Código

Page 25: Compiladores - aula01

Pág. 25

Gerador de Código

Produz o código objeto final

Cada máquina ou cada plataforma possui um conjunto

diferente de instruções e de meios de acesso ao sistema

operacional. Em geral é necessário um gerador de código

para cada plataforma.

Toma decisões com relação à:

– Alocação de espaço para os dados do programa;

– Seleção da forma de acessá-los;

– Definição de quais registradores serão usados, etc.

Projetar um gerador de código que produza programas

objeto eficientes é uma das tarefas mais difíceis no projeto

de um compilador

Page 26: Compiladores - aula01

Pág. 26

Gerador de Código

Várias considerações têm que ser feitas:

– Há vários tipos de instruções correspondendo a vários

tipos de dados e a vários modos de endereçamento;

– Há instruções de soma específicas, por exemplo para

incrementar/decrementar de 1;

– Algumas somas não foram especificadas explicitamente;

– Cálculo de endereço de posições em vetores;

– Incremento/decremento registrador de topo pilha;

– Local onde armazenar variáveis;

– Alocação de registradores.

Page 27: Compiladores - aula01

Pág. 27

Gerenciamento da Tabela de Símbolos

Uma função essencial do compilador é registrar os

identificadores usados no programa fonte e coletar

as informações sobre os seus diversos atributos de

um identificador, tais como: memória alocada, tipo,

escopo).

Uma tabela de símbolos é uma estrutura de dados

contendo um registro para cada identificador, com

os campos contendo os atributos do identificador.

Page 28: Compiladores - aula01

Pág. 28

Tratamento de Erros

Tipos de erros: léxicos, sintáticos, semânticos e

lógicos.

Os erros sintáticos são os mais freqüentes.

É ativado sempre que for detectado um erro no

programa fonte. Ele deve avisar o programador da

ocorrência do erro emitindo uma mensagem, e

ajustar-se novamente à informação sendo passada

de fase a fase de modo a poder completar o

processo de compilação (mesmo que não seja mais

possível gerar código objeto, a análise léxica e

sintática deve prosseguir até o fim).