Carregar apresentação
A apresentação está carregando. Por favor, espere
1
CES-41 COMPILADORES Capítulo I Introdução
2
Capítulo I - Introdução
1.1 – Compiladores 1.2 – Estrutura de um compilador 1.3 – Interpretadores 1.4 – Automação da construção de compiladores
3
1.1 – Compiladores 1.1.1 – Definição Compilador é um software que
Lê um programa escrito numa linguagem: a linguagem-fonte (é o programa-fonte) Traduz em um programa equivalente, escrito noutra linguagem : a linguagem-objeto (é o programa-objeto) Reporta a presença de erros no programa-fonte
4
Esquematicamente: Compilador Programa fonte Programa objeto Mensagens
de erro
5
Possíveis linguagens-fontes:
Mais comuns: linguagens tradicionais de programação: Fortran, Pascal, C, Modula-2, C++, Java, etc. Linguagens especializadas: simulação, computação gráfica, banco de dados, experimentos Possíveis linguagens-objetos: Mais comuns: linguagem assembly ou linguagem de máquina de vários computadores Outras linguagens de programação
6
Exemplos de linguagens de programação como linguagens-objetos:
Transformação de programas sequenciais escritos em C ou Fortran, em programas paralelos escritos em HPF (High Performance Fortran) for (i = 1; i <= n; i++) C[i] = A[i] + B[i] do parallel i = 1, n C[i] = A[i] + B[i] for (i = 1; i <= n; i++) C[i] = A[i] + C[i-1] do parallel i = 1, n C[i] = A[i] + C[i-1]
7
Tradução de programas realizadores de certos experimentos:
Escritos numa linguagem especializada Traduzidos (compilados) para uma linguagem de programação como C Compilados depois por um compilador similar ao de C Programas em Lex e Yacc são traduzidos para C Lex e Yacc são linguagens especializadas para construir componentes de um compilador
8
Enfoque desta disciplina:
A linguagem-fonte é uma linguagem tradicional e a linguagem-objeto é o Assembly de uma máquina Para a implementação, a linguagem-fonte é Lex e Yacc e a linguagem-objeto é C
9
1.1.2 – O contexto de um compilador
Além do compilador, outros programas são exigidos para criar um programa executável nalguma máquina
10
Pré-processador Compilador Montador Editor de Ligações Carregador
Programa fonte com diretivas de pré-processamento Pré-processador Programa fonte Compilador Programa objeto em Assembly Montador Código de máquina com endereçamento deslocado Bibliotecas e outros arquivos com endereçamento deslocado Editor de Ligações Código de máquina executável com endereçamento deslocado Código de máquina executável com endereçamento correto Carregador
11
a) Pré-processador – realiza várias tarefas antes da compilação:
Inclusão de arquivos ao programa – Por exemplo, na Linguagem C: #include <math.h>: inclui protótipos de funções matemáticas pertencentes à biblioteca da linguagem; essas funções já estão em linguagem de máquina #include “sistemas.c”: inclui arquivo pertencente ao acervo do programador; contém código fonte
12
Processamento de macros – para abreviar construções longas
Exemplo, em C, com as macros: #define EHPAR(x) (((x)%2)?0:1) #define ERRO(msg) printf (“ERRO: % s/n”, msg) pode-se escrever comandos dos tipos: if (EHPAR(a+b)) ; if (valor max) ERRO(“valor muito grande”); O resultado do pré-processamento é: if ((((a+b)%2)?0:1)) ; if (valor > max) printf(“ERRO:%s\n”,“valor muito grande”); O pré-processador substitui a primeira parte do #define pela segunda, realizando inclusive passagem de argumentos
13
Processamento de extensões de linguagens:
Algumas linguagens são acrescidas de certos artifícios para propósitos específicos de certas aplicações Exemplos: comandos para manipular banco de dados, para computação gráfica, processamento paralelo, etc. Muitas linguagens são, na realidade, extensões da Linguagem C Diretivas iniciadas pelos caracteres “##” são substituídas pelo pré-processador por chamadas de funções, comandos do sistema operacional, etc.
14
b) Montador (Assembler):
Transforma o código Assembly, produzido pelo compilador, em código de máquina relocável Exemplo: programa em C para o cálculo do fatorial de um número digitado e seus correspondentes em Assembly e em linguagem de máquina Supõe-se uma CPU bem simples, com apenas um registrador de propósitos gerais (AC - acumulador) Para fazer C = A + B Sendo A, B e C endereços de memória Instrução Significado LD A AC Mem(A) ADD B AC AC + Mem(B) ST C Mem(C) AC
15
C1: CONST 1 C2: CONST 2 #include <stdio.h> void main ( ) { int n, fat, i; scanf (“%d”, &n); fat = 1; i = 2; while (i <= n) { fat = fat * i; i = i + 1; } printf (“%d”, fat); Primeiramente, reserva de espaço para as constantes 1 e 2
16
C1: CONST 1 C2: CONST 2 n: CONST 0 fat: CONST 0 i: CONST 0 #include <stdio.h> void main ( ) { int n, fat, i; scanf (“%d”, &n); fat = 1; i = 2; while (i <= n) { fat = fat * i; i = i + 1; } printf (“%d”, fat); Em seguida, reserva de espaço para as variáveis n, i, fat
17
C1: CONST 1 C2: CONST 2 n: CONST 0 fat: CONST 0 i: CONST 0 #include <stdio.h> void main ( ) { int n, fat, i; scanf (“%d”, &n); fat = 1; i = 2; while (i <= n) { fat = fat * i; i = i + 1; } printf (“%d”, fat); Agora a tradução dos comandos
18
C1: CONST 1 C2: CONST 2 n: CONST 0 fat: CONST 0 i: CONST 0 inic: READ n Rótulo da 1ª instrução executável: inic #include <stdio.h> void main ( ) { int n, fat, i; scanf (“%d”, &n); fat = 1; i = 2; while (i <= n) { fat = fat * i; i = i + 1; } printf (“%d”, fat); Na realidade, a tradução de scanf é algo mais complexo: É uma chamada de subprograma
19
C1: CONST 1 C2: CONST 2 n: CONST 0 fat: CONST 0 i: CONST 0 inic: READ n LD C1 ST fat LD C2 ST i Rótulo da 1ª instrução executável: inic #include <stdio.h> void main ( ) { int n, fat, i; scanf (“%d”, &n); fat = 1; i = 2; while (i <= n) { fat = fat * i; i = i + 1; } printf (“%d”, fat);
20
C1: CONST 1 C2: CONST 2 n: CONST 0 fat: CONST 0 i: CONST 0 inic: READ n LD C1 ST fat LD C2 ST i loop: SUB n JP escrever JUMP loop Rótulo da 1ª instrução executável: inic #include <stdio.h> void main ( ) { int n, fat, i; scanf (“%d”, &n); fat = 1; i = 2; while (i <= n) { fat = fat * i; i = i + 1; } printf (“%d”, fat); “escrever” é o rótulo da instrução logo após JUMP
21
C1: CONST 1 C2: CONST 2 n: CONST 0 fat: CONST 0 i: CONST 0 inic: READ n LD C1 ST fat LD C2 ST i loop: SUB n JP escrever LD fat MULT i LD i ADD C1 JUMP loop Rótulo da 1ª instrução executável: inic #include <stdio.h> void main ( ) { int n, fat, i; scanf (“%d”, &n); fat = 1; i = 2; while (i <= n) { fat = fat * i; i = i + 1; } printf (“%d”, fat);
22
C1: CONST 1 C2: CONST 2 n: CONST 0 fat: CONST 0 i: CONST 0 inic: READ n LD C1 ST fat LD C2 ST i loop: SUB n JP escrever LD fat MULT i LD i ADD C1 JUMP loop escrever:WRITE fat Rótulo da 1ª instrução executável: inic #include <stdio.h> void main ( ) { int n, fat, i; scanf (“%d”, &n); fat = 1; i = 2; while (i <= n) { fat = fat * i; i = i + 1; } printf (“%d”, fat); Na realidade, a tradução de printf é algo mais complexo: É uma chamada de subprograma
23
C1: CONST 1 C2: CONST 2 n: CONST 0 fat: CONST 0 i: CONST 0 inic: READ n LD C1 ST fat LD C2 ST i loop: SUB n JP escrever LD fat MULT i LD i ADD C1 JUMP loop escrever:WRITE fat STOP END inic Rótulo da 1ª instrução executável: inic #include <stdio.h> void main ( ) { int n, fat, i; scanf (“%d”, &n); fat = 1; i = 2; while (i <= n) { fat = fat * i; i = i + 1; } printf (“%d”, fat);
24
C1: CONST 1 C2: CONST 2 n: CONST 0 fat: CONST 0 i: CONST 0 inic: READ n LD C1 ST fat LD C2 ST i loop: SUB n JP escrever LD fat MULT i LD i ADD C1 JUMP loop escrever:WRITE fat STOP END inic #include <stdio.h> void main ( ) { int n, fat, i; scanf (“%d”, &n); fat = 1; i = 2; while (i <= n) { fat = fat * i; i = i + 1; } printf (“%d”, fat); Final da compilação Agora vem a montagem
25
C1: CONST 1 C2: CONST 2 n: CONST 0 fat: CONST 0 i: CONST 0
inic: READ n LD C1 ST fat LD C2 ST i loop: SUB n JP escrever LD fat MULT i LD i ADD C1 JUMP loop escrever:WRITE fat STOP END inic rótulo endereço endereço codop ender 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 O Assembler monta uma tabela de rótulos para ajudar a preencher o programa em linguagem de máquina
26
C1: CONST 1 C2: CONST 2 n: CONST 0 fat: CONST 0 i: CONST 0
inic: READ n LD C1 ST fat LD C2 ST i loop: SUB n JP escrever LD fat MULT i LD i ADD C1 JUMP loop escrever:WRITE fat STOP END inic rótulo endereço endereço codop ender 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 Mnemônico Cod Op LD 1 ST 2 ADD 4 SUB 5 MULT 6 JUMP 11 JP 14 READ 15 WRITE 16 STOP 17
27
C1: CONST 1 C2: CONST 2 n: CONST 0 fat: CONST 0 i: CONST 0
inic: READ n LD C1 ST fat LD C2 ST i loop: SUB n JP escrever LD fat MULT i LD i ADD C1 JUMP loop escrever:WRITE fat STOP END inic rótulo endereço C1 C2 1 n 2 fat 3 i 4 endereço codop ender 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 Mnemônico Cod Op LD 1 ST 2 ADD 4 SUB 5 MULT 6 JUMP 11 JP 14 READ 15 WRITE 16 STOP 17
28
C1: CONST 1 C2: CONST 2 n: CONST 0 fat: CONST 0 i: CONST 0
inic: READ n LD C1 ST fat LD C2 ST i loop: SUB n JP escrever LD fat MULT i LD i ADD C1 JUMP loop escrever:WRITE fat STOP END inic rótulo endereço C1 C2 1 n 2 fat 3 i 4 inic 5 endereço codop ender 1 2 3 4 5 15 6 7 8 9 10 11 12 13 14 16 17 18 19 20 Mnemônico Cod Op LD 1 ST 2 ADD 4 SUB 5 MULT 6 JUMP 11 JP 14 READ 15 WRITE 16 STOP 17
29
C1: CONST 1 C2: CONST 2 n: CONST 0 fat: CONST 0 i: CONST 0
inic: READ n LD C1 ST fat LD C2 ST i loop: SUB n JP escrever LD fat MULT i LD i ADD C1 JUMP loop escrever:WRITE fat STOP END inic rótulo endereço C1 C2 1 n 2 fat 3 i 4 inic 5 endereço codop ender 1 2 3 4 5 15 6 7 8 9 10 11 12 13 14 16 17 18 19 20 Mnemônico Cod Op LD 1 ST 2 ADD 4 SUB 5 MULT 6 JUMP 11 JP 14 READ 15 WRITE 16 STOP 17
30
C1: CONST 1 C2: CONST 2 n: CONST 0 fat: CONST 0 i: CONST 0
inic: READ n LD C1 ST fat LD C2 ST i loop: SUB n JP escrever LD fat MULT i LD i ADD C1 JUMP loop escrever:WRITE fat STOP END inic rótulo endereço C1 C2 1 n 2 fat 3 i 4 inic 5 loop 10 endereço codop ender 1 2 3 4 5 15 6 7 8 9 10 11 12 13 14 16 17 18 19 20 Mnemônico Cod Op LD 1 ST 2 ADD 4 SUB 5 MULT 6 JUMP 11 JP 14 READ 15 WRITE 16 STOP 17
31
C1: CONST 1 C2: CONST 2 n: CONST 0 fat: CONST 0 i: CONST 0
inic: READ n LD C1 ST fat LD C2 ST i loop: SUB n JP escrever LD fat MULT i LD i ADD C1 JUMP loop escrever:WRITE fat STOP END inic rótulo endereço C1 C2 1 n 2 fat 3 i 4 inic 5 loop 10 escrever ??? endereço codop ender 1 2 3 4 5 15 6 7 8 9 10 11 14 ??? 12 13 16 17 18 19 20 Mnemônico Cod Op LD 1 ST 2 ADD 4 SUB 5 MULT 6 JUMP 11 JP 14 READ 15 WRITE 16 STOP 17
32
C1: CONST 1 C2: CONST 2 n: CONST 0 fat: CONST 0 i: CONST 0
inic: READ n LD C1 ST fat LD C2 ST i loop: SUB n JP escrever LD fat MULT i LD i ADD C1 JUMP loop escrever:WRITE fat STOP END inic rótulo endereço C1 C2 1 n 2 fat 3 i 4 inic 5 loop 10 escrever ??? endereço codop ender 1 2 3 4 5 15 6 7 8 9 10 11 14 ??? 12 13 16 17 18 19 20 Mnemônico Cod Op LD 1 ST 2 ADD 4 SUB 5 MULT 6 JUMP 11 JP 14 READ 15 WRITE 16 STOP 17
33
C1: CONST 1 C2: CONST 2 n: CONST 0 fat: CONST 0 i: CONST 0
inic: READ n LD C1 ST fat LD C2 ST i loop: SUB n JP escrever LD fat MULT i LD i ADD C1 JUMP loop escrever:WRITE fat STOP END inic rótulo endereço C1 C2 1 n 2 fat 3 i 4 inic 5 loop 10 escrever 19 endereço codop ender 1 2 3 4 5 15 6 7 8 9 10 11 14 19 12 13 16 17 18 20 Mnemônico Cod Op LD 1 ST 2 ADD 4 SUB 5 MULT 6 JUMP 11 JP 14 READ 15 WRITE 16 STOP 17
34
C1: CONST 1 C2: CONST 2 n: CONST 0 fat: CONST 0 i: CONST 0
inic: READ n LD C1 ST fat LD C2 ST i loop: SUB n JP escrever LD fat MULT i LD i ADD C1 JUMP loop escrever:WRITE fat STOP END inic rótulo endereço C1 C2 1 n 2 fat 3 i 4 inic 5 loop 10 escrever 19 endereço codop ender 1 2 3 4 5 15 6 7 8 9 10 11 14 19 12 13 16 17 18 20 Mnemônico Cod Op LD 1 ST 2 ADD 4 SUB 5 MULT 6 JUMP 11 JP 14 READ 15 WRITE 16 STOP 17
35
Endereço inicial da execução: 5
C1: CONST 1 C2: CONST 2 n: CONST 0 fat: CONST 0 i: CONST 0 inic: READ n LD C1 ST fat LD C2 ST i loop: SUB n JP escrever LD fat MULT i LD i ADD C1 JUMP loop escrever:WRITE fat STOP END inic rótulo endereço C1 C2 1 n 2 fat 3 i 4 inic 5 loop 10 escrever 19 endereço codop ender 1 2 3 4 5 15 6 7 8 9 10 11 14 19 12 13 16 17 18 20 Endereço inicial da execução: 5 Essa informação deve acompanhar o programa em linguagem de máquina
36
O programa em linguagem C é o programa-fonte
O programa gerado pelo Assembler é o programa-objeto O programa-objeto foi montado a partir do endereço zero da RAM Esse programa é guardado num arquivo (extensão obj) endereço codop ender 1 2 3 4 5 15 6 7 8 9 10 11 14 19 12 13 16 17 18 20 Endereço inicial da execução: 5
37
Esse local depende da disponibilidade da RAM
O local para execução é estabelecido pelo sistema operacional do computador Esse local depende da disponibilidade da RAM E se o local não for o endereço zero (por exemplo, endereço 3000)? endereço codop ender 1 2 3 4 5 15 6 7 8 9 10 11 14 19 12 13 16 17 18 20 Endereço inicial da execução: 5
38
Isso tem de ser corrigido antes da execução
Os locais para C1, C2, n, fat e i não são mais 0, 1, 2, 3 e 4, mas sim 3000, 3001, 3002, 3003 e 3004 Os rótulos inic, loop e escrever mudarão para os endereços 3005, 3010 e 3019 Então todos os campos ender das instruções estarão com um erro (deslocamento de 3000 posições) Isso tem de ser corrigido antes da execução endereço codop ender 3000 1 3001 2 3002 3003 3004 3005 15 3006 3007 3 3008 3009 4 3010 5 3011 14 19 3012 3013 6 3014 3015 3016 3017 3018 11 10 3019 16 3020 17 Endereço inicial da execução: 3005
39
c) Editor de ligações Antes de corrigir os endereços do programa-objeto, é necessário juntar a ele todos os subprogramas auxiliares pertencentes à biblioteca da linguagem Exemplos: funções para entrada e saída (scanf, printf, etc.), funções matemáticas (sqr, pow, sqrt, log, sin, cos, etc.) Esse trabalho de juntar o programa-objeto com tais subprogramas é feito por um software denominado editor de ligações (linkage-editor) O produto do editor de ligações é um arquivo denominado programa-executável (extensão exe)
40
d) Carregador A região de memória onde um programa será alocado para execução só será conhecida quando ele for chamado para isso Então o endereçamento do arquivo executável precisa ser corrigido, quando sua execução for solicitada Esse trabalho é feito pelo carregador (loader), que produz a versão final do programa, pronto para rodar
41
1.2 – Estrutura de um Compilador
1.2.1 – Componentes de um compilador O trabalho de compilação é dividido em 2 fases: Fase de análise e fase de síntese Além disso, existem atividades que fazem parte das duas fases
42
O processo não precisa ser sequencial
43
load i j Exemplo Programa-fonte (caracteres) Analisador léxico
Analisador sintático Analisador semântico Gerador de código intermediário Otimizador de código intermediário Gerador de código objeto while (i < n) i = i + j; while ( i < n ) = + j ; Sequência de átomos i n j int - - - while i < n = + j Árvore sintática Tabela de símbolos Código objeto load i R1: sub n JZ R2 JP R2 add j st i J R1 R2: R1: T1 = i < n JF T1 R2 T2 = i + j i = T2 JUMP R1 R2: R1: T1 = i < n JF T1 R2 i = i + j JUMP R1 R2: Código intermediário Exemplo
44
1.2.2 – A fase de análise São realizados três tipos de análise:
Análise linear ou léxica Análise hierárquica ou sintática Análise semântica
45
a) Análise léxica Os caracteres do texto são agrupados em átomos (tokens) A validade dos átomos é verificada Os átomos recebem uma classificação
46
Exemplo: frase da Língua Portuguesa:
ajbxswn o homem alto apanhou a laranja madura na laranjeira tdhf
47
Exemplo: um comando while em Pascal:
while num 50 do num := num * 2
48
b) Análise sintática Os átomos são agrupados em frases, em estrutura de árvore (árvore sintática) A validade da posição dos átomos é verificada
49
Exemplo: frase: o homem alto apanhou a laranja madura na laranjeira
50
Exemplo: comando while de Pascal:
while num 50 do num := num * 2
51
c) Análise semântica Verifica se a árvore sintática tem sentido Coleta informações de tipos para a fase de síntese
52
a laranja apanhou o homem
Exemplo: frase sem sentido: a laranja apanhou o homem Erro: o verbo apanhar não admite sujeito do tipo vegetal
53
Exemplo: comando while de Pascal: while n+3 do n*5 (com integer n)
Erro: A expressão de um comando while deve ser do tipo lógico Erro: O operador de uma atribuição deve ser “:=”
54
1.2.3 – A fase de síntese Depois da análise, a fase de síntese constrói o programa objeto São realizadas três tarefas: Geração do código intermediário Otimização do código intermediário Geração do código objeto
55
a) Geração do código intermediário:
A estrutura do programa-fonte costuma ser bem diferente da estrutura do programa-objeto A transformação da primeira estrutura para a segunda deve ser aliviada passando por uma fase intermediária Fazendo analogia com metamorfose na vida animal: Ovo Lagarta Borboleta Ovo Girino Sapo
56
Exemplo: while n 50 do n := n * 2 Código de três endereços:
2 endereços p/operandos 1 endereço p/resultado Quádruplas: 1º elemento: operador 2º e 3º elementos: operandos 4º elemento: resultado
57
O código intermediário deve ser fácil de:
Ser produzido Ser transformado em código objeto (Assembly da máquina)
58
b) Otimização do código intermediário:
Elimina operações desnecessárias e repetidas Visa simplificar o código intermediário Visa tornar o programa executável mais rápido Visa economia de memória
59
Exemplo: sejam os comandos
x := a + b + c; y := a + b + c + d;
60
Outros casos para otimização:
Detecção de atribuições e operações cujos valores não são usados no programa Detecção de código morto, ou seja, de código que não é executado, qualquer que seja a entrada de dados Otimização faz análise de fluxo de dados e de controle
61
c) Geração do código objeto:
Transformação do código intermediário otimizado no código objeto (normalmente o Assembly da máquina alvo) O código objeto pode também receber otimizações Exemplo: seja o comando while n < 50 do n := n * 2
62
1.2.4 – Atividades em ambas as fases
Manipulação da tabela de símbolos Tratamento de erros a) Tabela de símbolos Guarda informações sobre todos os identificadores usados em um programa
63
Informações sobre os identificadores:
Tipo do identificador: Variável Constante Definição de tipo Nome de subprograma Rótulo Escopo: em que trecho ele é válido
64
Se for nome de variável:
Tipo Se é ou não indexada Se é ou não estrutura Se é ou não ponteiro Endereço de memória Espaço a ser alocado Se for variável indexada Número de dimensões Número de elementos em cada dimensão Se for estrutura: Nome e tipo de cada campo Se for ponteiro: Tipo dos locais apontados por ela
65
Exemplos em C: int a; float X[7][5][4]; a nome var tipo int tipovar
eharray X nome var tipo real tipovar sim eharray 3 ndim 7 5 4 dims 1 2
66
Se for nome de subprograma:
Tipo de subprograma (função ou procedimento) Número de parâmetros Lista de parâmetros por valor Lista de parâmetros por referência Tipo a ser retornado Lista de variáveis locais
67
int fff (int m, int n) {float a, b; - - - - - }
Exemplo em C: int fff (int m, int n) {float a, b; } n nome var tipo int tipovar b nome var tipo real tipovar m nome var tipo int tipovar a nome var tipo real tipovar fff func int 2 nome tipo tipofun nparam List param List Var Loc
68
A tabela de símbolos é manipulada pelos vários componentes das fases de análise e síntese:
Análise léxica detecta e pode armazenar o identificador Análise sintática pode armazenar seu tipo e outras informações Análise semântica faz consultas à tabela Geração de código introduz e usa informações sobre espaço alocado
69
b) Detecção e tratamento de erros
Cada componente do compilador pode encontrar erros Encontrado um erro, um componente deve tratá-lo de forma a permitir que outros erros sejam detectados Um compilador que para, quando encontra o primeiro erro, não pode ajudar muito Existem erros léxicos, sintáticos e semânticos
70
Exemplos: Erro léxico: Conjunto de caracteres que não corresponde a nenhum átomo Erro sintático: Sequência de átomos que viola construções sintáticas Erro semântico: Construções sintáticas corretas porém sem sentido Cada componente da estrutura do compilador será estudado detalhadamente em capítulo específico
71
linguagem-fonte e máquina-alvo
1.2.5 – Outra decomposição de um compilador Compilador é uma interface entre: linguagem-fonte e máquina-alvo Frente ou front-end : parte do compilador dependente da linguagem-fonte Retaguarda ou back-end: parte do compilador dependente da máquina-alvo
72
Frente (front-end) compreende:
Análises léxica, sintática e semântica Criação e consultas à tabela de símbolos Geração do código intermediário Muita otimização do código intermediário Tratamento de erros léxicos, sintáticos e semânticos
73
Retaguarda (back-end) compreende:
Alguma otimização do código intermediário Geração de código objeto Otimização do código objeto Operações na tabela de símbolos Tratamento de alguns erros
74
Uma única linguagem para código intermediário
Essa decomposição facilita a criação de compiladores de: Mesma linguagem-fonte para várias máquinas-alvos Várias linguagens-fontes para mesma máquina-alvo L M1 M2 Mi M L1 L2 Lj Uma única linguagem para código intermediário
75
No primeiro caso: sucesso absoluto
Pode-se projetar um código intermediário que se aproxime bem da linguagem de máquina de uma variedade de arquiteturas L M1 M2 Mi M L1 L2 Lj
76
No segundo caso: sucesso limitado
Diferenças sutis entre algumas linguagens dificultam a obtenção de um código intermediário comum entre elas L M1 M2 Mi M L1 L2 Lj
Apresentações semelhantes
© 2024 SlidePlayer.com.br Inc.
All rights reserved.