llvm libLLVMCore源码分析 05 - Instruction Class
源码路径
llvm\include\llvm\IR\Instruction.h
llvm\include\llvm\IR\Instruction.def
llvm\include\llvm\IR\Instructions.h
llvm\include\llvm\IR\InstrTypes.h
Instruction和BasicBlock
在分析代码前,需要先介绍一下llvm IR的组织结构。在llmv中,一个Module中可以有n个Function,Function内可以有n个BasicBlock,BasicBlock是单进单出的n条Instruction序列。
以下面代码为例:
//test.cint foo(int a) {int b;if(a == 1) {b = 2;} else {b = 3;}return b;
}
使用命令:clang -emit-llvm -S test.c,生成IR文件test.ll:
; Function Attrs: noinline nounwind optnone uwtable
define dso_local i32 @foo(i32 %a) #0 {
entry:%a.addr = alloca i32, align 4%b = alloca i32, align 4%c = alloca i32, align 4%d = alloca i32, align 4%e = alloca i32, align 4store i32 %a, i32* %a.addr, align 4%0 = load i32, i32* %a.addr, align 4%cmp = icmp eq i32 %0, 3br i1 %cmp, label %if.then, label %if.elseif.then: ; preds = %entrystore i32 3, i32* %b, align 4store i32 2, i32* %c, align 4store i32 3, i32* %d, align 4br label %if.endif.else: ; preds = %entrystore i32 2, i32* %b, align 4store i32 3, i32* %c, align 4br label %if.endif.end: ; preds = %if.else, %if.then%1 = load i32, i32* %b, align 4%2 = load i32, i32* %c, align 4%add = add nsw i32 %1, %2store i32 %add, i32* %e, align 4%3 = load i32, i32* %d, align 4ret i32 %3
}
可以看到,Function foo被分割成了n块(entry/if.then/if.else/if.end),这n块既为n个BasicBlock。
llvm Instruction class
在llvm中,Instruction类是所有IR指令的基类。定义如下:
class Instruction : public User,public ilist_node_with_parent<Instruction, BasicBlock> {
...
};
Instruction继承自User比较好理解,因为指令大部分都有操作数(Operand),所以天然是User。
下面重点分析一下ilist_node_with_parent<Instruction, BasicBlock>。顾名思义,这个是一个拥有父节点的链表节点,主要的功能有2个:1)通过当前节点(Instruction),获取父节点(BasicBlock)。2)通过当前节点(Instruction),遍历链表上其他节点(Instruction)。这两部分功能的代码如下:
template <typename NodeTy, typename ParentTy, class... Options>
class ilist_node_with_parent : public ilist_node<NodeTy, Options...> {
protected:ilist_node_with_parent() = default;private:/// Forward to NodeTy::getParent().const ParentTy *getNodeParent() const {return static_cast<const NodeTy *>(this)->getParent();}public:/// Get the previous node, or \c nullptr for the list head.NodeTy *getPrevNode() {// Should be separated to a reused function, but then we couldn't use auto// (and would need the type of the list).const auto &List =getNodeParent()->*(ParentTy::getSublistAccess((NodeTy *)nullptr));return List.getPrevNode(*static_cast<NodeTy *>(this));}/// Get the next node, or \c nullptr for the list tail.NodeTy *getNextNode() {// Should be separated to a reused function, but then we couldn't use auto// (and would need the type of the list).const auto &List =getNodeParent()->*(ParentTy::getSublistAccess((NodeTy *)nullptr));return List.getNextNode(*static_cast<NodeTy *>(this));}
};} // end namespace llvm
可以看到,该基类要求NodeTy(Instruction)必须有一个getParent方法:
inline BasicBlock* Instruction::getParent() { return Parent; }
要求ParentTy(BasicBlock)必须有一个getSublistAccess方法:
/// Returns a pointer to a member of the instruction list.static InstListType BasicBlock::*getSublistAccess(Instruction*) {return &BasicBlock::InstList;}
完成上述实现后,即可通过如下代码,遍历BasicBlock中的Instruction:
BasicBlock& BB = ...
for (Instruction &I : BB)// The next statement works since operator<<(ostream&,...)// is overloaded for Instruction&errs() << I << "\n";
Instruction子类
Instruction的子类按照llvm\include\llvm\IR\Instruction.def中的定义,可以分为如下类别:
- Terminator Instructions
- Unary Operators
- Binary Operators
- Memory Operators
- Cast Operators
- Other Operators
在实现层面,Instruction的继承树并未严格按照这个分类去实现,而是分为了如下类别,类别中的实际的子类也与Instruction.def中的分类有所不同。
llvm libLLVMCore源码分析 05 - Instruction Class相关推荐
- llvm libLLVMCore源码分析 13 - Other Operators
源码路径 llvm\include\llvm\IR\Instruction.h llvm\include\llvm\IR\Instruction.def llvm\include\llvm\IR\In ...
- llvm libLLVMCore源码分析 08 - Memory Operators
源码路径 llvm\include\llvm\IR\Instruction.h llvm\include\llvm\IR\Instruction.def llvm\include\llvm\IR\In ...
- Mybatis3源码分析(05)-加载Configuration-加载MappedStatement
2019独角兽企业重金招聘Python工程师标准>>> Mybatis3源码分析(05)-加载Configuration-加载MappedStatement 博客分类: java m ...
- LLVM每日谈之十二 LLVM的源码分析之Pass相关
作者:snsn1984 题记:在学习LLVM的过程中,要想学的更加深入,掌握更多的技能,LLVM的源码是必须要读的,但是在这么多的源码中,从哪里下手?很容易让人找不到头脑,本文这里就先拿出几个Pass ...
- Libev源码分析05:Libev中的绝对时间定时器
Libev中的超时监视器ev_periodic,是绝对时间定时器,不同于ev_timer,它是基于日历时间的.比如如果指定一个ev_periodic在10秒之后触发(ev_now() + 10),然后 ...
- 非常适合新手的jq/zepto源码分析05
zepto的原型 $.fn 属性: constructor //构造行数 forEach: emptyArray.forEach, //都是原生数组的函数reduce: emptyArray.re ...
- Spring_AOP架构介绍与源码分析(含事务深度分析)
请见链接:http://edu.51cto.com/course/16573.html?source=so 第1章课程介绍6分钟1节 1-1课程介绍[免费试看]06:11 第2章AOP深入分析52分钟 ...
- v48.05 鸿蒙内核源码分析(信号生产) | 年过半百 活力十足 | 百篇博客分析HarmonyOS源码
德行:颜渊,闵子骞,冉伯牛,仲弓.言语:宰我,子贡.政事:冉有,季路.文学:子游,子夏. <论语>:先进篇 百篇博客系列篇.本篇为: v48.xx 鸿蒙内核源码分析(信号生产篇) | 年过 ...
- v45.05 鸿蒙内核源码分析(Fork) | 一次调用 两次返回 | 百篇博客分析HarmonyOS源码
孔子于乡党,恂恂如也,似不能言者.其在宗庙朝廷,便便言,唯谨尔. <论语>:乡党篇 百篇博客系列篇.本篇为: v45.xx 鸿蒙内核源码分析(Fork篇) | 一次调用 两次返回 进程管理 ...
最新文章
- 【论文阅读----DDI(1)】MUFFIN: multi-scale feature fusion for drug–drug interaction prediction
- 自定义报表 java_报表为什么会没完没了?怎么解决这个问题?
- 爬虫侵入计算机系统,【探讨】利用“爬虫技术”获取数据行为的刑事考量 ——以一起非法获取计算机信息系统数据案为例...
- html搞笑注释,9个最有趣的代码注释
- 为什么我不推荐敏捷开发?
- 仿百度文库实现文档在线预览
- [C/C++]堆栈的概念与区别
- model.load_state_dict(checkpoint[‘state_dict‘]) KeyError: ‘state_dict‘
- STM32——库函数版——RGB8x8全彩点阵程序
- 算法图解笔记(附PDF下载地址)
- 老男孩python全栈day01
- windows重置net use或者SMB协议
- 华为S5700交换机升级记录
- win10多任务处理快捷键
- 学习Python人工智能前景如何
- DBA生活篇之休闲:不做宅男!
- 计算机视觉-图像处理基础
- 论VM和Hyper-v虚拟机的使用场景
- 尚硅谷-康师傅-MySQL详细笔记(1-9章)
- 如何利用Dpabi,AFNI,FSL软件计算种子点的功能连接?