• Nenhum resultado encontrado

Conclui-se assim a descri¸c˜ao das ferramentas/sistemas de maior relevo para o trabalho desenvolvido neste doutoramento, cuja principal contribui¸c˜ao ´e uma arquitectura para siste- mas implementados atrav´es de frameworks. Nesta perspectiva, as ferramentas/sistemas mais significativos s˜ao aqueles que de forma assumida fazem uso de uma solu¸c˜ao deste tipo e que s˜ao compar´aveis/compat´ıveis com a solu¸c˜ao que ´e aqui proposta. ´E o caso do RTL System e do SUIF System, que servem de referˆencia para a avalia¸c˜ao das solu¸c˜oes apresentadas.

O gr´afico da Figura2.2quantifica a adequa¸c˜ao de cada um dos sistemas analisados, no desenvolvimento das tarefas de front-end, medium-level e back-end. Os trˆes primeiros sistemas (Eli, GENTLE e Cocktail) s˜ao representativos dos sistemas de gera¸c˜ao, caracterizados pela sua adequa¸c˜ao ao desenvolvimento de front-ends, mas tamb´em de back-ends. O GCC ´e o sistema que mais se aproxima de uma biblioteca, adequando-se mais `a constru¸c˜ao do medium- level do processo de compila¸c˜ao. O RTL System ´e o ´unico sistema cuja implementa¸c˜ao assenta unicamente numa framework, que como tal s´o permite suportar o desenvolvimento das tarefas de medium-level. Os trˆes ´ultimos sistemas (Zephyr, SUIF System e CoSy) s˜ao representativos da aplica¸c˜ao de ferramentas de gera¸c˜ao com frameworks, que de uma forma geral permitem suportar o desenvolvimento do medium-level e do back-end, mas por vezes tamb´em do front-end.

Figura 2.2: Gr´afico comparativo entre os v´arios sistemas.

2.9. Resumo do cap´ıtulo 27

CAP´ITULO 3

Framework Dolphin: Vers˜ao original

´Indice

3.1 Modelo de compila¸c˜ao . . . 32 3.2 Componentes . . . 33 3.3 Modelo da Representa¸c˜ao Interm´edia do C´odigo . . . 35 3.4 Interfaces . . . 36 3.5 Exemplo de utiliza¸c˜ao. . . 38 3.6 Resumo do cap´ıtulo . . . 40

No sentido de satisfazer o principal objectivo deste doutoramento, isto ´e, de tornar mais simples a constru¸c˜ao de compiladores, entendeu-se partir de uma solu¸c˜ao que claramente apostasse na reutiliza¸c˜ao, sem que no entanto impossibilitasse a utiliza¸c˜ao de ferramentas de gera¸c˜ao.

Eram v´arios os motivos que levavam a apostar na reutiliza¸c˜ao, em detrimento de so- lu¸c˜oes de gera¸c˜ao: em primeiro lugar, porque reutilizar significa pegar e fazer uso de algo que j´a existe, sem ter que ajustar, modificar ou alterar; em segundo lugar, porque se ´e to- talmente verdade que as ferramentas de gera¸c˜ao contribuem para simplificar a constru¸c˜ao de determinadas tarefas, tamb´em ´e verdade que especificar essas tarefas nem sempre ´e simples ou acess´ıvel para a grande maioria dos utilizadores. Por exemplo, ningu´em p˜oe em d´uvida a utilidade de ferramentas como o Lex e o Yacc, ou mesmo de ferramentas mais evolu´ıdas como o Eli, mas quantas pessoas neste mundo podem afirmar ter conseguido desenvolver umfront-endpara C++ ou at´e mesmo para C? E ferramentas como oImproved Bottom-Up Rewrite Generator-IBURG ou o BEG que permitem construir boa parte das tarefas deback-

end, que s˜ao sem d´uvida grandes auxiliares para quem constr´oi compiladores e que nem s˜ao dif´ıceis de utilizar. Mas quantas pessoas podem afirmar ter especificado um back-end que permita aproveitar razoavelmente os recursos disponibilizados por um processador do tipo Pentium? A verdade ´e que reutilizar ´e muito mais simples que especificar, seja para tarefas de front-end, back-end ou demedium-level.

Estas quest˜oes s˜ao de tal forma relevantes, que a grande maioria dos sistemas apresen- tados no Cap´ıtulo2, valem-se da reutiliza¸c˜ao para assim disponibilizarem aos seus utilizado- res front-ends e back-ends para as principais linguagens de programa¸c˜ao e arquitecturas de computa¸c˜ao.

N˜ao significa isto que se pretende excluir as ferramentas de gera¸c˜ao, antes pelo con- tr´ario, pretende-se poder fazer uso dessas ferramentas, mas apenas quando n˜ao ´e poss´ıvel reutilizar ou quando os componentes1que se desejaria utilizar n˜ao existem.

Praticamente todos os sistemas apresentados no Cap´ıtulo2permitem a reutiliza¸c˜ao e a aplica¸c˜ao de ferramentas de gera¸c˜ao, mas nem todos favorecem a reutiliza¸c˜ao em detrimento da gera¸c˜ao e nem todos disponibilizam uma solu¸c˜ao que permita integrar ambas op¸c˜oes.

Para potenciar a reutiliza¸c˜ao h´a que apostar em for¸ca no medium-level, tentando deslo- car o maior n´umero de componentes para este n´ıvel do processo de compila¸c˜ao, e se poss´ıvel disponibilizar tamb´em ferramentas que gerem componentes para este n´ıvel, permitindo assim reutilizar os componentes gerados.

O simples facto de se fazer uso de um medium-level por si s´o, j´a traz grandes benef´ı- cios. Nos compiladores em que este n´ıvel n˜ao existe, as tarefas tˆem que ser implementadas no front-end ou no back-end, mesmo que sejam integralmente ou parcialmente independentes da linguagem fonte e da arquitectura de computa¸c˜ao. No entanto, como est˜ao implemen- tadas sobre um modelo de RIC que ´e dependente destas caracter´ısticas (´arvore de sintaxe abstracta/assembly), n˜ao poder˜ao ser t˜ao facilmente reutiliz´aveis.

Acresce ainda que nem sempre os modelos de RIC utilizados nos front-ends e nos back- ends s˜ao os mais adequados para implementar as tarefas. Por exemplo, a atribui¸c˜ao global de registos, feita com base no algoritmo proposto por Chaitin [CAC+81, Cha82], requer o que se designa por inference graph, uma estrutura de dados que caracteriza a sobreposi¸c˜ao do per´ıodo de vida ´util das vari´aveis do programa. A computa¸c˜ao desta estrutura, que n˜ao ´e uma tarefa trivial, requer informa¸c˜ao que nem sempre est´a facilmente acess´ıvel nos ´

ultimos n´ıveis do processo de compila¸c˜ao. Acresce ainda que, apesar de suportar uma tarefa que ´e completamente dependente das caracter´ısticas do microprocessador (a atribui¸c˜ao de registos), a sua implementa¸c˜ao ´e em grande parte independente do tipo de arquitectura de computa¸c˜ao. Pelo que se for implementada no medium-level, poder´a ser reutilizada sem ser necess´ario qualquer tipo de altera¸c˜ao.

´

E j´a poss´ıvel tirar algumas conclus˜oes sobre as caracter´ısticas que uma ferramenta para constru¸c˜ao de compiladores deve satisfazer para potenciar a reutiliza¸c˜ao de componentes. A primeira ´e que o modelo de compila¸c˜ao a utilizar dever´a conter trˆes n´ıveis: front-end, medium- level e back-end. A segunda conclus˜ao ´e que as tarefas implementadas sobre o medium-level devem utilizar um modelo de RIC comum. A terceira conclus˜ao, ´e que come¸ca a fazer sentido a utiliza¸c˜ao de uma solu¸c˜ao do tipo framework em detrimento de ferramentas de gera¸c˜ao.

Verifica-se que a utiliza¸c˜ao de frameworks apresenta v´arias vantagens. ´E uma solu¸c˜ao orientada `a reutiliza¸c˜ao, que tem a vantagem adicional de permitir aplicar conceitos mais abstractos, nomeadamente de car´acter estrutural e comportamental, como por exemplo: de- finir um modelo de compila¸c˜ao, o tipo de entidades que utiliza e at´e mesmo a forma como estas se relacionam. ´E tamb´em uma excelente solu¸c˜ao para integrar ferramentas de gera¸c˜ao

1

O termo componente ´e utilizado para designar uma rotina ou conjunto de rotinas que visem executar uma ou mais tarefas de compila¸c˜ao.

31

ou inclusive outras frameworks.

Inverte-se assim o papel da framework no contexto das ferramentas/sistemas para cons- tru¸c˜ao de compiladores, passando agora a ser a base de todo o sistema. Esta solu¸c˜ao acaba mesmo por relegar as ferramentas de gera¸c˜ao para um segundo plano, em que funcionam como simples “acess´orios”. Isto para al´em dos benef´ıcios inerentes a qualquer framework, que:

• Pelo simples facto de disponibilizarem componentes j´a implementados, reduzem os custos de implementa¸c˜ao, teste e avalia¸c˜ao;

• Para al´em dos componentes, disponibilizam um desenho tipo para as aplica¸c˜oes (modelo funcional);

• Mas tamb´em de certa forma, o conhecimento e a experiˆencia de desenvolvimento e de implementa¸c˜ao;

• Pelo facto das aplica¸c˜oes partilharem o mesmo desenho e componentes, s˜ao mais nor- malizados, tendencialmente mais consistentes e com menores custos de actualiza¸c˜ao e manuten¸c˜ao;

• Contribuem para uma prototipagem r´apida dos componentes, interfaces, protocolos, e das pr´oprias aplica¸c˜oes;

• Facilitam o desenvolvimento cooperativo da framework ; • Funcionam como um reposit´orio de experiˆencia.

A utiliza¸c˜ao de frameworks segundo este modelo, encontra-se representada na Fi- gura1.2.

Dentro deste contexto, apenas dois dos sistemas apresentados no Cap´ıtulo 2satisfazem as condi¸c˜oes requeridas. ´E o caso doSUIF Compiler Systeme doRTL System. O CoSy fica de fora por falta de informa¸c˜ao de ´ındole cient´ıfica e por n˜ao ser um sistema aberto.

O SUIF System, apesar de ser um sistema que visa criar as condi¸c˜oes necess´arias para a experimenta¸c˜ao e investiga¸c˜ao de t´ecnicas de compila¸c˜ao, ´e uma solu¸c˜ao menos flex´ıvel no que diz respeito `a realiza¸c˜ao de experiˆencias com o pr´oprio sistema, isto devido `a sua dimens˜ao e complexidade. O que levou a considerar o RTL System como a solu¸c˜ao mais adequada para se desenvolver os trabalhos inerentes a este doutoramento.

O RTL System apresenta no entanto um pequeno sen˜ao: est´a implementado em Small- talk, quando as linguagens de elei¸c˜ao utilizadas nesta ´area s˜ao o C e o C++. A utiliza¸c˜ao do Smalltalk coloca logo `a partida problemas de compatibilidade. De notar que enquanto numa ferramenta de gera¸c˜ao, a linguagem utilizada na sua implementa¸c˜ao n˜ao tem que ser a mesma das rotinas geradas por essa ferramenta, j´a numa solu¸c˜ao do tipo framework n˜ao h´a esta diferen¸ca. Por exemplo, muitas ferramentas do Cocktail est˜ao implementadas em Modula-2, no entanto podem gerar c´odigo em linguagem C. Isto permite facilmente integrar esse c´odigo com solu¸c˜oes provenientes de outros sistemas, ou at´e mesmo integrar estas ferra- mentas noutros sistemas, n˜ao obstante o facto de estarem implementadas em Modula-2. No entanto, no caso das frameworks a linguagem que ´e utilizada na sua implementa¸c˜ao ´e neces- sariamente a mesma dos seus componentes, isto porque s˜ao os componentes que formam a framework. Significa isto que implementar frameworks com linguagens que n˜ao as de elei¸c˜ao, cria s´erias dificuldades `a integra¸c˜ao dos componentes com solu¸c˜oes provenientes de outros sistemas, mas tamb´em `a utiliza¸c˜ao dessas frameworks como plataformas de integra¸c˜ao de ferramentas de gera¸c˜ao.

Estes inconvenientes enfatizaram o trabalho j´a efectuado no ˆambito do projectoBack- End Development System- BEDS [Mat99], o qual poderia ser ´util para alcan¸car os objectivos propostos e que, para al´em de estar implementado em C++, j´a continha uma implementa¸c˜ao parcial do modelo de RIC utilizado pelo RTL System. Atendendo a que j´a havia algum know-how e mesmo algum c´odigo que poderia ser reaproveitado, ponderou-se e optou-se pela implementa¸c˜ao de uma solu¸c˜ao pr´opria.

Contribuiu ainda para esta op¸c˜ao, o facto de uma solu¸c˜ao pr´opria ser mais male´avel, menos propensa a restri¸c˜oes e mais incidente nos problemas que este doutoramento visa solucionar. Por um lado, isto significa que n˜ao ´e obrigat´orio utilizar solu¸c˜oes que n˜ao s˜ao relevantes para este doutoramento ou das quais se discorda; e por outro lado, ´e mais acess´ıvel fazer uso de solu¸c˜oes que tenham sido desenvolvidas propositadamente ou reaproveitadas de outros sistemas.

Do desenvolvimento desta solu¸c˜ao resultou a framework Dolphin, que apesar de n˜ao fazer parte dos objectivos deste doutoramento, serviu `a priori como test-bed para efectuar as experiˆencias que conduziram aos resultados aqui apresentados, e a posteriori como prova que esses resultados n˜ao s´o s˜ao funcionais, como satisfazem em grande parte os objectivos propostos.

Este cap´ıtulo visa apresentar o que se designou por framework Dolphin - Vers˜ao Ori- ginal (framework Dolphin-VO ), que foi desenvolvida `a imagem de outros sistemas, mas em especial do RTL System, e que foi utilizada para colocar em pr´atica e avaliar, as solu¸c˜oes idealizadas neste doutoramento.

´

E de real¸car que a implementa¸c˜ao desta framework, n˜ao tinha por objectivo desen- volver uma ferramenta/sistema para constru¸c˜ao de compiladores, previa-se apenas utiliz´a-la como test-bed. Resultou no entanto numa solu¸c˜ao bastante apraz´ıvel, com caracter´ısticas e uma filosofia pr´opria. O que levou a ponderar utiliz´a-la efectivamente (para l´a do contexto deste doutoramento) como uma ferramenta/sistema para constru¸c˜ao de compiladores, que faz mesmo parte de um projecto maior, o Sistema Dolphin (ver Cap´ıtulo 9). Houve assim necessidade de lhe dar um nome (inicialmente designada por framework Dolphin), e pos- teriormente de distinguir a vers˜ao utilizada como base para o trabalho desenvolvido neste doutoramento (framework Dolphin -VO ), da vers˜ao que resulta da aplica¸c˜ao das solu¸c˜oes aqui propostas (a qual se designa, simplesmente, por framework Dolphin2).

Para simplificar a compreens˜ao do texto, utilizar-se-´a o termo “framework Dolphin- VO ” apenas para referir aspectos espec´ıficos da vers˜ao original deste sistema. Quando o contexto visar a vers˜ao definitiva ou caracter´ısticas comuns entre ambas vers˜oes, ser´a utilizado simplesmente o termo “framework Dolphin”.

3.1

Modelo de compila¸c˜ao

Conceptualmente uma framework difere de uma biblioteca, porque pode incluir rotinas reutiliz´aveis, mas principalmente porque deve definir: o modelo da aplica¸c˜ao (a desenvolver atrav´es da framework ); as entidades que comp˜oem esse modelo; e a forma como essas enti- dades se relacionam. A framework reflecte assim a estrutura das aplica¸c˜oes a desenvolver, que neste caso s˜ao compiladores.

J´a foi dito que: os compiladores para este tipo de solu¸c˜ao s˜ao formados por um front- end, um medium-level e um back-end ; e que as tarefas do medium-level funcionam sobre um modelo comum de RIC. Apesar de j´a dizer muito acerca do modelo de compila¸c˜ao, h´a outras

2

Na realidade o trabalho desenvolvido neste doutoramento, permite que a vers˜ao original integre e coabite com a vers˜ao definitiva da framework Dolphin, de forma extremamente simples e eficiente e sem qualquer tipo de redundˆancia (ver Sec¸c˜ao3.4).