LLVM clang 功能使用集锦

发布于:2025-03-24 ⋅ 阅读:(14) ⋅ 点赞:(0)

小源代码 adddd.c:

int adddddd(int a_a_a, int b_b_b)
{
	return a_a_a + b_b_b;
}

1,clang 生成 AST

clang -cc1 -ast-dump adddd.c

2,clang 生成 LLVM IR

clang -S -emit-llvm adddd.c -o adddd.ll

3,clang opt 生成 CFG 图

summmm.c 源码:

int summ(int N_N_N)
{
	int tmp = 0;
	while(N_N_N>0)
	{
		tmp += N_N_N;
	}

	return tmp;
}

clang -S -emit-llvm summmm.c -o summmm.ll
opt -dot-cfg summmm.ll 

生成 cfg.summ.dot 文件。

dot文件:

digraph  "CFG for 'summ' function" {
        label="CFG for 'summ' function";

        Node0x6131151575d0 [shape=record,label="{entry:\l  %N_N_N.addr = alloca i32, align 4\l  %tmp = alloca i32, align 4\l  store i32 %N_N_N, i32* %N_N_N.addr, align 4\l  store i32 0, i32* %tmp, align 4\l  br label %while.cond\l}"];
        Node0x6131151575d0 -> Node0x613115167c30;
        Node0x613115167c30 [shape=record,label="{while.cond:                                       \l  %0 = load i32* %N_N_N.addr, align 4\l  %cmp = icmp sgt i32 %0, 0\l  br i1 %cmp, label %while.body, label %while.end\l|{<s0>T|<s1>F}}"];
        Node0x613115167c30:s0 -> Node0x613115166680;
        Node0x613115167c30:s1 -> Node0x613115164590;
        Node0x613115166680 [shape=record,label="{while.body:                                       \l  %1 = load i32* %N_N_N.addr, align 4\l  %2 = load i32* %tmp, align 4\l  %add = add nsw i32 %2, %1\l  store i32 %add, i32* %tmp, align 4\l  br label %while.cond\l}"];
        Node0x613115166680 -> Node0x613115167c30;
        Node0x613115164590 [shape=record,label="{while.end:                                        \l  %3 = load i32* %tmp, align 4\l  ret i32 %3\l}"];
}

复制到浏览器左侧:

https://dreampuf.github.io/GraphvizOnline/?engine=dot

补充知识点:

CFG:以基本块为节点的有向图;

CFG的编译流程位置: 通常由对 IR 的分析而得到: Lang -> LLVM IR -> CFG

CFG 中的基本块的定义;

基本块的Leader 指令;

基本块的产生征兆;

基本块的结束条件;

基本块的确定;

CFG 的构造步骤;

4,

5,

6,

7,

8,

9,