Buscar

UNIFACS DL - Compiladores - unidade IV

Faça como milhares de estudantes: teste grátis o Passei Direto

Esse e outros conteúdos desbloqueados

16 milhões de materiais de várias disciplinas

Impressão de materiais

Agora você pode testar o

Passei Direto grátis

Você também pode ser Premium ajudando estudantes

Faça como milhares de estudantes: teste grátis o Passei Direto

Esse e outros conteúdos desbloqueados

16 milhões de materiais de várias disciplinas

Impressão de materiais

Agora você pode testar o

Passei Direto grátis

Você também pode ser Premium ajudando estudantes

Faça como milhares de estudantes: teste grátis o Passei Direto

Esse e outros conteúdos desbloqueados

16 milhões de materiais de várias disciplinas

Impressão de materiais

Agora você pode testar o

Passei Direto grátis

Você também pode ser Premium ajudando estudantes
Você viu 3, do total de 37 páginas

Faça como milhares de estudantes: teste grátis o Passei Direto

Esse e outros conteúdos desbloqueados

16 milhões de materiais de várias disciplinas

Impressão de materiais

Agora você pode testar o

Passei Direto grátis

Você também pode ser Premium ajudando estudantes

Faça como milhares de estudantes: teste grátis o Passei Direto

Esse e outros conteúdos desbloqueados

16 milhões de materiais de várias disciplinas

Impressão de materiais

Agora você pode testar o

Passei Direto grátis

Você também pode ser Premium ajudando estudantes

Faça como milhares de estudantes: teste grátis o Passei Direto

Esse e outros conteúdos desbloqueados

16 milhões de materiais de várias disciplinas

Impressão de materiais

Agora você pode testar o

Passei Direto grátis

Você também pode ser Premium ajudando estudantes
Você viu 6, do total de 37 páginas

Faça como milhares de estudantes: teste grátis o Passei Direto

Esse e outros conteúdos desbloqueados

16 milhões de materiais de várias disciplinas

Impressão de materiais

Agora você pode testar o

Passei Direto grátis

Você também pode ser Premium ajudando estudantes

Faça como milhares de estudantes: teste grátis o Passei Direto

Esse e outros conteúdos desbloqueados

16 milhões de materiais de várias disciplinas

Impressão de materiais

Agora você pode testar o

Passei Direto grátis

Você também pode ser Premium ajudando estudantes

Faça como milhares de estudantes: teste grátis o Passei Direto

Esse e outros conteúdos desbloqueados

16 milhões de materiais de várias disciplinas

Impressão de materiais

Agora você pode testar o

Passei Direto grátis

Você também pode ser Premium ajudando estudantes
Você viu 9, do total de 37 páginas

Faça como milhares de estudantes: teste grátis o Passei Direto

Esse e outros conteúdos desbloqueados

16 milhões de materiais de várias disciplinas

Impressão de materiais

Agora você pode testar o

Passei Direto grátis

Você também pode ser Premium ajudando estudantes

Prévia do material em texto

11/06/2023, 19:23 E-book
https://student.ulife.com.br/ContentPlayer/Index?lc=e6IUL5ncVpNnpafasMtHtw%3d%3d&l=1OdIzZ8xcachsr3pzfvcBA%3d%3d&cd=euiSKCRHJrkiUp… 1/37
COMPILADORESCOMPILADORES
GERAÇÃO DE CÓDIGOGERAÇÃO DE CÓDIGO
Au to r ( a ) : D r. J o ã o C a r l o s L o p e s Fe r n a n d e s
R ev i s o r : Ed i l s o n R o d r i g u e s
Tempo de leitura do conteúdo estimado em 1 hora.
11/06/2023, 19:23 E-book
https://student.ulife.com.br/ContentPlayer/Index?lc=e6IUL5ncVpNnpafasMtHtw%3d%3d&l=1OdIzZ8xcachsr3pzfvcBA%3d%3d&cd=euiSKCRHJrkiUp… 2/37
Introdução
Olá, estudante!
Os códigos-fonte são originados de uma linguagem de programação que
atenda aos requisitos de uma arquitetura de computador sempre. Nela,
encontramos declarações, instruções, funções e outras de�nições necessárias,
que criam funcionalidades para que o software e/ou o programa consigam
apresentar os resultados esperados.
Dessa forma, os programas podem ser distribuídos em vários arquivos de
código-fonte, que serão, assim, considerados módulos ou subprogramas que,
moralmente, são utilizados em sistemas de banco de dados.
Os códigos-fonte podem ser divididos de duas formas, sendo os fechados os
que são de propriedade de uma empresa que os comercializa (programas) e
possuem, como objetivo, a proteção intelectual e os direitos autorais.
Já no caso das versões abertas, que fazem parte do software livre, a base para
a criação de software é o código-fonte que é compartilhado com vários
programadores que podem modi�cá-lo, distribuí-lo e criar customizações que
atendam às suas necessidades. Vamos estudar sobre isso!?
11/06/2023, 19:23 E-book
https://student.ulife.com.br/ContentPlayer/Index?lc=e6IUL5ncVpNnpafasMtHtw%3d%3d&l=1OdIzZ8xcachsr3pzfvcBA%3d%3d&cd=euiSKCRHJrkiUp… 3/37
A análise semântica trabalha se inter-relacionando com todas as partes do
programa e tem, como função, realizar as tarefas básicas que incluem
veri�cação de tipos, �uxo de controle e veri�cação da unicidade das variáveis.
Em algumas linguagens de programação, poderá existir a necessidade de
outros tipos de veri�cações (AHO et. al, 2008).
A análise semântica pode ser dividida em duas categorias. A primeira
é a análise de um programa requerido pelas regras da linguagem de
programação, para veri�car sua correção e garantir sua execução. O
quanto precisa ocorrer dessa análise requerida pela de�nição da
linguagem varia tremendamente de linguagem para linguagem.
(LOUDEN, 2004, p. 259).
Na análise semântica, estão englobadas duas tarefas principais, que são:
análise de contexto para geração de código e veri�cação de erros. A Figura 4.1
apresenta uma ideia semântica.
Análise Semântica
11/06/2023, 19:23 E-book
https://student.ulife.com.br/ContentPlayer/Index?lc=e6IUL5ncVpNnpafasMtHtw%3d%3d&l=1OdIzZ8xcachsr3pzfvcBA%3d%3d&cd=euiSKCRHJrkiUp… 4/37
Figura 4.1 - Semântica
Fonte: Cinemast / Wikimedia Commons.
#PraCegoVer: a imagem apresenta, na primeira linha do lado esquerdo, uma
sequência de 18 números, intercalados entre 0 e 1, que se repete por mais oito
linhas. Abaixo delas está a palavra “Dados”. No centro dessas oito linhas, há uma
seta azul da esquerda para a direita, com a frase “recursos de baixo nível”. Abaixo
da seta, na vertical, estão as palavras “codi�cação”, “resolução”, “cor” e “textura”. Na
extremidade da seta, do lado direito, existe o símbolo “{“, com o texto “semântica ...
gap” escrito em seu centro. Depois, há o símbolo “}”. Do lado direito de “}”, há uma
seta azul com o texto “recursos de alto nível”, em seu centro, que aponta para a
�gura de uma maçã. Abaixo da seta, na vertical, há as palavras “palavra-chave”,
“categoria”, “concepção” e “ontologia”. Abaixo da maçã, há as palavras “percepção
humana”.
O resultado da fase semântica é uma árvore que será analisada
gramaticalmente. As gramáticas de atributo são utilizadas para a descrição da
semântica dos programas.
Definição
11/06/2023, 19:23 E-book
https://student.ulife.com.br/ContentPlayer/Index?lc=e6IUL5ncVpNnpafasMtHtw%3d%3d&l=1OdIzZ8xcachsr3pzfvcBA%3d%3d&cd=euiSKCRHJrkiUp… 5/37
A semântica, no processo de compilação de uma linguagem de programação,
veri�ca os erros semânticos que possam existir como, por exemplo, a divisão
de números inteiros por números reais, que é conhecida com �oat no padrão do
American National Standards Institute (ANSI — Instituto Nacional Americano de
Padrões), e, assim, prepara o código-fonte coletando as informações que serão
necessárias na próxima fase da compilação. Outro cuidado que se deve tomar
está relacionado ao uso de palavras no contexto comunicativo que poderão
criar diferentes sentidos entre elas e prejudicar o processo de compilação.
Na prática, muitas veri�cações semânticas devem ser efetuadas
sobre elementos presentes em vários pontos do programa,
possivelmente distantes. Uma referência a um tipo, a um método ou a
uma variável pode estar distante da sua de�nição e, eventualmente,
aparecer em um arquivo diferente. Para resolver este problema é
usado um repositório central em que �ca armazenada toda a
informação relativa aos símbolos (identi�cadores de variáveis, tipos,
funções, métodos, classes etc.): a tabela dos símbolos (LANGLOIS,
2018, p. 126).
Então, mesmo que a análise sintática consiga veri�car se foram obedecidas as
regras de formação gramatical, �ca difícil expressar, pela gramática, algumas
regras utilizadas nas linguagens de programação. Por exemplo, as variáveis e
suas declarações possuem situações em que seu contexto apresenta
expressões e/ou tipos de variáveis que devem ser veri�cados constantemente.
Tradução Dirigida por sintaxe
Quando falamos da Tradução Dirigida por Sintaxe (SDD — Syntax-Directed
De�nition), estamos nos referindo ao método de implementação de
compiladores que a tradução do código-fonte será tratada, exclusivamente, pela
“análise sintática”. Um exemplo do método de tradução dirigida pela sintaxe é a
11/06/2023, 19:23 E-book
https://student.ulife.com.br/ContentPlayer/Index?lc=e6IUL5ncVpNnpafasMtHtw%3d%3d&l=1OdIzZ8xcachsr3pzfvcBA%3d%3d&cd=euiSKCRHJrkiUp… 6/37
tradução da cadeia de caracteres por uma sequência de ações interligando
cada ação a uma regra da gramática.
O princípio da tradução direcionada por sintaxe estabelece que o
signi�cado, ou semântica, da cadeia 3+4 deveria estar diretamente
relacionado a sua estrutura sintática representada na árvore de
análise sintática. Nesse caso, o princípio da tradução direcionada por
sintaxe indica que a árvore de análise sintática determina que o valor
de 3 e o valor de 4 devem ser somados (LOUDEN, 2004, p. 123).
Outro detalhe importante está relacionado ao fato de que a sintaxe utilizada na
SSD é gramática livre de contexto e recebe atributos e regras. Os atributos são
associados aos símbolos da gramática, e as regras são associadas às
produções.
Tabela de Símbolos
A tabela de símbolos é uma estrutura de dados, normalmente, em formato de
árvore e/ou tabela de hash, que é utilizada nos compiladores para o
armazenamento de informações dos identi�cadores sempre, como as
constantes, as funções, as variáveis e os tipos de dados.
A tabela de símbolos é uma estrutura de dados que tem como
objetivo armazenar as informações relativas aos identi�cadores do
programa. É essencial a tabela dos símbolos permitir um acesso
rápido a essas informações, porque será frequentemente consultada
ao longo do processo de compilação (LANGLOIS, 2018, p. 126).
Sendo assim, o processo de compilação de uma tabela de símbolos está ligado
com o retorno de parâmetros e/ou as variáveis utilizadas na veri�cação dos
tipos e contextos, assumindo o papel de informar como as declarações serão
usadas.
11/06/2023, 19:23 E-book
https://student.ulife.com.br/ContentPlayer/Index?lc=e6IUL5ncVpNnpafasMtHtw%3d%3d&l=1OdIzZ8xcachsr3pzfvcBA%3d%3d&cd=euiSKCRHJrkiUp… 7/37
Para que isso aconteça, a semântica �ca responsável pelas informações do
identi�cador da tabela de símbolos toda vez que a declaração for analisada.
11/06/2023, 19:23 E-book
https://student.ulife.com.br/ContentPlayer/Index?lc=e6IUL5ncVpNnpafasMtHtw%3d%3d&l=1OdIzZ8xcachsr3pzfvcBA%3d%3d&cd=euiSKCRHJrkiUp…8/37
O código intermediário tem, como função, facilitar o trabalho dos compiladores,
como em alguns casos, o código-fonte possui regras de linguagem, difíceis para
o compilador interpretar. Dessa forma, ele compila o código-fonte para uma
linguagem que ele conheça, isto é, o código intermediário que vai auxiliar na
compilação, ele não é o código �nal que vai gerar o código de máquina.
Geração de Código
Intermediário
11/06/2023, 19:23 E-book
https://student.ulife.com.br/ContentPlayer/Index?lc=e6IUL5ncVpNnpafasMtHtw%3d%3d&l=1OdIzZ8xcachsr3pzfvcBA%3d%3d&cd=euiSKCRHJrkiUp… 9/37
Fonte: M. Spiske /
Pexels.
Código intermediário
11/06/2023, 19:23 E-book
https://student.ulife.com.br/ContentPlayer/Index?lc=e6IUL5ncVpNnpafasMtHtw%3d%3d&l=1OdIzZ8xcachsr3pzfvcBA%3d%3d&cd=euiSKCRHJrkiU… 10/37
Como sua utilização é considerada como facilitadora para casos bem
complexos, a maioria dos compiladores o utiliza, ou permite que a função seja
acionada e/ou incorporada no processo, que pretendem fazer a otimização ou
criar certas features, caso contrário, o processo de compilação será difícil de
trabalhar.
Tipos e Declarações
Uma declaração, nas linguagens de programação, tem, como função,
especi�car os identi�cadores, os tipos e outros aspectos da linguagem, como
suas variáveis e/ou funções. Algumas linguagens, como o C, utilizam variáveis
e/ou funções para indicar a existência dos elementos a serem compilados, que
necessitam de variáveis declaradas, antes de manipulá-las (MENEZES, 2011).
S A I B A M A I S
Os compiladores utilizam as informações a respeito do tipo na busca de garantir que
as operações executadas tenham segurança. Sendo assim, se �zer uma declaração
de uma variável do tipo int (inteira), o compilador vai permitir o uso da variável em
operações matemáticas de adição e subtração apenas, caso tente realizar operações
em uma variável tipo bool, o compilador vai gerar um erro.
Para saber mais, acesse a seguir:
https://bit.ly/3NNMcVR
Fonte: Wagner, Sharkey e Forensic (2022).
https://bit.ly/3NNMcVR
11/06/2023, 19:23 E-book
https://student.ulife.com.br/ContentPlayer/Index?lc=e6IUL5ncVpNnpafasMtHtw%3d%3d&l=1OdIzZ8xcachsr3pzfvcBA%3d%3d&cd=euiSKCRHJrkiU… 11/37
As linguagens de programação da família BCPL, como C++ e Java, podem,
também, especi�car qual será a dimensão de suas variáveis (escalar, array ou
matriz). Nessas linguagens, as declarações são as responsáveis por anunciar a
existência e/ou as propriedades de cada elemento e suas de�nições
(implementação real). Assim, as declarações são, geralmente, realizadas no
cabeçalho dos arquivos, destinados a referenciar essas declarações. Dessa
forma, toda vez que uma de�nição não coincidir com sua declaração, será
gerado um erro no processo de compilação (DELAMARO, 2004).
No caso das variáveis, as de�nições, normalmente, atribuem valores em áreas
da memória que foram reservadas durante a fase das declarações.
No caso da linguagem simples, identi�camos expressões expr e
instruções stmt. A linguagem é muito simples, por isso não existem
declarações, funções ou tipos de dados compostos, como estruturas
ou classes de objetos, por exemplo (LANGLOIS, 2018, p. 149).
Enquanto as variáveis e/ou as funções podem ser declaradas mais de uma vez,
as declarações podem ser de�nidas apenas uma. A Figura 4.2 ilustra um
exemplo de declarações.
11/06/2023, 19:23 E-book
https://student.ulife.com.br/ContentPlayer/Index?lc=e6IUL5ncVpNnpafasMtHtw%3d%3d&l=1OdIzZ8xcachsr3pzfvcBA%3d%3d&cd=euiSKCRHJrkiU… 12/37
Figura 4.2 - Tipos e declarações
Fonte: Pixabay / Pexels.
#PraCegoVer: a imagem apresenta uma sequência de códigos a respeito da
linguagem Java e suas declarações, o fundo da tela é preto, e as linhas de código
estão com as cores branca e verde.
No caso das linguagens dinâmicas, como Javascript e/ou Python, a rede�nição
das funções é permitida, pois ela é, muitas vezes, utilizada para acessar
funções e/ou variáveis que foram de�nidas em arquivos que possuem origem
diferente, ou são bibliotecas.
Tradução de Expressões
As expressões utilizadas no código-fonte podem ser analisadas com simples
varreduras, como, por exemplo, da esquerda para a direita, e utilização de uma
pilha para manipulação dos operandos. Sendo assim, as expressões poderão
ser identi�cadas pelo simples caminhar na árvore sintática correspondente.
11/06/2023, 19:23 E-book
https://student.ulife.com.br/ContentPlayer/Index?lc=e6IUL5ncVpNnpafasMtHtw%3d%3d&l=1OdIzZ8xcachsr3pzfvcBA%3d%3d&cd=euiSKCRHJrkiU… 13/37
É importante ressaltar que, em um mesmo processo de compilação, o conteúdo
das regras semânticas poderá sofrer variação dependendo da atividade a ser
realizada.
Por sua vez, um esquema de tradução é uma notação para anexar
fragmentos de programa às produções de uma gramática. Os
fragmentos do programa são executados quando a produção é usada
durante a análise sintática. O resultado combinado de todas essas
execuções de fragmentos, na ordem induzida pela análise de sintaxe,
produz a tradução do programa ao qual este processo de
análise/síntese é aplicado (BARBOSA et al., 2021, p. 166).
Desse modo, preste atenção constantemente, pois os operandos devem vir
antes dos operadores sempre. Assim, caso seja necessário, deve existir
adequação na representação das expressões aritméticas e/ou lógicas.
Verificação de Tipo
Uma veri�cação importante relacionada aos tipos das construções sintáticas
está relacionada, diretamente, ao signi�cado lógico dela dentro de cada
linguagem. Então, veri�car a consistência das declarações e a utilização dos
identi�cadores é fundamental para um bom processo de compilação. Além
disso, devem-se realizar as conversões necessárias e permitidas, para criar o
signi�cado de cada sentença.
No contexto das linguagens de programação com tipos estáticos (C,
C++, Java, Ada etc.) é atribuído um tipo a cada variável. Este passo é
necessário, sendo proibido o uso de variáveis não previamente
declaradas. Durante a compilação é igualmente veri�cada a
compatibilidade entre os tipos dos operandos e os operadores
associados, bem como o número e o tipo dos argumentos nas
chamadas às funções ou aos métodos (LANGLOIS, 2018, p. 126).
11/06/2023, 19:23 E-book
https://student.ulife.com.br/ContentPlayer/Index?lc=e6IUL5ncVpNnpafasMtHtw%3d%3d&l=1OdIzZ8xcachsr3pzfvcBA%3d%3d&cd=euiSKCRHJrkiU… 14/37
Então, as veri�cações realizadas nos tipos de compilação podem ser estáticas
e/ou dinâmicas. A veri�cação estática é realizada no código-fonte sempre, no
processo de compilação dos códigos-fontes, e a veri�cação dinâmica é
realizada durante o tempo de execução da aplicação e/ou do programa.
Fluxo de Controle
Na área da computação, a estrutura de controle e/ou �uxo de controle se refere
às instruções, às expressões e às chamadas de função que deverão ser
analisadas e/ou executadas em programas de computador por intermédio de
uma programação imperativa e/ou funcional (compilação/interpretação).
Apesar de a árvore sintática abstrata ser uma representação
perfeitamente adequada do código-fonte, mesmo para a geração de
código, ela em nada se assemelha ao código-alvo, em particular em
sua representação das construções de �uxo de controle, na qual o
código-alvo como o código de máquina ou de montagem utiliza saltos
em vez de construções de alto nível, como as declarações if e while
(LOUDEN, 2004, p. 416).
As operações, nos controles de �uxo, são de�nidas em todas as linguagens
utilizadas para programação praticamente, como, por exemplo, C, C++, Python,
Pascal, Java e Fortran.
Conhecimento
11/06/2023, 19:23 E-book
https://student.ulife.com.br/ContentPlayer/Index?lc=e6IUL5ncVpNnpafasMtHtw%3d%3d&l=1OdIzZ8xcachsr3pzfvcBA%3d%3d&cd=euiSKCRHJrkiU… 15/37
Teste seus Conhecimentos
(Atividade não pontuada)
A fase do front-end é um processo de compilação no qual ocorre a análise da
linguagem de origem e a geração de uma representação intermediária. Já na
fase de back-end, o compilador pega essa representação intermediária e
produz o código de objeto.
Abaixo, são citadas algumas fases quedevem ocorrer dentro de um processo
de compilação front-end:
a - análise sintática;
b - análise semântica;
c - análise léxica;
d - gerador de código intermediário;
Assinale, a seguir, a sequência CORRETA na ordem crescente em que as fases
devem acontecer.
a) b – c – d – a.
b) b – c – a – d.
c) d – b – c – a.
d) c – a – b – d.
e) c – b – a – d.
11/06/2023, 19:23 E-book
https://student.ulife.com.br/ContentPlayer/Index?lc=e6IUL5ncVpNnpafasMtHtw%3d%3d&l=1OdIzZ8xcachsr3pzfvcBA%3d%3d&cd=euiSKCRHJrkiU… 16/37
Para realizar a implementação de um compilador, alguns cuidados devem ser
tomados. Isso porque esse processo não será executar as análises léxica,
semântica e sintática em um código-fonte e gerar seu resultado somente, já que
os testes de erros e a contabilização de arquiteturas devem ser pensados
também. Lembre-se de que a execução acontece em uma linguagem abstrata
primeiro para, em seguida, o código de máquina ser gerado.
Em uma implementação, as atividades de várias fases podem ser
agrupadas em uma passagem que lê um arquivo de entrada e grava
um arquivo de saída. Podemos citar como exemplo as fases front-end
de análise lexical, análise de sintaxe, análise semântica e geração de
código intermediário que podem ser incorporadas em uma única
passagem (BARBOSA et al., 2021, p. 25).
Dessa maneira, o principal objetivo ao implementar um compilador deve levar
em consideração a necessidade de resolver determinados problemas com o
apoio direto de linguagens abstratas sempre, ou seja, linguagens de alto nível,
que possuem especi�cidades. Sendo assim, identi�car os propósitos de cada
linguagem e saber qual seu principal propósito auxiliam bastante no processo
Implementação de
um Compilador
11/06/2023, 19:23 E-book
https://student.ulife.com.br/ContentPlayer/Index?lc=e6IUL5ncVpNnpafasMtHtw%3d%3d&l=1OdIzZ8xcachsr3pzfvcBA%3d%3d&cd=euiSKCRHJrkiU… 17/37
da compilação. Com tudo isso de�nido, o próximo passo será construir uma
gramática e escrever o detalhamento dos analisadores e geradores de código.
Criação de um Compilador para uma
Linguagem de Programação
Um compilador nada mais é do que um programa que traduz outros programas
que, normalmente, estão descritos em uma linguagem de alto nível para um
programa em código de máquina para determinados processadores
(arquitetura). Os programas de alto nível devem criar um arquivo com o texto do
código-fonte apenas, para alimentar o programa que vai realizar a compilação.
De modo geral, os compiladores não produzem o “código de máquina” de forma
direta, eles criam um programa em linguagem simbólica conhecido como
assembly, que, semanticamente, é equivalente ao programa criado na
linguagem de alto nível. Esses programas simbólicos são traduzidos para o
Fonte: davidoff205020 /
123RF.
11/06/2023, 19:23 E-book
https://student.ulife.com.br/ContentPlayer/Index?lc=e6IUL5ncVpNnpafasMtHtw%3d%3d&l=1OdIzZ8xcachsr3pzfvcBA%3d%3d&cd=euiSKCRHJrkiU… 18/37
programa em linguagem de máquina por meio dos montadores e,
posteriormente, liberados para execução.
Um ambiente de execução deve ser preparado para a geração de código, para
isso, ele deve relacionar as ações estáticas do programa com as ações em
tempo de execução. Durante o processo de execução, em alguns casos, o
código-fonte pode necessitar ser associado com diferentes objetos de dados na
máquina-alvo.
A maioria das linguagens necessita de uma ou mais bibliotecas para
apoiar a execução dos programas. Mesmo no caso de linguagens
com apoio à execução, como a linguagem C, a biblioteca denominada
libc.a inclui algumas das rotinas normalmente utilizadas no
desenvolvimento dos programas printf, atoi ou strlen (LANGLOIS,
2018, p. 7).
Ambientes de
Execução
11/06/2023, 19:23 E-book
https://student.ulife.com.br/ContentPlayer/Index?lc=e6IUL5ncVpNnpafasMtHtw%3d%3d&l=1OdIzZ8xcachsr3pzfvcBA%3d%3d&cd=euiSKCRHJrkiU… 19/37
A alocação e/ou a liberação dos objetos devem ser gerenciadas no ambiente de
tempo de execução (runtime environment). Assim, a cada execução, os
procedimentos são referidos a uma ativação. As chamadas recursivas podem
possuir várias ativações em um mesmo procedimento em determinados
instantes.
Organização da Memória
Como todo o processamento é realizado na memória sempre, antes da geração
do código, a compreensão da estrutura do programa é fundamental quando ele
está sendo executado. Então, precisamos saber quais os recursos o programa
vai utilizar quando entrar em execução (processamento) e a quantidade de
memória a ser utilizada. Quando falamos em tempo de execução, temos de
levar em conta alguns parâmetros da compilação, como as variáveis globais e
locais, os procedimentos, os parâmetros, os métodos, as classes e os objetos.
Todas essas construções necessitam estar bem re�etidas no código �nal que
for gerado.
11/06/2023, 19:23 E-book
https://student.ulife.com.br/ContentPlayer/Index?lc=e6IUL5ncVpNnpafasMtHtw%3d%3d&l=1OdIzZ8xcachsr3pzfvcBA%3d%3d&cd=euiSKCRHJrkiU… 20/37
As operações de leitura de valores da memória para o topo da pilha
permitem ler valores inteiros com sinal ou sem sinal, para as quatro
dimensões suportadas. Nos inteiros com sinal, o sinal é estendido ou
truncado, dependendo da dimensão dos valores da pilha. As
instruções de leitura são ld8, ld16, ld32 e ld64, dependendo do número
de bits do valor a ser lido. No caso de se tratar de inteiros sem sinal, o
valor é estendido com zeros ou truncado, sendo as instruções
designadas por uld8, uld16, uld32 e uld64 (LANGLOIS, 2018, p. 227).
REFLITA
Se a memória RAM é o local onde acontecem
todos os processamentos, ela necessita estar bem
organizada e possuir um tamanho su�ciente para
“rodar” os programas e/ou os sistemas
compilados. Partindo desse pressuposto, qual o
motivo, então, da utilização da memória virtual?
A resposta é simples, a memória secundária,
conhecida, normalmente, como memória de
armazenamento e/ou disco rígido, possui
capacidade bem superior à RAM e serve como
apoio ao processamento, permitindo, assim, que
11/06/2023, 19:23 E-book
https://student.ulife.com.br/ContentPlayer/Index?lc=e6IUL5ncVpNnpafasMtHtw%3d%3d&l=1OdIzZ8xcachsr3pzfvcBA%3d%3d&cd=euiSKCRHJrkiU… 21/37
Desse modo, a principal responsabilidade dos compiladores é tratar e evitar os
acessos não alinhados, ou seja, garantir que todos os endereços das variáveis
respeitem o alinhamento da arquitetura a ser utilizada. Algumas plataformas
possuem regras de alinhamento diferentes, como, por exemplo, o Mac OS X, seu
armazenamento utiliza 16 bytes para realizar seu alinhamento (compilador-
processador-memória).
Alocação de Espaço na Pilha
Todas as variáveis que serão de�nidas dentro de cada função (variáveis locais e
parâmetros) devem ser alocadas, automaticamente, na “pilha de execução” do
programa desenvolvido (stack). Um detalhe importante é que cada chamada de
função deve ser reinicializada toda vez que a função for encerrar. As pilhas de
execução, de forma geral, são pequenas, possuem 8 MB em média ou até
menos, sendo assim, alocar variáveis locais muito volumosas pode criar erros
na compilação e/ou na execução (Segmentation Fault — SIGSEGV —). Em
alguns casos, serão usadas as variáveis globais estáticas e/ou dinâmicas.
A pilha de registros de ativação (também chamada de pilha de
execução ou pilha de ativação) cresce e diminui segundo as ativações
ocorridas no programa em execução. Cada procedimento pode ter
diversos registros distintos de ativação na pilha de ativação ao
mesmo tempo, cada um deles representando uma ativação distinta
(LOUDEN, 2004, p. 356).
Um detalhe muito importante é que, caso a função seja chamada de forma
recursiva, todas as variáveis locais e os parâmetros serão alocados outra vez na
não existam erros casuais por falta de memória no
processamento.
11/06/2023, 19:23 E-book
https://student.ulife.com.br/ContentPlayer/Index?lc=e6IUL5ncVpNnpafasMtHtw%3d%3d&l=1OdIzZ8xcachsr3pzfvcBA%3d%3d&cd=euiSKCRHJrkiU… 22/37
pilha, logicamente, em áreas distintas que dependerão do nível de recursão.
Com isso, conseguem-sepreservar os valores anteriores antes da recursão.
Heap
Como as variáveis primitivas são armazenadas na stack diretamente, que é a
área de menor tamanho e a mais e�ciente na localização dos conteúdos, por
serem tipos de dados que não ocupam muito espaço de memória, permitem
uma “sobra” maior de espaço em memória, e as variáveis dinâmicas podem ser
alocadas no heap de forma mais e�caz.
As variáveis cujo valor está armazenado no heap correspondem às
variáveis que, em uma linguagem como C, foram alocadas
dinamicamente. O espaço em memória é reservado por uma função
de alocação (tipo malloc) e é responsabilidade do programador liberar
a memória associada quando já não é usada (LANGLOIS, 2018, p.
132).
Alguns tipos de dados ocupam mais espaço de memória e não podem ser
armazenados na stack diretamente, pois, caso fossem, a memória stack seria
“estourada”, causando o erro StackOver�owException. Por esse motivo, esses
dados devem ser armazenados na memória heap.
Coleta de lixo
A técnica de “coleta de lixo” ou Garbage Collector (GC) é uma função para
garantir uma recuperação “segura” de espaço de memória, pois todo
processamento é realizado nela. Para isso, o espaço disponível é muito
importante.
11/06/2023, 19:23 E-book
https://student.ulife.com.br/ContentPlayer/Index?lc=e6IUL5ncVpNnpafasMtHtw%3d%3d&l=1OdIzZ8xcachsr3pzfvcBA%3d%3d&cd=euiSKCRHJrkiU… 23/37
Um ambiente de execução totalmente dinâmico é signi�cativamente
mais complicado do que um ambiente baseado em pilhas, pois requer
o acompanhamento das referências durante a execução e a
capacidade de encontrar e liberar áreas inacessíveis de memória em
instantes arbitrários durante a execução (esse processo é
denominado coleta de lixo) (LOUDEN, 2004, p. 378).
Os GCs determinam um conjunto de raízes que contêm os objetos
referenciados diretamente, por cada variável local, eles marcam os objetos que
serão referenciados, ou seja, alcançados pelas raízes. Após essa etapa, o GC
examinará as referências em cada um desses objetos. Então, o GC continuará
em ação até que todos os objetos que não estão mais referenciados sejam
removidos.
praticar
Vamos Praticar
As Expressões Regulares (ER) são escritas em linguagens formais que podem
ser interpretadas pelos processadores, ou seja, são programas que auxiliam
os geradores dos analisadores sintáticos e/ou examinam textos para
identi�car possíveis erros de especi�cação.
Sendo assim, crie uma expressão regular para uma linguagem de
programação que utiliza letras do alfabeto {a, b, c}. A expressão apresenta,
11/06/2023, 19:23 E-book
https://student.ulife.com.br/ContentPlayer/Index?lc=e6IUL5ncVpNnpafasMtHtw%3d%3d&l=1OdIzZ8xcachsr3pzfvcBA%3d%3d&cd=euiSKCRHJrkiU… 24/37
exatamente, uma ocorrência de soma com as letras “a” e “b”, que �cam
anteriormente a uma ocorrência de multiplicação da letra “c” que �naliza a ER.
Um conjunto de instruções e declarações usadas por uma linguagem de
programação de computador é traduzido, assim, geramos o código �nal para a
máquina. Até chegarmos ao código ideal, existem vários passos que fazem
parte da criação (compilação).
“A escolha das instruções que serão utilizadas na criação do código-objeto
pode ser feita por meio de uma tabela de equivalências, com base em padrões e
em quais são as substituições adequadas para o código-fonte em questão”
(BARBOSA et al., 2021, p. 180).
Dessa forma, o código-fonte é o agrupamento das instruções necessárias para
o futuro funcionamento do software. É ele que passa pela compilação, e cada
linguagem de programação tem a sua.
Geração de Código
11/06/2023, 19:23 E-book
https://student.ulife.com.br/ContentPlayer/Index?lc=e6IUL5ncVpNnpafasMtHtw%3d%3d&l=1OdIzZ8xcachsr3pzfvcBA%3d%3d&cd=euiSKCRHJrkiU… 25/37
Linguagem-objeto
Os computadores atuam por um conjunto limitado de instruções que são
entendidas pelos processadores (RISC, CISC ou ARM). Nos primeiros
computadores, os programadores precisavam utilizar 0's e 1's para criar o
programa.
Atualmente, as linguagens de programação de alto nível simpli�cam as tarefas
dos programadores.
Um compilador recebe como entrada um programa escrito na
linguagem-fonte e produz um programa equivalente na linguagem-
alvo. Geralmente, a linguagem-fonte é uma linguagem de alto nível,
como C ou C++, e a linguagem-alvo é um código-objeto (algumas
vezes também chamado de código de máquina) para a máquina-alvo,
ou seja, um código escrito usando as instruções de máquina do
computador no qual ele será executado (LOUDEN, 2004, p. 15).
A linguagem-objeto, por exemplo, é uma dessas melhorias (avanços), pois ela
signi�ca a similaridade com o objeto que os programadores tentam alcançar.
Não se esqueça de um detalhe importante: não podemos confundir a
linguagem-objeto com a linguagem orientada a objetos, que é uma tipologia da
programação que auxilia na modelagem das informações.
Endereços no código-objeto
Como já sabemos, o código-objeto ou módulo-objeto é produzido por um
processo de compilação sempre. Ele nada mais é que a sequência de
comandos e/ou instruções de uma linguagem de computadores, geralmente,
ele pode ser considerado um código de máquina ou a linguagem intermediária,
como, por exemplo, o Register Transfer Language (RTL) (FEDOZZI, 2018).
11/06/2023, 19:23 E-book
https://student.ulife.com.br/ContentPlayer/Index?lc=e6IUL5ncVpNnpafasMtHtw%3d%3d&l=1OdIzZ8xcachsr3pzfvcBA%3d%3d&cd=euiSKCRHJrkiU… 26/37
Ao traduzir um programa-fonte para um código-objeto, um compilador
produz representações intermediárias do código, que podem assumir
mais de uma forma, mas que devem ser facilmente produzidas e
facilmente traduzidas para a linguagem-alvo ou código-objeto
(BARBOSA et al., 2021, p. 145).
Em alguns casos, poderemos encontrar o termo “código de 3 endereços”, pois o
código-objeto vem de uma árvore de derivação que gera o código-objeto �nal.
Blocos básicos
Os blocos básicos são a base para um compilador desenvolver suas tarefas.
Dentre as funções básicas, a primeira a ser realizada é a análise da estrutura do
código-fonte do programa de alto nível e o reconhecimento de possíveis erros.
Após essa fase, a atividade é a síntese, que vai traduzir o programa em um
equivalente em linguagem simbólica.
Uma sequência maximal de código de linha reta é denominada um
bloco básico, e por de�nição as otimizações locais são aquelas
restritas a blocos básicos. Otimizações que se estendam para além
dos blocos básicos, mas que sejam con�nadas a um procedimento
individual, são denominadas otimizações globais (LOUDEN, 2004, p.
474).
Desse modo, os blocos básicos podem ser representados com o uso de grafos
dirigidos, que são submetidos a um processo de otimização, ou seja, cada
bloco básico está relacionado a um trecho de programa que será iniciado.
Otimização de blocos básicos
11/06/2023, 19:23 E-book
https://student.ulife.com.br/ContentPlayer/Index?lc=e6IUL5ncVpNnpafasMtHtw%3d%3d&l=1OdIzZ8xcachsr3pzfvcBA%3d%3d&cd=euiSKCRHJrkiU… 27/37
A otimização dos blocos básicos está relacionada, diretamente, à forma de
como será realizado o processo de compilação do código-fonte, pois, a partir
dele, será gerado um arquivo “binário” que será enviado para a memória. Nesses
arquivos, constam todas as instruções do que deverá ser realizado.
O grafo de �uxo de controle permite detectar a existência de loops. Os
loops são importantes para a regra de loops. Aliás só a básicos
envolvidos em loops, deve dedicar a maior parte do tempo de
compilação de execução. Logo, um compilador, pois representa a
maioria do tempo otimização blocos dos otimização de ouro, diz que
10% do código é executado em 90% do tempo, na maioria dos casos
(LANGLOIS, 2018, p. 310).
Já a etapa �nal na geração de código pelo compilador é a chamada de fase de
otimização, pois ela é responsável por ajustar os requisitos de cada bloco de
comandos que faz parte do programa e por realizar e/ou sugerir otimizações.
Gerador de código
A geração de código é a última fase do processo de compilação, ela recebe, em
sua entrada, todas as representações intermediárias descritaspela linguagem-
objeto. A partir desse momento, é realizada a seleção dos registradores e
acontece a reserva de espaços de memória para receber as constantes e/ou as
variáveis, isso ocorre por uma árvore normalmente.
Um dos fatos mais relevantes no contexto da geração de código-alvo
está relacionado às especi�cidades do processador que irá executar o
código. Mesmo processadores de diferentes arquiteturas podem ser
agrupados em conjuntos que guardam semelhanças entre si, e uma
abordagem destes tipos se faz necessária antes de prosseguirmos
(BARBOSA et al., 2021, p. 153).
11/06/2023, 19:23 E-book
https://student.ulife.com.br/ContentPlayer/Index?lc=e6IUL5ncVpNnpafasMtHtw%3d%3d&l=1OdIzZ8xcachsr3pzfvcBA%3d%3d&cd=euiSKCRHJrkiU… 28/37
Então, os principais requisitos de um gerador de código são gerar códigos
corretos e otimizados, usar os recursos da máquina de forma otimizada (Figura
4.3), não permitir a passagem de erros e trabalhar, também, com técnicas
heurísticas para geração de bons códigos.
Figura 4.3 - Otimização
Fonte: Pronesto / Wikimedia Commons.
#PraCegoVer: na imagem, do lado esquerdo, há as palavras C, C++, Ada e Java, em
forma de coluna, todas apontam para a direita onde se encontra a palavra “front-
end”, da qual sai uma seta que termina na palavra “otimização”, que possui uma seta
que indica para a palavra “back-end”, da qual saem quatro setas que indicam quatro
palavras do lado direito, ARM, Sparc, x86-32 e PowerPC.
Dessa forma, o objetivo da fase de otimização de códigos é aplicar heurísticas
para tentar detectar e substituir ambiguidades por conta da renovação das
situações de ine�ciência (LOUDEN, 2004).
11/06/2023, 19:23 E-book
https://student.ulife.com.br/ContentPlayer/Index?lc=e6IUL5ncVpNnpafasMtHtw%3d%3d&l=1OdIzZ8xcachsr3pzfvcBA%3d%3d&cd=euiSKCRHJrkiU… 29/37
Fonte: Elaborado pelo autor.
#PraCegoVer:  o infográ�co estático, em formato de �uxograma, intitulado
“Compilação em sistemas operacionais diferentes”, possui seus elementos
posicionados verticalmente, da esquerda para a direita. No primeiro nível, há o
termo “Programa-fonte, Linguagem de alto nível”, rami�cado em três termos, no
segundo nível, respectivamente intitulados de “Compilador”, “Compilador” e
“Compilador”. No terceiro nível, a rami�cação continua com três elementos, cada
um em sua respectiva rami�cação, intitulados de “Programa-objeto”, “Programa-
objeto” e “Programa-objeto”. Continuando, no quarto nível, em cada rami�cação, há,
respectivamente, os termos “Linker”, “Linker” e “Linker”.  No nível cinco, em cada
rami�cação, há a mesma sequência de numeração binária “1010111000100001”.
No último nível, em cada rami�cação, há, respectivamente, as logomarcas do
Windows, Linux e Mac.
Quando vamos realizar um processo completo de compilação, deve �car bem
evidente que o hardware faz parte do processo também, principalmente, a
memória RAM, o processador e a arquitetura (RISC, CISC ou ARM).
11/06/2023, 19:23 E-book
https://student.ulife.com.br/ContentPlayer/Index?lc=e6IUL5ncVpNnpafasMtHtw%3d%3d&l=1OdIzZ8xcachsr3pzfvcBA%3d%3d&cd=euiSKCRHJrkiU… 30/37
Conhecimento
Teste seus Conhecimentos
(Atividade não pontuada)
No passado, os programadores tinham de interagir, diretamente, na memória
RAM (hardware) para fazer que um programa funcionasse. Isso era bem
complicado, essa era a programação de baixo nível. Atualmente, eles utilizam
a programação de alto nível, e os compiladores fazem a parte de alocação de
memória automaticamente, facilitando o processo.
Com relação aos processos de compilação, analise as a�rmativas a seguir.
I. Um compilador realiza uma rotina que trata uma linguagem de
programação, transformando-a em uma linguagem-objeto e, a partir dela,
traduz tudo para um programa equivalente em outra linguagem, ou seja, a
linguagem-fonte.
II. Os compiladores recebem, como entrada, um programa em qualquer
linguagem de programação, em formato de uma linguagem-fonte, depois,
realizam a tradução para um programa equivalente em outra linguagem, a
linguagem-objeto.
III. Tanto os compiladores como os interpretadores traduzem e processam
linguagens de programação que recebem como entrada.
IV. Os interpretadores realizam a execução direta das operações especi�cadas
em programas-fonte para uso direto dos usuários.
11/06/2023, 19:23 E-book
https://student.ulife.com.br/ContentPlayer/Index?lc=e6IUL5ncVpNnpafasMtHtw%3d%3d&l=1OdIzZ8xcachsr3pzfvcBA%3d%3d&cd=euiSKCRHJrkiU… 31/37
V. Os compiladores necessitam analisar a arquitetura do computador (RISC,
CISC e ARM), antes da geração do código de máquina.
Está correto o que se a�rma em:
a) I, II, III e V, apenas.
b) I e II, apenas.
c) II e III, apenas.
d) II, III, IV e V, apenas.
e) II, III e IV, apenas.
A compilação veio para facilitar o relacionamento entre as linguagens de alto e
baixo nível. Sendo assim, vamos praticar!
11/06/2023, 19:23 E-book
https://student.ulife.com.br/ContentPlayer/Index?lc=e6IUL5ncVpNnpafasMtHtw%3d%3d&l=1OdIzZ8xcachsr3pzfvcBA%3d%3d&cd=euiSKCRHJrkiU… 32/37
Material
Complementar
F I L M E
Matrix (The Matrix)
Ano: 1999
Comentário: O �lme descreve uma realidade que mistura
pessoas e códigos de programação, na verdade, uma
realidade simulada denominada "Matrix", que foi criada por
equipamentos com Inteligência Arti�cial. O �lme conta a
história de Neo, que é convidado para participar de uma
rebelião contra as máquinas e, assim, se desconectar delas,
que dominam seus cérebros com programas de
computação.
Para conhecer mais sobre o �lme, acesse o trailer disponível
em:
11/06/2023, 19:23 E-book
https://student.ulife.com.br/ContentPlayer/Index?lc=e6IUL5ncVpNnpafasMtHtw%3d%3d&l=1OdIzZ8xcachsr3pzfvcBA%3d%3d&cd=euiSKCRHJrkiU… 33/37
TRA I LER
L I V R O
Compiladores
Autores: Cynthia da Silva Barbosa, Maikon Lucian Lenz,
Paulo Sérgio Pádua de Lacerda, Ricardo César Ribeiro dos
Santos, Victor de Andrade Machado, Carlos Estevão Bastos
Sousa, Nicolli Souza Rios Alves, Rafael Leal Martins, Renata
Junges Padilha, Roque Maitino Neto e Vinícius Meyer
Editora: Sagah
Capítulo: Geração de código de máquina
Ano: 2021
ISBN: 978-65-5690-290-6
Comentário: A codi�cação tem, por função, a criação de um
programa e/ou um software, que serão executados em um
computador. Para que isso ocorra, é necessária a elaboração
de um código que interaja com os microprocessadores.
Então, para que isso aconteça, o compilador deve entrar em
ação para escalonar as instruções de máquina.
Disponível na Minha Biblioteca.
11/06/2023, 19:23 E-book
https://student.ulife.com.br/ContentPlayer/Index?lc=e6IUL5ncVpNnpafasMtHtw%3d%3d&l=1OdIzZ8xcachsr3pzfvcBA%3d%3d&cd=euiSKCRHJrkiU… 34/37
11/06/2023, 19:23 E-book
https://student.ulife.com.br/ContentPlayer/Index?lc=e6IUL5ncVpNnpafasMtHtw%3d%3d&l=1OdIzZ8xcachsr3pzfvcBA%3d%3d&cd=euiSKCRHJrkiU… 35/37
Conclusão
Chegamos ao �nal de nosso material, no qual aprendemos que a otimização deve
estar presente quando tratamos dos compiladores sempre. Para que isso aconteça,
são necessárias técnicas para melhoria do desempenho, que possam in�uenciar a
performance dos processadores (arquitetura).
Outro detalhe importante está relacionado com a alocação de memória que é
realizada no processo de compilação. Quanto maior for a capacidade da memória
disponibilizada e o código estiver bem otimizado, com certeza, a performance do
equipamento será melhor.
Assim, mesmo existindo diferenças nas arquiteturas RISC, CISC e ARM, os
compiladores devem permitir a compilação de código-fonte de forma integrada
utilizando o que de melhor cada arquitetura fornece.
Referênc
ias
AHO, A. V. et al. Compiladores:
princípios, técnicas e
ferramentas. São Paulo:
Pearson Addison-Wesley, 2008.
11/06/2023, 19:23 E-book
https://student.ulife.com.br/ContentPlayer/Index?lc=e6IUL5ncVpNnpafasMtHtw%3d%3d&l=1OdIzZ8xcachsr3pzfvcBA%3d%3d&cd=euiSKCRHJrkiU… 36/37
BARBOSA, C. da S. et al.
Compiladores. Porto Alegre:
Sagah, 2021. (Disponível na
Minha Biblioteca).
DELAMARO, M. Como construir um compilador utilizando ferramentas Java. São
Paulo: NovatecEditora, 2004. Disponível em:
http://conteudo.icmc.usp.br/pessoas/delamaro/SlidesCompiladores/CompiladoresFi
nal.pdf. Acesso em: 10 mar. 2022.
FEDOZZI, R. Compiladores. Londrina: Editora e Distribuidora Educacional S.A., 2018.
LANGLOIS, P. R. S. Compiladores: da teoria à prática. Rio de Janeiro: LTC, 2018.
LOUDEN, K. C. Compiladores: princípios e práticas. São Paulo: Cengage Learning,
2004.
MATRIX (The Matrix 1999). [S. l.: s. n.], 2017. 1 vídeo (2 min.). Publicado pelo canal
Arquivo de Trailers. Disponível em: https://youtu.be/2KnZac176Hs. Acesso em: 8 abr.
2022.
MENEZES, P. B. Linguagens formais e autômatos. Porto Alegre: Bookman, 2011.
O QUE é uma tabela de símbolos? Oque-e.com, [2022]. Disponível em: https://oque-
e.com/o-que-e-uma-tabela-de-simbolos/. Acesso em: 10 mar. 2022.
WAGNER, B.; SHARKEY, K.; FORENSIC, M. O sistema de tipos C#. Microsoft, 2022.
Disponível em: https://docs.microsoft.com/pt-
http://conteudo.icmc.usp.br/pessoas/delamaro/SlidesCompiladores/CompiladoresFinal.pdf
https://youtu.be/2KnZac176Hs
https://oque-e.com/o-que-e-uma-tabela-de-simbolos/
https://docs.microsoft.com/pt-br/dotnet/csharp/fundamentals/types/
11/06/2023, 19:23 E-book
https://student.ulife.com.br/ContentPlayer/Index?lc=e6IUL5ncVpNnpafasMtHtw%3d%3d&l=1OdIzZ8xcachsr3pzfvcBA%3d%3d&cd=euiSKCRHJrkiU… 37/37
br/dotnet/csharp/fundamentals/types/. Acesso em: 10 mar. 2022.
https://docs.microsoft.com/pt-br/dotnet/csharp/fundamentals/types/

Continue navegando