"Se um trabalhador quiser fazer bem o seu trabalho, ele deve primeiro afiar suas ferramentas." - Confúcio, "Os Analectos de Confúcio. Lu Linggong"
Primeira página > Programação > Resolução de alguns bugs

Resolução de alguns bugs

Publicado em 19/08/2024
Navegar:167

Resolução de alguns bugs

Para quem não está acompanhando o POJ (Pascal on the JVM) é um compilador que transforma um subset de Pascal para JASM (Java Assembly) de forma que possamos usar a JVM como ambiente de execução.

Na última postagem implementamos o suporte às functions do Pascal.

Nesta publicação vamos falar sobre coisas bacanas? Nem tanto rsrsrs. Desta vez só vamos falar de bugs mesmo :-)

Como estamos compilando para a JVM faz-se necessário detalhar o funcionamento de vários pontos desta incrível máquina virtual. Com isso, em vários momentos eu detalho o funcionamento interno da JVM bem como algumas das suas instruções (opcodes).

Bug referente aos parâmetros passados ao programa pela linha de comando

Quando implementei a declaração de variáveis eu não atentei para o fato de que, na JVM, a primeira variável na função principal é o args, um array que contém os argumentos passados para o programa. Com isso neste PR eu reservo a primeira posição implicitamente para args.

Bug ao lidar com variáveis locais e globais

Como os programas em Pascal de teste continham apenas variáveis globais eu não havia notado um erro grave na geração do JASM. No momento em que criei programas que continham variáveis globais e locais percebi que algo de errado não estava certo rsrsrs.

A partir do programa Pascal abaixo:

program global_var_declaration;
var
    globalvar : integer;
begin
    globalvar := 123;
    write (globalvar);
end.

O POJ gerava o seguinte JASM:

// Code generated by POJ 0.1
public class global_var_declaration {
    public static main([java/lang/String)V {
        ;; globalvar := 123;
        bipush 123
        istore 1

        ;; write (globalvar);
        getstatic java/lang/System.out java/io/PrintStream
        iload 1
        invokevirtual java/io/PrintStream.print(I)V

        return
    }
}

Para tentar identificar o problema criei um programa em Java equivalente ao programa em Pascal acima:

public class GlobalVarDeclaration {
    public static int globalVar;

    public static void main(String[] args) {
        globalVar = 123;
        System.out.println(globalVar);
    }
}

Quando desassemblei o class eu obtive o seguinte assembly:

 1: public class GlobalVarDeclaration {
 2:     public static globalVar I
 3:
 4:     public static main([java/lang/String)V {
 5:         bipush 123
 6:         putstatic GlobalVarDeclaration.globalVar I
 7:
 8:         getstatic java/lang/System.out java/io/PrintStream
 9:         getstatic GlobalVarDeclaration.globalVar I
10:         invokevirtual java/io/PrintStream.println(I)V
11:
12:         return
13:     }
14: }

Neste momento percebi a declaração "public static globalVar I" (linha 2) e as instruções putstatic (linha 6) e getstatic (linha 9). O esperado eram as instruções astore e istore utilizadas pelo POJ até o momento. Lendo a documentação da JVM percebi que o POJ estava declarando as variáveis globais como se fossem variáveis locais de uma função para a JVM :-D

Enfim, até o momento o POJ estava usando (erroneamente) os opcodes aload/iload/astore/istore para variáveis globais, mas o correto seria declarar as variáveis como públicas (como na linha 2) e utilizar o getstatic/putstatic.

Com isso o código foi refatorado aqui para que a tabela de símbolos consiga lidar com declarações locais e globais. E aqui o código foi refatorado para que a tabela de símbolos consiga gerar as instruções corretas para as variáveis locais e globais.

A geração de código JASM foi alterada aqui para lidar com a nova tabela de símbolos bem como limpar as declarações locais após o término de uma função ou procedimento.

Com isso, a partir do programa Pascal abaixo:

program GlobalVarDeclaration;
var
    globalvar : integer;
begin
    globalvar := 123;
    write (globalvar);
end.

O POJ passou a gerar corretamente o seguinte JASM:

// Code generated by POJ 0.1
public class global_var_declaration {
    public static globalvar I

    public static main([java/lang/String)V {
        ;; globalvar := 123;
        bipush 123
        putstatic global_var_declaration.globalvar I

        ;; write (globalvar);
        getstatic java/lang/System.out java/io/PrintStream
        getstatic global_var_declaration.globalvar I
        invokevirtual java/io/PrintStream.print(I)V

        return
    }
}

Próximos passos

Na próxima publicação vamos falar sobre contextos e sentenças aninhadas.

Código completo do projeto

O repositório com o código completo do projeto e a sua documentação está aqui.

Declaração de lançamento Este artigo está reproduzido em: https://dev.to/alexgarzao/resolucao-de-alguns-bugs-3a1i?1 Caso haja alguma infração, entre em contato com [email protected] para excluí-la
Tutorial mais recente Mais>

Isenção de responsabilidade: Todos os recursos fornecidos são parcialmente provenientes da Internet. Se houver qualquer violação de seus direitos autorais ou outros direitos e interesses, explique os motivos detalhados e forneça prova de direitos autorais ou direitos e interesses e envie-a para o e-mail: [email protected]. Nós cuidaremos disso para você o mais rápido possível.

Copyright© 2022 湘ICP备2022001581号-3