环境:win7 64位+llvm11+mingw+python3.7+libclang11
LLVM编译一个源文件的过程:预处理 -> 词法分析 -> Token -> 语法分析 -> AST -> 代码生成 -> LLVM IR -> 优化 -> 生成汇编代码 -> Link -> 目标文件
main.c 源码:
//#include<stdio.h> //可以注释,不影响分析
int main(int argc,char*argv[])
{
puts("hello world");
return 0;
}
使用LLVM的对一门语言编译的简图如下所示:
Clang和LLVM关系:
Clang是一个C++编写、基于LLVM、发布于LLVM BSD许可证下的C/C++/Objective-C/Objective-C++编译器。那么为什么已经有了GCC还要开发Clang呢?Clang相比于GCC有什么优势呢? 其实,这也是Clang当初在设计开发的时候所主要考虑的原因。Clang是一个高度模块化开发的轻量级编译器,它的编译速度快、占用内存小、非常方便进行二次开发。
LVM和Clang的关系是怎样的呢。我们将它们对应于传统的编译器当中的几个独立的部分,这样能够更加方便明确生动的表述。
1、查看程序编译过程:
clang -ccc-print-phases main.c
2、查看preprocessor(预处理)的结果
clang -E main.c
3、词法分析,生成token
clang -Xclang -dump-tokens main.c
4、语法分析,生成语法树
clang -fsyntax-only -Xclang -ast-dump main.c
Clang AST介绍可以参考
https://www.cnblogs.com/jourluohua/p/14524955.html
配置python clang
现在的Clang,不仅仅是一个编译器前端,同时也可以作为一个库使用。作为一个库使用的时候,可以用它去分析C/C++/ObjectC语言代码,可以分析源码得到AST,也可以获取已经分析好的AST,也可以遍历AST,还可以获取AST中基本元素的物理源码位置。这就是libclang。libclang提供了一系列的C语言的接口,但是这些接口并不能完全提供存储在Clang C++ AST中的所有信息,只能提供部分基本信息,但是这些基本信息已经可以满足一般情况下的使用。主要目的是为了稳定,并且可以支持开发工具的基本功能。
libclang很方便就打印了词法分析结果和AST语法树
C语言测试代码
typedef unsigned int VOS_UINT32; VOS_UINT32 add(VOS_UINT32 num1,VOS_UINT32 num2) { VOS_UINT32 result=num1+num2; return result; }
生成的AST语法树:
python解析代码
功能:遍历tokens流和AST抽象语法树
from clang.cindex import Config #配置 from clang.cindex import TypeKind from clang.cindex import CursorKind from clang.cindex import Index #主要API def GetTranslationUnit(filename): index = Index.create() tu = index.parse(filename) print("tTranslation Unit=%s"%(tu.spelling)) return tu def LoadLibClang(libclangPath): if Config.loaded == True: pass else: Config.set_library_file(libclangPath) #主函数 if __name__ == '__main__': filename='test.c' # C语言文件 libclangPath = r'C:\Program Files\LLVM\bin\libclang.dll' #libclang库路径 LoadLibClang(libclangPath) #加载libclang库 tu=GetTranslationUnit(filename)#解析main.c ast_root_node=tu.cursor #获取cursor根节点 # 获取词法分析结果 print("Print all tokens:") for token in ast_root_node.get_tokens():#遍历词法分析结果 print('%10s %s'%(token.spelling,token.kind)) print("Print all nodes in ast tree:") for node in ast_root_node.walk_preorder(): # 遍历词法分析结果 print('%10s %s %s '%(node.spelling,node.location.line,node.kind)) #help(Token) #help(Index)
运行结果
0.0分
1 人评分
C语言程序设计教程(第三版)课后习题6.5 (Java代码)浏览:1256 |
C语言程序设计教程(第三版)课后习题8.3 (C语言代码)浏览:677 |
C语言程序设计教程(第三版)课后习题7.5 (C语言代码)浏览:591 |
C语言程序设计教程(第三版)课后习题7.3 (C语言代码)浏览:644 |
时间转换 (Java代码)浏览:618 |
简单的a+b (C语言代码)浏览:720 |
C语言程序设计教程(第三版)课后习题10.5 (C语言代码)浏览:1489 |
C语言程序设计教程(第三版)课后习题1.5 (C语言代码)浏览:504 |
C语言训练-大、小写问题 (C语言代码)浏览:794 |
Wu-求圆的面积 (C++代码)浏览:1997 |