Skip to content

Implement text mapping, compiler optimizations, and benchmarks - #20

Merged
leonelsanchesdasilva merged 7 commits into
principalfrom
libs
Mar 29, 2026
Merged

Implement text mapping, compiler optimizations, and benchmarks#20
leonelsanchesdasilva merged 7 commits into
principalfrom
libs

Conversation

@ItaloCobains

Copy link
Copy Markdown
Collaborator

No description provided.

…clarações lazy

- Adiciona passes de otimização LLVM (SROA, EarlyCSE, InstCombine) via parâmetro `otimizar`
- Define target triple e data layout da plataforma nativa no módulo
- Adiciona atributos `nounwind` e `willreturn` em funções do usuário
- Elimina bloco `se_senao` vazio quando não há caminho alternativo
- Registra apenas módulos efetivamente importados no código (declarações lazy)
- Corrige coerção de literais inteiros em expressões binárias com resultado de subexpressões
- Corrige tipo de retorno em funções do usuário via `tipoRetornoFuncaoAtual`
- Corrige resolução de argumentos VariavelEscopo em chamadas de função
- Adiciona flag `-O2` na compilação e linkagem de bibliotecas nativas
- Adiciona benchmark suite (fibonacci recursivo + contagem de primos) comparando com C e Rust

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Este PR expande o backend LLVM do compilador Delégua com melhorias em vetores (alocação no heap, escrita por índice, métodos mapear/tamanho), adiciona um caminho opcional de otimizações LLVM (-O2/passes) e inclui uma suíte simples de benchmarks (Delégua vs C vs Rust).

Changes:

  • Vetores: alocação de elementos via malloc, suporte a escrita por índice e novos métodos (mapear para texto e tamanho), com novos testes.
  • Build/CLI: seleção de bibliotecas nativas a compilar/linkar com base nos módulos efetivamente importados + flags de link; clang/clang++ com -O2.
  • Benchmarks: programas (fib/primos/bubblesort) em Delégua/C/Rust e script para executar/validar.

Reviewed changes

Copilot reviewed 21 out of 21 changed files in this pull request and generated 5 comments.

Show a summary per file
File Description
testes/compilador-llvm.vetores.test.ts Atualiza expectativas de IR para vetores no heap e adiciona testes de escrita/leitura por índice.
testes/compilador-llvm.se.test.ts Atualiza asserts para comparações inteiras e geração condicional do bloco se_senao.
testes/compilador-llvm.metodos-vetor.test.ts Adiciona testes para método tamanho().
testes/compilador-llvm.metodos-vetor-com-funcoes.test.ts Adiciona testes para mapear como método (inteiro/número/texto) e função nomeada.
testes/compilador-llvm.importacao.test.ts Ajusta teste para cenário com múltiplos imports e tamanho do mapa de módulos.
testes/compilador-llvm.funcoes.test.ts Adiciona teste de recursão (fibonacci).
fontes/ilc.ts Passa otimizar=true para o compilador e compila/linka bibliotecas nativas com -O2 + flags por módulo importado.
fontes/compilador-llvm.ts Implementa mudanças de vetores (heap, cache de ponteiro), novos métodos, registro seletivo de módulos e passes de otimização.
fontes/bibliotecas/vetor.h Declara delegua_vetor_tamanho e delegua_vetor_mapear_texto.
fontes/bibliotecas/vetor.c Implementa delegua_vetor_mapear_texto e delegua_vetor_tamanho.
fontes/bibliotecas-compilacao.ts Novo helper para detectar módulos importados e determinar arquivos C/flags de link necessários.
benchmarks/* Adiciona benchmarks em C/Rust/Delégua + script executar.sh.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment thread fontes/compilador-llvm.ts
Comment on lines +1122 to +1128
valorFinal = this.montador.CreateLoad(tipoElemento, valorResolvido.variavelLlvm, 'val_store');
} else {
valorFinal = valorResolvido as llvm.Value;
}

this.montador.CreateStore(valorFinal, gepElemento);
return Promise.resolve(valorFinal);

Copilot AI Mar 29, 2026

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Na atribuição por índice em vetor, valorFinal é armazenado diretamente em gepElemento sem coerção para o tipo do elemento. Como literais numéricos frequentemente chegam como double no AST/IR, isso pode gerar store double em um i32* (IR inválido) para inteiro[]. Converta valorFinal para tipoElemento quando necessário (ex.: FPToSI/SIToFP) antes do CreateStore.

Suggested change
valorFinal = this.montador.CreateLoad(tipoElemento, valorResolvido.variavelLlvm, 'val_store');
} else {
valorFinal = valorResolvido as llvm.Value;
}
this.montador.CreateStore(valorFinal, gepElemento);
return Promise.resolve(valorFinal);
// Quando o valor é uma variável, carregamos já no tipo do elemento.
valorFinal = this.montador.CreateLoad(tipoElemento, valorResolvido.variavelLlvm, 'val_store');
} else {
valorFinal = valorResolvido as llvm.Value;
}
// Garante que o tipo do valor a armazenar coincide com o tipo do elemento do vetor.
let valorConvertido: llvm.Value = valorFinal;
const tipoValor = valorFinal.getType();
if (tipoValor !== tipoElemento) {
// Conversões numéricas comuns: double <-> inteiro.
const ehFloatOrigem = tipoValor.isFloatingPointTy && tipoValor.isFloatingPointTy();
const ehIntOrigem = tipoValor.isIntegerTy && tipoValor.isIntegerTy();
const ehFloatDestino = tipoElemento.isFloatingPointTy && tipoElemento.isFloatingPointTy();
const ehIntDestino = tipoElemento.isIntegerTy && tipoElemento.isIntegerTy();
if (ehFloatOrigem && ehIntDestino) {
// Ex.: armazenar literal double em vetor de inteiros.
valorConvertido = this.montador.CreateFPToSI(valorFinal, tipoElemento, 'val_store_fptosi');
} else if (ehIntOrigem && ehFloatDestino) {
// Ex.: armazenar inteiro em vetor de números de ponto flutuante.
valorConvertido = this.montador.CreateSIToFP(valorFinal, tipoElemento, 'val_store_sitofp');
} else {
// Fallback: tentativa de coerção por bitcast para tipos compatíveis.
valorConvertido = this.montador.CreateBitCast(valorFinal, tipoElemento, 'val_store_bitcast');
}
}
this.montador.CreateStore(valorConvertido, gepElemento);
return Promise.resolve(valorConvertido);

Copilot uses AI. Check for mistakes.
Comment thread fontes/compilador-llvm.ts
);
const ptrElementos = this.montador.CreateLoad(tipoPonteiro, gepCampoPtr, 'ptr_elementos');
// Carrega o ponteiro de elementos (com cache para evitar loads redundantes).
const nomeVetor = (alvoBruto as any)?.simbolo?.lexema ?? '';

Copilot AI Mar 29, 2026

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

O cache de ponteiro de elementos usa nomeVetor como chave, mas quando o acesso não é uma variável simples (alvoBruto sem simbolo.lexema) a chave vira string vazia. Isso pode causar colisões e reutilização do ponteiro errado entre vetores/expressões diferentes no mesmo bloco básico. Sugestão: keyar o cache pelo próprio vetorPtr (Map<llvm.Value, llvm.Value>) ou só usar cache quando houver um identificador estável e único.

Suggested change
const nomeVetor = (alvoBruto as any)?.simbolo?.lexema ?? '';
const nomeVetorBase = (alvoBruto as any)?.simbolo?.lexema;
const nomeVetor =
(nomeVetorBase && nomeVetorBase.length > 0)
? nomeVetorBase
: ((alvoResolvido.variavelLlvm as any)?.getName?.() ||
alvoResolvido.variavelLlvm.toString());

Copilot uses AI. Check for mistakes.
Comment thread fontes/compilador-llvm.ts
Comment on lines +4126 to +4133
// Detecta módulos importados para registrar apenas as funções necessárias.
const modulosImportados = new Set<string>();
const regexImportar = /importar\s*\(\s*['"](\w+)['"]\s*\)/;
const regexDe = /importar\s+.*\s+de\s+['"](\w+)['"]/;
for (const linha of codigo) {
const match = regexImportar.exec(linha) || regexDe.exec(linha);
if (match) modulosImportados.add(match[1]);
}

Copilot AI Mar 29, 2026

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

A detecção de módulos importados foi reimplementada aqui via regex linha-a-linha, mas já existe detectarModulosImportados() em fontes/bibliotecas-compilacao.ts. Para evitar divergências futuras (regex/sintaxe suportada), considere reutilizar o helper comum ou, idealmente, derivar os imports a partir do AST do avaliador sintático.

Copilot uses AI. Check for mistakes.
Comment thread fontes/compilador-llvm.ts
Comment on lines +3187 to +3192
let argumentoResolvido = await argumentoAjustado.aceitar(this);
if (argumentoResolvido instanceof VariavelEscopo) {
const tipoParam = tiposParametros[indice] || argumentoResolvido.tipo || 'número';
const tipoLlvm = this.obterTipoLlvm(tipoParam);
argumentoResolvido = this.montador.CreateLoad(tipoLlvm, argumentoResolvido.variavelLlvm, 'load_arg');
}

Copilot AI Mar 29, 2026

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Em visitarExpressaoDeChamada, o código faz CreateLoad() para qualquer VariavelEscopo retornada como argumento. Para parâmetros de função (onde VariavelEscopo.variavelLlvm é um llvm.Argument não-ponteiro), isso gera load em um valor não-pointer (IR inválido/erro no binding). Ajuste para só dar load quando o llvm.Value for ponteiro (ex.: usando tipoEhPonteiro(getType())/carregarValorSeNecessario) e, caso contrário, passar o valor direto.

Copilot uses AI. Check for mistakes.
Comment thread fontes/compilador-llvm.ts
Comment on lines +3198 to +3203
let argumentoResolvido = await argumentoAjustado.aceitar(this);
if (argumentoResolvido instanceof VariavelEscopo) {
const tipoParam = argumentoResolvido.tipo || argumento.tipo || 'número';
const tipoLlvm = this.obterTipoLlvm(tipoParam);
argumentoResolvido = this.montador.CreateLoad(tipoLlvm, argumentoResolvido.variavelLlvm, 'load_arg');
}

Copilot AI Mar 29, 2026

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Mesma questão no caminho sem construtoCorrespondente: argumentos que já são valores (ex.: parâmetros de função representados por llvm.Argument) não devem sofrer CreateLoad(). Hoje o bloco sempre faz load se instanceof VariavelEscopo, o que pode quebrar chamadas envolvendo parâmetros/valores agregados. Restrinja o load a casos onde variavelLlvm é ponteiro.

Copilot uses AI. Check for mistakes.

@leonelsanchesdasilva leonelsanchesdasilva left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Obrigado!

@leonelsanchesdasilva
leonelsanchesdasilva merged commit 16e1f07 into principal Mar 29, 2026
6 checks passed
@leonelsanchesdasilva
leonelsanchesdasilva deleted the libs branch March 29, 2026 18:23
leonelsanchesdasilva added a commit that referenced this pull request Mar 29, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants