• Nenhum resultado encontrado

A constru¸c˜ao de compiladores atrav´es da framework Dolphin dever´a passar em grande parte pela reutiliza¸c˜ao dos componentes, que ´e a op¸c˜ao desej´avel. No entanto quando um determinado componente n˜ao existir, o utilizador ter´a que optar pela op¸c˜ao menos desej´avel, que consiste em implementar o componente segundo o modelo de compila¸c˜ao e as interfaces definidas pela framework. Como o objectivo deste doutoramento ´e tornar a constru¸c˜ao de compiladores mais simples, implica fazer com que a reutiliza¸c˜ao, mas tamb´em a implemen- ta¸c˜ao de componentes, sejam ambas tarefas simples e f´aceis de realizar.

Em virtude de se estar a utilizar uma framework, a reutiliza¸c˜ao ´e uma tarefa bastante simples. Consiste em instanciar o componente desejado, efectuar o registo da RIC no com- ponente e execut´a-lo, conforme ilustra o exemplo da Figura 3.7(Program ´e uma das classes da DIR).

A reutiliza¸c˜ao dos front-ends ´e ligeiramente diferente. Nestes casos as opera¸c˜oes a realizar s˜ao as que se encontram representadas na Figura3.8:

3.5. Exemplo de utiliza¸c˜ao 39

(1) class Protocol:virtual public FObject{

(2) protected:

(3) // Variáveis do objecto

(4) PROTOCOL ___protocol;

(5) // Métodos do objecto

(6) virtual bool execute0(){return false;} // Protocolo P0

(7) virtual bool execute1(){return false;} // Protocolo P1

(8) virtual bool execute2(){return false;} // Protocolo P2

(9) ...

(10) virtual void setProtocol(PROTOCOL);

(11) // Construtor (12) Protocol(); (13) public : (14) // Destrutor (15) virtual ~Protocol(); (16) // Métodos do objecto

(17) virtual bool execute();

(18) virtual PROTOCOL getProtocol();

(19) };

Figura 3.6: Interface Protocol.

(1) // Opção 1 // Opção 2

(2) Program *p=...; Program *p=...;

(3) elimComSubExpr ecse(p); elimComSubExpr ecse();

(4) ecse.execute(); ecse.setElem(p);

(5) ecse.execute();

Figura 3.7: Reutiliza¸c˜ao de um componente.

A Figura 3.9 cont´em a especifica¸c˜ao integral de um compilador que possui: um front- end (littleC); um back-end (genX86 ), que ´e aplicado duas vezes; e algumas optimiza¸c˜oes. Alguns destes componentes integram outros componentes, nomeadamente do tipo An´alise e de Suporte ao Back-End.

Esta simplicidade tem no entanto um pre¸co bastante elevado, nomeadamente em termos da eficiˆencia do processo de compila¸c˜ao. A principal contribui¸c˜ao deste trabalho de douto- ramento ´e uma arquitectura que permite manter a simplicidade, sem no entanto deteriorar a eficiˆencia do processo de compila¸c˜ao (ver Cap´ıtulo5).

J´a no que diz respeito `a implementa¸c˜ao de componentes, a solu¸c˜ao proposta nesta disserta¸c˜ao passa pela concep¸c˜ao de um modelo de RIC (a DIR), cuja concep¸c˜ao foi feita no sentido de facilitar o desenvolvimento de novos componentes, conforme ´e explicado no Cap´ıtulo4.

(1) Program *p;

(2) littleC fe(...);

(3) fe.execute();

(4) p=fe.getElem();

Figura 3.8: Reutiliza¸c˜ao de um front-end.

(1) int main(int argc,char *argv[]){

(2) littleC fe(argc,argv); (3) fe.execute(); (4) Program *p=fe.getElem(); (5) if(p){ (6) elimUnreachCode euc(p); (7) euc.execute(); (8) elimJumpChains ejc(p); (9) ejc.execute(); (10) genX86 gx(p); (11) gx.setFile("output1"); (12) gx.execute(); (13) elimLoads el(p); (14) el.execute(); (15) gx.setFile("output2"); (16) gx.execute(); (17) } (18) return 0; (19) }

Figura 3.9: Exemplo da especifica¸c˜ao de um compilador.

3.6

Resumo do cap´ıtulo

Conclui-se assim este cap´ıtulo que serviu para apresentar a framework Dolphin-VO, sobre a qual se desenvolveram as solu¸c˜oes propostas nestas disserta¸c˜ao. ´E no entanto de destacar que, apesar deste ser o ponto de partida para o trabalho que ´e relatado neste documento, a realidade ´e que boa parte deste sistema foi desenvolvido no ˆambito deste doutoramento.

Apesar da sua simplicidade, ´e um sistema que apresenta algumas mais valias em ter- mos cient´ıficos. Por exemplo, a rela¸c˜ao entre componentes e RIC, que aparentemente n˜ao tem muito que se lhe diga, difere no entanto da solu¸c˜ao que ´e utilizada no SUIF System. Neste sistema os componentes s˜ao associados `a RIC, enquanto que na framework Dolphin os componentes s˜ao associados a elementos da RIC. Esta pequena diferen¸ca permite aos utili- zadores ter um controlo mais acurado sobre os componentes, garantindo maior flexibilidade na especifica¸c˜ao dos compiladores. Mas ´e tamb´em fundamental para garantir a eficiˆencia do

3.6. Resumo do cap´ıtulo 41

CAP´ITULO 4

Framework Dolphin: Modelo de Representa¸c˜ao

Interm´edia do C´odigo

´Indice

4.1 Modelos de RIC: Caracter´ısticas . . . 44 4.2 Modelos de RIC: Estado da arte . . . 45 4.2.1 Tuplos e ´arvores de express˜oes . . . 45 4.2.2 Modelo do GNU Compiler Collection. . . 46 4.2.3 Modelo do Zephyr . . . 47 4.2.4 Modelo do RTL System . . . 48 4.2.5 Stanford University Intermediate Format . . . 51 4.3 Dolphin Internal Representation . . . 53 4.3.1 Estrutura e classes da DIR . . . 54 4.3.2 Aplica¸c˜ao da DIR . . . 57 4.3.3 Caracter´ısticas da DIR. . . 60 4.4 Resumo do cap´ıtulo . . . 67

Conforme explicado no Cap´ıtulo 3, a utiliza¸c˜ao de frameworks como sistemas para constru¸c˜ao de compiladores apresenta v´arias vantagens comparativamente com outro tipo de solu¸c˜oes. No entanto, o sucesso deste tipo de solu¸c˜ao est´a dependente da utiliza¸c˜ao de um medium-levelna estrutura dos compiladores, que seja independente da linguagem fontee da arquitectura de computa¸c˜ao. ´E atrav´es deste medium-level, que uma framework potencia e

disponibiliza as condi¸c˜oes necess´arias `a implementa¸c˜ao de componentes reutiliz´aveis, isto ´e, que podem ser utilizados sem necessitarem de qualquer tipo de altera¸c˜ao. Mas para que tal seja poss´ıvel, ´e de todo conveniente que os componentes que operam a este n´ıvel fa¸cam uso de um modelo comum deRepresenta¸c˜ao Interm´edia do C´odigo (RIC).

O modelo de RIC ´e assim uma pe¸ca chave para o sucesso desta abordagem, pelo que a sua escolha ´e uma quest˜ao delicada e que deve ser bem ponderada. Isto porque tem de servir para representar c´odigo proveniente das mais diversas linguagens de programa¸c˜ao (correspondentes a diferentes paradigmas), tem de suportar um conjunto bastante grande e diversificado de componentes de an´alise, optimiza¸c˜ao e tradu¸c˜ao, e tem de ser adequado `as necessidades e exigˆencias das tarefas deback-end.

Acresce a tudo isto, o facto de se pretender contribuir com este trabalho para tornar a constru¸c˜ao de compiladores mais simples, o que se pretende conseguir pela conjuga¸c˜ao de duas estrat´egias distintas: uma que visa facilitar a utiliza¸c˜ao dos componentes, salvaguardando a qualidade do processo de compila¸c˜ao e do c´odigo a gerar pelos compiladores; e outra que vai no sentido de assegurar as condi¸c˜oes mais adequadas `a implementa¸c˜ao de novos componentes. Esta ´ultima est´a inevitavelmente relacionada com o modelo de RIC que ´e utilizado.

Este cap´ıtulo come¸ca por descrever o tipo de caracter´ısticas requeridas a um modelo de RIC. De seguida faz um pequeno levantamento do estado da arte, no que a este assunto diz respeito, e depois apresenta aDolphin Internal Representation(DIR), o modelo proposto nesta disserta¸c˜ao. Conclui com um pequeno resumo no qual se faz a compara¸c˜ao dos v´arios modelos, incluindo o modelo proposto.

4.1

Modelos de RIC: Caracter´ısticas

´

E cada vez mais percept´ıvel, que o modelo de RIC tem um papel fundamental no processo de constru¸c˜ao de compiladores e como tal, no desenvolvimento de sistemas para constru¸c˜ao de compiladores que tenham por base frameworks. Mas a verdade ´e que s˜ao poucos os estudos feitos que visem este assunto em concreto, nomeadamente no que concerne ao desenho, implementa¸c˜ao e avalia¸c˜ao de modelos de RIC. Surge na maioria da bibliografia como um assunto secund´ario ou subentendido, n˜ao tendo mesmo sido encontrado um ´unico artigo em que este fosse o tema principal.

´

E por exemplo not´oria a falta de requisitos que permitam avaliar um modelo de RIC. As poucas excep¸c˜oes encontradas, provˆem da bibliografia referente aoRegister Transfer List- RTL, que apresenta alguns requisitos, que apesar de se manterem v´alidos s˜ao insuficientes para caracterizar os modelos de RIC mais recentes.

Atendendo `a relevˆancia que o modelo de RIC tem para o tipo de solu¸c˜ao utilizada na prepara¸c˜ao desta disserta¸c˜ao, foi fundamental definir requisitos que ajudassem a classificar e a escolher o modelo mais adequado. Neste sentido, entendeu-se que um modelo de RIC deve ser:

Gen´erico: Capacidade para representar c´odigo proveniente de uma qualquer linguagem fonte, sem estar condicionado a detalhes relacionados com a arquitectura de computa- ¸

c˜ao.

Flex´ıvel: Capacidade para suportar novos operadores, novos modos de endere¸camento ou outros detalhes inevit´aveis que est˜ao relacionados com a linguagem fonte (como ´e o caso da tabela de identificadores), sem que isso comprometa a utiliza¸c˜ao dos componentes j´a desenvolvidos.