当前位置:网站首页>LLVM系列第二十六章:理解LLVMContext
LLVM系列第二十六章:理解LLVMContext
2022-08-02 14:07:00 【飞翼剑仆】
系列文章目录
LLVM系列第一章:编译LLVM源码
LLVM系列第二章:模块Module
LLVM系列第三章:函数Function
LLVM系列第四章:逻辑代码块Block
LLVM系列第五章:全局变量Global Variable
LLVM系列第六章:函数返回值Return
LLVM系列第七章:函数参数Function Arguments
LLVM系列第八章:算术运算语句Arithmetic Statement
LLVM系列第九章:控制流语句if-else
LLVM系列第十章:控制流语句if-else-phi
LLVM系列第十一章:写一个Hello World
LLVM系列第十二章:写一个简单的词法分析器Lexer
LLVM系列第十三章:写一个简单的语法分析器Parser
LLVM系列第十四章:写一个简单的语义分析器Semantic Analyzer
LLVM系列第十五章:写一个简单的中间代码生成器IR Generator
LLVM系列第十六章:写一个简单的编译器
LLVM系列第十七章:for循环
LLVM系列第十八章:写一个简单的IR处理流程Pass
LLVM系列第十九章:写一个简单的Module Pass
LLVM系列第二十章:写一个简单的Function Pass
LLVM系列第二十一章:写一个简单的Loop Pass
LLVM系列第二十二章:写一个简单的编译时函数调用统计器(Pass)
LLVM系列第二十三章:写一个简单的运行时函数调用统计器(Pass)
LLVM系列第二十四章:用Xcode编译调试LLVM源码
LLVM系列第二十五章:简单统计一下LLVM源码行数
LLVM系列第二十六章:理解LLVMContext
前言
在此,记录下对LLVM源码中LLVMContext这个类的理解,以备查阅。
How
不知您注意到没有,当我们调用LLVM提供的C++ API来生成IR代码时,第一行C++代码就是初始化LLVMContext。如下面这个简单的例子,它创建了一个模块(Module):
// HelloModule.cpp
#include "llvm/IR/Module.h"
#include "llvm/IR/LLVMContext.h"
using namespace llvm;
int main(int argc, char* argv[])
{
LLVMContext context;
Module* module = new Module("HelloModule", context);
module->print(outs(), nullptr);
return 0;
}
main函数的第一行就是初始化context的代码:
LLVMContext context;
注意到,当我们创建一个模块(Module)时,context是其中一个输入参数:
Module* module = new Module("HelloModule", context);
另外,我们还可以利用context创建Type(示例):
IntegerType* int32Type = Type::getInt32Ty(context);
Why
在LLVM API中,context是一个很重要的类,它能让我们在多线程中使用LLVM API。我们可以把它理解为一个黑盒,它包含(并管理)了LLVM中基础的、核心的“全局”数据,如类型(Type)、标准化的常量表等。
这里用到了“黑盒”这个词,是为了表明,API的调用者无需过多地深究context是什么。比如,我们无需深究它是如何实现的,包含了什么数据,作用是什么等各种问题。我们可以简单地把它当做一个“代表”,它代表了LLVM这个“引擎库”。我们只需记住,当一个函数需要context的时候,我们就把它传进去即可。
What
通常来说,LLVM的用户也许不需要知道context是什么,但编程语言的开发者(即编译器的开发者)是需要清楚地知道context是什么的。
Context包含了LLVM在一个线程中正常运行(比如一个编译任务)所需要的数据(即LLVM程序状态数据)。在很久以前,也就是LLVM的老版本中,这些状态数据都是全局数据。后来,它们被一股脑儿打包到了一个名叫“LLVMContext”的对象中,这样,LLVM就能支持在多线程中运行编译任务了。
多线程共享context
虽然context可以在多线程中共享使用,但它不是线程安全的,因为它自己不提供数据同步(如加锁)机制。Context本身以及它所包含的数据都是设计成给一个单独的线程使用的。所以,在多线程中共享使用context,可能会导致竞争、数据不同步等多线程常见问题。
线程独有context
当然,如果每个线程都创建一份自己独有的context,则不会有这些问题了。当每一个线程都有自己独立的一份context时,那命名冲突、类型冲突等问题就不再存在了。比如,某个线程正在处理模块A中的类型“Foo”,而另一个线程正在处理模块B中的类型“Foo”。那这两个类型不会互相干扰,因为它们处于不同的context下。
再举个例子,有这样一个多线程的程序,其中一个线程运行图像处理库(Graphics Library),另一个线程运行音频处理库(Audio Library),而这两个库都调用了LLVM。既然它们都调用了LLVM,为了避免这两个处理任务相互干扰,我们只需让它们各自创建一份context即可。所有在当前context之下创建出来的模块(Module)、类型(Type)、常量(Constant)等数据都属于当前的context。另外,我们还可以利用LLVM提供的工具Verifier(这是一个C++类)进行检查,它能确保一个模块下所有的IR对象都属于同一个模块。
Context融合
一般情况下,每一个线程都应该创建一份自己独有的context,以确保数据安全。但如果要合并两个线程的数据,我们不能直接融合两份context对象为一份context。我们可以做的是,把两份context对象转为IR代码,然后合并IR代码。
总结
本章,我们简单地分析了一下LLVM API中的LLVMContext的作用和用法。
边栏推荐
- 重新学习编程day1 【初始c语言】【c语言编写出计算两个数之和的代码】
- jwt (json web token)
- 1.RecyclerView是什么
- Using the cloud GPU + pycharm training model to realize automatic background run programs, save training results, the server automatically power off
- Hession使用
- 再见篇:App专项技术优化
- 7.如何给RecyclerView添加Click和LongClick事件
- 执行栈和执行上下文
- 利用c语言实现对键盘输入的一串字符的各类字符的计数
- MongoDB安装流程心得:
猜你喜欢
随机推荐
Redis持久化机制
C语言——一级指针初识
2. Basic use RecyclerView
MySQL知识总结 (十) 一条 SQL 的执行过程详解
drf routing component Routers
Visual studio代码中有红色波浪线解决办法
1.RecyclerView是什么
spark(standalone,yarn)
绕过正则实现SQL注入
spark写sql的方式
华为防火墙
C语言日记 1“Hello world“
Flink时间和窗口
[VCU] Detailed S19 file (S-record)
C语言初级—用一角,两角,五角和一元组成3.5元有多少种组合方法
flutter中App签名
重新学习编程day1 【初始c语言】【c语言编写出计算两个数之和的代码】
Spark_Core
getUserProfile接口不显示用户性别和地区
Flink前期代码结构