LLVM资料整理

  • LLVM是模块化、可重用的编译器以及工具链技术的
  • GCC、LLVM、clang
  • 传统的编译器架构:前端-优化器(中间代码)-后端->机器代码
  • 不同的前端后端使用统一的中间代码LLVM Intermediate Representation(LLVM IR)
  • 如果需要支持一种新的编程语言,只要实现一个新的前端
  • 如果需要支持一种新的硬件设备,只要实现一个新的后端
  • 优化阶段使用统一的LLVM IR,不需要做修改
  • GCC 前端后端耦合在一起,需要每个都实现
  • LLVM现在被作为实现各种静态和运行时编译语言的通用基础架构(GCC家族、Java、.Net、Python、Ruby、Scheme、Haskell、D等)

Clang

  • LLVM项目的一个子项目
  • 基于LLVM架构的C/C++/Objective-C编译
  • 相比GCC,Clang编译速度快(Debug模式下编译OC速度比GCC快三倍)、占用内存效(Clang生成的AST占用内存是GCC的1/5)、模块化设计(Clang基于库的模块化设计,易于IDE集成和其他用途的重用)、诊断信息可读性强(在编译过程种,Clang创建并保留了大量详细的元数据(metaData),有利于调试)
  • clang代码需要放在./llvm/tools下

Clang+LLVM

  • 前端使用Clang进行词法分析、语法分析、语义分析、生成中间代码
  • 优化器和后端使用LLVM

OC源文件的编译过程

  • 通过命令行查看编译过程:$ clang -ccc-print-phases main.m
  • 词法分析,生成token:$ clang -fmodules -E -Xclang -dump-tokens main.m
  • 生成语法树-AST:$ clang -fmodules -fsyntax-only -Xclang -ast-dump main.m

LLVM IR

LLVM IR有3种表现形式:

  • text:文本格式,$ clang -S -emit-llvm main.m
  • memory: 内存格式
  • bitcode:二进制格式,$ clang -C -emit-llvm main.m

LLVM IR语法:

  • 注释以分号;开头
  • 全局标识符以@开头,局部标识符以%开头
  • alloca,在当前函数栈帧种分配内存
  • i32,32bit
  • align,内存对齐
  • load,读取数据
  • store,写入数据

LLVM源码编译

  • 安装cmake和ninja,ninja可以直接从github下载解压到bin目录
brew install cmake
brew install ninja
  • 编译ninja模板:
cmake -G Ninja ../llvm -DCMAKE_INSTALL_PREFIX=LLVM的安装路径
  • $ ninja
  • $ ninja install
  • 也可以生成xcode模板进行编译

应用与实践

libclang、libTooling

clang插件开发

Pass开发

开发新的编程语言

clang插件开发

  • 在llvm源码目录下clang/tools目录下开发,新建目录XXPlugin,在CMakeList.txt添加该目录
  • XXPlugin下新建一个cpp文件,新建一个txt,txt中添加这个cpp
add_llvm_loadable_module(XXPlugin XXPlugin.cpp) 
//如果又多个Plugin,都放在括号中,逗号分割
  • 在cpp中写一个class XXAction继承自PluginASTAction
  • 注册插件
static FrontendPluginRegistry::Add<XXPlugin::XXAction>
X("XXPlugin", "description");
  • 重写CreateASTConsumer和ParseArgs(直接返回true)两个方法
  • 定义一个Consumer类继承自ASTConsumer
  • 重写HandleTranslationUnit方法,该方法当Clang编译完语法树时调用
  • 编译完成后的dylb动态库放在Xcode中,Build Settings中Other C Flags添加该动态库路径以及插件名称,同时Compiler需要改成自己编译好的llvm编译器(Default自带编译器不允许加载插件)。如果重新编译插件代码生成dylb,使用这个插件的工程需要Clean重新加载插件。
  • 需要对Xcode进行Hack,才能修改默认编译器。下载XcodeHacking.zip,修改HackedClang文件中的ExecPath的路径为llvm本地路径。然后在XcodeHacking目录下执行命令
$ sudo mv HackedClang.xcplugin `xcode-select -print-path`/../PlugIns/Xcode3Core.ideplugin/Contents/SharedSupport/Developer/Library/Xcode/Plug-ins
$ sudo mv HackedBuildSystem.xcspec `xcode-select -print-path`/Platforms/iPhoneSimulator.platform/Developer/Library/Xcode/Specifications
  • 构造一个Consumer,用来抛出警告或错误信息
  • MatchFinder可以用来查找语法树上下文

注:资料整理自MJ公开课。

©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

推荐阅读更多精彩内容