LoginSignup
3
2

More than 1 year has passed since last update.

【Clang/LLVM】CFGの生成

Last updated at Posted at 2022-09-18

はじめに

きつねさんの本を用いてLLVMの勉強を始めたところ、LLVMのVersion違いのために、CFGの生成に失敗してしまいました。同じ問題に直面する方がいるかと思いましたので、この記事では、LLVMのVersion 14.0.6(2022年8月時点の最新)で確認したCFGの生成方法を紹介します。尚、今回生成するCFGは単純な分岐処理を行うプログラムを対象としたもので、最終的に以下のように表示されます。
main.png

対象読者

LLVMに関する学習を開始した方

目標

CFGの生成ができるようになること

目次

  1. LLVMとは
  2. 環境構築
  3. CFGの生成
  4. まとめ

本文

1. LLVMとは

1.1 概要

LLVMは、プログラミング言語開発における主にミドルエンドとバックエンドの処理に必要な機能(コンパイル時、リンク時、実行時の最適化などの複雑な処理に関する機能)をAPIとして提供することで、プログラミング言語の開発を支援します。

また、下記の図に示すように、LLVMを用いたプログラミング言語開発では、ミドルエンドが抽象化されているために、複数のフロントエンド、複数のバックエンドに対応することができます。

Screenshot from 2022-08-14 10-52-21.png
引用元:Intro to LLVM

1.2 CFG (Control Flow Graph)

LLVMで解析する対象のプログラムはBasic Blockと呼ばれる単位に分解されます。
Basic Blockとは、1つの入口と1つの出口を備え、内部に命令を含むコードのセクションです。
CFGは、1つ以上のBasic Blockの入口と出口を矢印でつないだグラフであり、プログラムの制御フローを可視化したものです。

2. 環境構築

2.1 事前準備

今回の環境を示します。

  • OS
    Ubuntu 20.04.3 LTS

  • Kernel
    5.15.0-46-generic

  • Tool
    clang 10.0.0-4ubuntu1
    cmake 3.16.3
    gcc 9.4.0
    python 3.8.10
    make 4.2.1

2.2 LLVMビルド

LLVMをビルドします。

/bin/bash
git clone https://github.com/llvm/llvm-project.git
cd llvm-project
mkdir build 
cd build
cmake -DLLVM_ENABLE_PROJECTS=clang -DCMAKE_BUILD_TYPE=Release -G "Unix Makefiles" ../llvm
make
make check-clang

2.3 環境変数の設定

buildしたbinのパスを通します。
また、includeへのパスを変数として定義しておきます。

.bashrc
# llvm binのパス : $HOME/llvm-project/build/bin
export LLVM_BIN_PATH = "$HOME/llvm-project/build/bin"
export PATH=$PATH:$LLVM_BIN_PATH
# llvm includeのパス : $HOME/llvm-project/llvm/include
export LLVM_INC_PATH = "$HOME/llvm-project/llvm/include"

3. CFGの生成

確認用に、分岐のあるソースコードを準備します。

main.cpp
#include <stdio.h>

int main(int argc, char ** argv) {
	int i;
	if(argc == 0){
		i = 1;
	}else{
		i=2;
	}
	return 0;
}

以下のコマンドを実行し、中間表現のコード(LLVM IR)を生成します。

/bin/bash
clang++ -S -emit-llvm -I ${LLVM_INC_PATH} -o main.ll main.cpp

以下のコマンドを実行し、CFGの情報を隠しファイル(.main.dot)として生成します。

/bin/bash
opt -dot-cfg main.ll -disable-output -enable-new-pm=0

これまでに生成されたファイルを確認します。

/bin/bash
ls -a
main.cpp  .main.dot  main.ll

以下のコマンドを実行し、png形式の画像を生成します。

/bin/bash
dot -Tpng .main.dot -o main.png

以下のコマンドを実行し、png形式に変換した画像を表示します。

/bin/bash
eog main.png 

冒頭にも示しましたが、無事に表示されることが確認できました。
main.png

4. まとめ

LLVMにおけるCFGの生成方法について紹介しました。

参考文献

LLVM Documentation
LLVM Control Flow Graph
きつねさんでもわかるLLVM ~コンパイラを自作するためのガイドブック

3
2
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
3
2