O backend, e o que ele não é
Não há LLVM, não há código de máquina e não há target triple. O que existe no lugar, e por que a troca é essa.
Esta página existe porque a pergunta aparece, e porque a resposta certa é um não com o motivo — não um silêncio.
O que não existe#
| Pedido | Resposta |
|---|---|
| emitir LLVM IR | não existe. Emitir texto de IR é fácil; o que vem depois não é — seria preciso llc ou clang instalado, e aí a linguagem passaria a depender de um compilador C para rodar |
llvmlite, cffi, qualquer backend em pacote | recusado por regra: dataforge/ não tem dependência externa, e é isso que faz pip install dataforge-lang bastar |
| passes LLVM em C++ | não se aplica: não há IR para um passe transformar |
| target triple, cross compiler, RISC-V, WebAssembly, bare-metal | não existe. Não há código de máquina a produzir para alvo nenhum |
| debug info (DWARF), intrinsics | não se aplica. A informação de depuração existe, mas é a da linguagem: linha, coluna e o DAP |
O que existe no lugar#
| Em vez de | O DataForge tem |
|---|---|
| backend de código de máquina | compilador.py — a árvore vira fechamentos Python, uma vez, com a cobertura medida pelo LIR |
| passes customizados em C++ | plugins do `check` escritos em DataForge, que agora veem o MIR e o SSA por Arcane.Compilador |
| calling convention e ABI lowering | existem, e são de verdade — mas só na fronteira com o C: `Arcane.C` declara a assinatura e o ctypes aplica a ABI da plataforma |
| cross compilation | o release constrói nas quatro plataformas (Linux, macOS Intel, macOS ARM, Windows), com .deb, PKGBUILD e instalador do Windows; e dataforge devops gera Dockerfile e manifesto para outra arquitetura |
| instrumentação | o MIR e o SSA como dado, e Arcane.Macro para reescrever corpo de ação |
Um passe próprio, escrito na linguagem#
É o análogo honesto de "custom pass": não um .so carregado no otimizador, mas uma regra que lê as mesmas representações e devolve diagnóstico.
dataforge
adopt Arcane.Compilador as K
// A regra: acusar ramo que nunca roda, com o corpo e a linha.
action verificar(fonte):
achados := []
cycle morto in K.ramos_mortos(fonte):
achados.append($"{morto["corpo"]}:{morto["linha"]} ramo {morto["rotulo"]} nao roda")
yield achados
suspeito := "x := 1\ngiven x bigger 5:\n out 1\notherwise:\n out 2\n"
assert len(verificar(suspeito)) bigger 0
assert len(verificar("given entrada:\n out 1\n")) is 0A diferença entre isso e um passe do LLVM é real e vale dizer: um passe do LLVM transforma o IR que vai gerar código; isto relata. Transformar a árvore também é possível — é o que os passes de otimização fazem —, mas o ganho medido ali é 1,01×, e essa é a razão pela qual a instrumentação é o uso que paga.