源码路径

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相关推荐

  1. llvm libLLVMCore源码分析 13 - Other Operators

    源码路径 llvm\include\llvm\IR\Instruction.h llvm\include\llvm\IR\Instruction.def llvm\include\llvm\IR\In ...

  2. llvm libLLVMCore源码分析 08 - Memory Operators

    源码路径 llvm\include\llvm\IR\Instruction.h llvm\include\llvm\IR\Instruction.def llvm\include\llvm\IR\In ...

  3. Mybatis3源码分析(05)-加载Configuration-加载MappedStatement

    2019独角兽企业重金招聘Python工程师标准>>> Mybatis3源码分析(05)-加载Configuration-加载MappedStatement 博客分类: java m ...

  4. LLVM每日谈之十二 LLVM的源码分析之Pass相关

    作者:snsn1984 题记:在学习LLVM的过程中,要想学的更加深入,掌握更多的技能,LLVM的源码是必须要读的,但是在这么多的源码中,从哪里下手?很容易让人找不到头脑,本文这里就先拿出几个Pass ...

  5. Libev源码分析05:Libev中的绝对时间定时器

    Libev中的超时监视器ev_periodic,是绝对时间定时器,不同于ev_timer,它是基于日历时间的.比如如果指定一个ev_periodic在10秒之后触发(ev_now() + 10),然后 ...

  6. 非常适合新手的jq/zepto源码分析05

    zepto的原型  $.fn  属性: constructor //构造行数 forEach: emptyArray.forEach, //都是原生数组的函数reduce: emptyArray.re ...

  7. Spring_AOP架构介绍与源码分析(含事务深度分析)

    请见链接:http://edu.51cto.com/course/16573.html?source=so 第1章课程介绍6分钟1节 1-1课程介绍[免费试看]06:11 第2章AOP深入分析52分钟 ...

  8. v48.05 鸿蒙内核源码分析(信号生产) | 年过半百 活力十足 | 百篇博客分析HarmonyOS源码

    德行:颜渊,闵子骞,冉伯牛,仲弓.言语:宰我,子贡.政事:冉有,季路.文学:子游,子夏. <论语>:先进篇 百篇博客系列篇.本篇为: v48.xx 鸿蒙内核源码分析(信号生产篇) | 年过 ...

  9. v45.05 鸿蒙内核源码分析(Fork) | 一次调用 两次返回 | 百篇博客分析HarmonyOS源码

    孔子于乡党,恂恂如也,似不能言者.其在宗庙朝廷,便便言,唯谨尔. <论语>:乡党篇 百篇博客系列篇.本篇为: v45.xx 鸿蒙内核源码分析(Fork篇) | 一次调用 两次返回 进程管理 ...

最新文章

  1. 【论文阅读----DDI(1)】MUFFIN: multi-scale feature fusion for drug–drug interaction prediction
  2. 自定义报表 java_报表为什么会没完没了?怎么解决这个问题?
  3. 爬虫侵入计算机系统,【探讨】利用“爬虫技术”获取数据行为的刑事考量 ——以一起非法获取计算机信息系统数据案为例...
  4. html搞笑注释,9个最有趣的代码注释
  5. 为什么我不推荐敏捷开发?
  6. 仿百度文库实现文档在线预览
  7. [C/C++]堆栈的概念与区别
  8. model.load_state_dict(checkpoint[‘state_dict‘]) KeyError: ‘state_dict‘
  9. STM32——库函数版——RGB8x8全彩点阵程序
  10. 算法图解笔记(附PDF下载地址)
  11. 老男孩python全栈day01
  12. windows重置net use或者SMB协议
  13. 华为S5700交换机升级记录
  14. win10多任务处理快捷键
  15. 学习Python人工智能前景如何
  16. DBA生活篇之休闲:不做宅男!
  17. 计算机视觉-图像处理基础
  18. 论VM和Hyper-v虚拟机的使用场景
  19. 尚硅谷-康师傅-MySQL详细笔记(1-9章)
  20. 如何利用Dpabi,AFNI,FSL软件计算种子点的功能连接?

热门文章

  1. 微信小程序在线考试项目开发-接口封装调用
  2. 基于协同过滤 算法推荐系统图书推荐猜你喜欢
  3. 读书笔记---季凯帆的《解读基金,我的投资观与实践》
  4. Linux单网卡双IP
  5. 学习模拟集成电路的九个阶段
  6. 【MySql】windows下重置数据库密码
  7. 新型冠状病毒之物资的分配
  8. 如何输入带空格的字符串
  9. bit Byte bps Bps
  10. Unix时间戳 怎么计算