LLVM Commands
TyeYeah Lv4

Here are collections of LLVM commands about compilation using clang and some graph structure geneartion.

LLVM Compilation

To walk through the whole compilation using clang, first take the source a.c:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
#include <stdio.h>

int max(int num1, int num2);

int main ()
{
int a = 100;
int b = 200;
int ret;

ret = max(a, b);

printf( "Max value is : %d\n", ret );

return 0;
}

int max(int num1, int num2)
{
int result;

if (num1 > num2)
result = num1;
else
result = num2;

return result;
}

And start to compile:

1
2
3
4
5
6
7
8
9
10
$ clang -E a.c -o a.i   # pre-processing
$ clang -S a.i -o a.s # compiling
$ clang -c a.s -o a.o # assemble
$ clang a.o # linking
$ ./a.out
Max value is : 200
# or
$ clang -save-temps a.c -o a.out # save all intermediate temp files
$ ls
a.bc a.c a.i a.o a.out a.s

Here we can find an extra a.bc, which cannot be produced by gcc.
Actually LLVM compilation process includes following file formats:

  1. xxx.c, Source code.
  2. xxx.bc, Assembly LLVM bitcode
  3. xxx.ll, Textual LLVM bitcode
  4. xxx.s, Assembly code
  5. xxx.out, Executable

Like the image:
LLVM file formats

From a.c we go through the whole file format converting cycle. To get a.bc:

1
$ clang -emit-llvm -c a.c -o a.bc

And to get a.ll:

1
$ clang -emit-llvm -S a.c -o a.ll

They can convert to each other by:

1
2
$ llvm-dis a.bc -o a.ll     # a.bc -> a.ll
$ llvm-as a.ll -o a.bc # a.ll -> a.bc

We can use llc to convert a.bc to a.s, and even visualize SelectionDAG on LLVM debug version:

1
2
3
4
$ llc a.bc -o a.s
$ llc -view-xxxxxx-dags a.ll
# "--help" to see all DAG generation options,
# and the graph saved in "dot"

And to execute a.bc directly:

1
2
$ lli a.bc
Max value is : 200

Actually the intermediate files can be converted to exetuable a.out by using clang directly:

1
$ clang a.s/a.c/a.xxx a.out

LLVM Graph Structure Generation

LLVM framework is so powerful, that it can automatically generate control flow graph, and we can visualize it easily.
First we generate CFG using opt:

1
2
3
4
5
$ opt -enable-new-pm=0 -analyze -dot-cfg-only a.ll
Writing '.main.dot'...
Printing analysis 'Print CFG of function to 'dot' file (with no function bodies)' for function 'main':
Writing '.max.dot'...
Printing analysis 'Print CFG of function to 'dot' file (with no function bodies)' for function 'max':

And we get .main.dot and .max.dot:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
$ cat .main.dot
digraph "CFG for 'main' function" {
label="CFG for 'main' function";

Node0xe3b210 [shape=record,color="#b70d28ff", style=filled, fillcolor="#b70d2870",label="{%0}"];
}

$ cat .max.dot
digraph "CFG for 'max' function" {
label="CFG for 'max' function";

Node0xe3c470 [shape=record,color="#b70d28ff", style=filled, fillcolor="#b70d2870",label="{%2|{<s0>T|<s1>F}}"];
Node0xe3c470:s0 -> Node0xe3c5e0;
Node0xe3c470:s1 -> Node0xe3c930;
Node0xe3c5e0 [shape=record,color="#3d50c3ff", style=filled, fillcolor="#f59c7d70",label="{%9}"];
Node0xe3c5e0 -> Node0xe3cb70;
Node0xe3c930 [shape=record,color="#3d50c3ff", style=filled, fillcolor="#f59c7d70",label="{%11}"];
Node0xe3c930 -> Node0xe3cb70;
Node0xe3cb70 [shape=record,color="#b70d28ff", style=filled, fillcolor="#b70d2870",label="{%13}"];
}

To visualize, install libraries first:

1
$ sudo apt install graphviz

And then use dot:

1
2
$ dot .main.dot -T png -o main.cfg.png
$ dot .max.dot -T jpeg -o max.cfg.jpg

And the results:
main.cfg.png
max.cfg.jpg

Some other options:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
$ opt -h|grep "\-cfg"
--cfg-hide-cold-paths=<number> - Hide blocks with relative frequency below the given value
--cfg-hide-deoptimize-paths -
--cfg-hide-unreachable-paths -
--dot-cfg-mssa=<file name for generated dot file> - file name for generated dot file
--dot-cfg - Print CFG of function to 'dot' file
--dot-cfg-only - Print CFG of function to 'dot' file (with no function bodies)
--print-cfg-sccs - Print SCCs of each function CFG
--view-cfg - View CFG of function
--view-cfg-only - View CFG of function (with no function bodies)
--wasm-cfg-sort - Reorders blocks in topological order
--wasm-cfg-stackify - Insert BLOCK/LOOP/TRY markers for WebAssembly scopes

$ opt -h|grep callgraph
--dot-callgraph - Print call graph to 'dot' file
--print-callgraph - Print a call graph
--print-callgraph-sccs - Print SCCs of the Call Graph
--view-callgraph - View call graph

LLVM IR Grammar

stay tuned …

Powered by Hexo & Theme Keep
Total words 135.7k