在LLVM中编写pass的详细教程(3)
来源:互联网 发布:淘宝网闲余非要下载吗 编辑:程序博客网 时间:2024/04/28 20:26
LLVM是一个自由软件项目,它是一种编译器基础设施,以C++写成。它的发展起源于2000年伊利诺伊大学厄巴纳-香槟分校(UIUC)的维克拉姆·艾夫(Vikram Adve)与其第一博士生克里斯·拉特纳(Chris Lattner)的研究,彼时他们想要为所有静态及动态语言创造出动态的编译技术。
2005年,苹果电脑雇用了克里斯·拉特纳及他的团队为苹果电脑开发应用程序系统,LLVM为现今Mac OS X及iOS开发工具的一部分,Xcode开发环境的内核使用的即是LLVM。因LLVM对产业的贡献,ACM于2012年将ACM软件系统奖授与Adve、Lattner及Evan Cheng。
----------------------------------------------------------------------------------------------------------------------------------------
在前面的文章中,我们已经介绍了通过编写pass对函数中的Basic Blocks进行遍历的方法,本文将介绍利用pass对程序中的操作码(Operation Code, OPCode)进行计数的方法。
跟之前一样,假设你的LLVM之安装目录为 ... .../llvm,那么你首先在路径 ... .../llvm/lib/Transforms 中创建一个子文件夹,例如名字叫做OpcodeCounter。然后在此文件夹下创建如下三个文件:CMakeLists.txt、OpcodeCounter.exports、OpcodeCounter.cpp。因为LLVM中作为pass的一个示例,提供了另外一个现成的pass,即在Transforms中的Hello文件夹,你可以从该文件夹下面把三个名为CMakeLists.txt、Hello.exports、Hello.cpp的文件拷贝到OpcodeCounter文件夹中并修改相应的文件名。
然后修改上层目录(即Transforms)中的CMakeLists.txt,在其末尾添加:add_subdirectory(OpcodeCounter)。然后修改... .../llvm/lib/Transforms/OpcodeCounter 中的CMakeLists.txt。注意这个文件是你从... .../llvm/lib/Transforms/Hello 中拷贝过来的。You must set up a build script that will compile the source code for the new pass,具体来说,你需要把其中出现了三次的Hello,都修改成OpcodeCounter,修改后该文件的内容如下:
# If we don't need RTTI or EH, there's no reason to export anything# from the hello plugin.if( NOT LLVM_REQUIRES_RTTI ) if( NOT LLVM_REQUIRES_EH ) set(LLVM_EXPORTED_SYMBOL_FILE ${CMAKE_CURRENT_SOURCE_DIR}/OpcodeCounter.exports) endif()endif()if(WIN32 OR CYGWIN) set(LLVM_LINK_COMPONENTS Core Support)endif()add_llvm_loadable_module( LLVMOpcodeCounter OpcodeCounter.cpp DEPENDS intrinsics_gen PLUGIN_TOOL opt )然后,需要编写pass文件的具体内容。这个pass文件其实就是一个.cpp文件,就当前这个例子而言,我们要做的就是编辑OpcodeCounter.cpp的内容。该文件内容如下:
#include "llvm/IR/Function.h"#include "llvm/Pass.h"#include "llvm/Support/raw_ostream.h"using namespace llvm;namespace { struct OpcodeCounter : public FunctionPass { static char ID; // Pass identification, replacement for typeid OpcodeCounter() : FunctionPass(ID) {} bool runOnFunction(Function &F) override { std::map<std::string, int> opcode_map; errs() << "Function name: "; errs() << F.getName() << '\n'; for(Function::iterator bb = F.begin(), e = F.end(); bb!=e; bb++) { for(BasicBlock::iterator i = bb->begin(), i2 = bb->end(); i!=i2; i++) { if(opcode_map.find(i->getOpcodeName()) == opcode_map.end()) opcode_map[i->getOpcodeName()] = 1; else opcode_map[i->getOpcodeName()] += 1; } } std::map<std::string, int> :: iterator p_start = opcode_map.begin(); std::map<std::string, int> :: iterator p_final = opcode_map.end(); while(p_start != p_final) { outs()<< p_start->first << " ::: " << p_start->second <<"\n"; p_start++; } opcode_map.clear(); return false; } };}char OpcodeCounter::ID = 0;static RegisterPass<OpcodeCounter> X("OpcodeCounter", "Count the number of opcode for every type");接下来要做的就是重新bulid LLVM。进入... .../llvm/build文件夹下面,直接使用make。整个过程大概需要几分钟的样子。然后来试用一下上面编写的Pass,为此你需要在你期望的位置(例如Desktop)上建立一个新的测试文件,例如使用上一篇文章《在LLVM中编写pass的详细教程(2)》 中的名为test.c的文件。在使用Clang命令编译生成.ll文件之后,再使用下面的命令来执行上面编写的pass:
opt -load /Users/fzuo/llvm/build/lib/LLVMOpcodeCounter.dylib -OpcodeCounter test.ll
然后,你便会得到如下输出:
WARNING: You're attempting to print out a bitcode file.This is inadvisable as it may cause display problems. Ifyou REALLY want to taste LLVM bitcode first-hand, youcan force output with the `-f' option.Function name: addadd ::: 1alloca ::: 2load ::: 2ret ::: 1store ::: 2Function name: mainalloca ::: 2br ::: 3call ::: 4icmp ::: 1load ::: 2ret ::: 1store ::: 1分析上面的输出,对比之前文章中给出的IR文件,便可以知道我们的pass对每个函数进行了分析,然后统计了其中各个操作码出现的次数。
【本系列文章目录】
- 在LLVM中编写Pass的详细教程(1):一个Hello World的Pass
- 在LLVM中编写Pass的详细教程(2):遍历一个函数中的Basic Blocks
- 在LLVM中编写Pass的详细教程(3):对程序中的OpCode进行计数
- 在LLVM中编写Pass的详细教程(4):def use 与 use def
- 在LLVM中编写Backend Pass的详细教程(1)
- 在LLVM中编写Backend Pass的详细教程(2)
- 在LLVM中编写pass的详细教程(3)
- 在LLVM中编写pass的详细教程(1)
- 在LLVM中编写pass的详细教程(2)
- 在LLVM中编写pass的详细教程(4)
- LLVM--如何在代码中调用遍(Pass)
- LLVM教程(一)-- LLVM的简介
- LLVM教程(二)-- LLVM的安装
- LLVM 源码分析 (一) pass 类
- 编写LLVM的后端(一)
- llvm學習(三)————如何編譯自己的第一個Pass
- LLVM pass manager debugging
- LLVM Pass 初探
- CMake LLVM Pass配置
- 【LLVM】MyHello Pass
- LLVM教程( 三)-- LLVM IR
- LLVM每日谈之十二 LLVM的源码分析之Pass相关
- LLVM每日谈之十三 使用LLVM自带的PASS
- 在llvm中完成if else语句的编译
- 牛客练习赛8 A B D E
- 2017年浙江工业大学大学生程序设计迎新赛预赛
- LeetCode: Reverse Integer,Palindrome Number
- ResNet-2015
- 在LLVM中编写pass的详细教程(2)
- 在LLVM中编写pass的详细教程(3)
- xmind8 pro 3.75 专业版中文版思维导图软件安装注册图文教程(附下载)
- POJ2136-Vertical Histogram(C语言实现)
- ajax中文乱码问题解决方案
- NASA 首次让私有公司 SpaceX 执行发射任务,用的还是“二手”火箭
- CB Insights 发布全球最强AI创业公司榜单,7家中国公司上榜
- 受Project Loon助力?Alphabet X实验室大拓印度通信市场
- Window 系统下 Ruby安装, Sass安装 ,Compass安装
- PitchBook:2017年美国人工智能和机器学习行业投资额超过45亿美元