Baixe o app para aproveitar ainda mais
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/
Compartilhar