<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom">
  <channel>
    <title>Elisa Fröhlich</title>
    <description>Um blog pessoal sobre compiladores e algumas outras coisas interessantes</description>
    <link href="https://elisa-frohlich.github.io/ptbr/rss_ptbr.xml" rel="self"/>
    <link href="https://elisa-frohlich.github.io/ptbr/"/>
    <pubDate>11/03/26</pubDate>
    <lastBuildDate>11/03/26</lastBuildDate>
    <generator>Jekyll v3.10.0</generator>
    
     
      <item>
        <title>Escrevendo um Passe LLVM</title>
        <description>&lt;h3 id=&quot;introdução&quot;&gt;Introdução&lt;/h3&gt;

&lt;p&gt;Após um certo tempo, hora de voltar a escrever alguma coisa aqui. Dessa vez, vou sair um pouco da teoria e ir para um lado prático (não que as próximas postagens daquele assunto não tenham um lado prático).&lt;/p&gt;

&lt;p&gt;Nessa postagem, irei explicar, ou tentar explicar, como construir um passe para a infraestrutura LLVM. Tá, eu sei, existem diversos tutoriais que ensinam a escrever, compilar e executar um passe LLVM, mas será que fará mal escrever mais um? Acho que excesso de opções não é de fato um problema aqui, além do mais, quando eu for falar sobre aplicações de passes LLVM mais pra frente, não terei que sair caçando algum blog em português que explique de uma forma que eu ache satisfatória, que as coisas funcionem e esse tipo de coisa. Note que essa postagem será inicialmente escrita só em português (a versão em inglês vai sair quando eu tiver paciência pra traduzir isso aqui). Além disso, eu gostaria muito de poder só indicar o &lt;a href=&quot;https://llvm.org/docs/WritingAnLLVMNewPMPass.html&quot;&gt;tutorial&lt;/a&gt; da LLVM sobre o assunto mas, infelizmente, eu não achei a documentação da LLVM traduzida para português.&lt;/p&gt;

&lt;p&gt;Dessa forma, nessa postagem eu irei cobrir conteúdos bem básicos, assumindo que meus textos podem ser lidos por pessoas que não entendem quase nada de compiladores, porém têm um grande interesse na área. Porém, é esperado que a pessoa entenda um pouco de C++ para entender a parte da implementação.&lt;/p&gt;

&lt;p&gt;Por fim, um pequeno resumo do que será abordado:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;A infraestrutura LLVM;&lt;/li&gt;
  &lt;li&gt;O que são passes LLVM;&lt;/li&gt;
  &lt;li&gt;Como escrever um passe;&lt;/li&gt;
  &lt;li&gt;Como compilar e executar um passe.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3 id=&quot;llvm&quot;&gt;LLVM&lt;/h3&gt;

&lt;p&gt;A infraestrutura LLVM é um conjunto de ferramentas que permitem construir (e usar) diversos compiladores. Com ela, você pode construir um compilador muito eficiente para qualquer linguagem de programação sem &lt;strong&gt;muito&lt;/strong&gt; esforço.&lt;/p&gt;

&lt;p&gt;Dentre as principais ferramentas, podemos destacar:&lt;/p&gt;
&lt;ul&gt;
  &lt;li&gt;&lt;strong&gt;O núcleo da LLVM&lt;/strong&gt;: que permite uma série de otimizações no programa fonte, e também permite a geração de código de máquina para diversas arquiteturas de CPU;&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;O compilador Clang&lt;/strong&gt;, que é o compilador “nativo” da LLVM para C/C++; e&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;As bibliotecas padrões libc/libc++&lt;/strong&gt;, que é uma implementação muito otimizada da biblioteca padrão de C/C++.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Claro, existem outras ferramentas incríveis, e você pode dar uma olhada nelas no &lt;a href=&quot;https://llvm.org&quot;&gt;site da LLVM&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Porém, o que mais nos interessa agora é a representação intermediária da LLVM, a LLVM IR. Essa representação fica no meio termo entre uma linguagem de programação e uma linguagem assembly, e é muito útil para executar análises e transformações do código.&lt;/p&gt;

&lt;p&gt;Quando se pensa no desenvolvimento de um compilador para uma linguagem  de programação qualquer utilizando a LLVM, normalmente o processo envolve implementar o &lt;em&gt;front end&lt;/em&gt; do compilador para traduzir o código fonte para LLVM IR, e a partir daí usar o conjunto de ferramentas da LLVM para fazer umas magias no código e enfim gerar o código de máquina que será executado.&lt;/p&gt;

&lt;h3 id=&quot;passes-llvm&quot;&gt;Passes LLVM&lt;/h3&gt;

&lt;p&gt;A infraestrutura LLVM é altamente modular. Parte da utilização dessa modularidade é feita a partir dos passes LLVM. Eles são &lt;em&gt;plugins&lt;/em&gt; individuais que executam determinadas tarefas no código que está sendo compilado.&lt;/p&gt;

&lt;p&gt;Para executar um passe LLVM, você precisa executar a ferramenta &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;opt&lt;/code&gt;, que faz parte do arcabouço da LLVM. Um passe LLVM recebe um programa como entrada e percorre (daí o nome passe) todo o programa, podendo coletar informações acerca dele ou modificá-lo.&lt;/p&gt;

&lt;p&gt;Por conta disso, um passe pode ser dividido em 3 categorias:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;Análise: passes que extraem informações de programas e disponibilizam elas para serem utilizadas por outros passes;&lt;/li&gt;
  &lt;li&gt;Transformação: passes que modificam o programa de alguma forma;&lt;/li&gt;
  &lt;li&gt;Utilidade: passes que fornecem alguma utilidade na visualização de informações do programa, mas que não se encaixam nem como passe de análise, nem como passe de transformação.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Os passes podem operar sob diferentes níveis de hierarquia, porém normalmente trabalhamos com 2 tipos de hierarquias:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;Módulos: a grosso modo, representam um arquivo fonte do programa. Um módulo contêm funções, variáveis globais e metadados deste arquivo do programa;&lt;/li&gt;
  &lt;li&gt;Funções: representam as funções do programa, sendo que uma função contém uma assinatura (nome, parâmetros, tipo de retorno), blocos básicos (compostos por várias instruções), atributos e metadados.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;A partir disso, temos dois tipos de passes: passes de função (quando o passe percorre as funções do programa uma a uma) e passes de módulo (quando o passe percorre os módulos um a um).&lt;/p&gt;

&lt;p&gt;Por fim, um pequeno parênteses histórico: a LLVM possui dois gerenciadores de passes. O antigo é chamado de &lt;em&gt;Legacy Pass Manager&lt;/em&gt; (ou Gerenciador de Passe Legado), que foi descontinuado, e o novo é chamado de &lt;em&gt;New Pass Manager&lt;/em&gt; (Gerenciador de Passe Novo) ou NPM.&lt;/p&gt;

&lt;p&gt;Todas as minhas postagens em que eu falar sobre passes LLVM, incluindo essa, sempre estará se referindo ao NPM.&lt;/p&gt;

&lt;h3 id=&quot;desenvolvendo-um-passe&quot;&gt;Desenvolvendo um Passe&lt;/h3&gt;

&lt;p&gt;Além dos gerenciadores de passes, também existem duas formas diferentes de desenvolver os passes pra LLVM: “dentro da árvore” e “fora da árvore”.&lt;/p&gt;

&lt;p&gt;Confesso que nunca escrevi um passe “dentro da árvore”, mas a ideia é que você coloca o código do seu passe dentro da pasta da LLVM (por isso dentro da árvore) e, para compilar o passe, você recompila o &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;opt&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Então vamos nos contentar com a escrita de passes “fora da árvore”, porque é a forma que eu conheço (e, até onde eu vi, considero muito mais elegante). A questão aqui é que você pode desenvolver esse passe no diretório que você quiser, apenas tendo que escrever um pouco de código a mais (que praticamente não muda entre passes e, quando muda, muda pouco).&lt;/p&gt;

&lt;p&gt;A estrutura do passe vai ter uma organização de arquivos bem simples de ser utilizada:&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;meu_passe/
    |
    +--include/
    |   |
    |   +--MeuPasse.h
    |
    +--lib/
    |   |
    |   +--MeuPasse.cpp
    |   +--MeuPassePlugin.cpp
    |
    +--CMakeLists.txt
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Note que, para escrever o passe, iremos 
usar C++ para a implementação e o CMake como gerenciador de compilação. Se você não sabe usar CMake, não tem problemas, porque vou mostrar um jeito meio padrão de utilizar ele para compilar passes LLVM.&lt;/p&gt;

&lt;p&gt;Nessa estrutura, temos:&lt;/p&gt;
&lt;ul&gt;
  &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;MeuPasse.h&lt;/code&gt;: nosso arquivo de cabeçalho;&lt;/li&gt;
  &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;MeuPasse.cpp&lt;/code&gt;: nosso arquivo de implementação; e&lt;/li&gt;
  &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;MeuPassePlugin.cpp&lt;/code&gt;: onde registraremos nosso passe no sistema de &lt;em&gt;plugins&lt;/em&gt; da LLVM, para que a aplicação &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;opt&lt;/code&gt; consiga encontrá-lo.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Para nosso primeiro passe, vamos desenvolver um simples passe de análise: para cada função, vamos imprimir o nome dessa função e a quantidade de blocos básicos presentes nela. Note que, para isso, podemos desenvolver um passe de função, pois podemos analisar cada função independentemente.&lt;/p&gt;

&lt;p&gt;Vou explicar agora detalhadamente como funciona o desenvolvimento de cada arquivo, começando pelo&lt;/p&gt;

&lt;h4 id=&quot;meupasseh&quot;&gt;MeuPasse.h&lt;/h4&gt;

&lt;p&gt;O código desse cabeçalho consiste na declaração de uma classe que define o passe. Isto porque cada passe na LLVM é representado por uma classe em C++.&lt;/p&gt;

&lt;div class=&quot;language-cpp highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;cp&quot;&gt;#ifndef MEU_PASSE_H
#define MEU_PASSE_H
&lt;/span&gt;
&lt;span class=&quot;cp&quot;&gt;#include&lt;/span&gt; &lt;span class=&quot;cpf&quot;&gt;&quot;llvm/IR/PassManager.h&quot;&lt;/span&gt;&lt;span class=&quot;cp&quot;&gt;
&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;namespace&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;llvm&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;

&lt;span class=&quot;k&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;MeuPasse&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;public&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;PassInfoMixin&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;MeuPasse&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
&lt;span class=&quot;nl&quot;&gt;public:&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;PreservedAnalyses&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;run&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Function&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;amp;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;F&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;FunctionAnalysisManager&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;amp;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;FAM&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;};&lt;/span&gt;

&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;

&lt;span class=&quot;cp&quot;&gt;#endif // MEU_PASSE_H
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Vamos comentar alguns detalhes mais a fundo.&lt;/p&gt;

&lt;p&gt;A classe &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;MeuPasse&lt;/code&gt; herda da classe &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;PassInfoMixin&lt;/code&gt;, que é uma exemplo de uma classe modelo &lt;a href=&quot;https://en.cppreference.com/w/cpp/language/crtp.html&quot;&gt;CRTP&lt;/a&gt; (&lt;em&gt;Curiously Recurrent Template Pattern&lt;/em&gt;). Esse modelo de classe parece estranho a princípio, mas é um truque muito interessante que permite a configuração automática de um conjunto de informações necessários para a LLVM entender o seu passe.&lt;/p&gt;

&lt;p&gt;Essa classe declara apenas uma função: &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;run&lt;/code&gt;, que é responsável pela execução do passe (quase que equivalente a uma função &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;main&lt;/code&gt; de um programa qualquer).&lt;/p&gt;

&lt;p&gt;Essa função possui a seguinte assinatura:&lt;/p&gt;
&lt;ul&gt;
  &lt;li&gt;Recebe dois parâmetros:
    &lt;ol&gt;
      &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Function &amp;amp;F&lt;/code&gt;: Uma referência para a função em LLVM IR que o passe está analisando&lt;/li&gt;
      &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;FunctionAnalysisManager &amp;amp;FAM&lt;/code&gt;: Uma referência para um objeto que gerencia a execução de diferentes análises para um objeto do tipo &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Function&lt;/code&gt;.&lt;/li&gt;
    &lt;/ol&gt;
  &lt;/li&gt;
  &lt;li&gt;Retorna um objeto do tipo &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;PreservedAnalyses&lt;/code&gt;, que será explicado mais pra frente.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Por fim, note que estamos declarando a classe dentro do &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;namespace llvm&lt;/code&gt;. Fazemos isso porque o passe precisa ser declarado como uma classe dentro deste namespace para ser devidamente integrado à LLVM (portanto ficando algo como &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;llvm::MeuPasse&lt;/code&gt; quando “visto de fora”).&lt;/p&gt;

&lt;p&gt;Agora, tendo explicado a declaração da classe, vamos ver a implementação da função &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;run&lt;/code&gt;.&lt;/p&gt;

&lt;h4 id=&quot;meupassecpp&quot;&gt;MeuPasse.cpp&lt;/h4&gt;

&lt;p&gt;Vamos lembrar o que queremos fazer nesse passe. Para cada função, queremos imprimir:&lt;/p&gt;
&lt;ul&gt;
  &lt;li&gt;O nome da função; e&lt;/li&gt;
  &lt;li&gt;A quantidade de blocos básicos dela.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Para nossa sorte, todas essas informações podem ser facilmente acessadas e, dessa forma, o código se torna simples:&lt;/p&gt;

&lt;div class=&quot;language-cpp highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;cp&quot;&gt;#include&lt;/span&gt; &lt;span class=&quot;cpf&quot;&gt;&quot;MeuPasse.h&quot;&lt;/span&gt;&lt;span class=&quot;cp&quot;&gt;
&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;using&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;namespace&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;llvm&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;

&lt;span class=&quot;n&quot;&gt;PreservedAnalyses&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;MeuPasse&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;run&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Function&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;amp;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;F&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
                                &lt;span class=&quot;n&quot;&gt;FunctionAnalysisManager&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;amp;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;FAM&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;outs&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;lt;&amp;lt;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;F&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;getName&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;lt;&amp;lt;&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot; &quot;&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;lt;&amp;lt;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;F&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;size&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;lt;&amp;lt;&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;se&quot;&gt;\n&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;PreservedAnalyses&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;all&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;();&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Nessa função, estamos utilizando a função &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;outs()&lt;/code&gt;, que usa o formato de saída da LLVM. Esse formato é quase equivalente ao da função &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;std::cout&lt;/code&gt; da biblioteca &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;iostream&lt;/code&gt;, mas otimizado para lidar com os tipos da LLVM, sendo capaz de lidar com o tipo &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;StringRef&lt;/code&gt;, que é o tipo de retorno da função &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;getName()&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;A método &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;getName()&lt;/code&gt; da classe &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Function&lt;/code&gt; retorna o nome da função, enquanto que o método &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;size()&lt;/code&gt; retorna o número de blocos básicos da função.&lt;/p&gt;

&lt;p&gt;Por fim, retornamos &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;PreservedAnalyses::all()&lt;/code&gt;, então vamos explicar o que é o tipo &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;PreservedAnalyses&lt;/code&gt;. Esse tipo representa um conjunto de análises que afirmamos que nosso passe preserva. Nesse contexto, a função &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;all()&lt;/code&gt; indica que nosso passe garante que &lt;strong&gt;todas&lt;/strong&gt; as análises são preservadas.&lt;/p&gt;

&lt;p&gt;Num passe de análise, normalmente é garantido que todas as análises são preservadas, porém quando lidarmos com passes de transformação, existe sim a possibilidade de algumas análises não serem preservadas.&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;Extra: para ir além do básico do básico, vou mostrar como iterar pelos blocos básicos da função para obter o número de instruções presentes na função:&lt;/p&gt;
  &lt;div class=&quot;language-cpp highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;kt&quot;&gt;int&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;num_instr&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;for&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;BasicBlock&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;amp;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;BB&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;F&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;num_instr&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;+=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;BB&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;size&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;();&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;outs&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;lt;&amp;lt;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;num_instr&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;lt;&amp;lt;&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;se&quot;&gt;\n&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;  &lt;/div&gt;
&lt;/blockquote&gt;

&lt;h4 id=&quot;meupasseplugincpp&quot;&gt;MeuPassePlugin.cpp&lt;/h4&gt;

&lt;p&gt;Agora, vamos “registrar” o passe que acabamos de implementar, afinal queremos ser capazes de executar ele. Para isso, vamos implementar um monte de código padrão que eu vou &lt;em&gt;tentar&lt;/em&gt; explicar pra que serve cada coisa. Vamos começar com as importações:&lt;/p&gt;

&lt;div class=&quot;language-cpp highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;cp&quot;&gt;#include&lt;/span&gt; &lt;span class=&quot;cpf&quot;&gt;&quot;MeuPasse.h&quot;&lt;/span&gt;&lt;span class=&quot;cp&quot;&gt;
#include&lt;/span&gt; &lt;span class=&quot;cpf&quot;&gt;&quot;llvm/Passes/PassBuilder.h&quot;&lt;/span&gt;&lt;span class=&quot;cp&quot;&gt;
#include&lt;/span&gt; &lt;span class=&quot;cpf&quot;&gt;&quot;llvm/Passes/PassPlugin.h&quot;&lt;/span&gt;&lt;span class=&quot;cp&quot;&gt;
&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;using&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;namespace&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;llvm&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Que não têm nada de especial. Agora, vamos para a função que registra o &lt;em&gt;pipeline&lt;/em&gt; do passe:&lt;/p&gt;

&lt;div class=&quot;language-cpp highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;kt&quot;&gt;bool&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;registerPipeline&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;StringRef&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;Name&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;FunctionPassManager&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;amp;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;FPM&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
                      &lt;span class=&quot;n&quot;&gt;ArrayRef&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;PassBuilder&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;PipelineElement&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Name&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;==&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;meu-passe&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;n&quot;&gt;FPM&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;addPass&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;MeuPasse&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;());&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;true&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;false&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Nessa função, estamos dizendo que, quando o &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;opt&lt;/code&gt; for executado pedindo para executar o passe &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;meu-passe&lt;/code&gt;, será registrado um pipeline composto pelo passe &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;MeuPasse()&lt;/code&gt;. Note que &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;MeuPasse()&lt;/code&gt; é a função construtora da classe &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;MeuPasse&lt;/code&gt; que definimos anteriormente. O valor de retorno da função indica se o passe &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;meu-passe&lt;/code&gt; foi encontrado ou não. Além disso, é possível definir um pipeline modificado com múltiplos passes, os quais serão executados na ordem em que forem adicionados.&lt;/p&gt;

&lt;div class=&quot;language-cpp highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;n&quot;&gt;PassPluginLibraryInfo&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;getMeuPasse&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;n&quot;&gt;LLVM_PLUGIN_API_VERSION&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;meu-passe&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
        &lt;span class=&quot;n&quot;&gt;LLVM_VERSION_STRING&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;[](&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;PassBuilder&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;amp;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;PB&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
            &lt;span class=&quot;n&quot;&gt;PB&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;registerPipelineParsingCallback&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;registerPipeline&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
        &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;};&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Aqui, estamos definindo uma função que diz como o passe deve ser carregado. O tipo &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;PassPluginLibraryInfo&lt;/code&gt; é, nesse caso, uma struct que contém a versão da API da LLVM do plugin, o nome do passe, a versão da LLVM, e uma função que registra a pipeline do passe (nesse caso, a função que implementamos acima).&lt;/p&gt;

&lt;p&gt;Por fim, indicamos como inicializar o plugin (que diz como o passe será carregado) com:&lt;/p&gt;

&lt;div class=&quot;language-cpp highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;k&quot;&gt;extern&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;C&quot;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;LLVM_ATTRIBUTE_WEAK&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;PassPluginLibraryInfo&lt;/span&gt;
&lt;span class=&quot;nf&quot;&gt;llvmGetPassPluginInfo&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;getMeuPasse&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;();&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Agora, vamos ver como compilar isso tudo.&lt;/p&gt;

&lt;h4 id=&quot;cmakeliststxt&quot;&gt;CMakeLists.txt&lt;/h4&gt;

&lt;p&gt;Vou supor que você já tenha o LLVM instalado e, mais especificamente, tenha compilado e instalado ele usando CMake.&lt;/p&gt;

&lt;p&gt;Caso não tenha (e esteja disposto a passar muito tempo vendo seu computador fritar) veja o &lt;a href=&quot;#apêndice-a---compilando-a-llvm-usando-cmake&quot;&gt;Apêndice A - Compilando a LLVM usando CMake&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Vamos começar o arquivo CMake com duas linhas obrigatórias, onde definimos a versão mínima do CMake necessária para compilar o projeto e o nome do projeto:&lt;/p&gt;

&lt;div class=&quot;language-cmake highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;nb&quot;&gt;cmake_minimum_required&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;VERSION 3.20&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;nb&quot;&gt;project&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;MeuPasseLegal&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Agora vem um monte de código pra dizer onde encontrar os cabeçalhos da LLVM e configurar algumas &lt;em&gt;flags&lt;/em&gt; de compilação. Inclusive, isso é meio padrão pra qualquer passe fora da árvore:&lt;/p&gt;

&lt;div class=&quot;language-cmake highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;nb&quot;&gt;set&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;CMAKE_CXX_STANDARD 17 CACHE STRING &lt;span class=&quot;s2&quot;&gt;&quot;&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;

&lt;span class=&quot;nb&quot;&gt;set&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;LLVM_INSTALL_DIR &lt;span class=&quot;s2&quot;&gt;&quot;&quot;&lt;/span&gt; CACHE PATH &lt;span class=&quot;s2&quot;&gt;&quot;LLVM installation directory&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;nb&quot;&gt;set&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;LLVM_CMAKE_CONFIG_DIR &lt;span class=&quot;s2&quot;&gt;&quot;&quot;&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;si&quot;&gt;${&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;LLVM_INSTALL_DIR&lt;/span&gt;&lt;span class=&quot;si&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;/lib/cmake/llvm/&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;nb&quot;&gt;list&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;APPEND CMAKE_PREFIX_PATH &lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;si&quot;&gt;${&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;LLVM_CMAKE_CONFIG_DIR&lt;/span&gt;&lt;span class=&quot;si&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;

&lt;span class=&quot;nb&quot;&gt;find_package&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;LLVM REQUIRED CONFIG&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;

&lt;span class=&quot;nb&quot;&gt;include_directories&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;si&quot;&gt;${&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;LLVM_INCLUDE_DIRS&lt;/span&gt;&lt;span class=&quot;si&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;

&lt;span class=&quot;nb&quot;&gt;if&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;NOT LLVM_ENABLE_RTTI&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;nb&quot;&gt;set&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;CMAKE_CXX_FLAGS &lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;si&quot;&gt;${&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;CMAKE_CXX_FLAGS&lt;/span&gt;&lt;span class=&quot;si&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt; -fno-rtti&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;nb&quot;&gt;endif&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;

&lt;span class=&quot;nb&quot;&gt;set&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;CMAKE_LIBRARY_OUTPUT_DIRECTORY &lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;si&quot;&gt;${&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;PROJECT_BINARY_DIR&lt;/span&gt;&lt;span class=&quot;si&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;/lib&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Depois, vamos mostrar como o CMake deve compilar nosso código. Primeiro, definimos uma biblioteca de nome &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;MeuPasse&lt;/code&gt; do tipo &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;MODULE&lt;/code&gt;, com as implementações do passe:&lt;/p&gt;

&lt;div class=&quot;language-cmake highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;nb&quot;&gt;add_library&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;MeuPasse MODULE
    lib/MeuPasse.cpp
    lib/MeuPassePlugin.cpp&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Por fim, dizemos onde a biblioteca &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;MeuPasse&lt;/code&gt; deve buscar os arquivos de cabeçalho:&lt;/p&gt;

&lt;div class=&quot;language-cmake highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;nb&quot;&gt;target_include_directories&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;MeuPasse PRIVATE
    &lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;si&quot;&gt;${&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;CMAKE_CURRENT_SOURCE_DIR&lt;/span&gt;&lt;span class=&quot;si&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;/include&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Dessa forma, permitimos que o arquivo &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;MeuPasse.cpp&lt;/code&gt; enxergue o cabeçalho &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;MeuPasse.h&lt;/code&gt; sem precisar descrever o caminho exato para ele (que, relativo a &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;MeuPasse.cpp&lt;/code&gt;, seria &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;../include/MeuPasse.h&lt;/code&gt;). Lembre que, quando incluímos este cabeçalho neste arquivo, o fizemos apenas com &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;#include &quot;MeuPasse.h&quot;&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Pronto, agora nós temos um passe implementado, com instruções de como registrar ele no pipeline de passes da LLVM, e um arquivo CMake configurado para compilar o passe. Vamos enfim testar se isso tudo está funcionando.&lt;/p&gt;

&lt;h3 id=&quot;testando-um-passe&quot;&gt;Testando um Passe&lt;/h3&gt;

&lt;p&gt;Vamos começar pelo mais importante, que é compilar o passe. Para isso, vamos utilizar o CMake para gerar os arquivos de configuração numa pasta chamada &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;build&lt;/code&gt;:&lt;/p&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;nb&quot;&gt;mkdir &lt;/span&gt;build
&lt;span class=&quot;nb&quot;&gt;cd &lt;/span&gt;build
cmake ..
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Agora, vamos compilar com &lt;em&gt;Unix Makefiles&lt;/em&gt; executando:&lt;/p&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;make
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Se tudo der certo (e você não tiver mexido na variável &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;CMAKE_LIBRARY_OUTPUT_DIRECTORY&lt;/code&gt;), o seu passe compilado estará no arquivo &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;lib/libMeuPasse.so&lt;/code&gt; dentro da pasta &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;build&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Agora queremos executar, certo? Bom, primeiro, precisamos de um código para isso. Lembre que fizemos um passe para analisar &lt;strong&gt;códigos&lt;/strong&gt;. Vamos usar o código a seguir (que vou nomeá-lo preguiçosamente de &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;a.c&lt;/code&gt;), com uma função recursiva pra calcular o n-ésimo termo da sequência de Fibonacci recursivamente:&lt;/p&gt;

&lt;div class=&quot;language-c highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;cp&quot;&gt;#include&lt;/span&gt; &lt;span class=&quot;cpf&quot;&gt;&amp;lt;stdio.h&amp;gt;&lt;/span&gt;&lt;span class=&quot;cp&quot;&gt;
&lt;/span&gt;
&lt;span class=&quot;kt&quot;&gt;int&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;f&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;int&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;x&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;x&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;2&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;x&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;f&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;x&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;-&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;+&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;f&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;x&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;-&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;2&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;

&lt;span class=&quot;kt&quot;&gt;int&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;main&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;printf&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;%d&lt;/span&gt;&lt;span class=&quot;se&quot;&gt;\n&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;f&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;5&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;));&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Vamos compilar este código para LLVM IR usando o clang com os seguintes parâmetros:&lt;/p&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;clang a.c &lt;span class=&quot;nt&quot;&gt;-Xclang&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;-disable-O0-optnone&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;-S&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;-emit-llvm&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;-o&lt;/span&gt; a.ll
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Os parâmetros &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;-Xclang -disable-O0-optnone&lt;/code&gt; vão impedir que a LLVM marque as funções deste código como não otimizáveis, o que impediria nosso passe de executar nelas. Já os parâmetros &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;-S -emit-llvm&lt;/code&gt; fazem com que o clang gere o código em LLVM IR. O código gerado deve ficar algo como:&lt;/p&gt;

&lt;div class=&quot;language-llvm highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;p&quot;&gt;...&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;define&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;dso_local&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;i32&lt;/span&gt; &lt;span class=&quot;vg&quot;&gt;@f&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;i32&lt;/span&gt; &lt;span class=&quot;err&quot;&gt;noundef&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;%0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;vg&quot;&gt;#0&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;p&quot;&gt;...&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;br&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;i1&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;%5&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;label&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;%6&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;label&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;%8&lt;/span&gt;

&lt;span class=&quot;m&quot;&gt;6&lt;/span&gt;&lt;span class=&quot;err&quot;&gt;:&lt;/span&gt;  &lt;span class=&quot;c1&quot;&gt;; preds = %1&lt;/span&gt;
  &lt;span class=&quot;p&quot;&gt;...&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;br&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;label&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;%16&lt;/span&gt;

&lt;span class=&quot;m&quot;&gt;8&lt;/span&gt;&lt;span class=&quot;err&quot;&gt;:&lt;/span&gt;  &lt;span class=&quot;c1&quot;&gt;; preds = %1&lt;/span&gt;
  &lt;span class=&quot;p&quot;&gt;...&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;br&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;label&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;%16&lt;/span&gt;

&lt;span class=&quot;m&quot;&gt;16&lt;/span&gt;&lt;span class=&quot;err&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;c1&quot;&gt;; preds = %8, %6&lt;/span&gt;
  &lt;span class=&quot;nv&quot;&gt;%17&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;load&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;i32&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;err&quot;&gt;ptr&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;%2&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;align&lt;/span&gt; &lt;span class=&quot;m&quot;&gt;4&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;ret&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;i32&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;%17&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;

&lt;span class=&quot;k&quot;&gt;define&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;dso_local&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;i32&lt;/span&gt; &lt;span class=&quot;vg&quot;&gt;@main&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt; &lt;span class=&quot;vg&quot;&gt;#0&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;p&quot;&gt;...&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;ret&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;i32&lt;/span&gt; &lt;span class=&quot;m&quot;&gt;0&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;

&lt;span class=&quot;p&quot;&gt;...&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Perceba que a função &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;f&lt;/code&gt; possui 4 blocos básicos (0, que é omitido, 6, 8 e 16) e a função &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;main&lt;/code&gt; possui apenas 1 bloco básico (0, que é omitido). Agora, vamos executar nosso passe com o seguinte comando:&lt;/p&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;opt &lt;span class=&quot;nt&quot;&gt;-disable-output&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;-load-pass-plugin&lt;/span&gt; lib/libMeuPasse.so &lt;span class=&quot;nt&quot;&gt;-passes&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;meu-passe&quot;&lt;/span&gt; a.ll
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Note que, como nosso passe não está incluso no conjunto de passes padrões da LLVM, precisamos carregar o arquivo compilado do nosso passe com &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;-load-pass-plugin&lt;/code&gt;. Além disso, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;-disable-output&lt;/code&gt; fala para o &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;opt&lt;/code&gt; não imprimir o arquivo transformado como um código binário. A saída do passe com a função &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;outs()&lt;/code&gt; não é afetada por essa &lt;em&gt;flag&lt;/em&gt;, por mais contraintuitivo que pareça.&lt;/p&gt;

&lt;p&gt;Ao executar, a saída esperada é:&lt;/p&gt;
&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;f 4
main 1
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Nosso passe conseguiu analisar o programa, então parece que funcionou!&lt;/p&gt;

&lt;h3 id=&quot;conclusão&quot;&gt;Conclusão&lt;/h3&gt;

&lt;p&gt;Enfim, temos um passe da LLVM. Note que esse é um passe de análise muito simples, que não nos diz quase nada. De todo modo, a ideia era tentar explicar o conceito dos passes e como desenvolver um, mostrando como declarar ele, implementar as funções necessárias, integrar ele à LLVM e configurar o CMake para compilar o passe.&lt;/p&gt;

&lt;p&gt;Mas isso é só o começo. Na próxima postagem sobre construção de passes LLVM, vou tentar explicar como fazer um passe de transformação de código que faz algo um pouco mais útil (Spoiler: vamos contar quantas vezes cada aresta do CFG é atravessada).&lt;/p&gt;

&lt;p&gt;Caso tenha dúvidas e queira conversar sobre o assunto, lembre que meu email está no &lt;a href=&quot;/about&quot;&gt;sobre&lt;/a&gt;. Até (espero) breve.&lt;/p&gt;

&lt;h3 id=&quot;referências&quot;&gt;Referências&lt;/h3&gt;

&lt;ul&gt;
  &lt;li&gt;https://llvm.org/&lt;/li&gt;
  &lt;li&gt;https://llvm.org/doxygen/&lt;/li&gt;
&lt;/ul&gt;

&lt;h3 id=&quot;apêndice-a---compilando-a-llvm-usando-cmake&quot;&gt;Apêndice A - Compilando a LLVM usando CMake&lt;/h3&gt;

&lt;p&gt;Aqui eu vou mostrar como baixar, configurar, compilar e instalar a LLVM usando CMake no Linux. Não faço ideia de como isso funciona no Windows ou no Mac (apesar que esse é Unix-based pelo menos).&lt;/p&gt;

&lt;p&gt;Além disso, estarei mostrando aqui como instalar a LLVM 18.1.8, que é meio antiga (a versão mais atualizada, que não está em pre-release, é a 20.1.8), mas é a versão que eu uso no mestrado.&lt;/p&gt;

&lt;p&gt;Começamos baixando o código fonte da LLVM com&lt;/p&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;git clone https://github.com/llvm/llvm-project/ &lt;span class=&quot;nt&quot;&gt;--depth&lt;/span&gt; 1 &lt;span class=&quot;nt&quot;&gt;--branch&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;release/18.x
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Recomendo utilizar &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;--depth 1&lt;/code&gt; se você não pretende navegar nas diferentes branches e releases da LLVM.&lt;/p&gt;

&lt;p&gt;Agora, dentro da pasta &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;llvm-project&lt;/code&gt;, configuramos o projeto com (assumo que você possua &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;gcc&lt;/code&gt; e &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;g++&lt;/code&gt; instalados, e esteja numa arquitetura X86):&lt;/p&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;nb&quot;&gt;mkdir &lt;/span&gt;build
&lt;span class=&quot;nb&quot;&gt;cd &lt;/span&gt;build
cmake &lt;span class=&quot;nt&quot;&gt;-G&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;Unix Makefiles&quot;&lt;/span&gt; ../llvm &lt;span class=&quot;se&quot;&gt;\\&lt;/span&gt;
    &lt;span class=&quot;nt&quot;&gt;-DLLVM_TARGETS_TO_BUILD&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;X86 &lt;span class=&quot;nt&quot;&gt;-DCMAKE_BUILD_TYPE&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;Release &lt;span class=&quot;se&quot;&gt;\\&lt;/span&gt;
    &lt;span class=&quot;nt&quot;&gt;-DCMAKE_C_COMPILER&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;gcc &lt;span class=&quot;nt&quot;&gt;-DCMAKE_CXX_COMPILER&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;g++ &lt;span class=&quot;se&quot;&gt;\\&lt;/span&gt;
    &lt;span class=&quot;nt&quot;&gt;-DCMAKE_ASM_COMPILER&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;gcc &lt;span class=&quot;se&quot;&gt;\\&lt;/span&gt;
    &lt;span class=&quot;nt&quot;&gt;-DLLVM_ENABLE_PROJECTS&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;clang;lld&quot;&lt;/span&gt; &lt;span class=&quot;se&quot;&gt;\\&lt;/span&gt;
    &lt;span class=&quot;nt&quot;&gt;-DCMAKE_INSTALL_PREFIX&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;/usr/local
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Opcional: se você tiver o sistema de compilação &lt;a href=&quot;https://ninja-build.org/&quot;&gt;Ninja&lt;/a&gt; (recomendo muito), você pode configurar pra compilar a LLVM usando ele com &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;-G Ninja&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Com isso, o CMake irá configurar os arquivos de compilação. Agora, você pode compilar isso tudo usando:&lt;/p&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;make &lt;span class=&quot;nt&quot;&gt;-jn&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Aqui, troque &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;n&lt;/code&gt; pela quantidade de núcleos da CPU que você quer usar. Se você estiver usando Ninja, você pode executar apenas &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;ninja&lt;/code&gt; que ele irá compilar pra você usando todos os núcleos do seu processador (caso você esteja vendo sua memória RAM sumir, vale a dica do &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;-jn&lt;/code&gt; também pra limitar a quantidade de núcleos compilando).&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;Pode acontecer da compilação falhar. Minha recomendação é mandar compilar de novo quantas vezes forem necessárias. Já teve caso em que eu mandei compilar a LLVM com algo como:&lt;/p&gt;
  &lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;k&quot;&gt;for &lt;/span&gt;i &lt;span class=&quot;k&quot;&gt;in &lt;/span&gt;0..100&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;do &lt;/span&gt;ninja&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;done&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;  &lt;/div&gt;
  &lt;p&gt;E não ironicamente isso funcionou, com ele terminando de compilar na tentativa 50 e alguma coisa. Isso acontece porque, como está sendo compilado em paralelo (e o projeto não é tão bem configurado), ele tenta compilar alguma biblioteca que depende de outra biblioteca que ainda está sendo compilada, aí obviamente dá erro.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Quando terminar de compilar (e vai demorar muito tempo, vai por mim), você pode instalar com&lt;/p&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;nb&quot;&gt;sudo &lt;/span&gt;make &lt;span class=&quot;nb&quot;&gt;install&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Ou &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;sudo ninja install&lt;/code&gt;. Com a configuração do &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;DCMAKE_INSTALL_PREFIX=/usr/local&lt;/code&gt;, esse comando irá inserir os binários em &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;/usr/local/bin&lt;/code&gt;, os cabeçalhos das classes em &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;/usr/local/include&lt;/code&gt; e as implementações das classes em &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;/usr/local/lib&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Se quiser ver se deu tudo certo, basta rodar &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;clang --version&lt;/code&gt; e ver se ele imprime algo como:&lt;/p&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;clang version 18.1.8 ...
...
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
</description>
        <pubDate>09/08/25</pubDate>
        <link>https://elisa-frohlich.github.io/llvm/2025/08/09/writing-llvm-pass.html</link>
        <guid isPermaLink="true">https://elisa-frohlich.github.io/llvm/2025/08/09/writing-llvm-pass.html</guid>
        
        
        <category>LLVM</category>
        
      </item>
      
    
     
      <item>
        <title>Introdução a Análise Estática de Programas - Representação Intermediária</title>
        <description>&lt;h3 id=&quot;introdução&quot;&gt;Introdução&lt;/h3&gt;

&lt;p&gt;Bem, hora de escrever algum conteúdo de fato nesse site.&lt;/p&gt;

&lt;p&gt;Eu queria começar falando direto sobre alguma coisa que eu estou trabalhando no mestrado mas, parando pra pensar, eu abordaria conteúdos que algumas pessoas provavelmente nunca sequer ouviram falar, e eu trataria com a naturalidade que eu normalmente trato vendo eles todos os dias no mestrado.&lt;/p&gt;

&lt;p&gt;Por isso, decidi iniciar aqui uma série de postagens introdutórias sobre Análise Estática de Programas, que é uma parte muito importante de otimização de compiladores, e que provavelmente eu vou usar muitos conteúdos dessa área em postagens futuras (talvez tudo seja sobre análise estática, mas espero que não).&lt;/p&gt;

&lt;p&gt;Como um pontapé inicial dessa série de postagens, eu acho crucial falar de um assunto muito importante, que são as representações intermediárias (RI). De modo geral, uma representação intermediária é uma forma como o código é representado durante as etapas de compilação até que ele vire código de máquina. Normalmente, uma representação intermediária vai ser independente da arquitetura (x86, arm, risc-v, etc…) para a qual o código está sendo compilado, e tais representações permitem visualizar pontos onde um código pode ser otimizado.&lt;/p&gt;

&lt;p&gt;Para começar tratando de RI, vou começar falando sobre duas representações muito simples (pelo menos do meu ponto de vista, e eu sou péssimo para julgar a complexidade de algo): Código de Três Endereços (Three Address Code) e Grafo de Fluxo de Controle&lt;/p&gt;

&lt;p&gt;Uma pequena observação: eu não vou terminar essa postagem de primeira. Conforme eu for vendo a necessidade, eu vou adicionando novas representações intermediárias aqui e vou apontando nas postagens que usarem esses novos conteúdos.&lt;/p&gt;

&lt;h3 id=&quot;código-de-três-endereços&quot;&gt;Código de Três Endereços&lt;/h3&gt;

&lt;p&gt;A RI de Código de Três Endereços (tradução livre feita por mim, não me recordo de ver na literatura alguma tradução para esse termo) é uma representação onde cada instrução do código fonte é traduzida para uma sequência de instruções que possuem, no máximo, três endereços: dois para operandos e um para o resultado, que é onde o valor da operação será armazenado. Vale ressaltar que o código final lembra um pouco um código assembly, e de fato a tradução dessa representação para código de máquina (com muitas ressalvas aqui, porque existe muita otimização feita em cima desse código) passa muito pela adaptação dos operadores para instruções específicas de cada arquitetura.&lt;/p&gt;

&lt;p&gt;Algumas coisas importantes sobre essa RI:&lt;/p&gt;
&lt;ul&gt;
  &lt;li&gt;Ela se utiliza de diversas variáveis temporárias para armazenar valores;&lt;/li&gt;
  &lt;li&gt;As instruções são ordenadas na ordem que elas devem ser executadas, e supostamente deveriam ser executadas uma após a outra, a menos que tenha uma instrução de pulo ou ramificação;&lt;/li&gt;
  &lt;li&gt;Ela insere etiquetas no código para manter a informação do fluxo de controle do programa. Vale ressaltar que essas etiquetas não são comandos executáveis.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Dadas essas propriedades, podemos definir as seguintes operações:&lt;/p&gt;
&lt;ul&gt;
  &lt;li&gt;Atribuição: &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;a = b&lt;/code&gt;&lt;/li&gt;
  &lt;li&gt;Operação unária: &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;a = op b&lt;/code&gt;&lt;/li&gt;
  &lt;li&gt;Operação binária: &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;a = b op c&lt;/code&gt; ou &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;a = op b c&lt;/code&gt;&lt;/li&gt;
  &lt;li&gt;Ramificação: &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;br cmp L1 L2&lt;/code&gt;&lt;/li&gt;
  &lt;li&gt;Pulo: &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;jmp L&lt;/code&gt;&lt;/li&gt;
  &lt;li&gt;Retorno: &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;ret a&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Onde:&lt;/p&gt;
&lt;ul&gt;
  &lt;li&gt;a, b, c e cmp são variáveis (cmp é uma variável booleana)&lt;/li&gt;
  &lt;li&gt;op é um operador (+, -, *, /, %, etc…)&lt;/li&gt;
  &lt;li&gt;L, L1 e L2 são etiquetas&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Para exemplificar, vamos supor o seguinte código em C:&lt;/p&gt;

&lt;div class=&quot;language-c highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;kt&quot;&gt;int&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;foo&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;kt&quot;&gt;int&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;a&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;b&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;c&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;a&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;2&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;b&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;a&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;2&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;b&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;lt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;a&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;3&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;n&quot;&gt;c&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;5&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;else&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;n&quot;&gt;c&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;3&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;a&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;+&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;b&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;+&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;c&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Dada a definição acima, esse código seria traduzido para o seguinte Código de Três Endereços:&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;a = 2
b = a * 2
t1 = a * 3
cmp = b &amp;lt;= t1
br cmp L1 L2
L1:
    c = 5
    jmp L3
L2:
    c = 3
L3:
    r = a + b
    r = r + c
    ret r
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h3 id=&quot;grafo-de-fluxo-de-controle-gfc&quot;&gt;Grafo de Fluxo de Controle (GFC)&lt;/h3&gt;

&lt;p&gt;Antes de continuar, acho válido definir o que é o fluxo de controle de um programa. Basicamente, o fluxo de controle é a ordem em que as instruções são executadas.&lt;/p&gt;

&lt;p&gt;A partir da RI de Código de Três Endereços, nós podemos derivar uma outra representação intermediária que facilita a visualização do fluxo de controle do nosso código. Essa RI é chamada de Grafo de Fluxo de Controle. Portanto, como é um grafo (direcionado, nesse caso), sabemos que ele precisa de um conjunto de vértices e um conjunto de arestas. Portanto, dado um Código de Três Endereços, o que é vértice e o que é aresta nele?&lt;/p&gt;

&lt;p&gt;Bom, eu espero que você ainda lembre que o Código de Três Endereços mantém as instruções na ordem que elas devem ser executadas (com exceção de ramificações e pulos). Portanto, se nós temos uma sequência de instruções que não alteram o fluxo de controle do programa (isto é, não fazem pulos para outras partes do código), você concorda que nós podemos agrupar estas instruções em uma estrutura tipo, sei lá, um vértice?&lt;/p&gt;

&lt;p&gt;Pois bem, esses vértices num GFC são o que chamamos de &lt;strong&gt;blocos básicos&lt;/strong&gt; de um programa. De fato, todas as instruções de um bloco básico não alteram o fluxo de controle do programa, com exceção da última instrução, que pode tanto terminar o programa (ou seja, uma instrução de retorno) ou mudar o fluxo de controle (ou seja, uma instrução de ramificação ou pulo).&lt;/p&gt;

&lt;p&gt;Bom, nós definimos qual é a última instrução de um bloco básico, mas não seria mais fácil saber também qual seria a primeira instrução de cada bloco básico? Sim, e de fato, existe até uma denominação para essas instruções: &lt;strong&gt;cabeçalhos de bloco básico&lt;/strong&gt; (tradução livre de novo, o termo em inglês é &lt;em&gt;basic block headers&lt;/em&gt;). Nas nossas definições de Código de Três Endereços, nós temos duas definições para cabeçalhos de bloco básico:&lt;/p&gt;
&lt;ul&gt;
  &lt;li&gt;a primeira instrução de um programa é um cabeçalho de um bloco básico;&lt;/li&gt;
  &lt;li&gt;a instrução que sucede uma etiqueta é um cabeçalho de um bloco básico.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Agora que temos o conjunto de vértices do nosso grafo definido, precisamos definir o conjunto de arestas que, lembrando, são direcionadas. Para isso, vamos definir as arestas que saem dos blocos. Ou melhor, começaremos definindo aquelas que não saem, isto porque o bloco básico que termina o programa (cuja última instrução é um retorno) não possuí nenhuma aresta de saída. Para os outros blocos básicos, basta olhar para as etiquetas para onde as últimas instruções apontam, e se lembrar que essas etiquetas indicam quem são os blocos básicos. Então, será criada uma aresta com origem no bloco básico que tem essa instrução de modificação de fluxo de controle e com destino no bloco básico para o qual essa modificação de fluxo é dirigida.&lt;/p&gt;

&lt;p&gt;E bem, para exemplificar, eu gostaria muito de usar uma imagem aqui, mas eu não estou muito bem acostumado com o Jekyll ainda, então eu vou usar de um recurso muito simples (mas que fica péssimo em telas pequenas): ASCII art. Puxando do nosso exemplo de Código de Três Endereços, eu vou separar aquele código em blocos básicos e renomear as etiquetas para o nome dos blocos básicos para onde elas apontam:&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;-------------- bb0
a = 2
b = a * 2
t1 = a * 3
cmp = b &amp;lt;= t1
br cmp bb1 bb2
--------------

-------------- bb1
c = 5
jmp bb3
--------------

-------------- bb2
c = 3
--------------

-------------- bb3
r = a + b
r = r + c
ret r
--------------
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Agora, para representar as arestas, vou só usar os nomes. E lembre-se que as arestas têm direção, que nesse caso é de cima para baixo.&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;    bb0
    / \
  bb1  bb2
    \ /
    bb3
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Ahnn, isso ficou pior do que eu esperava, e eu certamente vou melhorar isso depois, mas espero que o exemplo tenha ficado claro sobre como que GFCs funcionam.&lt;/p&gt;

&lt;h3 id=&quot;conclusão-parcial&quot;&gt;Conclusão (Parcial)&lt;/h3&gt;

&lt;p&gt;Acho que eu cobri o básico (e talvez o essencial) de Código de Três Endereços e Grafo de Fluxo de Controle nessa postagem. E de verdade, eu espero que tenha dado para entender, porque esse assunto é muito importante para várias coisas que eu vou escrever aqui.&lt;/p&gt;

&lt;p&gt;Não sei com qual frequência que eu vou escrever postagens por aqui, então não crie expectativas de ver novas postagens, afinal o mestrado consome tempo, mas talvez nos veremos em breve. De qualquer forma, se quiser conversar comigo sobre o que eu escrevi aqui… bem, meu email tá no &lt;a href=&quot;/about&quot;&gt;sobre&lt;/a&gt;.&lt;/p&gt;

&lt;h3 id=&quot;referências&quot;&gt;Referências&lt;/h3&gt;

&lt;p&gt;Para escrever essa postagem, eu usei como material principal as &lt;a href=&quot;https://homepages.dcc.ufmg.br/~fernando/classes/dcc888/ementa/&quot;&gt;aulas do meu orientador sobre Análise Estática de Programas&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Se você quiser mais materiais sobre o assunto, recomendo a página da &lt;a href=&quot;https://homepages.dcc.ufmg.br/~fernando/classes/dcc888/biblio.html&quot;&gt;bibliografia do mesmo curso&lt;/a&gt;.&lt;/p&gt;
</description>
        <pubDate>03/11/24</pubDate>
        <link>https://elisa-frohlich.github.io/compilers/2024/11/03/intermediate-representation.html</link>
        <guid isPermaLink="true">https://elisa-frohlich.github.io/compilers/2024/11/03/intermediate-representation.html</guid>
        
        
        <category>Compilers</category>
        
      </item>
      
    
     
      <item>
        <title>Bem-vindo ao meu blog pessoal!</title>
        <description>&lt;p&gt;(Isso é apenas um ctrl+c ctrl+v do sobre)&lt;/p&gt;

&lt;p&gt;Olá, esse é meu blog pessoal. Nele, eu vou tentar escrever sobre algumas coisas que eu vou aprendendo e achando interessante durante os meus estudos. Como atualmente eu estou trabalhando com compiladores no mestrado, é esperado mais postagens voltadas para essa área, porém eu devo tentar escrever sobre outras coisas que eu acho interessante. Além disso, por ser brasileiro, mas a área ter a maior parte dos conteúdos voltados para inglês, eu vou tentar esse blog como um site bilíngue, com uma versão em inglês e outra em português para cada postagem (e, por via de regra, a versão em português deve estar melhor escrita, porque eu domino muito mais o idioma).&lt;/p&gt;

&lt;p&gt;Sobre mim:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;Graduado em ciência da computação pela Universidade do Estado de Santa Catarina (UDESC)&lt;/li&gt;
  &lt;li&gt;Mestrando em ciência da computação na Universidade Federal de Minas Gerais (UFMG), trabalhando no Laboratório de Compiladores (&lt;a href=&quot;https://lac-dcc.github.io/&quot;&gt;LAC&lt;/a&gt;)&lt;/li&gt;
  &lt;li&gt;Programador competitivo aposentado:
    &lt;ul&gt;
      &lt;li&gt;2 participações em finais brasileira da Maratona de Programação&lt;/li&gt;
      &lt;li&gt;1 medalha de bronze na XXVII final brasileira&lt;/li&gt;
      &lt;li&gt;2 vezes o melhor do sul na final brasileira&lt;/li&gt;
      &lt;li&gt;Ganhador das duas primeiras maratonas sul brasileiras de programação&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Minhas redes sociais (se é que posso chamar de rede social):&lt;/p&gt;

&lt;p&gt;&lt;a href=&quot;https://github.com/elisa-frohlich&quot;&gt;github&lt;/a&gt;&lt;/p&gt;
</description>
        <pubDate>02/11/24</pubDate>
        <link>https://elisa-frohlich.github.io/about/2024/11/02/welcome-to-my-blog.html</link>
        <guid isPermaLink="true">https://elisa-frohlich.github.io/about/2024/11/02/welcome-to-my-blog.html</guid>
        
        
        <category>About</category>
        
      </item>
      
    
  </channel>
</rss>
