1 / 22

Compiladores - Introdução

Compiladores - Introdução. Guilherme Amaral Avelino gavelino@gmail.com. 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.

Download Presentation

Compiladores - Introdução

An Image/Link below is provided (as is) to download presentation Download Policy: Content on the Website is provided to you AS IS for your information and personal use and may not be sold / licensed / shared on other websites without getting consent from its author. Content is provided to you AS IS for your information and personal use only. Download presentation by click this link. While downloading, if for some reason you are not able to download a presentation, the publisher may have deleted the file from their server. During download, if you can't get a presentation, the file might be deleted by the publisher.

E N D

Presentation Transcript


  1. Compiladores - Introdução Guilherme Amaral Avelino gavelino@gmail.com

  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.

  3. O que é um Compilador? • Nesse processo de tradução, há duas tarefas básicas a serem executadas por um compilador: • 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

  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.

  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.

  6. Arquivo Haskell ' Parser Verificador de Tipos Desugarer CorePrinter Otimizações Sintaxe Core CoreToSTG Arquivo Core Sintaxe STG Gerador GHC Gerador de IL PhxSTGCompiler Código Assembly / Código C Código MSIL (Texto) Assembler / Compilador C ILDASM JIT Código Nativo Código Nativo 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. • Um dos modelos possíveis para a construção de compiladores faz a separação total entre o frontend, 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 destino. • Simplifica a implementação de novos compiladores • Front-end específico para cada linguagem • Back-end específico para a arquitetura alvo Front-end GHC Nativo Haskell.NET Assembly MSIL Back-end

  7. Compiladores - Fases código fonte • 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 Analisador léxico Analisador sintático Gerador tabela de símbolos Tratador de erros Analisador semântico Gerador de código intermediário Otimizador de código Gerador de código código alvo

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

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

  10. 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 árvore de parse do programa • Gramática livre de contexto é usada para definir aestrutura do programa reconhecida por um parser • Yacc/Bisonsão ferramentas para gerar parsers

  11. Análise Sintática Comando := Identificador Expressão + montante Expressão Expressão * Identificador Expressão Expressão saldo Identificador Número taxa_de_juros 60 Árvore gerada para: montante := saldo + taxa_de_juros * 60

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

  13. Análise Semântica * * montante + montante + saldo saldo * * taxa_de_juros 60 inttoreal taxa_de_juros Conversão de inteiro para real inserida pela análise semântica

  14. 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 alinguagem de baixo nível

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

  16. Gerador de Código Intermediário • Toda operação aritmética (binária) gera 3 instruções. Para b*c • Carga do primeiro operando no acumulador load b • Executa a operação correspondente com o segundo operando, deixando o resultado no acumulador mult c • Armazena o resultado em uma nova variável temporária store t1 • Um comando de atribuição gera sempre duas instruções. Para x:= t2 • Carrega o valor da expressão no acumulador load t2 • Armazena o resultado na variável store x

  17. Para o comando de atribuição x := a + b * c; é gerado o código intermediário: • Load b { t1 := b * c } • Mult c • Store t1 • Load a { t2 := a + t1 } • Add t1 • Store t2 • Load t2 • Store x { x := t2 }

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

  19. Otimizador de Código Load b Mult c Add a Store x • Load b • Mult c • Store t1 • Load a • Add t1 • Store t2 • Load t2 • Store x

  20. Otimizador de Código

  21. Gerador de Código • Produz o código objeto final • 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

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

More Related