• Nenhum resultado encontrado

Análise estática de código para o portal de algoritmos da UCS

N/A
N/A
Protected

Academic year: 2021

Share "Análise estática de código para o portal de algoritmos da UCS"

Copied!
101
0
0

Texto

(1)

MATTHIAS BEBBER BREDA

AN ´ALISE EST ´ATICA DE C ´ODIGO PARA O PORTAL DE ALGORITMOS DA UCS

CAXIAS DO SUL 2018

(2)
(3)

AN ´

ALISE EST ´

ATICA DE C ´

ODIGO PARA O PORTAL DE

ALGORITMOS DA UCS

Trabalho de Conclus ˜ao de Curso para obtenc¸ ˜ao do t´ıtulo de Bacharel em Ci ˆencia da Computac¸ ˜ao pela Univer-sidade de Caxias do Sul.

Orientador Prof. Dr. Ricardo Vargas Dorneles

CAXIAS DO SUL 2018

(4)
(5)

AN ´

ALISE EST ´

ATICA DE C ´

ODIGO PARA O PORTAL DE

ALGORITMOS DA UCS

Trabalho de Conclus ˜ao de Curso para obtenc¸ ˜ao do t´ıtulo de Bacharel em Ci ˆencia da Computac¸ ˜ao pela Univer-sidade de Caxias do Sul.

Aprovado em: / /

Banca Examinadora

Prof Dr. Ricardo Vargas Dorneles Universidade de Caxias do Sul - UCS

Prof Dr. Andre Luis Martinotto

Universidade de Caxias do Sul - UCS

Prof MSc. Alexandre Erasmo Krohn Nascimento Universidade de Caxias do Sul - UCS

(6)
(7)

Agradecimentos.

Agradec¸o principalmente a minha fam´ılia, amigos e ao meu orientador Ricardo pela ajuda ao longo deste trabalho.

(8)
(9)

An ´alise est ´atica de c ´odigo ´e realizada sem a execuc¸ ˜ao real do algoritmo, que ´e o oposto de an ´alise din ˆamica que ´e realizada quando o algoritmo est ´a executando. O objetivo deste trabalho ´e desenvolver um analisador est ´atico de c ´odigo para o Portal de Algoritmos da UCS. Neste trabalho s ˜ao abordadas as t ´ecnicas mais conhecidas de an ´alise est ´atica, SSA (Static Single Assignment) (do ingl ˆes, Static Single Assignment - Atribuic¸ ˜ao ´Unica Est ´atica) e An ´alise de Fluxo de Dados e An ´alise de Intervalo de Valores. Estas t ´ecnicas foram utilizadas para reconhecer erros que o analisador l ´exico e sint ´atico do Portal de Algoritmos da UCS n ˜ao consegue identificar (vari ´aveis n ˜ao inicializadas, vari ´aveis n ˜ao utilizadas, func¸ ˜ao que n ˜ao define valor de retorno, c ´odigo inacess´ıvel entre outros), ajudando assim o aluno, indicando onde existem poss´ıveis erros no c ´odigo.

Palavras-chave: An ´alise est ´atica de c ´odigo, Portal de Algoritmo da UCS, SSA, An ´alise de Fluxo de Dados.

(10)
(11)

Static code analysis is the analysis of code that is executed without the actual execution of the algorithm, which is the opposite of dynamic analysis that is ex-ecuted when the algorithm is running. The objective of this work is to develop a static code analyzer for the Web-based Environment for Learning Introductory Programming. This work discusses the most known techniques of static analysis, SSA (Static Single Assignment), Data Flow Analysis and Values Interval Analy-sis. These techniques were be used to acknowledge errors which the lexical and syntactic parser can not identify (uninitialized variables, unused variables, func-tion that does not define the return value, unreachable code and others), thus helping the student, indicating where there are possible errors in the code.

Keywords: Static Code Analysis, Web-based Environment for Learning Introduc-tory Programming, SSA, Data Flow Analysis .

(12)
(13)

1 Exemplo de C ´odigo de tr ˆes enderec¸os . . . 25

2 C ´odigo de tr ˆes enderec¸os e sua representac¸ ˜ao em grafo de fluxo de controle . . . 26

3 Equac¸ ˜ao de Definic¸ ˜ao Incidente . . . 27

4 Equac¸ ˜ao para a an ´alise de vida de vari ´aveis . . . 28

5 Bloco de c ´odigo sequencial e sua convers ˜ao para a forma SSA . . . . 30

6 Exemplo de condicional. . . 38

7 C ´odigo em portugu ˆes estruturado e sua representac¸ ˜ao em SSA . . . . 38

8 Representac¸ ˜ao em e-SSA (Extended Static Single Assignment) do c ´odigo da Figura 7 (RODRIGUES; CAMPOS; PEREIRA, 2013) . . . 39

9 Sistema de restric¸ ˜oes . . . 40

10 Restric¸ ˜oes extra´ıdas do c ´odigo e-SSA da Figura 7 . . . 41

11 Restric¸ ˜oes extra´ıdas do c ´odigo e-SSA da Figura 7 . . . 41

12 Componentes fortemente conexos do grafo da Figura 11 . . . 43

13 Equac¸ ˜ao para alargamento de intervalo . . . 43

14 ´Ultimo CFC (Componentes Fortemente Conexos) ap ´os o alargamento de intervalos . . . 44

15 Equac¸ ˜ao para resolver valores futuros . . . 45

16 ´Ultimo CFC ap ´os corrigir intersecc¸ ˜oes . . . 45

17 Equac¸ ˜ao para estreitamento do intervalo . . . 46

18 Exemplo de propagac¸ ˜ao do valor de i . . . 46

19 Resultado da an ´alise de intervalo de valores . . . 47

20 Grafo de Fluxo de Controle do Trecho de C ´odigo 6 . . . 49

21 Grafo de Fluxo de Controle do Trecho de C ´odigo 7 . . . 50

22 Pacotes principais . . . 55

23 Representac¸ ˜ao da convers ˜ao para C ´odigo de Tr ˆes Enderec¸os . . . 56

24 Convers ˜ao de uma instruc¸ ˜ao . . . 57

25 Convers ˜ao de uma instruc¸ ˜ao . . . 58

26 Representac¸ ˜ao do Grafo de Fluxo de Controle . . . 59

27 Grafo de Fluxo de Controle gerado . . . 61

(14)

31 Representac¸ ˜ao da An ´alise de Vida de Vari ´aveis . . . 67

32 Representac¸ ˜ao da An ´alise de Intervalo de Valores . . . 70

33 Representac¸ ˜ao da An ´alise de Intervalo de Valores . . . 75

34 Grafo de Depend ˆencias . . . 77

35 Algoritmo com erro de ´ındice de um vetor . . . 85

36 Log com intervalos assumidos pelas vari ´aveis . . . 86

37 Algoritmo com express ˜ao constante . . . 86

38 Log com intervalos assumidos pelas vari ´aveis . . . 87

39 Algoritmo com loop infinito . . . 87

40 Log com intervalos assumidos pelas vari ´aveis . . . 88

41 Algoritmo com vari ´avel n ˜ao inicializada . . . 88

42 Algoritmo com c ´odigo morto . . . 89

43 Algoritmo da base de dados com c ´odigo morto . . . 90

(15)
(16)
(17)
(18)

1 Algoritmo iterativo para an ´alise de definic¸ ˜oes incidentes . . . 27

2 Algoritmo iterativo para an ´alise de vida de vari ´aveis . . . 29

3 Algoritmo para construir SSA m´ınima . . . 31

4 Algoritmo para identificar nomes n ˜ao-locais . . . 34

5 Algoritmo exemplo para propagac¸ ˜ao de constantes . . . 35

6 Exemplo de algoritmo com vari ´avel n ˜ao inicializada . . . 49

7 Exemplo de algoritmo com func¸ ˜ao que n ˜ao define valor de retorno . . . 49

8 Exemplo de algoritmo com vari ´aveis n ˜ao utilizadas . . . 51

9 Exemplo de algoritmo com express ˜ao constante, c ´odigo inacess´ıvel e loop . . . 51

10 Exemplo de algoritmo com erro de ´ındice de vetores . . . 52

11 Gerac¸ ˜ao do c ´odigo de tr ˆes enderec¸os. . . 56

12 Gerac¸ ˜ao de blocos b ´asicos de condicionais . . . 60

13 Gerac¸ ˜ao de identificador para os s´ımbolos . . . 60

14 Enumerador com os problemas mapeados . . . 62

15 Procurando por vari ´aveis n ˜ao inicializadas ou func¸ ˜oes que n ˜ao definem valor de retorno . . . 65

16 Procurando por c ´odigo morto . . . 68

17 M ´etodo principal da classeIntervalValueAnalisys . . . . 71

18 Calculando a fronteira de domin ˆancia . . . 71

19 Inserindo as func¸ ˜oes phi na fronteira de domin ˆancia de cada bloco b ´asico 72 20 Inserindo intervalo encontrado no condicional . . . 73

21 Uma parte do m ´etodorenameVariables(BasicBlock basicBlock) que preenche o identificador SSA . . . 73

22 Montando grafo de depend ˆencias . . . 75

23 Encontrando os componentes fortemente conexos . . . 78

24 Resoluc¸ ˜ao de um sistema de restric¸ ˜ao . . . 78

25 Processando intervalos . . . 79

26 Alargamento do intervalo e corrigindo intersecc¸ ˜oes de uma depend ˆencia 79 27 Estreitamento do intervalo de uma depend ˆencia . . . 80

28 Testando todas combinac¸ ˜oes poss´ıveis nos condicionais . . . 81

(19)
(20)
(21)

SSA Static Single Assignment

e-SSA Extended Static Single Assignment UCS Universidade de Caxias do Sul CFC Componentes Fortemente Conexos JDK Java Development Kit

(22)
(23)

1 INTRODUC¸ ˜AO 21 1.1 OBJETIVOS . . . 22 1.2 ESTRUTURA DO TRABALHO . . . 22

2 DESCRIC¸ ˜AO DAS T ´ECNICAS 24

2.1 AN ´ALISE DE FLUXO DE DADOS . . . 25 2.1.1 Definic¸ ˜oes Incidentes . . . . 27 2.1.2 An ´alise de Vida de Vari ´aveis . . . . 28 2.2 SSA . . . 29 2.2.1 SSA m´ınimo . . . 31 2.2.2 SSA podado . . . . 33 2.2.3 SSA semi podado . . . . 34 2.2.4 Comparac¸ ˜ao entre os algoritmos m´ınimo, podado e semi podado 35 2.2.5 Propagac¸ ˜ao de Constantes . . . 35 2.3 AN ´ALISE DE INTERVALO DE VALORES . . . 36 2.3.1 Intervalos de Valores . . . . 37 2.3.2 e-SSA . . . . 37 2.3.3 Propagac¸ ˜ao de intervalos de valores . . . . 39 2.3.4 Componentes Fortemente Conexos . . . . 42 2.3.5 Alargando o Intervalo das Vari ´aveis . . . . 43 2.3.6 Corrigindo as Intersecc¸ ˜oes . . . 44 2.3.7 Estreitando o Intervalo das Vari ´aveis . . . . 45

3 ESCOLHA DA T ´ECNICA PARA CADA ERRO 48

3.1 VARI ´AVEIS N ˜AO INICIALIZADAS E FUNC¸ ˜OES QUE N ˜AO DEFI-NEM O VALOR DE RETORNO . . . 48 3.2 C ´ODIGO MORTO . . . 50 3.3 EXPRESS ˜AO CONSTANTE, C ´ODIGO INACESS´IVEL E LOOP . . . 51 3.4 ´INDICES DE VETORES . . . 52

4 IMPLEMENTAC¸ ˜AO 54

4.1 C ´ODIGO DE TR ˆES ENDEREC¸ OS . . . 55 4.1.1 Exemplo de c ´odigo gerado . . . . 57 4.2 GRAFO DE FLUXO DE CONTROLE . . . 58 4.2.1 Estrutura para an ´alise est ´atica . . . . 62 4.3 AN ´ALISE DE DEFINIC¸ ˜OES INCIDENTES . . . 63 4.3.1 Identificac¸ ˜ao de erros . . . . 64

(24)

4.5 AN ´ALISE DE INTERVALO DE VALORES . . . 69 4.5.1 Convers ˜ao do c ´odigo para e-SSA . . . . 71 4.5.2 Montando Grafo de Depend ˆencias . . . . 75 4.5.3 Encontrando Componentes Fortemente Conexos . . . . 78 4.5.4 Processando intervalos . . . . 78 4.5.5 Identificando erros . . . 80 4.6 INTEGRAC¸ ˜AO COM O PORTAL DE ALGORITMOS . . . 83

5 TESTES REALIZADOS 85

6 CONCLUS ˜OES 92

(25)

1 INTRODUC¸ ˜AO

´

E pr ´atica comum nos cursos da ´area de computac¸ ˜ao comec¸ar o ensina-mento de programac¸ ˜ao de computadores por uma disciplina na qual s ˜ao discu-tidos conceitos b ´asicos como tipos de dados, vari ´aveis e constantes, ao mesmo tempo em que s ˜ao apresentados comandos de entrada e sa´ıda de dados, ope-radores de atribuic¸ ˜ao, aritm ´eticos, relacionais e l ´ogicos (SOUZA, 2009).

Entre os meios que podem ser utilizados, est ˜ao os ambientes de aprdizagem de programac¸ ˜ao. O uso deste ambiente nos est ´agios iniciais do en-sino de programac¸ ˜ao tem-se mostrado bastante produtivo por permitir que desde o in´ıcio os estudantes tenham contato com um ambiente de desenvolvimento pr ´oximo ao que encontrar ˜ao em sua vida profissional, embora mais simples e usando uma linguagem de programac¸ ˜ao sem tantos recursos (SOUZA, 2009).

Por ´em os ambientes de aprendizagem de programac¸ ˜ao somente mos-tram erros l ´exicos, sint ´aticos e alguns sem ˆanticos (erros de tipo). Existem alguns erros que poderiam ser identificados mas que requerem uma an ´alise mais com-plexa como uma an ´alise de fluxo de dados.

An ´alise est ´atica de c ´odigo ´e a an ´alise de c ´odigo que ´e executada sem a execuc¸ ˜ao real dos programas constru´ıdos a partir desse algoritmo, que ´e o oposto de an ´alise din ˆamica (GOMES et al., 2009). Para a maioria dos casos a an ´alise ´e realizada em alguma vers ˜ao do c ´odigo fonte e em outros casos em forma de c ´odigo de representac¸ ˜ao intermedi ´aria (GOMES et al., 2009).

Os tipos de erros que o analisador est ´atico pode detectar s ˜ao bastante diversificados, variando de erros de codificac¸ ˜ao, como por exemplo, vari ´aveis n ˜ao inicializadas, vari ´aveis n ˜ao utilizadas, func¸ ˜oes que n ˜ao definem o valor de retorno, c ´odigo inacess´ıvel, express ˜oes constantes, erros de ´ındices de vetores e at ´e padr ˜oes c ´odigos como MIRSA-C/C++ ou CERT C/C++ (BIGGIN, 2012).

(26)

O Portal de Algoritmos da UCS (Universidade de Caxias do Sul) ´e um portal de ensino e aprendizagem onde o aluno tem a oportunidade de aprender e melhorar suas habilidades desenvolvendo algoritmos a partir de problemas que est ˜ao cadastrados no portf ´olio. ´E um ambiente WEB composto por quatro partes: um conjunto de problemas algor´ıtmicos, o que se refere ao portf ´olio de problema, um editor de algoritmo, uma ferramenta de avaliac¸ ˜ao de soluc¸ ˜ao e uma interface do professor (DORNELES; JR; ADAMI, 2010).

Por ´em o ambiente de desenvolvimento n ˜ao tem uma ferramenta que auxilia o usu ´ario a detectar erros que n ˜ao s ˜ao encontrados pela an ´alise l ´exica e sint ´atica. Este trabalho pretende encontrar estes erros:

• Vari ´aveis n ˜ao inicializadas. • Vari ´aveis n ˜ao utilizadas.

• Func¸ ˜oes que n ˜ao define valor de retorno. • C ´odigo inacess´ıvel.

• Express ˜oes constantes. • Erros de ´ındices de vetores.

• Loop em situac¸ ˜oes espec´ıficas (nas situac¸ ˜oes em que ´e poss´ıvel calcular a vari ´avel de controle do loop).

1.1 OBJETIVOS

Este trabalho apresenta como principal objetivo o desenvolvimento de um analisador est ´atico de c ´odigo para o Portal de Algoritmo da UCS capaz de encontrar erros que n ˜ao s ˜ao encontrados pela an ´alise sint ´atica e indica ao aluno onde est ´a o erro para ajud ´a-lo no aprendizado de algoritmos.

1.2 ESTRUTURA DO TRABALHO

No Cap´ıtulo 2 ´e apresentada detalhadamente a descric¸ ˜ao das t ´ecnicas de an ´alise est ´atica.

No Cap´ıtulo 3 ´e descrita a t ´ecnica utilizada para identificar cada erro. No Cap´ıtulo 4 ´e apresentada a forma como o projeto foi desenvolvido em sua fase de implementac¸ ˜ao.

(27)
(28)

2 DESCRIC¸ ˜AO DAS T ´ECNICAS

Qualquer an ´alise de programa requer alguma representac¸ ˜ao abstrata do c ´odigo para que seja poss´ıvel extrair caracter´ısticas importantes que possam ser usadas para realizar otimizac¸ ˜oes e encontrar erros no c ´odigo (ATKINSON; GRISWOLD, 2001; HAVLAK, 1995). Linguagens de programac¸ ˜ao de alto n´ıvel s ˜ao valiosas ferramentas porque permitem a especificac¸ ˜ao dos algoritmos em notac¸ ˜oes mais naturais para expressar os conceitos abstratos envolvidos (KEN-NEDY, 1981).

A linguagem de c ´odigo intermedi ´aria ´e o fator chave para a efici ˆencia das an ´alises para otimizac¸ ˜ao de c ´odigo e identificac¸ ˜ao de erros e tem sido am-plamente estudada (KOSCHKE; GIRAD; WURTHNER, 1998).

O c ´odigo de tr ˆes enderec¸os ´e a linguagem intermedi ´aria utilizada neste trabalho. Foi escolhida pois ´e utilizada na maioria dos artigos e livros em que este trabalho se baseia. No c ´odigo de tr ˆes enderec¸os cada instruc¸ ˜ao tem no m ´aximo tr ˆes operandos e ´e normalmente uma combinac¸ ˜ao de atribuic¸ ˜ao e um operador bin ´ario. Como por exemplo x := y op z, onde x, y e z s ˜ao nomes, constantes ou objetos de dados tempor ´arios criado pelo compilador e op ´e um operador aritm ´etico ou um operador l ´ogico (AHO; ULLMAN; SETHI, 2008).

O c ´odigo de tr ˆes enderec¸os tem semelhanc¸a a Assembly (linguagem de montagem). Os enunciados podem ter r ´otulos simb ´olicos (como Labels em C) e enunciados para fluxo de controle (goto, em portugu ˆes, ir para) (LEUPERS, 2001; AHO; ULLMAN; SETHI, 2008).

Tamb ´em possui instruc¸ ˜ao de desvio condicional tal como if x relop y goto L. Onde relop ´e um operador relacional (<, =, ≥, ≤, etc). Se a condic¸ ˜ao x relop y for verdadeira o comando goto L ´e executado, sen ˜ao segue o pr ´oximo comando da lista de enunciados (AHO; ULLMAN; SETHI, 2008).

(29)

Na Figura 1 ´e representado um c ´odigo de tr ˆes enderec¸os com as instruc¸ ˜oes que foram descritas acima.

Figura 1 — Exemplo de C ´odigo de tr ˆes enderec¸os x ← 50 y ← 2 z ← x ∗ y if z ≥100 gotoF1 z ← 0 F1: x ← z

Fonte: Pr ´oprio autor

Existem v ´arias t ´ecnicas de an ´alise est ´atica de c ´odigo e estas podem ser caracterizadas pela sua natureza e profundidade (GERMAN, 2003). Natureza se refere aos objetivos gerais da an ´alise, como por exemplo, portabilidade do c ´odigo ou encontrar erros, e a profundidade significa a profundidade da an ´alise da t ´ecnica. A seguir s ˜ao citadas algumas t ´ecnicas.

• An ´alise de Fluxo de Controle. • An ´alise de Fluxo de Dados. • An ´alise de Fluxo de Informac¸ ˜oes. • An ´alise de Caminho de Func¸ ˜ao. • Verificac¸ ˜ao Formal.

• An ´alise de Intervalo de Valores. • Atribuic¸ ˜ao ´Unica Est ´atica.

O objetivo deste cap´ıtulo ´e descrever os m ´etodos mais conhecidos de an ´alise est ´atica para detectar os erros n ˜ao encontrados pela an ´alise l ´exica e sint ´atica.

2.1 AN ´ALISE DE FLUXO DE DADOS

An ´alise de fluxo de dados (em ingl ˆes, Data Flow Analysis) tem se mos-trado como uma ferramenta ´util para demonstrar a presenc¸a ou aus ˆencia de uma s ´erie de erros de programac¸ ˜ao (COOPER; HARVEY; KENNEDY, 2004). ´E uma importante t ´ecnica de verificac¸ ˜ao de software, pois ´e barata computacionalmente e confi ´avel. (TAYLOR; OSTERWEIL, 1980).

Na an ´alise de fluxo de dados o programa ´e analisado de um modo sis-tem ´atico e as informac¸ ˜oes de uso de vari ´aveis s ˜ao coletadas de modo que

(30)

cer-tas deduc¸ ˜oes podem ser feicer-tas sobre o efeito desses usos em outros pontos do c ´odigo (FOSDICK; OSTERWEIL, 1976). O grafo de fluxo de controle (em ingl ˆes, Control Flow Graph) ´e usado para determinar at ´e onde um determinado valor atribu´ıdo a uma vari ´avel pode alcanc¸ar (ZADECK, 1988). A Figura 2 mostra um c ´odigo de tr ˆes enderec¸os e a sua representac¸ ˜ao em grafo de fluxo de controle. Figura 2 — C ´odigo de tr ˆes enderec¸os e sua representac¸ ˜ao em grafo de fluxo de controle

t ← 1 i ← 0 n ← 100

Lac¸o: if i ≥n goto FimLaco i ← i + 1 t ← t ∗ i gotoLac¸o FimLac¸o: x ← t t ← 1 i ← 0 n ← 100 if i ≥ n x ← t i ← i + 1 t ← t ∗ i

Fonte: Pr ´oprio autor

Os nodos do grafo de fluxo de controle s ˜ao blocos b ´asicos (MOHNEN, 2002). Um bloco b ´asico ´e uma sequencia linear de instruc¸ ˜oes de c ´odigo que tem um ´unico ponto de entrada (a primeira instruc¸ ˜ao executada) e um ´unico ponto de sa´ıda (a ´ultima instruc¸ ˜ao executada) (KNOOP; KOSHCHUTZKI; STEFFEN, 1997).

Existem dois tipos de an ´alise de fluxo de dados, uma se chama forward analysis (an ´alise prospectiva) e backward analysis (an ´alise para tr ´as) (COOPER; HARVEY; KENNEDY, 2004). O algoritmo reaching definitions analysis (an ´alise de definic¸ ˜oes incidentes) ´e do tipo de an ´alise prospectiva, esse algoritmo cal-cula para cada ponto do c ´odigo o conjunto de definic¸ ˜oes que potencialmente alcanc¸ariam aquele ponto do programa. J ´a o algoritmo chamado live variable analysis (an ´alise de vida de vari ´avel) ´e do tipo an ´alise para tr ´as, e calcula para cada ponto do c ´odigo as vari ´aveis que potencialmente ser ˜ao utilizadas posterior-mente antes de sua pr ´oxima atribuic¸ ˜ao (KENNEDY, 1981). Com estas an ´alises ´e poss´ıvel descobrir uma s ´erie de erros, como detecc¸ ˜ao de vari ´aveis n ˜ao inicializa-das e vari ´aveis n ˜ao utilizainicializa-das que s ˜ao uns dos erros que este trabalho pretende identificar (COOPER; HARVEY; KENNEDY, 2004; MOHNEN, 2002).

(31)

2.1.1 Definic¸ ˜oes Incidentes

Uma definic¸ ˜ao d incide um ponto p (ou chega em um ponto p) se existir um caminho do ponto que se segue imediatamente a d at ´e p, tal que d n ˜ao seja ”morta” ao longo do caminho. Ent ˜ao, se uma definic¸ ˜ao d de determinada vari ´avel a incide em um ponto p, d poderia ser o local no qual o valor de a usado em p teria ficado definido, mas ”matamos” uma definic¸ ˜ao de uma vari ´avel a se, entre dois pontos ao longo do caminho, existir uma nova definic¸ ˜ao de a (AHO; ULLMAN; SETHI, 2008). A Figura 3 mostra a equac¸ ˜ao de definic¸ ˜ao incidente.

Figura 3 — Equac¸ ˜ao de Definic¸ ˜ao Incidente

EntradaBloco(B) ← S

p em pred(B) SaidaBloco(P )

SaidaBloco(B) ← Def inicoesGeradas(B) S (EntradaBloco(B) − M ortas(B))

Fonte: (AHO; ULLMAN; SETHI, 2008, p. 272)

A equac¸ ˜ao Def inicoesGeradas(B) cont ´em as definic¸ ˜oes geradas no bloco B e M ortas(B) cont ´em as definic¸ ˜oes mortas.

Para calcular as definic¸ ˜oes incidentes ´e necess ´ario aplicar as equac¸ ˜oes da Figura 3 em cada bloco b ´asico enquanto exista alguma alterac¸ ˜ao na equac¸ ˜ao SaidaBloco(B), um algoritmo iterativo ´e apresentado abaixo no Trecho de C ´odigo 1.

Trecho de C ´odigo 1 — Algoritmo iterativo para an ´alise de definic¸ ˜oes incidentes

1 // i n i c i a l i z a t o d o s o b l o c o de e n t r a d a c o m v a z i o 2 // e a s a ´ı d a c o m as d e f i n i ¸c ~o e s g e r a d a s em B 3 p a r a c a d a b l o c o b ´a s i c o B f a ¸c a 4 E n t r a d a B l o c o ( B ) = e s t a d o V a z i o ; 5 S a i d a B l o c o ( B ) = D e f i n i c o e s G e r a d a s ( B ) ; 6 f i m p a r a 7 8 a l t e r a d o = v e r d a d e i r o ; 9 // e n q u a n t o h o u v e r a l t e r a ¸c ~a o o a l g o r i t m o c o n t i n u a e x e c u t a n d o 10 e n q u a n t o ( a l t e r a d o ) f a ¸c a 11 a l t e r a d o = f a l s o ; 12 p a r a c a d a b l o c o b ´a s i c o B f a ¸c a 13 // e n t r a d a do b l o c o r e c e b e a s a i d a d o s p r e c e s s o r e s de B 14 E n t r a d a B l o c o ( B ) = S p∈pred(B) SaidaBloco(P ) 15 16 // g r a v a o e s t a d o de s a ´ı d a do b l o c o em u m a v a r i ´a v e l a u x i l i a r 17 S a i d a B l o c o A u x ( B ) = S a i d a B l o c o ( B ) ; 18 19 // a s a i d a do b l o c o B r e c e b e a u n i ~a o d a s d e f i n i ¸c ~o e s g e r a d a s c o m a e n t r a d a do b l o c o m e n o s as d e f i n i ¸c ~o e s m o r t a s

20 S a i d a B l o c o ( B ) = Def inicoesGeradas(B)S(EntradaBloco(B) − Def inocoesM ortas(B)) ;

(32)

21 22 se ( S a i d a B l o c o ( B ) < > S a i d a B l o c o A u x ( B ) ) e n t ~a o 23 a l t e r a d o = v e r d a d e i r o ; 24 f i m s e 25 f i m e n q u a n t o 26 f i m e n q u a n t o

Fonte: (AHO; ULLMAN; SETHI, 2008, p. 272)

2.1.2 An ´alise de Vida de Vari ´aveis

Uma vari ´avel est ´a viva em uma aresta se h ´a um caminho da aresta at ´e um uso da vari ´avel que n ˜ao passar por nenhuma outra definic¸ ˜ao da vari ´avel (AHO; ULLMAN; SETHI, 2008).

Para calcular a vida das vari ´aveis s ˜ao definidas equac¸ ˜oes em cada bloco, b, com dois conjuntos, V ivasN aEntrada(b) e V ivasN aSaida(b). O con-junto V ivasN aEntrada(b) cont ´em todas as vari ´aveis que est ˜ao vivas na entrada de b enquanto o conjunto V ivasN aSaida(b) cont ´em todas as vari ´aveis que est ˜ao vivas na sa´ıda de b (COOPER; HARVEY; KENNEDY, 2004; ALLEN; COCKE, 1976). As equac¸ ˜oes que definem esses conjuntos s ˜ao apresentados na Figura 4.

Figura 4 — Equac¸ ˜ao para a an ´alise de vida de vari ´aveis

V ivasN aEntrada(b) ← LocaisV ivas(b) S (V ivasN aSaida(b) − M ortas(b)) V ivasN aSaida(b) ← {∅se b ´e o bloco de sa´ıda,

sen ˜ao, S

s∈succs(b) V ivasN aEntrada(S) }

Fonte: (AHO; ULLMAN; SETHI, 2008, p. 275)

O termo LocaisV ivas(b) cont ´em as vari ´aveis que foram usadas no bloco b e M ortas(b) cont ´em cada vari ´avel que foi definida em b. O termo succs(b) cont ´em os blocos sucessores de b.

Para resolver as equac¸ ˜oes da Figura 4 ´e necess ´ario aplicar em cada bloco b ´asico enquanto exista alguma alterac¸ ˜ao nas equac¸ ˜oes V ivasN aEntrada(b) e V ivasN aSaida(B), um algoritmo iterativo que ´e descrito no Trecho de C ´odigo 2.

(33)

Trecho de C ´odigo 2 — Algoritmo iterativo para an ´alise de vida de vari ´aveis 1 // i n i c i a l i z a t o d o s os b l o c o s c o m v a z i o 2 p a r a c a d a b l o c o b ´a s i c o B f a ¸c a 3 V i v a s N a E n t r a d a ( B ) = e s t a d o V a z i o ; 4 V i v a s N a S a i d a ( B ) = e s t a d o V a z i o ; 5 f i m p a r a 6 7 a l t e r a d o = v e r d a d e i r o ; 8 // e n q u a n t o h o u v e r a l t e r a ¸c ~a o o a l g o r i t m o c o n t i n u a e x e c u t a n d o 9 e n q u a n t o ( a l t e r a d o ) f a ¸c a 10 a l t e r a d o = f a l s o ; 11 p a r a c a d a b l o c o b ´a s i c o B f a ¸c a 12 // g r a v a o e s t a d o de e n t r a d a do b l o c o em u m a v a r i ´a v e l a u x i l i a r 13 V i v a s N a E n t r a d a A u x ( B ) = V i v a s N a E n t r a d a ( B ) ; 14 // g r a v a o e s t a d o de s a ´ı d a do b l o c o em u m a v a r i ´a v e l a u x i l i a r 15 V i v a s N a S a i d a A u x ( B ) = V i v a s N a S a i d a ( B ) ; 16 17 // r e c e b e as v a r i a v e i s v i v a s d a s e n t r a d a s d o s b l o c o s s u c e s s o r e s 18 // se o b l o c o f o r de s a ´ı d a n ~a o r e c e b e n e n h u m a v a r i ´a v e l p o i s n ~a o t e m s u c e s s o r 19 V i v a s N a S a i d a ( B ) = S

s∈succs(b) V ivasN aEntrada(S)

20

21 V i v a s N a E n t r a d a ( B ) = LocaisV ivas(b) S

(V ivasN aSaida(b) − M ortas(b)) 22 23 // v e r i f i c a se f o i a l t e r a d o 24 se (( V i v a s N a E n t r a d a ( B ) < > V i v a s N a E n t r a d a A u x ( B ) ) ou ( V i v a s N a S a i d a ( B ) < > V i v a s N a S a i d a A u x ( B ) ) ) 25 a l t e r a d o = v e r d a d e i r o ; 26 f i m s e 27 f i m p a r a 28 f i m p a r a

Fonte: (AHO; ULLMAN; SETHI, 2008, p. 275)

2.2 SSA

SSA (Static Single Assignment), em portugu ˆes Atribuic¸ ˜ao ´Unica Est ´atica, ´e uma representac¸ ˜ao intermedi ´aria que compiladores utilizam para facilitar a an ´alise do programa e otimizac¸ ˜ao (BRIGGS et al., 1998).

A propriedade essencial do SSA ´e que cada uso de uma vari ´avel se refere a exatamente uma definic¸ ˜ao ou, de forma equivalente, que a definic¸ ˜ao de uma vari ´avel domina cada utilizac¸ ˜ao (STAIGER et al., 2007). Isto significa que a vari ´avel ´e um nome de um valor (no sentido matem ´atico) e n ˜ao de um local de armazenamento (KESLEY, 1995; STAIGER et al., 2007).

A forma SSA e o grafo de controle de depend ˆencias s ˜ao propostos para representar o fluxo de dados e as propriedades de fluxo de controle de progra-mas (STAIGER et al., 2007; CYTRON et al., 1991). SSA pode ser vista como uma

(34)

representac¸ ˜ao esparsa para a informac¸ ˜ao contida nas cadeias de uso-definic¸ ˜ao e definic¸ ˜ao-uso cl ´assicas, e se tornou em muitas aplicac¸ ˜oes a representac¸ ˜ao prim ´aria do programa (BRIGGS et al., 1998).

Com SSA ´e poss´ıvel identificar c ´odigo morto utilizando o algoritmo de propagac¸ ˜ao de c ´opias (WEGMAN; ZADECK, 1995).

Figura 5 — Bloco de c ´odigo sequencial e sua convers ˜ao para a forma SSA

i ← ...

i

0

← ...

j ← i + i

j

0

← i

0

+ i

0

i ← i + j

i

1

← i

0

+ j

0

k ← i + j

k

0

← i

1

+ j

0

Antes Depois

Fonte: Pr ´oprio autor

A Figura 5 mostra em um simples c ´odigo a propriedade de atribuic¸ ˜ao ´unica que a forma SSA aplica. Como houve uma atribuic¸ ˜ao ao i0 ele passou a

ser i1 no pr ´oximo uso.

A func¸ ˜ao ø(phi) representa a junc¸ ˜ao de m ´ultiplos nomes SSA em um ´unico nome e ´e inserida em cada ponto de junc¸ ˜ao do fluxo de controle (SRE-EDHAR et al., 1999; HAVLAK, 1995). Por exemplo, quanto mais func¸ ˜oes ø exis-tirem mais processamento ´e necess ´ario (STAIGER et al., 2007).

Existem tr ˆes algoritmos que convertem o c ´odigo na forma SSA, um de-les se chama SSA ”m´ınimo”, o segundo se chama SSA ”podado” e o terceiro se chama SSA ”semi podado”. Em ordem de complexidade vem o algoritmo ”m´ınimo”, depois o ”semi podado” e por ´ultimo o ”podado”. O que diferencia en-tre os tr ˆes algoritmos ´e a quantidade de func¸ ˜oes ø que s ˜ao colocadas no c ´odigo (BRIGGS et al., 1998).

O algoritmo ”m´ınimo” insere func¸ ˜oes ø em todo ponto em que o fluxo de controle se funde e re ´une dois ou mais nomes SSA para um ´unico nome. Nesse caso pode ser inserido um func¸ ˜ao ø para juntar dois valores que nunca v ˜ao ser utilizados depois da fus ˜ao no fluxo de controle pois os valores n ˜ao est ˜ao vivos (terminologia de an ´alise de fluxo de dados) (BRIGGS et al., 1998).

J ´a o algoritmo ”podado” utiliza um an ´alise de fluxo de dados que indica se o valor ´e potenciavelmente vivo, diminuindo o n ´umero de func¸ ˜oes ø e, assim, diminuir o n ´umero de nomes SSA, por ´em este algoritmo tem um custo elevado

(35)

pois necessita calcular a informac¸ ˜ao de vida de cada vari ´avel (BRIGGS et al., 1998).

E por ´ultimo o algoritmo ”semi podado”, este por sua vez tenta reduzir o n ´umero de func¸ ˜oes ø diminuindo o custo elevado para calcular a informac¸ ˜ao da vida de cada vari ´avel. Se uma vari ´avel nunca estiver viva na entrada de um bloco b ´asico n ˜ao ´e necess ´aria uma func¸ ˜ao ø. Ent ˜ao durante a construc¸ ˜ao da forma SSA func¸ ˜oes ø para quaisquer vari ´aveis de bloco local s ˜ao omitidas (BRIGGS et al., 1998).

Basicamente os tr ˆes algoritmos diferem no seu tempo e complexidade, o algoritmo ”m´ınimo” n ˜ao processa a informac¸ ˜ao de fluxo de dados ent ˜ao ´e poten-ciavelmente menos custoso que o algoritmo ”podado” e ”semi podado”, porem resulta em uma forma SSA com muitas func¸ ˜oes ø (BRIGGS et al., 1998). Nas pr ´oximas sec¸ ˜oes s ˜ao descritos cada algoritmo.

Na Sec¸ ˜ao 2.2.5 ´e descrito o algoritmo chamado de propagac¸ ˜ao de cons-tantes. Este algoritmo ´e aplicado na forma SSA convertida de forma que possa ser identificado c ´odigo morto que ´e um dos erros que este trabalho pretende identificar (STAIGER et al., 2007).

2.2.1 SSA m´ınimo

O Trecho de C ´odigo 3 mostra um algoritmo simples para construc¸ ˜ao da forma SSA m´ınima a partir de uma representac¸ ˜ao de grafo de fluxo de controle. O algoritmo tem duas etapas b ´asicas, que s ˜ao determinar os lugares das func¸ ˜oes ø e renomear as vari ´aveis.

Trecho de C ´odigo 3 — Algoritmo para construir SSA m´ınima

1 p r o c e d i m e n t o C a l c u l a S S A M i n i m o () 2 /* P a s s o 1: D e t e r m i n a r os l o c a i s p a r a c o l o c a r as f u n ¸c ~o e s p h i */ 3 C a l c u l a r a ´a r v o r e de d o m i n ^a n c i a e a f r o n t e i r a de d o m i n ^a n c i a 4 5 /* P a s s o 2: C o l o c a r as f u n ¸c ~o e s p h i */ 6 P a r a c a d a v a r i a v e l , v , f a ¸c a 7 A ( v ) = { b l o c o s que c o n t ´e m a t r i b u i ¸c ~a o a v }; 8 C o l o q u e uma f u n ¸c ~a o phi na f r o n t e i r a de d o m i n ^a n c i a de A ( v ) 9 f i m p a r a 10 11 /* P a s s o 3: R e n o m e a r c a d a v a r i ´a v e l , t r o c a n d o v , c o m o n o m e a p r o p r i a d o c r i a d o p e l a s f u n ¸c ~o e s p h i */ 12 P a r a c a d a v a r i a v e l , v , f a ¸c a 13 C o n t a d o r e s ( v ) = 0; 14 P i l h a s ( v ) = p i l h a V a z i a () ; 15 f i m p a r a 16

(36)

17 P e s q u i s a ( B l o c o I n i c i a l ) ; 18 end 19 20 /* R e c u r s i v a m e n t e p e s q u i s a p e l a ´a r v o r e de d o m i n ^a n c i a r e n o m e a n d o as v a r i ´a v e i s */ 21 p r o c e d i m e n t o P e s q u i s a ( B l o c o B ) 22 b e g i n 23 p a r a c a d a n o d o phi , v = phi ( . . . ) no b l o c o B f a ¸c a 24 i = C o n t a d o r e s ( V ) ; 25 T r o c a v por vi; 26 e m p i l h a ( i , P i l h a s ( v ) ) ; 27 C o n t a d o r e s [ v ] = i + 1; 28 f i m p a r a 29 30 p a r a c a d a i n s t r u ¸c ~a o v = x op y no B l o c o B f a ¸c a 31 T r o c a x por xi, o n d e i = t o p o ( P i l h a s ( x ) ) ; 32 T r o c a y por yi, o n d e i = t o p o ( P i l h a s ( y ) ) ; 33 i = C o n t a d o r e s ( v ) ; 34 T r o c a v por vi; 35 e m p i l h a ( i , P i l h a s ( v ) ) ; 36 C o n t a d o r e s ( v ) = i + 1; 37 f i m p a r a 38 39 p a r a c a d a s u c e s s o r , S , do b l o c o B f a ¸c a 40 j = q u a l P r e d ( s , B ) ; 41 p a r a c a d a f u n ¸c ~a o phi , P , em S f a ¸c a 42 v = jth o p e r a n d o de p ; 43 T r o c a v por vi, o n d e i = t o p o ( P i l h a s [ v ]) ; 44 f i m p a r a 45 f i m p a r a 46 47 p a r a c a d a filho , C , do b l o c o na ´a r v o r e de d o m i n ^a n c i a f a ¸c a 48 P e s q u i s a ( C ) ; 49 f i m p a r a 50 51 p a r a c a d a i n s t r u ¸c ~a o , v = x op y , ou n o d o phi , v = phi ( . . . ) , no B l o b o B f a ¸c a 52 d e s e m p i l h a ( P i l h a s ( v ) ) ; 53 f i m p a r a 54 55 end

Fonte: (BRIGGS et al., 1998, p. 8)

O primeiro passo para inserir as func¸ ˜oes ø ´e construir a ´arvore de do-min ˆancia do grafo de controle de fluxo e calcular a fronteira de dodo-min ˆancia para cada nodo. A fronteira de domin ˆancia de um nodo N ´e um conjunto de nodos X em que N domina o predecessor de X, mas N n ˜ao domina estritamente o X. Isto define precisamente os pontos onde as func¸ ˜oes ø tem que ser inseridas, j ´a que a ´arvore de domin ˆancia inclui somente blocos que podem ser alcanc¸ados ao longo de caminhos diferentes do fluxo de controle (BRIGGS et al., 1998).

Ap ´os a inserc¸ ˜ao das func¸ ˜oes ø as vari ´aveis tem que ser renomeadas para o novo nome criado. Isto ´e realizado num ´unico passeio recursivo na

(37)

´arvore de domin ˆancia, mostrado no procedimento Pesquisa(). Para cada nome no c ´odigo original, Pesquisa() mant ´em duas estruturas de dados. A primeira, Contadores(v), cont ´em o ´ındice que ser ´a atribu´ıdo na pr ´oxima definic¸ ˜ao de v. A segunda, Pilhas(v), mant ´em o ´ındice atual para o v. A cada definic¸ ˜ao de v, Pes-quisa() renomeia v com o ´ındice do Contadores(v), empilha o valor na Pilhas(v), e incrementa o Contadores(v).

Durante a primeira etapa s ˜ao renomeadas as vari ´aveis, sendo incre-mentados os v ´arios contadores e empilhados os novos nomes em suas apro-priadas pilhas. Em seguida, reescreve func¸ ˜oes ø em cada bloco sucessor no grafo de fluxo de controle para que o nome seja herdado do bloco atual e tenha o ´ındice corrente.

A func¸ ˜ao qualPred() determina qual func¸ ˜ao ø no sucessor corresponde no bloco atual. Para continuar a pesquisa, o algoritmo procura em cada filho na ´arvore de fronteira de domin ˆancia. Ao retornar da recurs ˜ao, processa o bloco atual novamente para desempilhar cada pilha e contadores adicionados enquanto processava.

2.2.2 SSA podado

Para construir a forma SSA podada ´e necess ´ario primeiramente exe-cutar a an ´alise de vida de vari ´aveis para definir as vari ´aveis vivas na entrada de cada bloco b ´asico (CHOI; CYTRON; FERRANTE, 1991). Na Sec¸ ˜ao 2.1.2 foi abordado um algoritmo para este c ´alculo.

A construc¸ ˜ao do SSA podada ´e muito similar `a construc¸ ˜ao do SSA m´ınimo. No Trecho de C ´odigo 3 ´e necess ´ario somente adicionar um passo que calcula a an ´alise de vida de vari ´aveis e modifica o primeiro passo que define aonde as func¸ ˜oes ø ser ˜ao inseridas. O SSA m´ınimo insere a func¸ ˜ao ø para cada v em cada nodo na fronteira de domin ˆancia dos blocos b ´asicos que contenha a atribuic¸ ˜ao a v. No SSA podado isto muda, ´e somente inserido em blocos onde v esteja vivo na entrada do bloco. O algoritmo do SSA podado pode ter um custo maior que o SSA m´ınimo, pois para inserir as func¸ ˜oes ø exige a an ´alise de vida de vari ´aveis que tem um custo computacional elevado.

(38)

2.2.3 SSA semi podado

A vantagem de velocidade e efici ˆencia da forma semi podado sobre os outros dois algoritmos se baseia na observac¸ ˜ao de que muitos nomes em uma rotina s ˜ao definidos e usados inteiramente em um ´unico bloco b ´asico (BRIGGS et al., 1998). Por exemplo, o compilador tipicamente gera nomes tempor ´arios para executar passos intermedi ´arios, esses nomes gerados frequentemente tem vidas curtas. A forma SSA semi podado aproveita esta informac¸ ˜ao pelo c ´alculo do conjunto de nomes que s ˜ao vivos na entrada para alguns blocos b ´asicos. S ˜ao chamados de n ˜ao-locais esses nomes.

O n ´umero resultante de func¸ ˜oes ø fica entre o algoritmo m´ınimo e o po-dado, mas o c ´alculo dos nomes n ˜ao-locais ´e muito mais barato do que a an ´alise de vida de vari ´aveis (BRIGGS et al., 1998). Portanto, a forma semi podado con-segue ter um custo de processamento consideravelmente menor que a vers ˜ao podado mas com o n ´umero de func¸ ˜oes ø parecido.

Trecho de C ´odigo 4 — Algoritmo para identificar nomes n ˜ao-locais

1 // i n i c i a l i z a c o n j u n t o n a o l o c a i s 2 n a o _ l o c a i s = e s t a d o V a z i o ; 3 4 // p a r a c a d a b l o c o b ´a s i c o 5 p a r a c a d a b l o c o B f a ¸c a 6 m o r t o s = e s t a d o V a z i o ; 7 p a r a c a d a i n t r u ¸c ~a o v = x op y no b l o c o B f a ¸c a 8 se x n~ao p e r t e n c e ao m o r t o s e n t ~a o 9 n a o _ l o c a i s = n a o _ l o c a i s S {x} 10 f i m s e 11 se y n~ao p e r t e n c e ao m o r t o s e n t ~a o 12 n a o _ l o c a i s = n a o _ l o c a i s S {y} 13 f i m s e 14 15 m o r t o s = m o r t o s S {v} 16 f i m p a r a 17 f i m p a r a

Fonte: (BRIGGS et al., 1998, p. 12)

Para descobrir os nomes n ˜ao-locais ´e utilizado o algoritmo mostrado no Trecho de C ´odigo 4. O compilador faz uma an ´alise simples em cada bloco b ´asico, quando descobre um operando que n ˜ao foi morto no bloco ele ´e definido como um nome n ˜ao-local, e o nome que foi definido na atribuic¸ ˜ao ´e colocado no conjunto mortos. O conjunto de n ˜ao-locais ´e inicializado somente uma vez, o conjunto mortos ´e reinicializado para cada bloco. Portanto ´e muito mais simples do que calcular a an ´alise de vida de vari ´aveis completa.

(39)

2.2.4 Comparac¸ ˜ao entre os algoritmos m´ınimo, podado e semi podado

Nas ultimas sec¸ ˜oes foram descritos 3 algoritmos de SSA, m´ınimo, po-dado e semi popo-dado que utilizam meios diferentes para definir onde as func¸ ˜oes ø ser ˜ao colocadas. Na Tabela 1 temos uma comparac¸ ˜ao com v ´arias rotinas em cada algoritmo, comparando n ´umero de func¸ ˜oes ø adicionadas e tempo para construc¸ ˜ao da forma SSA. Os testes foram executados em um computa-dor Sparc10 modelo 512 rodando a 50 MHz com 1 MB de cache e 115 MB de mem ´oria RAM (BRIGGS et al., 1998). O n ´umero de func¸ ˜oes ø da forma semi podada esta sempre entre a vers ˜ao m´ınima e podada e o tempo para construir a forma semi podada ´e sempre menor que a vers ˜ao m´ınima e podada.

Tabela 1 — Comparac¸ ˜ao entre os algoritmos SSA

N ´umero de nodos ø Tempo para construir a forma SSA Rotina M´ınimo Semi Podada M´ınimo Semi Podada

twldrv 73778 11989 9886 1.265 0.332 0.427 deseco 8610 2216 1842 0.231 0.172 0.232 ddeflu 5852 1560 1222 0.116 0.070 0.091 iniset 5364 1080 462 0.127 0.101 0.157 debflu 4715 1748 1542 0.098 0.069 0.087 paroi 3597 767 632 0.079 0.060 0.077 efill 3170 357 74 0.047 0.020 0.025 inisla 2722 267 141 0.048 0.025 0.034 tomcatv 2699 365 145 0.051 0.033 0.042 pastem 2584 374 62 0.055 0.036 0.049 prophy 2021 436 401 0.054 0.042 0.054 inithx 1967 267 85 0.042 0.033 0.044 debico 1880 171 112 0.045 0.030 0.039 repvid 1094 141 45 0.029 0.020 0.031 bilan 1080 70 34 0.028 0.020 0.028

Fonte: (BRIGGS et al., 1998, p. 16)

2.2.5 Propagac¸ ˜ao de Constantes

O algoritmo de propagac¸ ˜ao de constantes tem como princ´ıpio substituir os valores conhecidos de vari ´aveis em express ˜oes em que s ˜ao utilizadas e assim detectando c ´odigo morto (STAIGER et al., 2007).

Trecho de C ´odigo 5 — Algoritmo exemplo para propagac¸ ˜ao de constantes

1 //

2 se X = verdadeiro e n t ~a o 3 Y1= 8;

(40)

5 Y2= 10;

6

7 Y3= phi(Y1, Y2);

Fonte: Pr ´oprio autor

Inicialmente o algoritmo assume que cada bloco b ´asico n ˜ao ´e execut ´avel (nunca foi executado) e cada vari ´avel ´e uma constante com um valor at ´e agora desconhecido (denotado >) (STAIGER et al., 2007). Suponha que o algoritmo encontre que a vari ´avel X n ˜ao ´e uma constante (denotado ⊥) portanto se as-sume que os dois caminhos do condicional podem ser tomados. Quando Y1 = 8

´e executado, a suposic¸ ˜ao sobre o Y1 ´e trocada de > por 8 e em todos seus usos

s ˜ao notificados com o valor 8 (cada uso de Y1 realmente tem o valor 8 grac¸as

`a propriedade de atribuic¸ ˜ao ´unica). Ent ˜ao a func¸ ˜ao ø ´e combinac¸ ˜ao de 8 com Y2. O segundo operando da func¸ ˜ao ø no entanto est ´a associado no ponto de

junc¸ ˜ao que corresponde `a ramificac¸ ˜ao do sen ˜ao, que at ´e ent ˜ao era considerada n ˜ao execut ´avel, o algoritmo utiliza > para o segundo operando. Como a vari ´avel X pode tomar o valor falso pois n ˜ao ´e uma constante ent ˜ao o segundo caminho ´e tomado, e o comando Y2 = 10 ´e executado e o Y2 recebe o valor de 10. Por

fim onde o Y2 ´e utilizado ´e trocado pelo valor 10, ent ˜ao a func¸ ˜ao ø agora tem 8 e

10como valores poss´ıveis. Se no final da an ´alise algum bloco estiver marcado como n ˜ao execut ´avel este bloco ´e declarado como morto e pode ser removido do c ´odigo (WEGMAN; ZADECK, 1995).

Com isso ´e poss´ıvel simular o algoritmo propagando as constantes e eliminando o c ´odigo morto encontrado (STAIGER et al., 2007).

2.3 AN ´ALISE DE INTERVALO DE VALORES

An ´alise de Intervalo de Valores (do ingl ˆes, Value Range Analysis) ´e utili-zada para determinar os limites de intervalo de valores assumidos pelas vari ´aveis em v ´arios pontos do c ´odigo de um programa (XU, 2001). A informac¸ ˜ao de inter-valos pode ser usada para remover testes redundantes, escolher representac¸ ˜ao de dados, verificar a operac¸ ˜ao correta e prover informac¸ ˜oes para diagn ´osticos (BIRCH; ENGELEN; GALLIVAN, 2004; HARRISON, 1977).

Informac¸ ˜oes sobre o intervalo de valores de vari ´aveis podem ser pro-pagadas por um programa do mesmo jeito que a propagac¸ ˜ao de constantes (BLUME; EIGENMANN, 1994).

(41)

2.3.1 Intervalos de Valores

Um intervalo de uma vari ´avel x pode ser definido como x = ⊥ (intervalo vazio) ou x = [l,u] com l ≤ u, chamando-se l de limite inferior e u de limite superior (GOUGH; KLAEREN, 1996). Para denotar o intervalo inferior de x utilizamos x ↓ e para o superior x ↑ (HARRISON, 1977).

No intervalo de valores assumimos que as operac¸ ˜oes aritm ´eticas est ˜ao dispon´ıveis para tipos ordinais (GOUGH; KLAEREN, 1996). Operac¸ ˜oes como S e T tamb ´em entram para a soluc¸ ˜ao de intervalos. No entanto, as operac¸ ˜oes aritm ´eticas em intervalo de valores utilizadas neste trabalho s ˜ao diferentes de sua sem ˆantica usual e os intervalos podem estar entre −∞ e +∞.

2.3.2 e-SSA

A forma e-SSA (Extended Static Single Assignment), em portugu ˆes, atribuic¸ ˜ao ´unica est ´atica estendida, ´e uma vers ˜ao estendida do SSA como o pr ´oprio nome diz. O e-SSA foi criado para um ´unico prop ´osito, facilitar o pro-cessamento de intervalo de valores. No artigo de HARRISON que trata sobre an ´alise de intervalo de valores, ele destaca dois problemas dif´ıceis de se tratar, um deles ´e encontrar pontos de corte de um lac¸o e o outro problema ´e a proprie-dade de intervalos de express ˜oes booleanas complexas que ocorrem em testes (HARRISON, 1977). Ambos problemas se tornam praticamente triviais utilizando o e-SSA (GOUGH; KLAEREN, 1996).

A diferenc¸a entre SSA e e-SSA ´e que uma nova vari ´avel ´e criada com instruc¸ ˜oes que definem o intervalo. Por exemplo, i1 = [10, +∞] nos diz que

os valores poss´ıveis para a vari ´avel i1 est ˜ao contidos no intervalo de 10 e +∞

(RODRIGUES; CAMPOS; PEREIRA, 2013).

Desvios condicionais cont ´em informac¸ ˜oes que podem ser usadas para fazer com que a an ´alise de intervalo seja mais precisa (GOUGH; KLAEREN, 1996). Com essas informac¸ ˜oes ´e poss´ıvel, por exemplo, dizer que na Figura 6 ap ´os o teste condicional if j1 ≤ 100 resultar em verdadeiro o intervalo de valores

(42)

Figura 6 — Exemplo de condicional.

if j

1

≤ 100

j

2

= j

1

T[101, +∞]

j

3

= j

1

T[−∞, 100]

Fonte: Pr ´oprio autor

Na Figura 7 temos um c ´odigo em portugu ˆes estruturado e sua representac¸ ˜ao na forma SSA. E na Figura 8 temos a representac¸ ˜ao desse c ´odigo na forma e-SSA. Pode-se perceber que quando h ´a uma comparac¸ ˜ao entre duas vari ´aveis ´e colocado o r ´otulo ft, indicando que o valor de uma vari ´avel depende do valor de outra, mas esse valor vai ser obtido posteriormente no algoritmo de propagac¸ ˜ao de intervalos (GOUGH; KLAEREN, 1996).

Figura 7 — C ´odigo em portugu ˆes estruturado e sua representac¸ ˜ao em SSA

k = 0 enquanto k < 100 i ← 0 j ← k enquanto i < j i ← i + 1 j ← j − 1 fimenquanto k ← k + 1 fimenquanto

(43)

Figura 8 — Representac¸ ˜ao em e-SSA do c ´odigo da Figura 7 (RODRIGUES; CAMPOS; PEREIRA, 2013)

Fonte: (RODRIGUES; CAMPOS; PEREIRA, 2013, p. 3)

Para gerar a forma e-SSA ´e preciso fazer uma pequena alterac¸ ˜ao no algoritmo da forma SSA descrito no Cap´ıtulo 2.2. Para cada derivac¸ ˜ao de um condicional ser ´a criada uma nova vari ´avel (somente para as que estiverem vi-vas) com a atribuic¸ ˜ao dos intervalos poss´ıveis, como exemplificado na Figura 6 (RODRIGUES; CAMPOS; PEREIRA, 2013).

2.3.3 Propagac¸ ˜ao de intervalos de valores

Para fazer an ´alise de intervalo de valores ´e necess ´ario resolver um sis-tema de restric¸ ˜ao (RODRIGUES; CAMPOS; PEREIRA, 2013). As restric¸ ˜oes s ˜ao constru´ıdas em torno de uma func¸ ˜ao de avaliac¸ ˜ao e. O sistema de restric¸ ˜oes para resolver o problema de intervalo de valores ´e apresentado na Figura 9.

(44)

Figura 9 — Sistema de restric¸ ˜oes

Fonte: (RODRIGUES; CAMPOS; PEREIRA, 2013, p. 2)

Cada restric¸ ˜ao ´e extra´ıda de uma instruc¸ ˜ao da forma e-SSA do pro-grama. A soluc¸ ˜ao para esse sistema de restric¸ ˜ao ´e a soluc¸ ˜ao da an ´alise de intervalo de valores (RODRIGUES; CAMPOS; PEREIRA, 2013). As restric¸ ˜oes extra´ıdas do c ´odigo e-SSA da Figura 7 s ˜ao apresentadas na Figura 10.

(45)

Figura 10 — Restric¸ ˜oes extra´ıdas do c ´odigo e-SSA da Figura 7

Fonte: (RODRIGUES; CAMPOS; PEREIRA, 2013, p. 2)

Para isso, o primeiro passo ´e construir o grafo de depend ˆencias do c ´odigo em formato e-SSA para representar as restric¸ ˜oes extra´ıdas do c ´odigo fonte (RODRIGUES; CAMPOS; PEREIRA, 2013). Para cada vari ´avel V criamos um v ´ertice vari ´avel Nv, e para cada restric¸ ˜ao C, criamos um v ´ertice restric¸ ˜ao

Nc. Adicionamos uma aresta de Nv para Nc se V ´e usada em C e adicionamos

uma aresta de Nc para V se a restric¸ ˜ao C define V (COUSOT; COUSOT, 1977;

RODRIGUES; CAMPOS; PEREIRA, 2013).

Figura 11 — Restric¸ ˜oes extra´ıdas do c ´odigo e-SSA da Figura 7

Fonte: (RODRIGUES; CAMPOS; PEREIRA, 2013, p. 3)

(46)

intervalos das vari ´aveis inteiras do c ´odigo. Essa etapa ´e dividida em quatro par-tes. A primeira ´e encontrar e reduzir CFC (Componentes Fortemente Conexos) do grafo, a segunda ´e alargar o intervalo das vari ´aveis, a terceira ´e colocar os valores corretos nas restric¸ ˜oes obtidas nos desvios condicionais e por ultimo a quarta etapa ´e estreitar o intervalo das vari ´aveis tanto quanto poss´ıvel (GOUGH; KLAEREN, 1996; RODRIGUES; CAMPOS; PEREIRA, 2013).

2.3.4 Componentes Fortemente Conexos

Para reduzir o tempo de execuc¸ ˜ao da an ´alise ´e utilizada a t ´ecnica de divis ˜ao e conquista a fim de dividir o problema original em sub-problemas. Para isso, ´e utilizada a t ´ecnica de encontrar as CFC, do grafo e reduzir cada CFC a um ´unico v ´ertice (RODRIGUES; CAMPOS; PEREIRA, 2013). Neste ponto, temos um grafo dirigido ac´ıclico, e ent ˜ao esse grafo ´e ordenado topologicamente. Essa etapas s ˜ao aplicadas em ordem topol ´ogica para cada componente fortemente conexo do grafo (RODRIGUES; CAMPOS; PEREIRA, 2013).

A Figura 12 mostra os componentes fortemente conexos do grafo da Figura 11.

(47)

Figura 12 — Componentes fortemente conexos do grafo da Figura 11

Fonte: (RODRIGUES; CAMPOS; PEREIRA, 2013, p. 3)

2.3.5 Alargando o Intervalo das Vari ´aveis

Este passo tem o prop ´osito de determinar como os valores das vari ´aveis do programa mudam ao longo do tempo. Por exemplo, as vari ´aveis `as quais somente s ˜ao atribu´ıdos valores positivos apenas crescem em seu tempo de execuc¸ ˜ao, enquanto as vari ´aveis `as quais somente s ˜ao atribu´ıdos valores nega-tivos apenas decrescem e em algumas situac¸ ˜oes existem vari ´aveis que crescem em ambas direc¸ ˜oes (RODRIGUES; CAMPOS; PEREIRA, 2013). Neste passo n ˜ao s ˜ao considerados ainda os intervalos impostos pelos condicionais.

Figura 13 — Equac¸ ˜ao para alargamento de intervalo

(48)

A Figura 13 apresenta a equac¸ ˜ao para alargamento dos intervalos. Cada vari ´avel Y ´e associada com seu atual intervalo I[Y]. A sem ˆantica abstrata desta vari ´avel ´e dada por uma func¸ ˜ao de avaliac¸ ˜ao chamada e(Y) (RODRIGUES; CAM-POS; PEREIRA, 2013). Por exemplo, se e(Y) for diminuindo o intervalo inferior de Y, ent ˜ao ´e atribu´ıdo para esse intervalo inferior −∞.

Para simplificar o exemplo, ´e utilizado somente o ´ultimo CFC da Figura 11. Ap ´os aplicar a equac¸ ˜ao iterativamente no grafo o resultado ´e apresentado na Figura 14.

Figura 14 — ´Ultimo CFC ap ´os o alargamento de intervalos

Fonte: (RODRIGUES; CAMPOS; PEREIRA, 2013, p. 4)

2.3.6 Corrigindo as Intersecc¸ ˜oes

Quando os intervalos das vari ´aveis s ˜ao alargados s ˜ao encontradas vari ´aveis que tem limites fixos. Com isso podemos utilizar esses limites para corrigir as intersecc¸ ˜oes que dependem de valores futuros, ft(V) (GOUGH; KLAEREN, 1996).

(49)

Figura 15 — Equac¸ ˜ao para resolver valores futuros

Y = X

T[l, f t(V ) + c]

I[V ] ↑= u

Y = X

T[l, u + c]

Y = X

T[f t(V ) + c, u]

I[V ] ↓= l

Y = X

T[l + c, u]

Fonte: (RODRIGUES; CAMPOS; PEREIRA, 2013, p. 4)

Na Figura 15 ´e apresentada a equac¸ ˜ao para resolver valores futuros, com a aplicac¸ ˜ao dela ´e poss´ıvel substituir os r ´otulos ft[V] por valores obtidos no alargamento de vari ´aveis. Seguindo o exemplo do ´ultimo CFC o resultado ´e apresentado na Figura 16.

Figura 16 — ´Ultimo CFC ap ´os corrigir intersecc¸ ˜oes

Fonte: (RODRIGUES; CAMPOS; PEREIRA, 2013, p. 4)

2.3.7 Estreitando o Intervalo das Vari ´aveis

A etapa de alargamento do intervalo das vari ´aveis atribui valores con-servativos ao intervalo de cada vari ´avel. Esse estreitamento ´e guiado pelas intersecc¸ ˜oes que foram derivadas dos testes condicionais (RODRIGUES; CAM-POS; PEREIRA, 2013). Na Figura 17 ´e apresentada a equac¸ ˜ao para estreitar os valores das vari ´aveis.

(50)

Figura 17 — Equac¸ ˜ao para estreitamento do intervalo

Fonte: (RODRIGUES; CAMPOS; PEREIRA, 2013, p. 4)

Continuando com o exemplo do ´ultimo CFC ap ´os corrigir as intersecc¸ ˜oes mostrados na Figura 16. Sabemos que o valor de i ´e menor que 99, esse n ´umero foi descoberto na etapa de corrigir as intersecc¸ ˜oes. Esse valor ´e propagado por cada caminho do grafo que ´e influenciado por i utilizando a equac¸ ˜ao de estreita-mento do intervalo da Figura 17.

Figura 18 — Exemplo de propagac¸ ˜ao do valor de i

Fonte: (RODRIGUES; CAMPOS; PEREIRA, 2013, p. 5)

A representac¸ ˜ao de como a vari ´avel i se propagou em cada caminho ´e mostrada na Figura 18. ´E poss´ıvel perceber que com esse ´ultimo passo ´e obtido um resultado dos intervalos de valores da vari ´avel i (RODRIGUES; CAMPOS; PEREIRA, 2013).

Na Figura 19 ´e apresentado o resultado de intervalo de cada vari ´avel do algoritmo ap ´os executar todas estas etapas (Alargando o Intervalo das Vari ´aveis, Corrigindo as Intersecc¸ ˜oes e Estreitando o Intervalo das Vari ´aveis) em todos os CFC.

(51)

Figura 19 — Resultado da an ´alise de intervalo de valores

Fonte: (RODRIGUES; CAMPOS; PEREIRA, 2013, p. 3)

Com essas informac¸ ˜oes ´e poss´ıvel identificar se existe acesso a uma posic¸ ˜ao de um vetor que n ˜ao existe ou tamb ´em identificar express ˜oes condicio-nais que resultariam sempre o mesmo resultado (GOUGH; KLAEREN, 1996).

(52)

3 ESCOLHA DA T ´ECNICA PARA CADA ERRO

Neste cap´ıtulo s ˜ao descritas as t ´ecnicas que s ˜ao utilizadas para cada erro. Em cada Sec¸ ˜ao ´e descrito o erro, como funciona a t ´ecnica e um exemplo de c ´odigo com o respectivo erro.

Uma das t ´ecnicas utilizadas ´e o SSA. Nela ´e utilizada o algoritmo da vers ˜ao podada pois a an ´alise de vida de vari ´aveis ´e reaproveitada da an ´alise de c ´odigo morto. O e-SSA ir ´a utilizar a estrutura criada pelo SSA e ser ´a utilizado para an ´alise de intervalo de valores.

3.1 VARI ´AVEIS N ˜AO INICIALIZADAS E FUNC¸ ˜OES QUE N ˜AO DEFINEM O VA-LOR DE RETORNO

O erro de vari ´aveis n ˜ao inicializadas acontece quando em qualquer ca-minho do algoritmo uma vari ´avel ´e usada sem ter sido pelo menos definida uma vez ao longo do caminho. Para fazer esta detecc¸ ˜ao foi escolhida a t ´ecnica de definic¸ ˜oes incidentes que foi apresentada na Sec¸ ˜ao 2.1.1 pois apresenta a in-cid ˆencia de cada vari ´avel em pontos do algoritmo (COOPER; HARVEY; KEN-NEDY, 2004). Ao executar o algoritmo de definic¸ ˜oes incidentes teremos as defini-c¸ ˜oes que incidem em cada bloco b ´asico. Para detectar as vari ´aveis n ˜ao iniciali-zadas ser ´a executado um teste em cada caminho poss´ıvel separadamente. Para cada vari ´avel usada (utilizada do lado direito de uma atribuic¸ ˜ao ou em um teste) dever ´a haver pelo menos uma incid ˆencia na sa´ıda de algum dos blocos anterio-res.

Por exemplo no Trecho de C ´odigo 6 assumimos que a vari ´avel x nunca foi definida e a vari ´avel a e b foram definidas pelo menos uma vez em algum momento at ´e o ponto inicial do exemplo. Se o teste condicional a = b resultar em falso a vari ´avel x n ˜ao ser ´a definida em nenhum ponto do caminho e ao ser usada na atribuic¸ ˜ao y = x * b ocorrer ´a um erro pois nunca houve uma incid ˆencia

(53)

da definic¸ ˜ao de x neste caminho.

Trecho de C ´odigo 6 — Exemplo de algoritmo com vari ´avel n ˜ao inicializada

1 // A s s u m i n d o q u e a v a r i ´a v e l x n u n c a f o i d e f i n i d a e a e b f o r a m d e f i n i d a s p e l o m e n o s em um m o m e n t o a t ´e e s t e p o n t o 2 se a = b e n t ~a o 3 x = 7; 4 s e n ~a o 5 b = 1; 6 f i m s e 7 8 y = x * b ;

Fonte: Pr ´oprio autor

Pelo grafo de fluxo de controle ´e mais vis´ıvel identificar os caminhos que o algoritmo pode tomar. A Figura 20 mostra o grafo de fluxo de controle do Trecho de C ´odigo 6. ´E poss´ıvel ver que a aresta do lado direito n ˜ao tem nenhuma definic¸ ˜ao de x.

Figura 20 — Grafo de Fluxo de Controle do Trecho de C ´odigo 6

se a = b

x = 7

b = 1

y = x ∗ b

Fonte: Pr ´oprio autor

O erro de func¸ ˜oes que n ˜ao definem o valor de retorno acontece quando em algum caminho a partir do in´ıcio da func¸ ˜ao o valor de retorno da func¸ ˜ao n ˜ao ´e definido. Este problema ´e similar ao das vari ´aveis n ˜ao inicializadas, pois a vari ´avel de retorno da func¸ ˜ao deve ter pelo menos alguma incid ˆencia em qualquer caminho da func¸ ˜ao. Se existir mais de uma instruc¸ ˜ao retorne na func¸ ˜ao cada uma tem que ter incid ˆencia para o retorno. Portanto, ´e poss´ıvel resolver com o mesmo algoritmo descrito anteriormente.

Trecho de C ´odigo 7 — Exemplo de algoritmo com func¸ ˜ao que n ˜ao define valor de retorno

1 F u n c a o e x e m p l o ( x : i n t e i r o ) : i n t e i r o 2 var k , b : i n t e i r o

(54)

3 i n i c i o 4 se x = 8 e n t ~a o 5 k = 7; 6 s e n ~a o 7 b = 1; 8 f i m s e 9 10 r e t o r n e k ; 11 f i m f u n c a o

Fonte: Pr ´oprio autor

No grafo de fluxo da Figura 21 ´e poss´ıvel visualizar com mais clareza que o erro de func¸ ˜ao que n ˜ao define o valor de retorno ´e similar ao erro de vari ´aveis n ˜ao inicializadas.

Figura 21 — Grafo de Fluxo de Controle do Trecho de C ´odigo 7

x = param[0]

se x = 8

k = 7

b = 1

retorne k

Fonte: Pr ´oprio autor

3.2 C ´ODIGO MORTO

C ´odigo morto podem ser um conjunto de uma ou mais instruc¸ ˜oes que foram executadas ao longo do algoritmo mas nunca foram usadas ap ´os a sua definic¸ ˜ao. Para a detecc¸ ˜ao deste erro foi escolhida a t ´ecnica de an ´alise de vida de vari ´aveis descrita na Sec¸ ˜ao 2.1.2 pois informa a vida das vari ´aveis em cada ponto do algoritmo (AHO; ULLMAN; SETHI, 2008). Inicialmente ´e feita a an ´alise de vida em cada bloco b ´asico, ap ´os ´e feito uma an ´alise de baixo para cima para cada atribuic¸ ˜ao feita, chamada de an ´alise de uso subsequente, com esta an ´alise ´e poss´ıvel saber se a vari ´avel n ˜ao ´e utilizada naquele ponto em diante (AHO; ULLMAN; SETHI, 2008). Cada atribuic¸ ˜ao com estas propriedades ´e marcada como c ´odigo morto.

(55)

vari ´aveis k e h foram definidas mas n ˜ao foram utilizadas depois no algoritmo. No Trecho de C ´odigo 8 temos um exemplo onde a vari ´avel h foi definida mas n ˜ao foi utilizada, portanto esta instruc¸ ˜ao ´e marcada como c ´odigo morto. A instruc¸ ˜ao que define a vari ´avel k tamb ´em ´e marcada como c ´odigo morto pois ´e somente usada na atribuic¸ ˜ao de h que foi marcada como c ´odigo morto.

Trecho de C ´odigo 8 — Exemplo de algoritmo com vari ´aveis n ˜ao utilizadas

1 a = 3; 2 x = 10; 3 y = 8; 4 z = x + y ; 5 j = a + x + y ; 6 k = y + 10; 7 h = k + 15; 8 p r o c e d i m e n t o _ t e s t e ( z , j ) ;

Fonte: Pr ´oprio autor

3.3 EXPRESS ˜AO CONSTANTE, C ´ODIGO INACESS´IVEL E LOOP

O erro de express ˜ao constante, c ´odigo inacess´ıvel e loop s ˜ao erros que podem ser encontrados da mesma forma, pois um c ´odigo inacess´ıvel ocorre quando existe um condicional que nunca ir ´a passar por uma das arestas portanto ´e uma express ˜ao constante e o loop ´e um lac¸o que contem uma express ˜ao cons-tante que faz com que o lac¸o nunca encontre a sa´ıda. Para detectar estes erros foi escolhida a forma e-SSA com o algoritmo de an ´alise de intervalo de valores mas adicionando um passo a mais. Ao terminar o c ´alculo de intervalo de valores o algoritmo ir ´a utilizar os dados dos intervalos para detectar se existem as ex-press ˜oes constantes com isso detectando c ´odigo inacess´ıvel e loop (STAIGER et al., 2007; XU, 2001).

O Trecho de C ´odigo 9 mostra um exemplo onde h ´a c ´odigo inacess´ıvel, express ˜ao constante e um loop. A express ˜ao j = 15 vai ser sempre verdadeira pois a vari ´avel j ´e composta pela multiplicac¸ ˜ao de a e b que s ˜ao 3 e 5 respec-tivamente, resultando no valor 15, e assim temos um c ´odigo inacess´ıvel que ´e o caminho da aresta-falsa do teste. No loop a express ˜ao i <> a ser ´a sempre verdadeira pois o i sempre ser ´a 3 e diferente de a que possui valor 5.

Trecho de C ´odigo 9 — Exemplo de algoritmo com express ˜ao constante, c ´odigo inacess´ıvel e loop

1 a l g o r i t m o 2 var

(56)

3 a , b , j , k , i : i n t e i r o 4 i n i c i o 5 a = 5; 6 b = 3; 7 j = a * b ; 8 9 se j = 15 e n t ~a o 10 i = 3; 11 s e n ~a o 12 i = 1; 13 f i m s e 14 15 e n q u a n t o i < > a f a ¸c a 16 i n i c i o 17 k = k + 1; 18 j = i + b ; 19 f i m e n q u a n t o 20 21 f i m a l g o r i t m o

Fonte: Pr ´oprio autor

3.4 ´INDICES DE VETORES

O erro de ´ındices de vetores ocorre quando ´e feita uma tentativa de acesso a uma posic¸ ˜ao do vetor que n ˜ao existe. Este erro ´e detectado utilizando a forma e-SSA com o algoritmo de an ´alise de intervalo de valores, da mesma forma da Sec¸ ˜ao 3.3. Ao propagar os intervalos de valores o algoritmo testar ´a o ´ındice do vetor com a declarac¸ ˜ao dele, se o ´ındice estiver fora do declarado ser ´a identificado como erro (BIRCH; ENGELEN; GALLIVAN, 2004).

No Trecho de C ´odigo 10 temos um exemplo de erro de ´ındices de ve-tores. A vari ´avel vet ´e um vetor com posic¸ ˜oes de intervalo de 1 a 10, no lac¸o repita o i ´e incrementando de uma unidade a cada iterac¸ ˜ao e o teste de sa´ıda ´e atei > 10. Portanto na pen ´ultima iterac¸ ˜ao o i estar ´a valendo 10 mas ir ´a para o in´ıcio do lac¸o novamente pois 10 n ˜ao ´e maior que10, com isso i ser ´a incremen-tado para o valor 11 e ocorrer ´a o erro.

Trecho de C ´odigo 10 — Exemplo de algoritmo com erro de ´ındice de vetores

1 a l g o r i t m o 2 var 3 vet : v e t o r [ 1 . . 1 0 ] de i n t e i r o 4 i : i n t e i r o 5 i n i c i o 6 i = 0; 7 // na ´u l t i m a i t e r a ¸c ~a o o i v a i s e r i n c r e m e n t a d o p a r a 11 8 // a s s i m o c o r r e n d o um e r r o 9 r e p i t a 10 i = i +1;

(57)

11 vet [ i ] = i ; 12 ate i > 10 13

14 f i m l a g o r i t m o

(58)

4 IMPLEMENTAC¸ ˜AO

O analisador est ´atico de c ´odigo foi desenvolvido em Java SE (Stan-dard Editon) utilizando a vers ˜ao 1.8.0 171 JDK (Java Development Kit) que ´e mantido pela ORACLE. Maiores informac¸ ˜oes podem ser encontradas na p ´agina de apresentac¸ ˜ao (ORACLE, 2018) e na documentac¸ ˜ao da vers ˜ao 8 (ORACLE, 2017).

Para gerenciamento do projeto foi utilizada a vers ˜ao 3.5.2 do Apache Maven. Essa ferramenta gerencia o projeto, serve para fazer compilac¸ ˜ao, atuali-zar e manter depend ˆencias e tem integrac¸ ˜ao com o GitLab. ´E mantido pela Apa-che e maiores informac¸ ˜oes sobre podem ser encontradas na p ´agina de apresen-tac¸ ˜ao (APACHE, 2018).

Para versionamento e gerenciamento de fontes foi utilizado o Git utili-zando a vers ˜ao 2.6.2 que ´e mantido por Linus Torvalds e Junio Hamano. Maiores informac¸ ˜oes podem ser encontradas na p ´agina de apresentac¸ ˜ao (TORVALDS, 2018).

Foi criado um projeto novo contendo somente o analisador est ´atico de c ´odigo para separar os projetos por responsabilidades. Desta forma o analisador est ´atico de c ´odigo pode ser incorporado em outro portal de algoritmos e tamb ´em fica facilitada a evoluc¸ ˜ao.

Durante o desenvolvimento deste trabalho, buscou-se implementar o analisador de forma que a evoluc¸ ˜ao do mesmo seja garantida por testes unit ´arios. Testes unit ´arios foram desenvolvidos somente para classes com grande critici-dade no analisador. Estas classes foram identificadas ao longo do desenvolvi-mento, pois necessitavam incremento de funcionalidades e precisavam manter caracter´ısticas antes desenvolvidas, ent ˜ao foram criados testes unit ´arios para cada comportamento que a classe necessitava manter. Desta forma a evoluc¸ ˜ao do analisador foi produtiva e ao longo do desenvolvimento foram poucos

(59)

momen-tos que se identificou falhas das classes com testes unit ´arios.

Todas as an ´alises s ˜ao intra procedural, ou seja, cada func¸ ˜ao, procedi-mento e c ´odigo principal s ˜ao processados separadamente.

O projeto ´e separado em 5 pacotes principais, cada um cont ´em o nome que busca representar sua func¸ ˜ao na arquitetura. O pacoteTAC (br.com.staticc.co de.analysis.tac), respons ´avel pela convers ˜ao para c ´odigo de tr ˆes enderec¸os, Control Flow Graph (br.com.staticc.code.analysis.control.flow.graph), respons ´a-vel por gerar o grafo de fluxo de controle,Live Variable (br.com.staticc.code.ana lysis.live.variable), respons ´avel pela an ´alise de vida de vari ´aveis,Reaching Defi-nitions (br.com.staticc.code.analysis.live.reaching.defiDefi-nitions), respons ´avel pela an ´alise de definic¸ ˜oes incidentes eInterval Values (br.com.staticc.code.analysis. interval.values), respons ´avel pela an ´alise de intervalo de valores. A Figura 22 apresenta o diagrama UML de pacotes que comp ˜oem o analisador, indicando tamb ´em a relac¸ ˜ao de utilizac¸ ˜ao entre eles.

Figura 22 — Pacotes principais

Fonte: Pr ´oprio autor

As pr ´oximas sec¸ ˜oes descrevem e ilustram cada um destes pacotes mos-trando de forma sucinta as classes que os comp ˜oem. O c ´odigo completo pode ser encontrado no CD em anexo a este trabalho.

4.1 C ´ODIGO DE TR ˆES ENDEREC¸ OS

Para o c ´odigo ser analisado ´e necess ´ario converte-lo para a representa-c¸ ˜ao intermedi ´aria chamadaC ´odigo de Tr ˆes Enderec¸os. Este assunto foi abor-dado no Cap´ıtulo 2. A Figura 23 cont ´em a composic¸ ˜ao das principais classes para convers ˜ao do c ´odigo.

(60)

Figura 23 — Representac¸ ˜ao da convers ˜ao para C ´odigo de Tr ˆes Enderec¸os

Fonte: Pr ´oprio autor

Cada comando do algoritmo estende a classe abstrata NodoAnalise-Generico que estende a classe abstrata Nodo que cont ´em a func¸ ˜ao para imple-mentar a gerac¸ ˜ao de c ´odigo de tr ˆes enderec¸os.

O algoritmo ´e representado pela classeNodoAlgoritmo que cont ´em o nome do algoritmo, declarac¸ ˜ao de vari ´aveis e a lista de comandos. Esta classe cont ´em a func¸ ˜ao generateThreeAdressCode() que ´e respons ´avel por gerar uma lista com o objetoThreeAdressCodeAlgorithm. Este objeto cont ´em o nome do algoritmo, func¸ ˜ao ou procedimento, a declarac¸ ˜ao das vari ´aveis, os par ˆametros de entrada e o tipo do c ´odigo, se ´e o principal, func¸ ˜ao ou procedimento. O Trecho de C ´odigo 11 apresenta como ´e gerado o c ´odigo de tr ˆes enderec¸os.

Trecho de C ´odigo 11 — Gerac¸ ˜ao do c ´odigo de tr ˆes enderec¸os.

1 p u b l i c List < T h r e e A d r e s s C o d e A l g o r i t h m > g e n e r a t e T h r e e A d r e s s C o d e () { 2 List < T h r e e A d r e s s C o d e A l g o r i t h m > l i s t = new A r r a y L i s t < >() ;

(61)

3 4 // g e t a l l f u n c t i o n s / p r o c e d u r e s 5 for ( N o d e F u n c t i o n f u n c i o n : t h i s . d e c V a r i a v e i s . g e t P r o c e d u r e A n d F u n c t i o n s () ) { 6 T h r e e A d r e s s C o d e L i s t g e n e r a t e T h r e e A d r e s s C o d e = f u n c i o n . g e n e r a t e T h r e e A d r e s s C o d e () ; 7 8 l i s t . add ( new T h r e e A d r e s s C o d e A l g o r i t h m ( f u n c i o n . g e t N a m e () , f u n c i o n . g e t D e c l a r a t i o n s () , f u n c i o n . g e t I n p u t () , f u n c i o n . g e t T y p e () , g e n e r a t e T h r e e A d r e s s C o d e , f u n c i o n . g e t C o m m a n d s () ) ) ; 9 } 10 11 // m a i n c o d e a l g o r i t h m 12 T h r e e A d r e s s C o d e A l g o r i t h m a l g o = new T h r e e A d r e s s C o d e A l g o r i t h m ( pNome , d e c V a r i a v e i s , F u n c t i o n T y p e . MAIN , l i s t a C o m a n d o s . g e n e r a t e T h r e e A d r e s s C o d e () , l i s t a C o m a n d o s ) ; 13 a l g o . g e t C o d e () . c o n c a t e n a t e C o d e ( " S T O P " , n u l l ) ; 14 l i s t . add ( a l g o ) ; 15 16 r e t u r n l i s t ; 17 }

Fonte: Pr ´oprio autor

Note que as func¸ ˜oes e procedimentos est ˜ao declaradas dentro da declara-c¸ ˜ao de vari ´aveis na linguagem portugol.

4.1.1 Exemplo de c ´odigo gerado

No c ´odigo de tr ˆes enderec¸os as operac¸ ˜oes se limitam no m ´aximo a tr ˆes operandos. ´E permitido uma instruc¸ ˜ao onde a vari ´avel de destino ´e atribu´ıda por dois operandos e um operador aritm ´etico entre eles. Quando uma operac¸ ˜ao en-volve mais de tr ˆes enderec¸os s ˜ao geradas vari ´aveis tempor ´arias com as operac¸ ˜oes quebradas em n operac¸ ˜oes, no final a vari ´avel tempor ´aria com resultado ´e atribu´ıda

`a vari ´avel destino. A Figura 24 ilustra a convers ˜ao de uma instruc¸ ˜ao. Figura 24 — Convers ˜ao de uma instruc¸ ˜ao

Fonte: Pr ´oprio autor

Neste trabalho foi feita uma otimizac¸ ˜ao na convers ˜ao de instruc¸ ˜oes. Na Figura 24 antes do resultado chegar na vari ´avel a ´e atribu´ıdo o resultado na vari ´avel tempor ´aria t3, nesta otimizac¸ ˜ao o resultado foi diretamente atribu´ıdo a

(62)

vari ´avela sem passar pela vari ´avel tempor ´aria.

Como n ˜ao existe lac¸o de controle e condicional com ent ˜ao e sen ˜ao no c ´odigo de tr ˆes enderec¸os ´e poss´ıvel alcanc¸ar o mesmo comportamento utilizando condicional com r ´otulos. O condicional cont ´em o r ´otulo a ser acessado se a condic¸ ˜ao resultar em verdadeiro, se n ˜ao for segue a pr ´oxima instruc¸ ˜ao. A Figura 25 ilustra a convers ˜ao de um condicional tradicional.

Figura 25 — Convers ˜ao de uma instruc¸ ˜ao

Fonte: Pr ´oprio autor

4.2 GRAFO DE FLUXO DE CONTROLE

Para facilitar an ´alises est ´aticas ´e necess ´ario construir um grafo de fluxo de controle. Todas as an ´alises seguintes apresentadas utilizam o grafo de fluxo de controle para se orientar no algoritmo. A Figura 26 cont ´em a composic¸ ˜ao das principais classes.

(63)

Figura 26 — Representac¸ ˜ao do Grafo de Fluxo de Controle

Fonte: Pr ´oprio autor

A principal classe ´e a ControlFlowGraph, ela faz o processamento e monta os blocos b ´asicos e o grafo de fluxo de controle, o par ˆametro de en-trada ´e oThreeAdressCodeAlgorithm gerado no conversor para c ´odigo de tr ˆes enderec¸os. O bloco b ´asico ´e representado pela classe BasicBlock. Neste ob-jeto existe a lista de blocos predecessores e sucessores a ele. Na lista de blocos sucessores existe um enumerador chamadoLinkEnum que define se aquele su-cessor ´e resultante de um condicional verdadeiro, falso ou se ´e somente um fluxo normal sem condicional. A Figura 12 cont ´em um Trecho de C ´odigo que descreve a gerac¸ ˜ao de blocos b ´asicos em condicionais.

Referências

Documentos relacionados

Para Souza (2004, p 65), os micros e pequenos empresários negligenciam as atividades de planejamento e controle dos seus negócios, considerando-as como uma

O Documento Orientador da CGEB de 2014 ressalta a importância do Professor Coordenador e sua atuação como forma- dor dos professores e que, para isso, o tempo e

Quando conheci o museu, em 2003, momento em foi reaberto, ele já se encontrava em condições precárias quanto à conservação de documentos, administração e organização do acervo,

F REQUÊNCIAS PRÓPRIAS E MODOS DE VIBRAÇÃO ( MÉTODO ANALÍTICO ) ... O RIENTAÇÃO PELAS EQUAÇÕES DE PROPAGAÇÃO DE VIBRAÇÕES ... P REVISÃO DOS VALORES MÁXIMOS DE PPV ...

Os principais objectivos definidos foram a observação e realização dos procedimentos nas diferentes vertentes de atividade do cirurgião, aplicação correta da terminologia cirúrgica,

psicológicos, sociais e ambientais. Assim podemos observar que é de extrema importância a QV e a PS andarem juntas, pois não adianta ter uma meta de promoção de saúde se

forficata recém-colhidas foram tratadas com escarificação mecânica, imersão em ácido sulfúrico concentrado durante 5 e 10 minutos, sementes armazenadas na geladeira (3 ± 1

Our contributions are: a set of guidelines that provide meaning to the different modelling elements of SysML used during the design of systems; the individual formal semantics for