Skip to content
On this page

clang-check

如何打印ast

c
//min.c
int min(int a, int b) {
  if (a < b)
    return a;
  return b;
}

运行 clang-check min.c -ast-dump --

txt
TranslationUnitDecl 0x7f7d66822408 <<invalid sloc>> <invalid sloc>
|-TypedefDecl 0x7f7d66822c30 <<invalid sloc>> <invalid sloc> implicit __int128_t '__int128'
| `-BuiltinType 0x7f7d668229d0 '__int128'
|-TypedefDecl 0x7f7d66822ca0 <<invalid sloc>> <invalid sloc> implicit __uint128_t 'unsigned __int128'
| `-BuiltinType 0x7f7d668229f0 'unsigned __int128'
|-TypedefDecl 0x7f7d66822fa8 <<invalid sloc>> <invalid sloc> implicit __NSConstantString 'struct __NSConstantString_tag'
| `-RecordType 0x7f7d66822d80 'struct __NSConstantString_tag'
|   `-Record 0x7f7d66822cf8 '__NSConstantString_tag'
|-TypedefDecl 0x7f7d66823040 <<invalid sloc>> <invalid sloc> implicit __builtin_ms_va_list 'char *'
| `-PointerType 0x7f7d66823000 'char *'
|   `-BuiltinType 0x7f7d668224b0 'char'
|-TypedefDecl 0x7f7d66823338 <<invalid sloc>> <invalid sloc> implicit __builtin_va_list 'struct __va_list_tag[1]'
| `-ConstantArrayType 0x7f7d668232e0 'struct __va_list_tag[1]' 1
|   `-RecordType 0x7f7d66823120 'struct __va_list_tag'
|     `-Record 0x7f7d66823098 '__va_list_tag'
`-FunctionDecl 0x7f7d66848760 </Users/bai/dev/llvm/example/min.c:1:1, line:5:1> line:1:5 min 'int (int, int)'
  |-ParmVarDecl 0x7f7d66848600 <col:9, col:13> col:13 used a 'int'
  |-ParmVarDecl 0x7f7d66848680 <col:16, col:20> col:20 used b 'int'
  `-CompoundStmt 0x7f7d66848998 <col:23, line:5:1>
    |-IfStmt 0x7f7d66848930 <line:2:3, line:3:16>
    | |-BinaryOperator 0x7f7d668488c8 <line:2:7, col:11> 'int' '<'
    | | |-ImplicitCastExpr 0x7f7d66848898 <col:7> 'int' <LValueToRValue>
    | | | `-DeclRefExpr 0x7f7d66848858 <col:7> 'int' lvalue ParmVar 0x7f7d66848600 'a' 'int'
    | | `-ImplicitCastExpr 0x7f7d668488b0 <col:11> 'int' <LValueToRValue>
    | |   `-DeclRefExpr 0x7f7d66848878 <col:11> 'int' lvalue ParmVar 0x7f7d66848680 'b' 'int'
    | `-ReturnStmt 0x7f7d66848920 <line:3:9, col:16>
    |   `-ImplicitCastExpr 0x7f7d66848908 <col:16> 'int' <LValueToRValue>
    |     `-DeclRefExpr 0x7f7d668488e8 <col:16> 'int' lvalue ParmVar 0x7f7d66848600 'a' 'int'
    `-ReturnStmt 0x7f7d66848988 <line:4:3, col:10>
      `-ImplicitCastExpr 0x7f7d66848970 <col:10> 'int' <LValueToRValue>
        `-DeclRefExpr 0x7f7d66848950 <col:10> 'int' lvalue ParmVar 0x7f7d66848680 'b' 'int'

LLVM IR的attribute有啥用?

readnone attribute

c
var bar();
int add(int x,int y){
 //bar();
 return x+y;
}
int foo(int x,int y){
 return add(x,y)+add(x,y);
}

foo中的两次add,可以合并么?

; Function Attrs:norecurse nounwind readnone uwtable willreturn mustprogress
define dso_local i32 @_Z3fooii(i32 %x, i32 %y)
local_unnamed_addr #1 {
entry:
%call = tail call i32 @_Z3addii(i32 %x, i32 %y)
%add = shl nsw i32 %call, 1
ret i32 %add
3

因为add有readone attribute,表示:Function does not access memory 所有,可以合并.

c
//a.h
extern int fool(void);
extern void foo2(void);
extern void foo4(void);
c
//a.c
#include "a.h"
static signed int i = 0;
void foo2(void){i= -1; }
static int foo3()}
foo4();
return 10;
}
int fool(void){
int data=0;
if(i<0)
	data=foo3();
data = data + 42;
return data;
}
c
#include "a.h"
void foo4(void){
	printf("Hi\n");
}
int main()
	return foo1();
}

如果支持LTO,考虑到foo2根本不会被调用,那么推出i永远为0, 所以foo1经过优化以后:

c
int foo1(){
	return 42;
}

但是代价确实大,要对整个可执行程序将进行整体优化.

BOLT Binary Optimization and Layout Tool

让二进制code布局更合理,让cpu的指令预测更有效率.

tools

编译期

  • clang-tidy

不会执行数据流分析和符号执行的能力,主要是做一些语法层级的一些代码规范的检查.

  • Clang-rename
  • clangd
  • modularize
  • pseudo

运行期

  • addresssanitizer
  • Threadsanitizer data race condition
  • undefinedbehaviorsanitizer 未定义行为
  • memorysanitizer 未初始化的检测
  • leaksanitizer 检测内存泄漏
  • dataflowsanitizer 基于llvm的污点传播框架,用户需要自己特定的使用场景来定义一些source,sink,sanitizer
  • Memprof

LLVM 开发资料来源:

  • reviews.llvm.org 有特性的实现细节和说明
  • llvm’s developers’ meeting 有很好的视频教程
  • 单元测试