Appearance
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 所有,可以合并.
LTO Link Time Optimization
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 有很好的视频教程
- 单元测试